-!-
-!- htmlized version of this is here: http://ft.bewatermyfriend.org/comp/zshtalk.html
-!-
--- Log opened Sat Sep 10 14:31:07 2005
16:03 <@caphuso> ok...
16:03 <@caphuso> so, let's start with clarifying a few things
16:04 <@caphuso> zsh is a unix shell, hopefully known to anybody in here
16:04 <@caphuso> from the bourne shell family
16:05 <@caphuso> it has dozens of nifty features, making it an excellent shell for both interactive use and scripting
16:05 <@caphuso> some of those features will be covered in this talk
16:05 <@caphuso> which is basically all it is about
16:06 <@caphuso> so... let's start with why you would want to use zsh
16:06 <@caphuso> there are a few catches... you probably don't want to use zsh if all you do is really simple stuff in your shell, e.g. because you're a gnome/kde/xfce user
16:07 <@caphuso> you also don't want to use zsh if you are afraid of complex programs
16:07 <@caphuso> and zsh is _very_ complex
16:07 <@caphuso> and a third reason to not use zsh is that you're working in a unicode environment, for which there is no support yet
16:07 <@caphuso> big drawback
16:08 <@caphuso> Nei: that's not using, that's pretending to use :)
16:08 <@caphuso> right now development is happening to add unicode support, but the current state is that it's incomplete and very buggy, so you need to wait a few months
16:09 <@caphuso> now the reasons why you would want to use zsh
16:09 <@caphuso> it offers almost anything you expect from a shell, but has tons of improvements
16:10 <@caphuso> the first of those improvements that made me go "wow! wanna have!" is that it has sane wordsplitting (by default)
16:10 <@caphuso> that means that a variable FOO="hello bar" will, when you use it like $FOO not be split into two words
16:11 <@caphuso> in bash etc. you almost always need to use double quotes, zsh makes that unnecessary
16:11 <@caphuso> next: prompts
16:12 <@caphuso> most shells have prompts, which are more or less customizable, but zsh is better :)
16:12 <@caphuso> you have the regular $prompt (the one to the left), $rprompt (at the right side of the command line)
16:13 <@caphuso> that's standard stuff though
16:13 <@caphuso> you might know PROMPT_COMMAND from bash
16:13 <@caphuso> zsh has two functions, precmd and preexec, which do basically the same, but run before a prompt is displayed and between you hitting enter and executing the command line
16:14 <@caphuso> the latter allows you e.g. to set the xterm title to the name of the program you just started, very cool
16:14 <@caphuso> and you can do even scarier things: http://apheriodic.net/phil/prompt/
16:14 <@caphuso> (it's lengthy, you probably want to read it later)
16:15 <@caphuso> another standard feature: aliases
16:15 <@caphuso> sorry, http://aperiodic.net/phil/prompt/
16:16 <@caphuso> i did say i didn't beta test this stuff :-)
16:17 <@caphuso> back to aliases... zsh has sh style aliases, so they are limited. OTOH, you don't have to deal with the csh silliness of undebuggable !!!!!!!
16:17 <@caphuso> but it has two major achievements over e.g. bash: alias -g and alias -s
16:18 <@caphuso> alias -g is used to define global aliases, which means that those aliases are expanded everywhere on the command line, not just at the beginning
16:18 <@caphuso> example: alias -g L='| less'; grep -r foo . L
16:19 <@caphuso> the grep command will get expanded to "grep -r foo . | less", which saves a lot of typing
16:19 <@caphuso> BUT global aliases are dangerous
16:19 <@caphuso> it can happen that something gets expanded that really shouldn't
16:19 <@caphuso> so be careful, e.g. by sticking to only very few, or by using "safe" names
16:20 <@caphuso> alias -s defines suffix aliases
16:20 <@caphuso> example: alias -s pdf=xpdf
16:21 <@caphuso> if you now "execute" a single file name ending in .pdf (e.g. foo.pdf), the command line will get rewritten to xpdf foo.pdf
16:22 <@caphuso> one limitation: won't work for stuff like "alias -s tar.gz="tar tzf"
16:22 <@caphuso> the dot in tar.gz confuses it :-(
16:22 <@caphuso> dp___: yes
16:23 <@caphuso> i've mentioned that csh style aliases aren't supported
16:23 <@caphuso> that's ok, because functions are a much nicer way of doing their work
16:23 <@caphuso> functions in zsh work basically the same as in any other sh like shell, with only few improvements
16:24 <@caphuso> one borrowed from ksh is that they can be made autoloadable
16:24 <@caphuso> to reduce memory usage
16:24 <@caphuso> you can define functions by simply putting their body into a file named like the function
16:25 <@caphuso> that allows you to have a function work as a script
16:25 <@caphuso> functions are pretty boring, so we get to the next feature: history
16:26 <@caphuso> that is, remembering what commands you ran for later reuse
16:26 <@caphuso> handling of that is horribly adjustable to your exact needs, with various options
16:27 <@caphuso> zsh's history mechanism also allow you to use the csh style bang history expansion (stuff like !-2:t and so)
16:27 <@caphuso> pretty cool if you can get used to it
16:27 <@caphuso> a unique feature of zsh is that you can have multiple histories
16:28 <@caphuso> fc -p/fc -a/fc -P dealwith the "history stack"
16:29 <@caphuso> "fc -p" will clear out the current history and start remembering a new one, until you run fc -P, which will restore the old history
16:30 <@caphuso> i use that to "bind" certain histories to specific directories
16:30 <@caphuso> e.g. my ~/.seti directory, in which everything seti@home related is stored, has its own history, which gets automatically loaded when i cd into it
16:31 <@caphuso> also useful for source trees in which you often do the same commands like "cvs update", ...
16:32 <@caphuso> big topic: parameter expansion
16:32 <@caphuso> that's basically just $FOO or ${FOO%bar}
16:33 <@caphuso> florolf: fc -p fileinwhichthehistoryyouwanttouseisstoredin
16:33 <@caphuso> it's also the most frightening part of zsh
16:34 <@caphuso> and it makes people who think that perl looks like line noise vomit
16:35 <@caphuso> i'll show a few examples later
16:35 <@caphuso> next big thing is pattern matching
16:35 <@caphuso> this includes globbing (*.txt etc.) and comparisions [[ $foo == * ]]
16:35 <@caphuso> extremely sophisticated in zsh
16:36 <@caphuso> again, some interesting examples later
16:36 <@caphuso> documentation is also a very good reason to use zsh
16:36 <@caphuso> it is by far the best documented shell around
16:37 <@caphuso> you have a huge reference manual (as man pages, texinfo, HTML, pdf, ...)
16:37 <@caphuso> $ man zshall 2> /dev/null | wc 19882 132867 1035768
16:37 <@caphuso> oops, should be two lines
16:37 <@caphuso> Nei: i do!
16:38 <@caphuso> this reference manual is very complete and well written, but terse
16:38 <@caphuso> so we also got the user-friendly user guide
16:39 <@caphuso> you can get it from zsh.sunsite.dk
16:39 <@caphuso> if you want to get the most out of zsh, then a printout of it will be your best friend in the next few weeks
16:39 <@caphuso> it's slightly outdated, but not much, and misses a few things
16:39 <@caphuso> but still incredibly cool
16:40 <@caphuso> if you got money to spend, then you might buy "from bash to z shell", which is a real book. i haven't read it myself, so i can't say how good it is
16:41 <@caphuso> now completion
16:41 <@caphuso> this is where zsh excells at, because really absolutely nothing comes even close
16:41 <@caphuso> if you ever thought that bash or tcsh would do a good job, be surprised
16:42 <@caphuso> the zsh completion system is better in any respect
16:42 <@caphuso> Nei: huh?
16:42 <@caphuso> it's highly configurable without forcing you to rewrite functions
16:43 <@caphuso> Nei: indeed, fish sucks. it's not really programmable completion what it offers
16:44 <@caphuso> it's basically all built in
16:44 <@caphuso> i'll point out some impressive examples later
16:44 <@caphuso> next topic: zle
16:44 <@caphuso> zle is the line editor zsh uses (what readline is for bash)
16:45 <@caphuso> i.e. the thing that let's you have a way to delete words, move around lines, copy, paste, ...
16:46 <@caphuso> it's good enough that you can play tetris with it!
16:46 <@caphuso> this obviously involves several features, including the ability to use multiple lines for your command
16:47 <@caphuso> it's also extensible by simply writing shell functions
16:47 <@caphuso> so you can implement everything you need
16:47 <@caphuso> there will be some examples later on
16:47 <@caphuso> just one more feature: dynamically loadable modules
16:47 <@caphuso> (assuming your OS supports those)
16:48 <@caphuso> there are a couple of modules that extend zsh's features
16:48 <@caphuso> the line editor for example is such a module
16:48 <@caphuso> there are also modules for ftp or tcp networking
16:49 <@caphuso> a math module to do stuff like print $(( sin(5) ))
16:49 <@caphuso> oh, yes, zsh does floating point math!
16:49 <@caphuso> no more kludging with bc
16:50 <@caphuso> ok, this first quick overview is done, from now on i'll touch a couple of features more detailed
16:50 <@caphuso> any questions so far?
16:51 <@caphuso> ok... i'll paste a small ~/.zshrc, that's just enough to get you started
16:51 <@caphuso> zmodload zsh/complist
16:51 <@caphuso> autoload compinit && compinit
16:51 <@caphuso> HISTFILE=~/.zsh_history
16:51 <@caphuso> SAVEHIST=1000
16:51 <@caphuso> HISTSIZE=1000
16:51 <@caphuso> setopt APPEND_HISTORY
16:51 <@caphuso> setopt nobeep
16:51 <@caphuso> prompt="%# "
16:51 <@caphuso> rpompt=" %~"
16:51 <@caphuso> nothing fancy in there, just setting up of the history and loading of the completion system
16:52 <@caphuso> cow: printf
16:52 <@caphuso> e1f`: thanks
16:52 <@caphuso> RPROMPT=" %~"
16:53 <@caphuso> ok, globbing
16:53 <@caphuso> zsh's globbing makes find(1) useless for most jobs
16:54 <@caphuso> e.g. you can do stuff like *(.) to match only regular files or *(/) to match only directories
16:55 <@caphuso> Stara: one moment
16:56 <@caphuso> http://84.129.253.97/~caphuso/talk
16:56 <@caphuso> theclaw: because rprompt is wrong, needs to be upper case
16:57 <@caphuso> theclaw: hysterical reasons?
16:57 <@caphuso> dunno
16:57 <@caphuso> back on topic: it can also match files larger or smaller than a certain size, older or newer than {a,m,c}time, files being block devices etc.
16:58 <@caphuso> those can be combined with and, or and inverted
16:58 <@caphuso> there's a way to deal with symlinks (reference or not)
16:58 <@caphuso> permissions can also be matched
16:58 <@caphuso> *(f:a+x,o+w:)
16:59 <@caphuso> the most impressive thing is the e glob qualifier (this is what those things are called)
16:59 <@caphuso> *(e:'file $REPLY | grep -q JPEG':)
16:59 <@caphuso> this one will match all files of which file says that they are JPEGs
17:00 <@caphuso> i had to use that one to dig through a browser cache, where all files were named 234346 or 456745234
17:00 <@caphuso> glob qualifiers aren't the only thing zsh adds
17:01 <@caphuso> it does all the regular stuff, like foo? or *bar*
17:01 <@caphuso> [a-z]
17:01 <@caphuso> but also things like (foo|bar|baz)
17:02 <@caphuso> or foo*~*bar* to match everything that starts with foo but doesn't contain bar
17:02 <@caphuso> it can recurse down directory trees with **
17:03 <@caphuso> "print -l /**/*" will list _any_ file or directory on your system
17:03 <@caphuso> be careful when using that one with external commands, you run very quickly into ARG_MAX problems
17:03 <@caphuso> florolf: no, to any subdirectory
17:04 <@caphuso> no matter how deep into the tree they are
17:04 <@caphuso> well, compare "print /**" with "print /**/*"
17:04 <@caphuso> you'll see the difference in a few minutes >:-)
17:05 <@caphuso> globbing is just a special use of the more general pattern matching
17:05 <@caphuso> the other use is in comparisons and replacements
17:06 <@caphuso> in those the glob qualifiers are obviously useless (a number that's -eq'ed doesn't have permissions or a file size)
17:07 <@caphuso> but it has a need for other things, most of which are well known from regular expressions
17:07 <@caphuso> theclaw: (e:'file $REPLY | grep -q JPEG':) is the glob qualifier
17:07 <@caphuso> $REPLY is a special parameter that contains the name of the file being matched
17:08 <@caphuso> back on topic: e.g. (#s) or (#e) for what ^ and $ are in regexps
17:09 <@caphuso> beginning of line/end of line
17:09 <@caphuso> (#b) or (#m) to enable backreferences
17:09 <@caphuso> (#i) to match case insensitive
17:10 <@caphuso> and... *tadaa* (#a) to match approximately
17:10 <@caphuso> (the latter isn't typically available in regular expressions)
17:11 <@caphuso> approximate matching means that certain errors are ignored, e.g. "(#a1)foo*" would still match the string "ofobar"
17:12 <@caphuso> there's quite a bit more on this topic, and explaining it in detail would take a few hours
17:12 <@caphuso> (the topic == pattern matching)
17:12 <@caphuso> i suggest strongly that you read the appropriate chapter in the user guide
17:13 <@caphuso> if you want to look at some real life example, look for the compaudit function
17:13 <@caphuso> one example of mine:
17:14 <@caphuso> setopt functionargzero
17:14 <@caphuso> readme liesmich () { less -- (#ia3)${~0}*(OL[1,3]) }
17:14 <@caphuso> touch LiesMich README readme.txt Read_ME.doc lies-mich
17:14 <@caphuso> readme; liesmich
17:14 <@caphuso> first line sets the functionargzero option, which does nothing but setting $0 inside a function to the name of the function
17:14 <@caphuso> normally it'd be /bin/zsh or something like that
17:15 <@caphuso> the next line defines _two_ functions (readme and liesmich), that are the same
17:15 <@caphuso> (liesmich is german and means readme)
17:16 <@caphuso> the line noise after -- is a typical zsh glob
17:16 <@caphuso> it consists of three parts ${~0}, (#ia3) and (OL[1,3])
17:17 <@caphuso> the first is a simple parameter expansion of $0, but turned into something eligable for pattern matching
17:17 <@caphuso> this means that the names of the two functions will be used to match files
17:17 <@caphuso> the (#ia3) makes the whole thing 1) case insensitive and 2) allows up to 3 mistakes
17:18 <@caphuso> the (OL[1,3]) at the end sorts the resulting list by size (biggest first) and uses only the first three files
17:18 <@caphuso> the mere * in there does what it always does, it matches anything
17:19 <@caphuso> the touch command creates 4 empty files
17:19 <@caphuso> and running the two functions in the last line results in less displaying first README, Read_ME.doc and readme.txt, then LIESMICH and lies-mich
17:21 <@caphuso> in lesser shells you'd need three times as much code, and probably several external programs
17:21 <@caphuso> questions?
17:22 <@caphuso> now the real horror: parameter expansion
17:22 <@caphuso> things like this:
17:22 <@caphuso> for a in **/*(.); mv $a ${a:h}/${${a:t}//(#m)((#s)?|(_| )?)/${(U)MATCH}}
17:22 <@caphuso> or this:
17:22 <@caphuso> function foo () { print -l ${(q)${${(f)"$(<$1)"}:#(#s)[[:space:]]#\#*}%%[[:space:]]##\#*}}
17:22 <@caphuso> parameter expansion in zsh can be nested
17:23 <@caphuso> if you want to remove foo at the beginning and bar at the end of a parameter, you'd normally do tmp=${FOO%bar}; FOO=${tmp#foo}
17:24 <@caphuso> in zsh you can use ${${FOO%bar}#tmp}
17:24 <@caphuso> err, ${${FOO%bar}#foo}
17:24 <@caphuso> and those things can grow really big
17:24 <@caphuso> especially when you start using arrays or associative arrays (hashes in perl lingo)
17:26 <@caphuso> _the_ killer example is _pids
17:26 <@caphuso> it's a function of the completion system that completes PIDs
17:26 <@caphuso> you need several hours with the reference manual, the user guide and 2l coffee
17:26 <@caphuso> maybe even more
17:27 <@caphuso> the sad thing is, anything i'd try to teach you about parameter expansion would be wasted
17:27 <@caphuso> so, for the beginning, stick to the standard stuff
17:27 <@caphuso> work your way up from there, while reading the user guide
17:28 <@caphuso> ZHOST=localhost
17:28 <@caphuso> ZPORT=1234
17:28 <@caphuso> ZHOME=/tmp
17:28 <@caphuso> ZDATA="this is a stupid example"
17:28 <@caphuso> : ${(AA)zopt:=${(z)${(ps:=:)${(f)$( this is just one small example, showing that all this insanity can be used for good reasons
17:29 <@caphuso> the first 4 lines are the content of a simple config file
17:29 <@caphuso> and the line starting with : reads that file in and creates an associative array $zopt with the keys ZHOST, ZPORT, ZHOME and ZDATA
17:30 <@caphuso> the values of those keys are simply the things behind the =
17:30 <@caphuso> doing it the old fashioned way would be more cumbersome
17:31 <@caphuso> but here we simply read in the whole file with $( split on newlines and create an array with ${(f)...}
17:31 <@caphuso> split on = with ${(ps:=:)...}
17:32 <@caphuso> so we have an array with the elements ZHOST, localhost, ZPORT, 1234, ZHOME, /tmp, ...
17:32 <@caphuso> and then we put that into an associative array with ${(AA)zopt:=...}
17:33 <@caphuso> Nei: no, start reading from the inner to the outer, not from the right to the left
17:34 <@caphuso> third big topic: ZLE
17:34 <@caphuso> micikas: #emacs on the 24th
17:35 <@caphuso> i already mentioned the multi line editing support
17:35 <@caphuso> this means you get a real multi line buffer, just like you'd do in a text editor
17:35 <@caphuso> it's also saved and restored in multiple lines when using the history
17:36 <@caphuso> this is quite convenient, because your throw away shell scripts can grow
17:36 <@caphuso> (because of the increased legibility)
17:37 <@caphuso> tcsh users will know run-help
17:38 <@caphuso> hitting "ESC, h" (or meta-h) will fire up the man page of whatever command you have on the command line, let you read it, then go back and continue editing where you left of
17:39 <@caphuso> push-line is a more general solution for that kind of problem: it simply pushes the current line on the stack, type in another command line, execute that, then turb back to where you left of
17:39 <@caphuso> bound to ctrl-q by default
17:40 <@caphuso> so, but some basics first
17:40 <@caphuso> the two commands with which you deal with zle are bindkey and zle
17:40 <@caphuso> bindkey is used to handle keymaps
17:41 <@caphuso> emacs users will know the concept of keymaps
17:41 <@caphuso> basically just tables containing key-function pairs
17:41 <@caphuso> one of those keymaps zsh uses is the emacs keymap, it contains the standard emacs like stuff
17:42 <@caphuso> ctrl-a == beginning-of-line, "ESC, f" == forward-word
17:42 <@caphuso> viins is the keymap for the vi insert mode, vicmd the one for the command mode
17:42 <@caphuso> you can switch between emacs and vi with bindkey -e and bindkey -v
17:43 <@caphuso> you are free to bind any key to any function, in any table
17:43 <@caphuso> so you can add emacs bindings to vi, and run the vi functions in emacs mode
17:43 <@caphuso> btw, what i named "functions" are called "editing widgets"
17:44 <@caphuso> Nei: oh, yes, i've changed that
17:44 * caphuso lost track of default zsh settings years ago
17:44 <@caphuso> some of those widgets are built into zle
17:45 <@caphuso> some others are provided by those loadable modules mentioned earlier
17:45 <@caphuso> the most interesting ones though are those written as shell functions
17:46 <@caphuso> a simple example: run-with-sudo () { LBUFFER="sudo $LBUFFER" }
17:46 <@caphuso> zle -N run-with-sudo
17:46 <@caphuso> bindkey '^X^E' run-with-sudo
17:47 <@caphuso> $LBUFFER is one of the zle special parameters, it contains the part of the command line left to the cursor
17:47 <@caphuso> it simply gets "sudo " prepended to it
17:48 <@caphuso> zle -N ... makes zle aware that run-with-sudo is from now on a bindable widget
17:48 <@caphuso> and the bindkey command binds it to ctrl-x ctrl-e
17:48 <@caphuso> now you can type at any moment C-x C-e and you'll have your current command line with sudo at the beginning
17:48 <@caphuso> if you like me forget that way too often, you'll love this
17:49 * caphuso can't count how often he saw E: Could not open lock file /var/lib/apt/lists/lock - open (13 Permission denied)
17:49 <@caphuso> of course, those shell functions can grow to any degree of "complicatedness" you like
17:50 <@caphuso> there's a few interesting ones in the zsh distribution, look for smart-insert-last-word or the *-word-match family
17:50 <@caphuso> also a whole chapter in the user guide
17:51 <@caphuso> ok... now the very last topic: completion
17:51 <@caphuso> probably the one most interesting to all of you, because it's the one you can start using without actually knowing anything ;-)
17:51 <@caphuso> simply hitting your tab key in random places is sufficient
17:52 <@caphuso> the completion system is loaded with "autoload compinstall && compinstall"
17:52 <@caphuso> after that, you're ready to go
17:53 <@caphuso> until you find that some things don't behave like you want them to
17:53 <@caphuso> that's why you get the chance of tweaking and customizing
17:53 <@caphuso> in order to be able to do that, we need to learn about context
17:54 <@caphuso> :completion:FUNCTION:COMPLETER:COMMAND-OR-MAGIC-CONTEXT:ARGUMENT:TAG
17:54 <@caphuso> this is what a context looks like: 6 fields, seperated with :
17:54 <@caphuso> the first field is simply "completion"
17:55 <@caphuso> FUNCTION is of no interest, unless you get your hands really dirty
17:55 <@caphuso> COMPLETER is the name of the shell function that creates matches at the moment of the context lookup. i'll explain those later
17:58 <@caphuso> COMMAND-OR-MAGIC-CONTEXT is either the name of the command you are trying to complete for (e.g. in case of "make cle" it'd be make" or a magic context like -redirect- (after > or <) or -math- (when you're at a point of arithmetic expansion)
17:58 <@caphuso> ARGUMENT is also less useful, unless you already know enough to be bored by me talking
17:59 <@caphuso> and TAGS are basically short yet descriptive names of what exactly you are completion at the moment
17:59 <@caphuso> e.g. in "make " the tag would be "targets", because you're trying to complete Makefile targets
18:00 <@caphuso> "kill you can look them up with "ctrl-x, h"
18:01 <@caphuso> so, some hands on examples: :completion:*:*:xpdf:*:*
18:01 <@caphuso> this specifies: whenever we're completing for xpdf
18:01 <@caphuso> :completion:*:approximate:rm:*:*
18:01 <@caphuso> whenever we're completion after rm and are using the _approximate completer (description follows later)
18:02 <@caphuso> more specific settings win over the general ones
18:02 <@caphuso> :completion:*:*:*:*:processes
18:02 <@caphuso> :completion:*:*:kill:*:processes
18:02 <@caphuso> the first one says: whenever we complete the tag "processes"
18:03 <@caphuso> the second: whenever we complete processes after kill
18:03 <@caphuso> if i had two clashing settings for those two context, then after kill only the second one would be used
18:03 <@caphuso> this is just common sense
18:03 <@caphuso> the system would be useless if it worked otherwise :)
18:04 <@caphuso> now how to use those contexts
18:04 <@caphuso> setting and lookup of that stuff is done with the builtin zstyle
18:04 <@caphuso> you can use that outside of the completion system to store and retrieve data too, some of the zle functions do that for example
18:05 <@caphuso> we'll only deal with setting, not with retrieving
18:05 <@caphuso> zstyle ':completion:*:*:(^rm):*:*' ignored-pattern '*.(o|~)' '#*#(D)'
18:06 <@caphuso> he're we set the style 'ignored-pattern' (you can find a list and descriptions of styles in the manual) to '*.(o|~)' '#*#(D)'
18:06 <@caphuso> when completing after anything except rm
18:06 <@caphuso> ^rm means "don't match rm"
18:07 <@caphuso> the two globs match *.o files (C programmers will know), *~ (backup files) and #*# files (emacs autosave files). the (D) qualifier turns on globbing of .* files
18:08 <@caphuso> ignored-pattern means: when completion, then ignore everything that matches the value of this style
18:08 <@caphuso> so, after any command that's not rm, we won't get those files offered as completions
18:09 <@caphuso> this is just one simple example of how extensible the zsh completion system is configurable
18:09 <@caphuso> there are a few dozen styles
18:10 <@caphuso> you'll need to read the manual, i really don't wanna talk till tomorrow morning :-)
18:11 <@caphuso> now the completers i wanted to explain quickly
18:11 <@caphuso> a completer is simply a shell function that looks up the current context and creates a list of possible completions, offering those to the user
18:11 <@caphuso> of course, nothing is that simple in zsh
18:11 <@caphuso> the first completer available is "_complete"
18:12 <@caphuso> it does basically what bash does
18:12 <@caphuso> nothing fancy at all
18:12 <@caphuso> just looking up stuff, then straight completion mozi -> mozilla
18:13 <@caphuso> _expand is the first exception, because it doesn't really generate possible completions
18:13 <@caphuso> it expands certain things on the command line, e.g. $PARAMETERS or $(print -c *)
18:13 <@caphuso> $PATH would become /home/caphuso/bin:/usr/local/bin::/usr/games:/usr/bin:/bin on the command line
18:14 <@caphuso> _correct does what the name implies: it corrects typos
18:14 <@caphuso> _approximate is _correct on crack
18:14 <@caphuso> it not only corrects typoes, it also generates completions
18:15 <@caphuso> given a directory ~/public_html, then _correct would do the right thing for "cd ~/pbulic_html", but not for "cd ~/pb"
18:16 <@caphuso> there are a few more, but those are the most interesting ones
18:17 <@caphuso> using completers is a matter of setting the style "completer" properly
18:17 <@caphuso> zstyle ':completion:*' completer _complete
18:18 <@caphuso> (bash emulation again ;-)
18:18 <@caphuso> zstyle ':completion:*' completer _complete _approximate
18:18 <@caphuso> this means: first try _complete, if it can't generate any possible matches, then try _approximate
18:19 <@caphuso> zstyle ':completion:*' completer _complete _correct _complete:-extended _complete:-substring
18:19 <@caphuso> this means: first _complete, if it fails _correct, then _complete again, then _complete again
18:20 <@caphuso> the trick is that by appending :-foo the completer will look up the context not under its regular name (_complete) but as (_complete-foo)
18:21 <@caphuso> this allows to do the same completion with different settings because the context differ
18:21 <@caphuso> zstyle ':completion:*:complete-extended:*' matcher-list 'm:{a-z}={A-Z}' 'r:|[+._-]=*'
18:21 <@caphuso> zstyle ':completion:*:complete-substring:*' matcher-list 'm:{a-z}={A-Z} l:|=**'
18:22 <@caphuso> we do that here... as COMPLETER field we have now not complete but complete-extended and complete-substring, and for both we set the style matcher-list to yet another kind of line noise
18:22 <@caphuso> those matchers configure how zsh is doing comparisons
18:22 <@caphuso> the default way is to simply compare the string on the command line with all possible completions
18:23 <@caphuso> foo with the possible completions of foobar, foobaz and moo_foo will offer the first two as possible completions
18:23 <@caphuso> because only they match "foo*"
18:24 <@caphuso> matching control can change that, make it ignore certain things
18:24 <@caphuso> e.g. m:{a-z}={A-Z} tells it that lower case characters match upper case characters
18:24 <@caphuso> echo $disp echo $DISPLAY
18:27 <@caphuso> r:|[+._-]=* makes the characters +, ., _ and - special, so that "cd p_h -> cd public_html" or "rm x.txt -> rm xenomorph.txt" works
18:27 <@caphuso> and the l:|=** does a simple substring match, so that "foo" will also match barfoobaz
18:28 <@caphuso> now the whole list of completers in this last example explained slowly
18:29 <@caphuso> when the user hits TAB, the _complete is tried. if it fails to generate any matches, the word on the command line is tried to be corrected. if this doesn't help, case-insensitive matching with a few special characters is tried, and if that fails too, substring matching
18:29 <@caphuso> and as soon as one completer succeeds with creating at least one match, the whole thing stops
18:30 <@caphuso> now you might wonder why to do that so complicated
18:30 <@caphuso> easy: 1) the more possible matches you try to generate, the slower the whole thing becomes
18:31 <@caphuso> _complete is noticably faster than _complete:-extended, and i've seen _approximate run for several minutes, due to a large directory
18:31 <@caphuso> so you want to be careful
18:31 <@caphuso> 2) the more matches you create, the longer the list of possible completion becomes
18:32 <@caphuso> when _complete might only show 5 matches, _approximate can go up to 50
18:32 <@caphuso> or more
18:33 <@caphuso> this doesn't only take longer, it also makes it hard to handle
18:33 <@caphuso> so, that's the reasoning behind
18:33 <@caphuso> ok
18:34 <@caphuso> AFAICT, that's it
18:34 <@caphuso> i hope it's been interesting enough, and would glad to see a few more enthusiastic zsh users in #zsh in the next few weeks
18:34 <@caphuso> any questions?
--- Log closed Sat Sep 10 18:35:39 2005