#!/bin/sh
# 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 $::w
LES: 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 = https://wiki.tcl-lang.org/4 chat = 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