Merge remote-tracking branch 'origin/github/pr/45'
[grml.org.git] / zsh / zshtalk
1 --- Log opened Sat Sep 10 14:31:07 2005
2 16:03 @caphuso> ok...
3 16:03 @caphuso> so, let's start with clarifying a few things
4 16:04 @caphuso> zsh is a unix shell, hopefully known to anybody in here
5 16:04 @caphuso> from the bourne shell family
6 16:05 @caphuso> it has dozens of nifty features, making it an excellent shell
7       for both interactive use and scripting
8 16:05 @caphuso> some of those features will be covered in this talk
9 16:05 @caphuso> which is basically all it is about
10 16:06 @caphuso> so... let's start with why you would want to use zsh
11 16:06 @caphuso> there are a few catches... you probably don't want to use zsh
12       if all you do is really simple stuff in your shell, e.g. because you're a
13       gnome/kde/xfce user
14 16:07 @caphuso> you also don't want to use zsh if you are afraid of complex
15       programs
16 16:07 @caphuso> and zsh is _very_ complex
17 16:07 @caphuso> and a third reason to not use zsh is that you're working in a
18       unicode environment, for which there is no support yet
19 16:07 @caphuso> big drawback
20 16:08 @caphuso> Nei: that's not using, that's pretending to use :)
21 16:08 @caphuso> right now development is happening to add unicode support, but
22       the current state is that it's incomplete and very buggy, so you need to
23       wait a few months
24 16:09 @caphuso> now the reasons why you would want to use zsh
25 16:09 @caphuso> it offers almost anything you expect from a shell, but has tons
26       of improvements
27 16:10 @caphuso> the first of those improvements that made me go "wow! wanna
28       have!" is that it has sane wordsplitting (by default)
29 16:10 @caphuso> that means that a variable FOO="hello bar" will, when you use
30       it like $FOO not be split into two words
31 16:11 @caphuso> in bash etc. you almost always need to use double quotes, zsh
32       makes that unnecessary
33 16:11 @caphuso> next: prompts
34 16:12 @caphuso> most shells have prompts, which are more or less customizable,
35       but zsh is better :)
36 16:12 @caphuso> you have the regular $prompt (the one to the left), $rprompt
37       (at the right side of the command line)
38 16:13 @caphuso> that's standard stuff though
39 16:13 @caphuso> you might know PROMPT_COMMAND from bash
40 16:13 @caphuso> zsh has two functions, precmd and preexec, which do basically
41       the same, but run before a prompt is displayed and between you hitting
42       enter and executing the command line
43 16:14 @caphuso> the latter allows you e.g. to set the xterm title to the name
44       of the program you just started, very cool
45 16:14 @caphuso> and you can do even scarier things:
46       http://apheriodic.net/phil/prompt/
47 16:14 @caphuso> (it's lengthy, you probably want to read it later)
48 16:15 @caphuso> another standard feature: aliases
49 16:15 @caphuso> sorry, http://aperiodic.net/phil/prompt/
50 16:16 @caphuso> i did say i didn't beta test this stuff :-)
51 16:17 @caphuso> back to aliases... zsh has sh style aliases, so they are
52       limited. OTOH, you don't have to deal with the csh silliness of
53       undebuggable !!!!!!!
54 16:17 @caphuso> but it has two major achievements over e.g. bash: alias -g and
55       alias -s
56 16:18 @caphuso> alias -g is used to define global aliases, which means that
57       those aliases are expanded everywhere on the command line, not just at
58       the beginning
59 16:18 @caphuso> example: alias -g L='| less'; grep -r foo . L
60 16:19 @caphuso> the grep command will get expanded to "grep -r foo . | less",
61       which saves a lot of typing
62 16:19 @caphuso> BUT global aliases are dangerous
63 16:19 @caphuso> it can happen that something gets expanded that really
64       shouldn't
65 16:19 @caphuso> so be careful, e.g. by sticking to only very few, or by using
66       "safe" names
67 16:20 @caphuso> alias -s defines suffix aliases
68 16:20 @caphuso> example: alias -s pdf=xpdf
69 16:21 @caphuso> if you now "execute" a single file name ending in .pdf (e.g.
70       foo.pdf), the command line will get rewritten to xpdf foo.pdf
71 16:22 @caphuso> one limitation: won't work for stuff like "alias -s tar.gz="tar
72       tzf"
73 16:22 @caphuso> the dot in tar.gz confuses it :-(
74 16:22 @caphuso> dp___: yes
75 16:23 @caphuso> i've mentioned that csh style aliases aren't supported
76 16:23 @caphuso> that's ok, because functions are a much nicer way of doing
77       their work
78 16:23 @caphuso> functions in zsh work basically the same as in any other sh
79       like shell, with only few improvements
80 16:24 @caphuso> one borrowed from ksh is that they can be made autoloadable
81 16:24 @caphuso> to reduce memory usage
82 16:24 @caphuso> you can define functions by simply putting their body into a
83       file named like the function
84 16:25 @caphuso> that allows you to have a function work as a script
85 16:25 @caphuso> functions are pretty boring, so we get to the next feature:
86       history
87 16:26 @caphuso> that is, remembering what commands you ran for later reuse
88 16:26 @caphuso> handling of that is horribly adjustable to your exact needs,
89       with various options
90 16:27 @caphuso> zsh's history mechanism also allow you to use the csh style
91       bang history expansion (stuff like !-2:t and so)
92 16:27 @caphuso> pretty cool if you can get used to it
93 16:27 @caphuso> a unique feature of zsh is that you can have multiple histories
94 16:28 @caphuso> fc -p/fc -a/fc -P dealwith the "history stack"
95 16:29 @caphuso> "fc -p" will clear out the current history and start
96       remembering a new one, until you run fc -P, which will restore the old
97       history
98 16:30 @caphuso> i use that to "bind" certain histories to specific directories
99 16:30 @caphuso> e.g. my ~/.seti directory, in which everything seti@home
100       related is stored, has its own history, which gets automatically loaded
101       when i cd into it
102 16:31 @caphuso> also useful for source trees in which you often do the same
103       commands like "cvs update", ...
104 16:32 @caphuso> big topic: parameter expansion
105 16:32 @caphuso> that's basically just $FOO or ${FOO%bar}
106 16:33 @caphuso> florolf: fc -p fileinwhichthehistoryyouwanttouseisstoredin
107 16:33 @caphuso> it's also the most frightening part of zsh
108 16:34 @caphuso> and it makes people who think that perl looks like line noise
109       vomit
110 16:35 @caphuso> i'll show a few examples later
111 16:35 @caphuso> next big thing is pattern matching
112 16:35 @caphuso> this includes globbing (*.txt etc.) and comparisions [[ $foo ==
113       * ]]
114 16:35 @caphuso> extremely sophisticated in zsh
115 16:36 @caphuso> again, some interesting examples later
116 16:36 @caphuso> documentation is also a very good reason to use zsh
117 16:36 @caphuso> it is by far the best documented shell around
118 16:37 @caphuso> you have a huge reference manual (as man pages, texinfo, HTML,
119       pdf, ...)
120 16:37 @caphuso> $ man zshall 2> /dev/null | wc 19882 132867 1035768
121 16:37 @caphuso> oops, should be two lines
122 16:37 @caphuso> Nei: i do!
123 16:38 @caphuso> this reference manual is very complete and well written, but
124       terse
125 16:38 @caphuso> so we also got the user-friendly user guide
126 16:39 @caphuso> you can get it from zsh.sunsite.dk
127 16:39 @caphuso> if you want to get the most out of zsh, then a printout of it
128       will be your best friend in the next few weeks
129 16:39 @caphuso> it's slightly outdated, but not much, and misses a few things
130 16:39 @caphuso> but still incredibly cool
131 16:40 @caphuso> if you got money to spend, then you might buy "from bash to z
132       shell", which is a real book. i haven't read it myself, so i can't say
133       how good it is
134 16:41 @caphuso> now completion
135 16:41 @caphuso> this is where zsh excells at, because really absolutely nothing
136       comes even close
137 16:41 @caphuso> if you ever thought that bash or tcsh would do a good job, be
138       surprised
139 16:42 @caphuso> the zsh completion system is better in any respect
140 16:42 @caphuso> Nei: huh?
141 16:42 @caphuso> it's highly configurable without forcing you to rewrite
142       functions
143 16:43 @caphuso> Nei: indeed, fish sucks. it's not really programmable
144       completion what it offers
145 16:44 @caphuso> it's basically all built in
146 16:44 @caphuso> i'll point out some impressive examples later
147 16:44 @caphuso> next topic: zle
148 16:44 @caphuso> zle is the line editor zsh uses (what readline is for bash)
149 16:45 @caphuso> i.e. the thing that let's you have a way to delete words, move
150       around lines, copy, paste, ...
151 16:46 @caphuso> it's good enough that you can play tetris with it!
152 16:46 @caphuso> this obviously involves several features, including the ability
153       to use multiple lines for your command
154 16:47 @caphuso> it's also extensible by simply writing shell functions
155 16:47 @caphuso> so you can implement everything you need
156 16:47 @caphuso> there will be some examples later on
157 16:47 @caphuso> just one more feature: dynamically loadable modules
158 16:47 @caphuso> (assuming your OS supports those)
159 16:48 @caphuso> there are a couple of modules that extend zsh's features
160 16:48 @caphuso> the line editor for example is such a module
161 16:48 @caphuso> there are also modules for ftp or tcp networking
162 16:49 @caphuso> a math module to do stuff like print $(( sin(5) ))
163 16:49 @caphuso> oh, yes, zsh does floating point math!
164 16:49 @caphuso> no more kludging with bc
165 16:50 @caphuso> ok, this first quick overview is done, from now on i'll touch a
166       couple of features more detailed
167 16:50 @caphuso> any questions so far?
168 16:51 @caphuso> ok... i'll paste a small ~/.zshrc, that's just enough to get
169       you started
170 16:51 @caphuso> zmodload zsh/complist
171 16:51 @caphuso> autoload compinit && compinit
172 16:51 @caphuso> HISTFILE=~/.zsh_history
173 16:51 @caphuso> SAVEHIST=1000
174 16:51 @caphuso> HISTSIZE=1000
175 16:51 @caphuso> setopt APPEND_HISTORY
176 16:51 @caphuso> setopt nobeep
177 16:51 @caphuso> prompt="%# "
178 16:51 @caphuso> rpompt=" %~"
179 16:51 @caphuso> nothing fancy in there, just setting up of the history and
180       loading of the completion system
181 16:52 @caphuso> cow: printf
182 16:52 @caphuso> e1f`: thanks
183 16:52 @caphuso> RPROMPT=" %~"
184 16:53 @caphuso> ok, globbing
185 16:53 @caphuso> zsh's globbing makes find(1) useless for most jobs
186 16:54 @caphuso> e.g. you can do stuff like *(.) to match only regular files or
187       *(/) to match only directories
188 16:55 @caphuso> Stara: one moment
189 16:56 @caphuso> http://84.129.253.97/~caphuso/talk
190 16:56 @caphuso> theclaw: because rprompt is wrong, needs to be upper case
191 16:57 @caphuso> theclaw: hysterical reasons?
192 16:57 @caphuso> dunno
193 16:57 @caphuso> back on topic: it can also match files larger or smaller than a
194       certain size, older or newer than {a,m,c}time, files being block devices
195       etc.
196 16:58 @caphuso> those can be combined with and, or and inverted
197 16:58 @caphuso> there's a way to deal with symlinks (reference or not)
198 16:58 @caphuso> permissions can also be matched
199 16:58 @caphuso> *(f:a+x,o+w:)
200 16:59 @caphuso> the most impressive thing is the e glob qualifier (this is what
201       those things are called)
202 16:59 @caphuso> *(e:'file $REPLY | grep -q JPEG':)
203 16:59 @caphuso> this one will match all files of which file says that they are
204       JPEGs
205 17:00 @caphuso> i had to use that one to dig through a browser cache, where all
206       files were named 234346 or 456745234
207 17:00 @caphuso> glob qualifiers aren't the only thing zsh adds
208 17:01 @caphuso> it does all the regular stuff, like foo? or *bar*
209 17:01 @caphuso> [a-z]
210 17:01 @caphuso> but also things like (foo|bar|baz)
211 17:02 @caphuso> or foo*~*bar* to match everything that starts with foo but
212       doesn't contain bar
213 17:02 @caphuso> it can recurse down directory trees with **
214 17:03 @caphuso> "print -l /**/*" will list _any_ file or directory on your
215       system
216 17:03 @caphuso> be careful when using that one with external commands, you run
217       very quickly into ARG_MAX problems
218 17:03 @caphuso> florolf: no, to any subdirectory
219 17:04 @caphuso> no matter how deep into the tree they are
220 17:04 @caphuso> well, compare "print /**" with "print /**/*"
221 17:04 @caphuso> you'll see the difference in a few minutes >:-)
222 17:05 @caphuso> globbing is just a special use of the more general pattern
223       matching
224 17:05 @caphuso> the other use is in comparisons and replacements
225 17:06 @caphuso> in those the glob qualifiers are obviously useless (a number
226       that's -eq'ed doesn't have permissions or a file size)
227 17:07 @caphuso> but it has a need for other things, most of which are well
228       known from regular expressions
229 17:07 @caphuso> theclaw: (e:'file $REPLY | grep -q JPEG':) is the glob
230       qualifier
231 17:07 @caphuso> $REPLY is a special parameter that contains the name of the
232       file being matched
233 17:08 @caphuso> back on topic: e.g. (#s) or (#e) for what ^ and $ are in
234       regexps
235 17:09 @caphuso> beginning of line/end of line
236 17:09 @caphuso> (#b) or (#m) to enable backreferences
237 17:09 @caphuso> (#i) to match case insensitive
238 17:10 @caphuso> and... *tadaa* (#a) to match approximately
239 17:10 @caphuso> (the latter isn't typically available in regular expressions)
240 17:11 @caphuso> approximate matching means that certain errors are ignored,
241       e.g. "(#a1)foo*" would still match the string "ofobar"
242 17:12 @caphuso> there's quite a bit more on this topic, and explaining it in
243       detail would take a few hours
244 17:12 @caphuso> (the topic == pattern matching)
245 17:12 @caphuso> i suggest strongly that you read the appropriate chapter in the
246       user guide
247 17:13 @caphuso> if you want to look at some real life example, look for the
248       compaudit function
249 17:13 @caphuso> one example of mine:
250 17:14 @caphuso> setopt functionargzero
251 17:14 @caphuso> readme liesmich () { less -- (#ia3)${~0}*(OL[1,3]) }
252 17:14 @caphuso> touch LiesMich README readme.txt Read_ME.doc lies-mich
253 17:14 @caphuso> readme; liesmich
254 17:14 @caphuso> first line sets the functionargzero option, which does nothing
255       but setting $0 inside a function to the name of the function
256 17:14 @caphuso> normally it'd be /bin/zsh or something like that
257 17:15 @caphuso> the next line defines _two_ functions (readme and liesmich),
258       that are the same
259 17:15 @caphuso> (liesmich is german and means readme)
260 17:16 @caphuso> the line noise after -- is a typical zsh glob
261 17:16 @caphuso> it consists of three parts ${~0}, (#ia3) and (OL[1,3])
262 17:17 @caphuso> the first is a simple parameter expansion of $0, but turned
263       into something eligable for pattern matching
264 17:17 @caphuso> this means that the names of the two functions will be used to
265       match files
266 17:17 @caphuso> the (#ia3) makes the whole thing 1) case insensitive and 2)
267       allows up to 3 mistakes
268 17:18 @caphuso> the (OL[1,3]) at the end sorts the resulting list by size
269       (biggest first) and uses only the first three files
270 17:18 @caphuso> the mere * in there does what it always does, it matches
271       anything
272 17:19 @caphuso> the touch command creates 4 empty files
273 17:19 @caphuso> and running the two functions in the last line results in less
274       displaying first README, Read_ME.doc and readme.txt, then LIESMICH and
275       lies-mich
276 17:21 @caphuso> in lesser shells you'd need three times as much code, and
277       probably several external programs
278 17:21 @caphuso> questions?
279 17:22 @caphuso> now the real horror: parameter expansion
280 17:22 @caphuso> things like this:
281 17:22 @caphuso> for a in **/*(.);
282       mv $a ${a:h}/${${a:t}//(#m)((#s)?|(_| )?)/${(U)MATCH}}
283 17:22 @caphuso> or this:
284 17:22 @caphuso> function foo () {
285       print -l ${(q)${${(f)"$(<$1)"}:#(#s)[[:space:]]#\#*}%%[[:space:]]##\#*
286       }
287 17:22 @caphuso> }
288 17:22 @caphuso> parameter expansion in zsh can be nested
289 17:23 @caphuso> if you want to remove foo at the beginning and bar at the end
290       of a parameter, you'd normally do tmp=${FOO%bar}; FOO=${tmp#foo}
291 17:24 @caphuso> in zsh you can use ${${FOO%bar}#tmp}
292 17:24 @caphuso> err, ${${FOO%bar}#foo}
293 17:24 @caphuso> and those things can grow really big
294 17:24 @caphuso> especially when you start using arrays or associative arrays
295       (hashes in perl lingo)
296 17:26 @caphuso> _the_ killer example is _pids
297 17:26 @caphuso> it's a function of the completion system that completes PIDs
298 17:26 @caphuso> you need several hours with the reference manual, the user
299       guide and 2l coffee
300 17:26 @caphuso> maybe even more
301 17:27 @caphuso> the sad thing is, anything i'd try to teach you about parameter
302       expansion would be wasted
303 17:27 @caphuso> so, for the beginning, stick to the standard stuff
304 17:27 @caphuso> work your way up from there, while reading the user guide
305 17:28 @caphuso> ZHOST=localhost
306 17:28 @caphuso> ZPORT=1234
307 17:28 @caphuso> ZHOME=/tmp
308 17:28 @caphuso> ZDATA="this is a stupid example"
309 17:28 @caphuso> : ${(AA)zopt:=${(z)${(ps:=:)${(f)$(<configfile)}}}}
310 17:29 @caphuso> this is just one small example, showing that all this insanity
311       can be used for good reasons
312 17:29 @caphuso> the first 4 lines are the content of a simple config file
313 17:29 @caphuso> and the line starting with : reads that file in and creates an
314       associative array $zopt with the keys ZHOST, ZPORT, ZHOME and ZDATA
315 17:30 @caphuso> the values of those keys are simply the things behind the =
316 17:30 @caphuso> doing it the old fashioned way would be more cumbersome
317 17:31 @caphuso> but here we simply read in the whole file with $(<configfile)
318 17:31 @caphuso> split on newlines and create an array with ${(f)...}
319 17:31 @caphuso> split on = with ${(ps:=:)...}
320 17:32 @caphuso> so we have an array with the elements ZHOST, localhost, ZPORT,
321       1234, ZHOME, /tmp, ...
322 17:32 @caphuso> and then we put that into an associative array with
323       ${(AA)zopt:=...}
324 17:33 @caphuso> Nei: no, start reading from the inner to the outer, not from
325       the right to the left
326 17:34 @caphuso> third big topic: ZLE
327 17:34 @caphuso> micikas: #emacs on the 24th
328 17:35 @caphuso> i already mentioned the multi line editing support
329 17:35 @caphuso> this means you get a real multi line buffer, just like you'd do
330       in a text editor
331 17:35 @caphuso> it's also saved and restored in multiple lines when using the
332       history
333 17:36 @caphuso> this is quite convenient, because your throw away shell scripts
334       can grow
335 17:36 @caphuso> (because of the increased legibility)
336 17:37 @caphuso> tcsh users will know run-help
337 17:38 @caphuso> hitting "ESC, h" (or meta-h) will fire up the man page of
338       whatever command you have on the command line, let you read it, then go
339       back and continue editing where you left of
340 17:39 @caphuso> push-line is a more general solution for that kind of problem:
341       it simply pushes the current line on the stack, type in another command
342       line, execute that, then turb back to where you left of
343 17:39 @caphuso> bound to ctrl-q by default
344 17:40 @caphuso> so, but some basics first
345 17:40 @caphuso> the two commands with which you deal with zle are bindkey and
346       zle
347 17:40 @caphuso> bindkey is used to handle keymaps
348 17:41 @caphuso> emacs users will know the concept of keymaps
349 17:41 @caphuso> basically just tables containing key-function pairs
350 17:41 @caphuso> one of those keymaps zsh uses is the emacs keymap, it contains
351       the standard emacs like stuff
352 17:42 @caphuso> ctrl-a == beginning-of-line, "ESC, f" == forward-word
353 17:42 @caphuso> viins is the keymap for the vi insert mode, vicmd the one for
354       the command mode
355 17:42 @caphuso> you can switch between emacs and vi with bindkey -e and bindkey
356       -v
357 17:43 @caphuso> you are free to bind any key to any function, in any table
358 17:43 @caphuso> so you can add emacs bindings to vi, and run the vi functions
359       in emacs mode
360 17:43 @caphuso> btw, what i named "functions" are called "editing widgets"
361 17:44 @caphuso> Nei: oh, yes, i've changed that
362 17:44  * caphuso lost track of default zsh settings years ago
363 17:44 @caphuso> some of those widgets are built into zle
364 17:45 @caphuso> some others are provided by those loadable modules mentioned
365       earlier
366 17:45 @caphuso> the most interesting ones though are those written as shell
367       functions
368 17:46 @caphuso> a simple example: run-with-sudo () { LBUFFER="sudo $LBUFFER" }
369 17:46 @caphuso> zle -N run-with-sudo
370 17:46 @caphuso> bindkey '^X^E' run-with-sudo
371 17:47 @caphuso> $LBUFFER is one of the zle special parameters, it contains the
372       part of the command line left to the cursor
373 17:47 @caphuso> it simply gets "sudo " prepended to it
374 17:48 @caphuso> zle -N ... makes zle aware that run-with-sudo is from now on a
375       bindable widget
376 17:48 @caphuso> and the bindkey command binds it to ctrl-x ctrl-e
377 17:48 @caphuso> now you can type at any moment C-x C-e and you'll have your
378       current command line with sudo at the beginning
379 17:48 @caphuso> if you like me forget that way too often, you'll love this
380 17:49  * caphuso can't count how often he saw E: Could not open lock file
381       /var/lib/apt/lists/lock - open (13 Permission denied)
382 17:49 @caphuso> of course, those shell functions can grow to any degree of
383       "complicatedness" you like
384 17:50 @caphuso> there's a few interesting ones in the zsh distribution, look
385       for smart-insert-last-word or the *-word-match family
386 17:50 @caphuso> also a whole chapter in the user guide
387 17:51 @caphuso> ok... now the very last topic: completion
388 17:51 @caphuso> probably the one most interesting to all of you, because it's
389       the one you can start using without actually knowing anything ;-)
390 17:51 @caphuso> simply hitting your tab key in random places is sufficient
391 17:52 @caphuso> the completion system is loaded with "autoload compinstall &&
392       compinstall"
393 17:52 @caphuso> after that, you're ready to go
394 17:53 @caphuso> until you find that some things don't behave like you want them
395       to
396 17:53 @caphuso> that's why you get the chance of tweaking and customizing
397 17:53 @caphuso> in order to be able to do that, we need to learn about context
398 17:54 @caphuso>
399       :completion:FUNCTION:COMPLETER:COMMAND-OR-MAGIC-CONTEXT:ARGUMENT:TAG
400 17:54 @caphuso> this is what a context looks like: 6 fields, seperated with :
401 17:54 @caphuso> the first field is simply "completion"
402 17:55 @caphuso> FUNCTION is of no interest, unless you get your hands really
403       dirty
404 17:55 @caphuso> COMPLETER is the name of the shell function that creates
405       matches at the moment of the context lookup. i'll explain those later
406 17:58 @caphuso> COMMAND-OR-MAGIC-CONTEXT is either the name of the command you
407       are trying to complete for (e.g. in case of "make cle<TAB>" it'd be make"
408       or a magic context like -redirect- (after > or <) or -math- (when you're
409       at a point of arithmetic expansion)
410 17:58 @caphuso> ARGUMENT is also less useful, unless you already know enough to
411       be bored by me talking
412 17:59 @caphuso> and TAGS are basically short yet descriptive names of what
413       exactly you are completion at the moment
414 17:59 @caphuso> e.g. in "make <TAB>" the tag would be "targets", because you're
415       trying to complete Makefile targets
416 18:00 @caphuso> "kill <TAB" has the tags "processes" and "jobs"
417 18:00 @caphuso> you can look them up with "ctrl-x, h"
418 18:01 @caphuso> so, some hands on examples: :completion:*:*:xpdf:*:*
419 18:01 @caphuso> this specifies: whenever we're completing for xpdf
420 18:01 @caphuso> :completion:*:approximate:rm:*:*
421 18:01 @caphuso> whenever we're completion after rm and are using the
422       _approximate completer (description follows later)
423 18:02 @caphuso> more specific settings win over the general ones
424 18:02 @caphuso> :completion:*:*:*:*:processes
425 18:02 @caphuso> :completion:*:*:kill:*:processes
426 18:02 @caphuso> the first one says: whenever we complete the tag "processes"
427 18:03 @caphuso> the second: whenever we complete processes after kill
428 18:03 @caphuso> if i had two clashing settings for those two context, then
429       after kill only the second one would be used
430 18:03 @caphuso> this is just common sense
431 18:03 @caphuso> the system would be useless if it worked otherwise :)
432 18:04 @caphuso> now how to use those contexts
433 18:04 @caphuso> setting and lookup of that stuff is done with the builtin
434       zstyle
435 18:04 @caphuso> you can use that outside of the completion system to store and
436       retrieve data too, some of the zle functions do that for example
437 18:05 @caphuso> we'll only deal with setting, not with retrieving
438 18:05 @caphuso> zstyle ':completion:*:*:(^rm):*:*' ignored-pattern '*.(o|~)'
439       '#*#(D)'
440 18:06 @caphuso> he're we set the style 'ignored-pattern' (you can find a list
441       and descriptions of styles in the manual) to '*.(o|~)' '#*#(D)'
442 18:06 @caphuso> when completing after anything except rm
443 18:06 @caphuso> ^rm means "don't match rm"
444 18:07 @caphuso> the two globs match *.o files (C programmers will know), *~
445       (backup files) and #*# files (emacs autosave files). the (D) qualifier
446       turns on globbing of .* files
447 18:08 @caphuso> ignored-pattern means: when completion, then ignore everything
448       that matches the value of this style
449 18:08 @caphuso> so, after any command that's not rm, we won't get those files
450       offered as completions
451 18:09 @caphuso> this is just one simple example of how extensible the zsh
452       completion system is configurable
453 18:09 @caphuso> there are a few dozen styles
454 18:10 @caphuso> you'll need to read the manual, i really don't wanna talk till
455       tomorrow morning :-)
456 18:11 @caphuso> now the completers i wanted to explain quickly
457 18:11 @caphuso> a completer is simply a shell function that looks up the
458       current context and creates a list of possible completions, offering
459       those to the user
460 18:11 @caphuso> of course, nothing is that simple in zsh
461 18:11 @caphuso> the first completer available is "_complete"
462 18:12 @caphuso> it does basically what bash does
463 18:12 @caphuso> nothing fancy at all
464 18:12 @caphuso> just looking up stuff, then straight completion mozi<tab> ->
465       mozilla
466 18:13 @caphuso> _expand is the first exception, because it doesn't really
467       generate possible completions
468 18:13 @caphuso> it expands certain things on the command line, e.g. $PARAMETERS
469       or $(print -c *)
470 18:13 @caphuso> $PATH<TAB> would become
471       /home/caphuso/bin:/usr/local/bin:/usr/X11R6/bin:/usr/sbin:/sbin:/usr/game
472       s:/usr/lib/surfraw:/usr/bin:/bin:/usr/bin/X11 on the command line
473 18:14 @caphuso> _correct does what the name implies: it corrects typos
474 18:14 @caphuso> _approximate is _correct on crack
475 18:14 @caphuso> it not only corrects typoes, it also generates completions
476 18:15 @caphuso> given a directory ~/public_html, then _correct would do the
477       right thing for "cd ~/pbulic_html<TAB>", but not for "cd ~/pb<TAB>"
478 18:16 @caphuso> there are a few more, but those are the most interesting ones
479 18:17 @caphuso> using completers is a matter of setting the style "completer"
480       properly
481 18:17 @caphuso> zstyle ':completion:*' completer _complete
482 18:18 @caphuso> (bash emulation again ;-)
483 18:18 @caphuso> zstyle ':completion:*' completer _complete _approximate
484 18:18 @caphuso> this means: first try _complete, if it can't generate any
485       possible matches, then try _approximate
486 18:19 @caphuso> zstyle ':completion:*' completer _complete _correct
487       _complete:-extended _complete:-substring
488 18:19 @caphuso> this means: first _complete, if it fails _correct, then
489       _complete again, then _complete again
490 18:20 @caphuso> the trick is that by appending :-foo the completer will look up
491       the context not under its regular name (_complete) but as (_complete-foo)
492 18:21 @caphuso> this allows to do the same completion with different settings
493       because the context differ
494 18:21 @caphuso> zstyle ':completion:*:complete-extended:*' matcher-list 'm:{a-z}={A-Z}' 'r:|[+._-]=*'
495 18:21 @caphuso> zstyle ':completion:*:complete-substring:*' matcher-list 'm:{a-z}={A-Z} l:|=**'
496 18:22 @caphuso> we do that here... as COMPLETER field we have now not complete
497       but complete-extended and complete-substring, and for both we set the
498       style matcher-list to yet another kind of line noise
499 18:22 @caphuso> those matchers configure how zsh is doing comparison
500 18:22 @caphuso> s
501 18:22 @caphuso> the default way is to simply compare the string on the command
502       line with all possible completions
503 18:23 @caphuso> foo<tab> with the possible completions of foobar, foobaz and
504       moo_foo will offer the first two as possible completions
505 18:23 @caphuso> because only they match "foo*"
506 18:24 @caphuso> matching control can change that, make it ignore certain things
507 18:24 @caphuso> e.g. m:{a-z}={A-Z} tells it that lower case characters match
508       upper case characters
509 18:24 @caphuso> echo $disp<TAB -> echo $DISPLAY
510 18:27 @caphuso> r:|[+._-]=* makes the characters +, ., _ and - special, so that
511       "cd p_h<TAB> -> cd public_html" or "rm x.txt<TAB> -> rm xenomorph.txt"
512       works
513 18:27 @caphuso> and the l:|=** does a simple substring match, so that
514       "foo<TAB>" will also match barfoobaz
515 18:28 @caphuso> now the whole list of completers in this last example explained
516       slowly
517 18:29 @caphuso> when the user hits TAB, the _complete is tried. if it fails
518       to generate any matches, the word on the command line is tried to be
519       corrected. if this doesn't help, case-insensitive matching with a few
520       special characters is tried, and if that fails too, substring matching
521 18:29 @caphuso> and as soon as one completer succeeds with creating at least
522       one match, the whole thing stops
523 18:30 @caphuso> now you might wonder why to do that so complicated
524 18:30 @caphuso> easy: 1) the more possible matches you try to generate, the
525       slower the whole thing becomes
526 18:31 @caphuso> _complete is noticably faster than _complete:-extended, and
527       i've seen _approximate run for several minutes, due to a large directory
528 18:31 @caphuso> so you want to be careful
529 18:31 @caphuso> 2) the more matches you create, the longer the list of possible
530       completion becomes
531 18:32 @caphuso> when _complete might only show 5 matches, _approximate can go
532       up to 50
533 18:32 @caphuso> or more
534 18:33 @caphuso> this doesn't only take longer, it also makes it hard to handle
535 18:33 @caphuso> so, that's the reasoning behind
536 18:33 @caphuso> ok
537 18:34 @caphuso> AFAICT, that's it
538 18:34 @caphuso> i hope it's been interesting enough, and would glad to see a
539       few more enthusiastic zsh users in #zsh in the next few weeks
540 18:34 @caphuso> any questions?
541 --- Log closed Sat Sep 10 18:35:39 2005