PDA

View Full Version : Case-insensitive completion using zsh?


sapporo
10-19-2002, 04:48 AM
I recently started using zsh instead of bash for it's programmable completion feature. It lets you define how zsh will complete a command when you hit <TAB>. My favorite example is this:
$ compctl -g '*.java' javac
makes javac see java source files only:
$ ls
Test.java Test.class
$ javac T<TAB>
will be completed to
$ javac Test.java
immediately.
and it gets even better:
myclasslist () { reply=(${$(ls *.class)%.class}) }
compctl -K myclasslist java
makes java see only java class names:
java T<TAB>
will be completed to
$ java Test
immediately.

But there's one thing I couldn't figure out yet, and that's case-insensitive completion, which I would like to work like this:
$ ls
Test.java
$ more t<TAB>
will be completed to
$ more Test.java
immediately.

It's even mentioned in the zsh manual at http://zsh.sunsite.dk/ , but I couldn't get it to work on Mac OS 10.2 so far.

If anyone could help, I'd appreciate it.

TIA,
-sapporo.

ps: zsh is in many ways very similar to bash (unless you're a real pro, I guess), so I highly recommend giving it a try.

santin
10-19-2002, 05:22 AM
You should use the new completion system of zsh4.0.4

Here is the sample zshrc I used as a starting point... of course it needs to be tuned up...

http://free-po.hinet.hr/MarijanPeh/files/zshrc

It does not only include what you're looking for, but also a bunch of other nice features. However you will have to test and modify to get best results...

sapporo
10-19-2002, 06:33 AM
Hmm, that's a nice ~/.zshrc with many interesting settings and lots of comments.
It also includes the settings for case-insensitive completion as seen in the zsh manual, but unfortunately, they don't work for me..
After applying

## case-insensitive (uppercase from lowercase) completion
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
## case-insensitive (all) completion
#zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}'
## case-insensitive,partial-word and then substring completion
#zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'


$ touch Hello.txt
$ more h<TAB>

will still not expand h to Hello.txt.

Any ideas?

TIA,
-sapporo.

santin
10-19-2002, 07:18 AM
Well, it does expand in my terminal
Here you have my config:

/etc/zshrc
##
## /etc/zshrc
##

#print /etc/zshrc

## Aliases & functions
#alias -- .='pwd' # !!! be careful with this one: usually . <=> source
alias -- ..='cd ..'
alias -- cd..='cd ..'
alias -- cdwd='cd `pwd`'
alias -- cwd='echo $cwd'
alias -- l='ls -lg'
alias -- list_all_hostnames='grep -v "^#" /etc/hosts'
alias find='noglob find'
ff () {
# ff x find file named x
find . -name $1 -print
}
files () {
# files x => list files in x
find $1 -type f -print
}
line () {
# line 5 file => show line 5 of file
sed -n "$1 p" $2
}
ll () {
ls -lag $* | more
}
term () {
setopt noglob;
unset TERMCAP;
eval `tset -s -I -Q - $*`
}
word () {
# Grep thru dictionary
grep $* /usr/share/dict/web2
}
wordcount () {
# Histogram words
(cat $* | tr -s ' .,;:?!()[]"' '\012' | cat -n | tail -1 | awk '{print $1}')
}

## History
HISTFILE=~/.zsh_history
HISTSIZE=1000
SAVEHIST=1000
## History options
setopt incappendhistory \
extendedhistory \
histfindnodups \
histreduceblanks \
histignorealldups \
histsavenodups

## Global options
setopt correct

## Normal prompt
PS1=$'[%m] %n%# '

## Spelling prompt
SPROMPT='zsh: correct '%R' to '%r' ? ([Y]es/[N]o/[E]dit/[A]bort) '


/etc/zshenv
##
## /etc/zshenv
##

#print /etc/zshenv

## new files are -rw-r--r--
umask 022

## Set paths
path=( $path \
~/bin \
/usr/local/bin \
/usr/bin \
/bin \
)
## admins: add sbin dirs to path
for usergroup in `id -G -n`; do
if [[ $usergroup == admin ]]; then
path=( \
$path \
/usr/local/sbin \
/usr/sbin \
/sbin \
);
break;
fi;
done

## man pages
manpath=( $manpath \
${HOME}/man \
/usr/local/man \
/usr/local/share/man \
/usr/share/man \
)
## teTex
path=( \
$path \
/usr/local/teTex/bin/powerpc-apple-darwin-current \
)
manpath=( \
$manpath \
/usr/local/teTex/man \
)

## remove duplicate entries from paths
typeset -U path cdpath manpath fpath


~/.zshrc
##
## ~/.zshrc
##

#print ~/.zshrc

## fink init file
[ -f /sw/bin/init.sh ] && source /sw/bin/init.sh

## add Developer Tools to path
path=($path /Developer/Tools)

## Get rid of dups in paths
typeset -U path cdpath manpath fpath

## cd : dirs in home and one dir up
#cdpath=(~ ..)

## Options
setopt promptsubst \
cshnullglob \
extendedglob \
histignorespace \
correctall

## prompt: [user@host:path]% _
PS1=$'%{\e[0;31m%}[%{\e[0;36m%}%n%{\e[0;32m%}@%{\e[0;35m%}%m%{\e[0;34m%}:%{\e[0;33m%}%.%{\e[0;31m%}]%{\e[0;0m%}%# '
#PS1=$'[%n@%m:%.]%# '
## prompt themes:
#autoload -U prompinit
#promptinit
## Currently available prompt themes:
## adam1 adam2 bart bigfade clint elite2 elite
## fade fire off oliver redhat suse zefram
#prompt clint

## Functions for displaying neat stuff in *term title
if [[ $TERM == (*xterm*|rxvt|(dt|k|E)term); || $TERM_PROGRAM == Apple_Terminal ]]; then
precmd () {
print -Pn "\e]0;%n@%m:%~\a"
}
preexec () {
print -Pn "\e]0;%n@%m:%~ <$1>\a"
};
fi

## Colors in ls
eval `dircolors 2>& /dev/null | sed 's/:do=..;..://'`

## Custom aliases
alias ls='ls -v'
(( ${+LS_COLORS} )) && alias ls='ls --color=auto'
alias pu='pushd'
alias po='popd'
alias cp='nocorrect cp'
alias mv='nocorrect mv'
alias ln='nocorrect ln'

## Completions
autoload -U compinit
compinit -C
## completions ####
autoload -U zstyle+
## General completion technique
## complete as much u can ..
zstyle ':completion:*' completer _complete _list _oldlist _expand _ignored _match _correct _approximate _prefix
## complete less
#zstyle ':completion:*' completer _expand _complete _list _ignored _approximate
## complete minimal
#zstyle ':completion:*' completer _complete _ignored

## allow one error
#zstyle ':completion:*:approximate:*' max-errors 1 numeric
## allow one error for every three characters typed in approximate completer
zstyle -e ':completion:*:approximate:*' max-errors \
'reply=( $(( ($#PREFIX+$#SUFFIX)/3 )) numeric )'

## formatting and messages
zstyle ':completion:*' verbose yes
zstyle ':completion:*:descriptions' format $'%{\e[0;31m%}%d%{\e[0m%}'
zstyle ':completion:*:messages' format $'%{\e[0;31m%}%d%{\e[0m%}'
zstyle ':completion:*:warnings' format $'%{\e[0;31m%}No matches for: %d%{\e[0m%}'
zstyle ':completion:*:corrections' format $'%{\e[0;31m%}%d (errors: %e)%{\e[0m%}'
zstyle ':completion:*' group-name ''

## determine in which order the names (files) should be
## listed and completed when using menu completion.
## `size' to sort them by the size of the file
## `links' to sort them by the number of links to the file
## `modification' or `time' or `date' to sort them by the last modification time
## `access' to sort them by the last access time
## `inode' or `change' to sort them by the last inode change time
## `reverse' to sort in decreasing order
## If the style is set to any other value, or is unset, files will be
## sorted alphabetically by name.
zstyle ':completion:*' file-sort name

## how many completions switch on menu selection
## use 'long' to start menu compl. if list is bigger than screen
## or some number to start menu compl. if list has that number
## of completions (or more).
zstyle ':completion:*' menu select=long

## case-insensitive (uppercase from lowercase) completion
#zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
## case-insensitive (all) completion
#zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}'
## case-insensitive,partial-word and then substring completion
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'

## offer indexes before parameters in subscripts
zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters

## insert all expansions for expand completer
zstyle ':completion:*:expand:*' tag-order all-expansions

## ignore completion functions (until the _ignored completer)
zstyle ':completion:*:functions' ignored-patterns '_*'

## completion caching
zstyle ':completion::complete:*' use-cache 1
zstyle ':completion::complete:*' cache-path ~/.zcompcache/$HOST

## add colors to completions
zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}

## don't complete backup files as executables
zstyle ':completion:*:complete:-command-::commands' ignored-patterns '*\~'

## filename suffixes to ignore during completion (except after rm command)
zstyle ':completion:*:*:(^rm):*:*files' ignored-patterns '*?.(o|c~|old|pro|zwc)'

## add colors to processes for kill completion
zstyle ':completion:*:*:kill:*:processes' command 'ps -axco pid,user,command'
zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'

## Key bindings
bindkey "^x^e" expand-cmd-path

## recompile zsh files
src ()
{
autoload -U zrecompile
[ -f ~/.zshrc ] && zrecompile -p ~/.zshrc
[ -f ~/.zshenv ] && zrecompile -p ~/.zshenv
[ -f ~/.zcompdump ] && zrecompile -p ~/.zcompdump
[ -f ~/.zlogin ] && zrecompile -p ~/.zlogin
[ -f ~/.zlogout ] && zrecompile -p ~/.zlogout
[ -f ~/.zprofile ] && zrecompile -p ~/.zprofile
[ -f ~/.zshrc.zwc.old ] && rm -f ~/.zshrc.zwc.old
[ -f ~/.zshenv.zwc.old ] && rm -f ~/.zshenv.zwc.old
[ -f ~/.zcompdump.zwc.old ] && rm -f ~/.zcompdump.zwc.old
[ -f ~/.zlogin.zwc.old ] && rm -f ~/.zlogin.zwc.old
[ -f ~/.zlogout.zwc.old ] && rm -f ~/.zlogout.zwc.old
[ -f ~/.zprofile.zwc.old ] && rm -f ~/.zprofile.zwc.old
}

## toys...
#fortune -a


~/.zshenv
##
## ~/.zshenv
##

#print ~/.zshenv

## new files are -rw------
#umask 077

## CVS
(( ${+CVSROOT} )) || export CVSROOT=/usr/local/cvsrep
#(( ${+CVS_RSH} )) || export CVS_RSH=ssh


Hope it helps...

[Edit: I've removed the smilies]

sapporo
10-19-2002, 07:50 AM
Thanks, that did the trick!

For the record, here's the minimal config needed to get case-insensitive completion (from my ~/.zshrc):


## Completions
autoload -U compinit
compinit -C

## case-insensitive (all),partial-word and then substring completion
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'

Please note that I changed the last line to use {a-zA-Z}={A-Za-z} instead of {a-z}={A-Z} to make it expand both ways (upper to lower and vice versa).

Thanks, santin!
-sapporo.

santin
10-19-2002, 11:28 AM
I'm glad it helped you sapporo, I think zsh is THA SHELL... if you take your time to tune it up; it has so many options...

By the way, I'm sorry about those smilies, I didn't notice them when posting...

Titanium Man
10-20-2002, 01:41 PM
Wow santin, thanks for posting your .z* files. I love the options that you get with zsh, but documentation can be a little sparse, so I take every chance I get to examing other people's .z* files.

santin
10-20-2002, 02:39 PM
So do I, TiMan, so do I...

In fact, I think that is the best way to get something done... look at "someone's examples" and adapt it them to your needs.

I would suggest anyone that has an interesting thing in his/her configuration should share it with those who are willing to learn and test...

Talking about zsh, I've just installed zsh 4.0.6 via fink as it's newest than the one in Jaguar... No problems with the update, it's supposed to correct some minor bugs and enhance the completion system... a must have.

I almost forgot, as you can see, I tried to make it have the alias almost like the old config in tcsh in 10.1

Titanium Man
10-20-2002, 06:37 PM
Ok, well here are some things from my .zshrc:

my_accounts=(
{tom,dick,harry,root}@10.0.1.201
{tom,dick,harry,root}@othermachine.com
user@12.345.678.90
)
zstyle ':completion:*:my-accounts' users-hosts $my_accounts

This way, I get tab completion when doing ssh.

Here's another tidbit:

compdef _man bman

This way I get tab completion for the comands 'man' and 'bman'. bman is a little thing put together by pmccann:

#!/bin/sh
# Writes an html formatted manpage to a given file, then
# opens the default browser to display the thing (assuming
# that you've associated .html files with your browser of choice
# Otherwise use eg "open -a mozilla $tfile" on the last line
tfile=/Users/pmccann/junk/somefile.html
man $1 | rman -f HTML > $tfile
open $tfile

One last bit of zsh magic:

preexec ()
{
print -Pn "\e]0;%n@%m < %20>...>$1%<< > (%y)\a"
}

This puts the following info in the Terminal title:

user@host <currentcommand> (tty#)

The funny thing is I don't even use 20% of what you can do with zsh, but I'm able to do more with it than with other shells I've used.

santin
10-20-2002, 07:05 PM
Here is another nice option:
setopt printeightbit
This allows extended characters to be shown when tabbing to complete, and so on...

And to show them when listing folder contents with ls you have:
ls -v
for standard ls, and
ls --show-control-chars
for fink ls

sapporo
11-02-2002, 08:18 AM
Originally posted by Titanium Man
Ok, well here are some things from my .zshrc:

my_accounts=(
{tom,dick,harry,root}@10.0.1.201
{tom,dick,harry,root}@othermachine.com
user@12.345.678.90
)
zstyle ':completion:*:my-accounts' users-hosts $my_accounts

This way, I get tab completion when doing ssh.


Nice one! Works great with ssh, but how do I enable the same completion for sftp?

TIA,
-sapporo.

Titanium Man
11-02-2002, 08:59 PM
Well, you might play around with something like this:

hostnames=(onedomain.org otherdomain.com)
zstyle ':completion:*:*:ftp:*:hosts' hosts $hostnames

Don't listen to me, though, as I come here to GET advice, not give it :D I'd defer to the judgement of people like OSXPEZ, santin, and pmccann, who seem to be much more competent zsh users than I am. Also, check out the .zshrc files at www.dotfiles.com. Good luck with that.

Regards,
TiMan

santin
11-03-2002, 01:13 AM
In fact it should say
zstyle ':completion:*:*:sftp:*:hosts' hosts $hostnames

However, I get the completion for sftp with the first trick, it works for both ssh, sftp, scp...

Titanium Man
11-03-2002, 01:52 AM
Doh! Sapporo did mention trying to use sftp, not ftp. Thanks for the correction.

sapporo
11-03-2002, 06:58 AM
Thanks guys!

Here's what I ended up using:

my_accounts=( sapporo@{ahost.com, somehost.com} {root,someone}@anotherhost.org )
zstyle ':completion:*:my-accounts' users-hosts $my_accounts
zstyle ':completion:*:(ssh|scp):*' tag-order users-hosts users hosts
zstyle ':completion:*:(ssh|scp):*' group-order users-hosts users hosts

But I just can't get it to work for sftp. I guess the reason is that there's no completion function for sftp on my system:


$ echo $_comps[scp]
_ssh
$ echo $_comps[sftp]

$


And then there's one tiny little bit that I would like to figure out.. Using the above configuration, when I type
$ ssh s<TAB>
zsh correctly offers both sapporo and someone as user names, and <TAB> lets me cycle through the options.

Now how do I tell zsh to accept the current name and start completing the hostname? I can currently do this with <Arrow-Right> and hitting <TAB> twice, but of course I'd like to map this to something more convenient..
Any idea?

TIA,
-sapporo.

santin
11-03-2002, 12:39 PM
I see, sapporo, you must be using version 4.0.4 of zsh (it comes with Jaguar), I am using version 4.0.6 installed via fink and it comes with the builtin completion for sftp as well as many other features and bug corrections.

The main feature that is missing from Jaguar's zsh is loading modules... it comes without any module.

I advise you to install fink and get the latest version of zsh.

However you can fix the completion function to allow completion in sftp:

Edit the file /usr/share/zsh/4.0.4/functions/_ssh and change the first line
#compdef ssh slogin=ssh scp ssh-add ssh-agent ssh-keygen to #compdef ssh slogin=ssh scp ssh-add ssh-agent ssh-keygen sftp

It should work now as expected.

Hasta pronto,
#!santin

sapporo
11-03-2002, 02:26 PM
Thanks santin!

I just upgraded to zsh 4.0.6, and sftp completion works as promised.
Modules work, too, but I haven't found much use for them so far. I'm interested in zftp, since I use ftp a lot (currently using lftp), but the docs give me headaches..

TIA,
-sapporo.