UPDATE July 1, 2010: univ_open() has been updated here.
Like my previous post, the goal is to use a single alias to open up any kind of file or directory intelligently. I’ve decided to write a new post because of various improvements over the old code. For one, I’ve implemented everything in Zsh — now everything is much faster, especially for older systems. So now the components are: (1) a custom zsh function called univ_open and (2) some custom options in ~/.zshrc to complement univ_open.
Here is the new univ_open:
1 # Author: Shinobu (https://zuttobenkyou.wordpress.com) 2 # Date: December 2009 3 # License: PUBLIC DOMAIN 4 # Program Name: univ_open 5 # Description: open up directories and files intelligently 6 7 univ_open() { 8 ls="ls -Ahs --color=auto" 9 if [[ -z $@ ]]; then 10 # if we do not provide any arguments, go to the home directory 11 cd && ${=ls} 12 elif [[ ! -e $@ ]]; then 13 # go to the nearest valid parent directory if file does not exist; we 14 # use a while loop to find the closest valid directory, just in case 15 # the user gave a butchered-up path 16 d=$@:h 17 while [[ ! -d $d ]] 18 do 19 d=$d:h 20 done 21 cd $d && ${=ls} 22 elif [[ -d $@ ]]; then 23 cd $@ && ${=ls} 24 else 25 case $@:e:l in 26 (doc|odf|odt|rtf) 27 soffice -writer $@ &>/dev/null & disown 28 ;; 29 (htm|html) 30 firefox $@ &>/dev/null & disown 31 ;; 32 (pdf|ps) 33 evince $@ &>/dev/null & disown 34 ;; 35 (bmp|gif|jpg|jpeg|png|svg|tiff) 36 eog $@ &>/dev/null & disown 37 ;; 38 (psd|xcf) 39 gimp $@ &>/dev/null & disown 40 ;; 41 (aac|flac|mp3|ogg|wav|wma) 42 smplayer $@ &>/dev/null & disown 43 ;; 44 (mid|midi) 45 timidity $@ 46 ;; 47 (avi|flv|ogv|mkv|mov|mp4|mpg|mpeg|wmv) 48 smplayer $@ &>/dev/null & disown 49 ;; 50 *) 51 vim $@ 52 ;; 53 esac 54 fi 55 }
The basic operation of this function remains the same: if no arguments given, go to the home directory (this is cd‘s default behavior); if path is invalid, go to the nearest valid parent directory; if path is a valid directory, cd to it; otherwise, it must be a valid file, so open it up with a program based on the file’s extension, and use vim as the default program for unrecognized extensions (or files with no extensions). Again, filename extensions are lowercased to ensure that we are case-insensitive.
Some improvements over the old code: (1) univ_open now correctly handles messed-up, invalid directories by trying to find the closest valid parent directory — this is achieved with a simple while loop, and zsh’s neat little “:h” method to extract the parent directory (same functionality as the UNIX dirname utility); if there is not a single valid directory in the given path, then it will simply cd into the current directory (i.e., nothing happens); (2) the file extensions are handled much better depending on filetype — for commands that are GUI-based, we redirect its STDOUT and STDERR to /dev/null to silence any error messages, immediately background it with the “&” operator, and finally disown it so that we can continue other work from the same terminal where we used our alias from. Terminal-bound commands, such as timidity and vim, are left as-is.
The neat thing about this new version of univ_open is that this makes bashrun for me obsolete! I can do pretty much everything from the terminal as it is.
And now, the pertinent options in ~/.zshrc to complement our use of univ_open:
fpath=(~/.zsh/func $fpath) # add ~/.zsh/func to $fpath autoload -U ~/.zsh/func/*(:t) # load all functions in ~/.zsh/func zmodload zsh/complist setopt auto_menu unsetopt listambiguous zstyle ':completion:*' menu select=1 _complete _ignored _approximate zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS} bindkey -M menuselect '^M' .accept-line LISTMAX=9999 alias d='univ_open' # alias to use univ_open()
auto_menu enables the menu selection system after pressing TAB. unsetopt listambiguous makes zsh automatically complete an ambiguous word to the nearest, partial-word match (combined with auto_menu, this makes it so that you only have to type TAB once, and only once, in all situations). The zstyle lines affect the style of how the menu is displayed. The bindkey portion makes the ENTER key execute the command when using the menu. (Note, ^M is a special character that represents a newline; in vim, you have to type CTRL-V, then CTRL-M to insert it). Finally, setting LISTMAX to a high number prevents zsh from asking “do you wish to see all N possibilities?”, unless N > 9999.
Happy zsh-ing!
UPDATE January 13, 2010: If you’re in a hurry, then you can put bindkey ‘\t’ menu-expand-or-complete to make it so that pressing TAB once brings up the menu and select the first item in that menu. (Or, if there is just 1 possibility, then to expand to that item).
UPDATE February 25, 2010: See my comment #1 below.