# execute in wish from path \
exec wish "$0" ${1+"$@"}
# Alias.tcl - Takes an "alias" from an input box and runs the alias'
# corresponding command
#
# Author: Luciano Espirito Santo
#
# More on the purpose of this program:
# The very first time I used Linux, I really liked the concept of aliases: the
# ability to create short or easier to remember alternative names to commands
# or even sequences of commands.
# In Windows, I found a very convenient way to do this with PowerPro
# ( http://ppro.org/
). It provides an input box and a scripting back end. So I
# implemented this application with it and got terribly used to it.
# A few years later, using Linux a lot more often, I missed my aliases and
# decided to reimplement the whole thing, this time with Tcl.
# Of course, Linux/Unix already provides its own alias capability. The
# advantages of my application over Bash's aliases, for example, are few and
# small. Basically, it's just another approach to it.
# In Windows, the advantages are obvious: there is no alias capability in
# Windows that I ever heard of, unless Bash (again) under Cygwin and a couple
# of other applications that are very similar to this one, but do not run on
# Linux and therefore are totally inadequate to people who dual-boot often and
# otherwise would be forced to keep two isolated alias lists. Keep this
# application and the alias list in a partition accessible to both (or all)
# your operating systems and you should find no trouble in keeping the alias
# list always updated, regardless of which OS you're running at the time.
#
# History
#
# Version 1.0 2005-03-02 Luciano Espirito Santo
# First beta.
#
# Version 1.1 2005-03-02 Luciano Espirito Santo
# - Added some voodoo magic to cope with kfmclient because it won't do
# the right thing with full paths or single program names that
# otherwise could be found easily in $PATH.
#
# Version 1.2 2005-03-09 Luciano Espirito Santo
# - Fixed conflict between kstart and kfmclient. Now they are (hopefully)
# never run together.
# - Fixed bug revealed by empty/blank lines in the alias file.
# - KDE's own Run box would pop up right after attempts to run an invalid
# alias. Fixed that too.
#
# KNOWN ISSUES:
# - For the time being, this application requires KDE if used in
# Linux/Unix. We could get by without it, but the commands would become
# longer, more awkward and prone to errors.
# - Many commands are likely not to work due to all very well-known
# issues related with Tcl's exec command.
#
# This program offers no guarantees! Use it at your own risk!
#
# TO DO:
# - Anybody want to write another "voodoo" proc to work around exec's problems?
# - Lots of improvements planned. Stay tuned!
#
# LICENSE: BSD
#
# How to use it:
#
# - Save this file in any directory with read and write permission.
#
# - Create another file called Alias_list.txt in that same directory. Copy
# the sample provided right after the script. That is where you will
# maintain your alias list.
#
# - The following rules apply to the alias list:
# Each alias-separator-command group must be in its own single line.
# Format:
# alias = command [optional arguments]
# In other words:
# + the alias (any character except the "equals" sign), followed by:
# + any number of "blanks" (space or tabs), followed by:
# + an "equals" sign (=), followed by:
# + any number of "blanks" (space or tabs), followed by:
# + any command, with options and/or arguments.
#
# - Some commands may cause an error. Please see the "KNOWN ISSUES" above.
#
# - The first "equals" sign works as a delimiter, so that symbol cannot be
# used in any alias. It can be part of any command, though.
#
# - You may comment out any line you want. Lines starting with the
# "hash" symbol (#), with or without "blanks" (space or tabs), before or
# after the "hash" symbol, are ignored.
#
# - If you use Linux/Unix and KDE, open KDE's Control Center and, in the
# HotKeys section, assign a shortcut key to this command:
# '/path/to/tcl/wish /path/to/Alias.tcl'
#
# - If you use another window manager, I suggest you use a nice program
# called "xbindkeys". It works in any window manager. Just assign a
# shortcut key to this command: '/path/to/tcl/wish /path/to/Alias.tcl'
# Note, however, that you still must have KDE installed.
#
# - If you use Windows, create a new shortcut to this application (in
# your Start menu or any other place), right-click it, select
# "Properties" and assign a keyboard shortcut to it.
#
# - When (and if) the input box appears, type in an alias and press the
# Enter/Return key. If you want to cancel the action and close the box
# without running anything, press the Esc key.
#
# - Whenever you want to edit the alias list, launch the program and
# press the F5 key.
#
# - If you know Tcl, you may want to change the value of a few variables
# in the next section, "SET VARS".
# ================================================
# SET VARS
# myAliasFile: Alias list file location
# myAliasBg: input box's (entry widget) background color
# myAliasFg: input box's (entry widget) foreground font color
# myAliasFont: input box's (entry widget) font face
# myAliasWidth: input box's (entry widget) width (measured in characters)
# myAliasAlign: input box's (entry widget) text alignment
# mySoundEnabled: Boolean: whether to play a sound in case of error
# myErrorSound: sound file to play in case of error
# myHasTitle: set to "yes" if you want the box to have a title/caption
# myWindowTitle: the title/caption of the box
# ================================================
if { $::tcl_platform(platform) == "windows" } {
set myAliasFile "[ file normalize [pwd]/Alias_list.txt ]"
set myAliasBg "#ffffff" ;# or "white"
set myAliasFg "#000000" ;# or "black"
set myAliasFont "Arial 12" ;#or "{Times New Roman}12"
set myAliasWidth 40
set myAliasAlign center
set mySoundEnabled "yes"
set myErrorSound "D:/System/Sound/uh-oh.wav"
}
if { $::tcl_platform(platform) == "unix" } {
set myAliasFile "/am/d/home/xxxx/Alias_list.txt"
set myAliasBg "#ffffff" ;# or "white"
set myAliasFg "#000000" ;# or "black"
set myAliasFont "Helvetica 18"
set myAliasWidth 40
set myAliasAlign center
set mySoundEnabled "no"
set myErrorSound "/am/d/System/Sound/uh-oh.wav"
}
set myHasTitle "yes"
set myWindowTitle "A rose, by any other name..."
# this is an ugly hack, will fix it someday. DO NOT CHANGE IT.
set myNotFound 0
# ================================================
# PROCS
# packages: sound (optional)
# p.1.playwav: plays a sound file
# p.2.error: plays error sound and clears input box
# p.3.center_window: place a window at the center of the screen
# p.4.check_alias_file: checks existence of alias list file
# p.5.get_alias: reads input box, parses alias list and returns final command
# p.6.which: searches a program in $PATH
# p.7.voodoo: voodoo magic to workaround kfmclient's idiosyncrasy
# p.8.run_alias: the final command that runs the alias's corresponding command
# p.9.edit_alias: open alias list file in text editor so it can be edited
# ================================================
# ----------------------------------------------------------------
# proc 1 of 9
# plays a sound file
proc p.1.playwav { argWavFile } {
if { $::mySoundEnabled != "yes" } { return }
package require sound
snack::sound s -file $argWavFile; s play -block 1
}
# ----------------------------------------------------------------
# proc 2 of 9
# plays error sound and clears input box
proc p.2.error {} {
p.1.playwav $::myErrorSound
$::w.frame0.aliasbox delete 0 end
}
# ----------------------------------------------------------------
# proc 3 of 9
# place a window at the center of the screen
# argW = window to be placed at the center of the screen
proc p.3.center_window { argW } {
wm withdraw $argW
update idletasks
set x [ expr [ winfo screenwidth $argW ] /2 - [ winfo reqwidth $argW ] /2 - [ winfo vrootx [ winfo parent $argW ] ] ]
set y [ expr [ winfo screenheight $argW ] /2 - [ winfo reqheight $argW ] /2 - [ winfo vrooty [ winfo parent $argW ] ] ]
wm geom $argW +$x+$y
wm deiconify $argW
}
# ----------------------------------------------------------------
# proc 4 of 9
# checks existence of alias list file
# complains loudly if file is not found
proc p.4.check_alias_file {} {
if { ! [ file exists $::myAliasFile ] } {
p.2.error
$::w.frame0.aliasbox insert end "ALIAS LIST FILE NOT FOUND"
$::w.frame0.aliasbox selection range 0 end
set ::myNotFound 1
return "0"
} else { return "1" }
}
# ----------------------------------------------------------------
# proc 5 of 9
# reads input box, parses alias list and returns final command
proc p.5.get_alias {} {
# first check the existence of the alias list file
if { ! [ p.4.check_alias_file ] } {
return
}
array set ::myAliasHash {}
set myRegex {([^=]+)\s*=\s*(.*)}
# Parse $::myAliasFile and build the array myAliasHash
set myFP [ open $::myAliasFile r ]
while { ! [ eof $myFP ] } {
set myLine [ string trim [ gets $myFP ] ]
# Bug fix! This excludes empty lines of the alias file
if { [ regexp {^$} $myLine ] } {
continue
}
# this excludes commented out lines in the alias file
if { [ regexp {^#.*$} $myLine ] } {
continue
}
regexp $myRegex $myLine => myKey myValue
set myKey [ string trim $myKey ]
set myValue [ string trim $myValue ]
set myAliasHash($myKey) $myValue
}
close $myFP
# if alias is found in hash, return command
# if alias is not found in hash, produce error
set myRun [ array get myAliasHash $::myAlias ]
if { $myRun == "" } {
p.2.error
return "!!ERROR!!"
}
if { $myRun != "" } {
set myRun $myAliasHash($::myAlias)
return $myRun
}
}
# ----------------------------------------------------------------
# proc 6 of 9
# searches a program in PATH
# myFilename = name of file to search in PATH; an executable
proc p.6.which { myFilename } {
switch $::tcl_platform(platform) {
windows { set myPathList [ split $::env(PATH) \; ] }
default { set myPathList [ split $::env(PATH) : ] }
}
foreach dir $myPathList {
foreach ext { "" .bin .exe .dll .com .bat } {
set myCTL [ file join $dir "$myFilename$ext" ]
if { [ file exists $myCTL ] \
&& [ file readable $myCTL ] \
&& [ file executable $myCTL ] } {
return $myCTL
}
}
}
return ""
}
# ----------------------------------------------------------------
# proc 7 of 9
# applies some voodoo on the command string so as to workaround kfmclient's
# and maybe even exec's quirks in the future
proc p.7.voodoo { argRun } {
# if it is an Internet address, do nothing.
if { [ regexp -nocase {^(ht|f)tp.*} $argRun ] } {
return $argRun
}
# we need to go to / due to kfmclient's idiosyncrasy: it always
# assumes the HOME directory. Full paths are useless to it.
if { $::tcl_platform(platform) == "unix" } {
cd /
}
# "command" may have arguments (multiple words). Isolate the program:
set myProgram [ lindex $argRun 0 ]
# check if full path to program was provided and if exists.
# If yes, nothing else to do.
if { [ file exists [ file normalize "[pwd]/$myProgram" ] ] } {
return $argRun
}
# if full path to program was NOT provided, find out where it is.
# find it with 'which' then replace Program with Full Path
set myFullPath [ p.6.which $myProgram ]
regsub $myProgram $argRun $myFullPath myRun
return $myRun
}
# ----------------------------------------------------------------
# proc 8 of 9
# the final command that runs the alias's corresponding command
proc p.8.run_alias {} {
# First we get alias and corresponding command
set myRun [ p.5.get_alias ]
# If p.5.get_alias returns error, alias does not exist.
# Return and start all over again
if { $myRun == "!!ERROR!!" } {
return
}
# If no error is found, apply voodoo on it.
set myRun [ p.7.voodoo $myRun ]
# Run command on Windows
if { $::tcl_platform(platform) == "windows" } {
eval exec start $myRun &
exit
}
# Run command on Unices
if { $::tcl_platform(platform) == "unix" } {
# This avoids using kfmclient with kstart
set myProgram [ lindex $myRun 0 ]
if [ regexp {^[^ ]*kstart$} $myProgram ] {
eval exec $myRun &
} else { eval exec kfmclient exec $myRun & }
}
# and here is the ugly hack again
if { $::myNotFound != 1 } {
exit
}
}
# ----------------------------------------------------------------
# proc 9 of 9
# open alias list file in text editor so it can be edited
proc p.9.edit_alias {} {
if { $::tcl_platform(platform) == "windows" } {
eval exec start $::myAliasFile &
}
if { $::tcl_platform(platform) == "unix" } {
cd /
eval exec kfmclient exec $::myAliasFile &
}
exit
}
# ================================================
# DRAW WINDOW
# Using these widgets:
# toplevel .popbox
# frame $::w.frame0
# entry $::w.frame0.aliasbox
# ================================================
catch { destroy .popbox }
set w [ toplevel .popbox ]
wm withdraw .
wm geometry $::w +50+200
wm title $::w $myWindowTitle
wm overrideredirect $::w [ expr { $myHasTitle=="yes" ? "0" : "1" } ]
# --------------------------------
frame $::w.frame0
$::w.frame0 configure -relief sunken
$::w.frame0 configure -bd 0
pack $::w.frame0 -fill both -expand 1
entry $::w.frame0.aliasbox
$::w.frame0.aliasbox configure -takefocus 1
$::w.frame0.aliasbox configure -relief sunken
$::w.frame0.aliasbox configure -bd 0
$::w.frame0.aliasbox configure -width $myAliasWidth
$::w.frame0.aliasbox configure -background $myAliasBg
$::w.frame0.aliasbox configure -foreground $myAliasFg
$::w.frame0.aliasbox configure -font $myAliasFont
$::w.frame0.aliasbox configure -justify $myAliasAlign
$::w.frame0.aliasbox configure -textvariable myAlias
pack $::w.frame0.aliasbox -expand 1
# ================================================
# BINDINGS
# ================================================
bind $::w.frame0.aliasbox <Return> { p.8.run_alias }
bind $::w <Key-Escape> { exit }
bind $::w <Key-F5> { p.9.edit_alias }
wm protocol $::w WM_DELETE_WINDOW { exit }
# ================================================
# RUN
# ================================================
# Disappoint Mac users
if { $::tcl_platform(platform) == "macintosh" } {
wm withdraw $::w
tk_messageBox -message "This application does not run on Macs" -title "Ooops!"
exit
}
focus $::w.frame0.aliasbox
p.3.center_window $::wLES: Here is the alias list sample. It MUST be called "Alias_list.txt" and reside in the same directory as the application:
# ================================================ # ALIAS LIST # ================================================ 2d = ~/Desktop/todo.txt 4 = http://wiki.tcl.tk/4chat = D:/TclTk/chat/tkchat.kit clt = http://groups.google.com/groups?ie=UTF-8&group=comp.lang.tcl
ff = /usr/local/bin/firefox ffex = http://texturizer.net/firefox/extensions/
ggf = http://www.googlefight.com
pkg = ftp://ftp.netbsd.org/pub/NetBSD/packages/pkgsrc/README-all.html
rot = http://www.rottentomatoes.com
sp 1 = /usr/local/bin/adsl on sp 0 = /usr/local/bin/adsl off tz = http://www.timeanddate.com/worldclock/
ws = http://www.wordspy.com/
xc = http://www.x-rates.com/calculator.html

