26763: fix problem on failed cd -s to relative path
[zsh.git] / Src / Zle / zle_keymap.c
blob7f59d9d9b34d1cea8745010cc22bbaca640f9853
1 /*
2 * zle_keymap.c - keymaps and key bindings
4 * This file is part of zsh, the Z shell.
6 * Copyright (c) 1992-1997 Paul Falstad
7 * All rights reserved.
9 * Permission is hereby granted, without written agreement and without
10 * license or royalty fees, to use, copy, modify, and distribute this
11 * software and to distribute modified versions of this software for any
12 * purpose, provided that the above copyright notice and the following
13 * two paragraphs appear in all copies of this software.
15 * In no event shall Paul Falstad or the Zsh Development Group be liable
16 * to any party for direct, indirect, special, incidental, or consequential
17 * damages arising out of the use of this software and its documentation,
18 * even if Paul Falstad and the Zsh Development Group have been advised of
19 * the possibility of such damage.
21 * Paul Falstad and the Zsh Development Group specifically disclaim any
22 * warranties, including, but not limited to, the implied warranties of
23 * merchantability and fitness for a particular purpose. The software
24 * provided hereunder is on an "as is" basis, and Paul Falstad and the
25 * Zsh Development Group have no obligation to provide maintenance,
26 * support, updates, enhancements, or modifications.
30 #include "zle.mdh"
33 * Keymap structures:
35 * There is a hash table of keymap names. Each name just points to a keymap.
36 * More than one name may point to the same keymap.
38 * Each keymap consists of a table of bindings for each character, and a
39 * hash table of multi-character key bindings. The keymap has no individual
40 * name, but maintains a reference count.
42 * In a keymap's table of initial bindings, each character is either bound to
43 * a thingy, or is a prefix (in which case NULL is stored). Those prefix
44 * entries are matched by more complex entries in the multi-character
45 * binding hash table. Each entry in this hash table (which is indexed by
46 * metafied key sequence) either has a normal thingy binding or a string to
47 * send (in which case the NULL thingy is used). Each entry also has a count
48 * of other entries for which it is a prefix.
51 typedef struct keymapname *KeymapName;
52 typedef struct key *Key;
54 struct keymapname {
55 HashNode next; /* next in the hash chain */
56 char *nam; /* name of the keymap */
57 int flags; /* various flags (see below) */
58 Keymap keymap; /* the keymap itsef */
61 #define KMN_IMMORTAL (1<<1)
63 struct keymap {
64 Thingy first[256]; /* base binding of each character */
65 HashTable multi; /* multi-character bindings */
66 int flags; /* various flags (see below) */
67 int rc; /* reference count */
70 #define KM_IMMUTABLE (1<<1)
72 struct key {
73 HashNode next; /* next in hash chain */
74 char *nam; /* key sequence (metafied) */
75 Thingy bind; /* binding of this key sequence */
76 char *str; /* string for send-string (metafied) */
77 int prefixct; /* number of sequences for which this is a prefix */
80 /* This structure is used when listing keymaps. */
82 struct bindstate {
83 int flags;
84 char *kmname;
85 char *firstseq;
86 char *lastseq;
87 Thingy bind;
88 char *str;
89 char *prefix;
90 int prefixlen;
93 /* This structure is used when scanning for prefix bindings to remove */
95 struct remprefstate {
96 Keymap km;
97 char *prefix;
98 int prefixlen;
101 #define BS_LIST (1<<0)
102 #define BS_ALL (1<<1)
104 /* local functions */
106 #include "zle_keymap.pro"
108 /* currently selected keymap, and its name */
110 /**/
111 Keymap curkeymap, localkeymap;
112 /**/
113 char *curkeymapname;
115 /* the hash table of keymap names */
117 /**/
118 mod_export HashTable keymapnamtab;
120 /* key sequence reading data */
122 /**/
123 char *keybuf;
125 static int keybuflen, keybufsz = 20;
127 /* last command executed with execute-named-command */
129 static Thingy lastnamed;
131 /**********************************/
132 /* hashtable management functions */
133 /**********************************/
135 /**/
136 static void
137 createkeymapnamtab(void)
139 keymapnamtab = newhashtable(7, "keymapnamtab", NULL);
141 keymapnamtab->hash = hasher;
142 keymapnamtab->emptytable = emptyhashtable;
143 keymapnamtab->filltable = NULL;
144 keymapnamtab->cmpnodes = strcmp;
145 keymapnamtab->addnode = addhashnode;
146 keymapnamtab->getnode = gethashnode2;
147 keymapnamtab->getnode2 = gethashnode2;
148 keymapnamtab->removenode = removehashnode;
149 keymapnamtab->disablenode = NULL;
150 keymapnamtab->enablenode = NULL;
151 keymapnamtab->freenode = freekeymapnamnode;
152 keymapnamtab->printnode = NULL;
155 /**/
156 static KeymapName
157 makekeymapnamnode(Keymap keymap)
159 KeymapName kmn = (KeymapName) zshcalloc(sizeof(*kmn));
161 kmn->keymap = keymap;
162 return kmn;
165 /**/
166 static void
167 freekeymapnamnode(HashNode hn)
169 KeymapName kmn = (KeymapName) hn;
171 zsfree(kmn->nam);
172 unrefkeymap(kmn->keymap);
173 zfree(kmn, sizeof(*kmn));
176 /**/
177 static HashTable
178 newkeytab(char *kmname)
180 HashTable ht = newhashtable(19,
181 kmname ? dyncat("keytab:", kmname) : "keytab:", NULL);
183 ht->hash = hasher;
184 ht->emptytable = emptyhashtable;
185 ht->filltable = NULL;
186 ht->cmpnodes = strcmp;
187 ht->addnode = addhashnode;
188 ht->getnode = gethashnode2;
189 ht->getnode2 = gethashnode2;
190 ht->removenode = removehashnode;
191 ht->disablenode = NULL;
192 ht->enablenode = NULL;
193 ht->freenode = freekeynode;
194 ht->printnode = NULL;
196 return ht;
199 /**/
200 static Key
201 makekeynode(Thingy t, char *str)
203 Key k = (Key) zshcalloc(sizeof(*k));
205 k->bind = t;
206 k->str = str;
207 return k;
210 /**/
211 static void
212 freekeynode(HashNode hn)
214 Key k = (Key) hn;
216 zsfree(k->nam);
217 unrefthingy(k->bind);
218 zsfree(k->str);
219 zfree(k, sizeof(*k));
222 /**************************/
223 /* main keymap operations */
224 /**************************/
226 static HashTable copyto;
228 /**/
229 mod_export Keymap
230 newkeymap(Keymap tocopy, char *kmname)
232 Keymap km = zshcalloc(sizeof(*km));
233 int i;
235 km->rc = 0;
236 km->multi = newkeytab(kmname);
237 if(tocopy) {
238 for(i = 256; i--; )
239 km->first[i] = refthingy(tocopy->first[i]);
240 copyto = km->multi;
241 scanhashtable(tocopy->multi, 0, 0, 0, scancopykeys, 0);
242 } else {
243 for(i = 256; i--; )
244 km->first[i] = refthingy(t_undefinedkey);
246 return km;
249 /**/
250 static void
251 scancopykeys(HashNode hn, UNUSED(int flags))
253 Key k = (Key) hn;
254 Key kn = zalloc(sizeof(*k));
256 memcpy(kn, k, sizeof(*k));
257 refthingy(kn->bind);
258 kn->str = ztrdup(k->str);
259 copyto->addnode(copyto, ztrdup(k->nam), kn);
262 /**/
263 void
264 deletekeymap(Keymap km)
266 int i;
268 deletehashtable(km->multi);
269 for(i = 256; i--; )
270 unrefthingy(km->first[i]);
271 zfree(km, sizeof(*km));
274 static Keymap skm_km;
275 static int skm_last;
276 static KeyScanFunc skm_func;
277 static void *skm_magic;
279 /**/
280 void
281 scankeymap(Keymap km, int sort, KeyScanFunc func, void *magic)
283 char m[3];
285 skm_km = km;
286 skm_last = sort ? -1 : 255;
287 skm_func = func;
288 skm_magic = magic;
289 scanhashtable(km->multi, sort, 0, 0, scankeys, 0);
290 if(!sort)
291 skm_last = -1;
292 while(skm_last < 255) {
293 skm_last++;
294 if(km->first[skm_last] && km->first[skm_last] != t_undefinedkey) {
295 m[0] = skm_last;
296 metafy(m, 1, META_NOALLOC);
297 func(m, km->first[skm_last], NULL, magic);
302 /**/
303 static void
304 scankeys(HashNode hn, UNUSED(int flags))
306 Key k = (Key) hn;
307 int f = k->nam[0] == Meta ? STOUC(k->nam[1])^32 : STOUC(k->nam[0]);
308 char m[3];
310 while(skm_last < f) {
311 skm_last++;
312 if(skm_km->first[skm_last] &&
313 skm_km->first[skm_last] != t_undefinedkey) {
314 m[0] = skm_last;
315 metafy(m, 1, META_NOALLOC);
316 skm_func(m, skm_km->first[skm_last], NULL, skm_magic);
319 skm_func(k->nam, k->bind, k->str, skm_magic);
322 /**************************/
323 /* keymap name operations */
324 /**************************/
326 /**/
327 Keymap
328 openkeymap(char *name)
330 KeymapName n = (KeymapName) keymapnamtab->getnode(keymapnamtab, name);
331 return n ? n->keymap : NULL;
334 /**/
335 mod_export int
336 unlinkkeymap(char *name, int ignm)
338 KeymapName n = (KeymapName) keymapnamtab->getnode(keymapnamtab, name);
339 if(!n)
340 return 2;
341 if(!ignm && (n->flags & KMN_IMMORTAL))
342 return 1;
343 keymapnamtab->freenode(keymapnamtab->removenode(keymapnamtab, name));
344 return 0;
347 /**/
348 mod_export int
349 linkkeymap(Keymap km, char *name, int imm)
351 KeymapName n = (KeymapName) keymapnamtab->getnode(keymapnamtab, name);
352 if(n) {
353 if(n->flags & KMN_IMMORTAL)
354 return 1;
355 if(n->keymap == km)
356 return 0;
357 unrefkeymap(n->keymap);
358 n->keymap = km;
359 } else {
360 n = makekeymapnamnode(km);
361 if (imm)
362 n->flags |= KMN_IMMORTAL;
363 keymapnamtab->addnode(keymapnamtab, ztrdup(name), n);
365 refkeymap(km);
366 return 0;
369 /**/
370 void refkeymap(Keymap km)
372 km->rc++;
375 /**/
376 void unrefkeymap(Keymap km)
378 if (!--km->rc)
379 deletekeymap(km);
382 /* Select a keymap as the current ZLE keymap. Can optionally fall back *
383 * on the guaranteed safe keymap if it fails. */
385 /**/
387 selectkeymap(char *name, int fb)
389 Keymap km = openkeymap(name);
391 if(!km) {
392 char *nm = nicedup(name, 0);
393 char *msg = tricat("No such keymap `", nm, "'");
395 zsfree(nm);
396 showmsg(msg);
397 zsfree(msg);
398 if(!fb)
399 return 1;
400 km = openkeymap(name = ".safe");
402 if(name != curkeymapname) {
403 char *oname = curkeymapname;
404 Thingy chgthingy;
406 curkeymapname = ztrdup(name);
408 if (oname && zleactive && strcmp(oname, curkeymapname) &&
409 (chgthingy = rthingy_nocreate("zle-keymap-select"))) {
410 char *args[2];
411 int saverrflag = errflag, savretflag = retflag;
412 args[0] = oname;
413 args[1] = NULL;
414 errflag = retflag = 0;
415 execzlefunc(chgthingy, args, 1);
416 unrefthingy(chgthingy);
417 errflag = saverrflag;
418 retflag = savretflag;
420 zsfree(oname);
422 curkeymap = km;
423 return 0;
426 /* Select a local key map. */
428 /**/
429 mod_export void
430 selectlocalmap(Keymap m)
432 localkeymap = m;
435 /* Reopen the currently selected keymap, in case it got deleted. This *
436 * should be called after doing anything that might have run an *
437 * arbitrary user-specified command. */
439 /**/
440 void
441 reselectkeymap(void)
443 selectkeymap(curkeymapname, 1);
446 /******************************/
447 /* operations on key bindings */
448 /******************************/
450 /* Add/delete/change a keybinding in some keymap. km is the keymap to be *
451 * altered. seq is the metafied key sequence whose binding is to change. *
452 * bind is the thingy to which the key sequence is to be bound. For *
453 * send-string, bind is NULL and str is the metafied key sequence to push *
454 * back onto the input. */
456 /**/
457 mod_export int
458 bindkey(Keymap km, char *seq, Thingy bind, char *str)
460 Key k;
461 int f = seq[0] == Meta ? STOUC(seq[1])^32 : STOUC(seq[0]);
462 char *buf, *ptr;
464 if(km->flags & KM_IMMUTABLE)
465 return 1;
466 if(!*seq)
467 return 2;
468 if(!bind || ztrlen(seq) > 1) {
469 /* key needs to become a prefix if isn't one already */
470 if(km->first[f]) {
471 char fs[3];
472 fs[0] = f;
473 metafy(fs, 1, META_NOALLOC);
474 km->multi->addnode(km->multi, ztrdup(fs),
475 makekeynode(km->first[f], NULL));
476 km->first[f] = NULL;
478 k = (Key) km->multi->getnode(km->multi, seq);
479 } else {
480 /* If the sequence is a prefix entry only due to being *
481 * a send-string binding, we can remove that entry. */
482 if(!km->first[f]) {
483 k = (Key) km->multi->getnode(km->multi, seq);
484 if(!k->prefixct)
485 km->multi->freenode(km->multi->removenode(km->multi, seq));
486 else
487 goto domulti;
488 } else
489 unrefthingy(km->first[f]);
490 /* Just replace the single-character binding. */
491 km->first[f] = bind;
492 return 0;
494 domulti:
495 buf = ztrdup(seq);
496 ptr = strchr(buf, 0);
497 if(bind == t_undefinedkey) {
498 if(k) {
499 zsfree(k->str);
500 unrefthingy(k->bind);
501 k->bind = t_undefinedkey;
502 k->str = NULL;
503 while(!k->prefixct && k->bind == t_undefinedkey) {
504 km->multi->freenode(km->multi->removenode(km->multi, buf));
505 *--ptr = 0;
506 if(ptr[-1] == Meta)
507 *--ptr = 0;
508 k = (Key) km->multi->getnode(km->multi, buf);
509 k->prefixct--;
510 if(!k->prefixct && k->bind &&
511 (!buf[1] || (buf[0] == Meta && !buf[2]))) {
512 km->first[f] = refthingy(k->bind);
513 km->multi->freenode(km->multi->removenode(km->multi, buf));
514 break;
518 } else {
519 if(!k) {
520 int added;
522 km->multi->addnode(km->multi, ztrdup(buf), makekeynode(bind, ztrdup(str)));
523 do {
524 *--ptr = 0;
525 if(ptr > buf && ptr[-1] == Meta)
526 *--ptr = 0;
527 k = (Key) km->multi->getnode(km->multi, buf);
528 if((added = !k))
529 km->multi->addnode(km->multi, ztrdup(buf),
530 k = makekeynode(refthingy(t_undefinedkey), NULL));
531 k->prefixct++;
532 } while(added);
533 } else {
534 unrefthingy(k->bind);
535 zsfree(k->str);
536 k->bind = bind;
537 k->str = bind ? NULL : ztrdup(str);
540 free(buf);
541 return 0;
544 /* Look up a key binding. The binding is returned. In the case of a *
545 * send-string, NULL is returned and *strp is modified to point to the *
546 * metafied string of characters to be pushed back. */
548 /**/
549 Thingy
550 keybind(Keymap km, char *seq, char **strp)
552 Key k;
554 if(ztrlen(seq) == 1) {
555 int f = seq[0] == Meta ? STOUC(seq[1])^32 : STOUC(seq[0]);
556 Thingy bind = km->first[f];
558 if(bind)
559 return bind;
561 k = (Key) km->multi->getnode(km->multi, seq);
562 if(!k)
563 return t_undefinedkey;
564 *strp = k->str;
565 return k->bind;
568 /* Check whether a key sequence is a prefix of a longer bound sequence. *
569 * One oddity: if *nothing* in the keymap is bound, this returns true *
570 * for the empty sequence, even though this is not strictly accurate. */
572 /**/
573 static int
574 keyisprefix(Keymap km, char *seq)
576 Key k;
578 if(!*seq)
579 return 1;
580 if(ztrlen(seq) == 1) {
581 int f = seq[0] == Meta ? STOUC(seq[1])^32 : STOUC(seq[0]);
583 if(km->first[f])
584 return 0;
586 k = (Key) km->multi->getnode(km->multi, seq);
587 return k && k->prefixct;
590 /*******************/
591 /* bindkey builtin */
592 /*******************/
595 * THE BINDKEY BUILTIN
597 * Keymaps can be specified to bindkey in the following ways:
599 * -e select "emacs", also link it to "main"
600 * -v select "viins", also link it to "main"
601 * -a select "vicmd"
602 * -M first argument gives map name
603 * defaults to "main"
605 * These operations cannot have a keymap selected in the normal way:
607 * -l list all the keymap names
608 * -d delete all keymaps and reset to the default state (no arguments)
609 * -D delete named keymaps
610 * -A link the two named keymaps (2 arguments)
611 * -N create new empty keymap (1 argument)
612 * -N create new keymap, copying the second named keymap (2 arguments)
614 * Other operations:
616 * -m add the meta bindings to the selected keymap (no arguments)
617 * -r unbind each named string in the selected keymap
618 * -s bind send-strings in the selected keymap (2+ arguments)
619 * bind commands in the selected keymap (2+ arguments)
620 * display one binding in the selected keymap (1 argument)
621 * display the entire selected keymap (no arguments)
623 * There is an exception that the entire keymap display will not be performed
624 * if the -e or -v options were used.
626 * Other options:
628 * -L do listings in the form of bindkey commands
629 * -R for the binding operations, accept ranges instead of sequences
632 /**/
634 bin_bindkey(char *name, char **argv, Options ops, UNUSED(int func))
636 static struct opn {
637 char o;
638 char selp;
639 int (*func) _((char *, char *, Keymap, char **, Options, char));
640 int min, max;
641 } const opns[] = {
642 { 'l', 0, bin_bindkey_lsmaps, 0, 0 },
643 { 'd', 0, bin_bindkey_delall, 0, 0 },
644 { 'D', 0, bin_bindkey_del, 1, -1 },
645 { 'A', 0, bin_bindkey_link, 2, 2 },
646 { 'N', 0, bin_bindkey_new, 1, 2 },
647 { 'm', 1, bin_bindkey_meta, 0, 0 },
648 { 'r', 1, bin_bindkey_bind, 1, -1 },
649 { 's', 1, bin_bindkey_bind, 2, -1 },
650 { 0, 1, bin_bindkey_bind, 0, -1 },
652 struct opn const *op, *opp;
653 char *kmname;
654 Keymap km;
655 int n;
657 /* select operation and ensure no clashing arguments */
658 for(op = opns; op->o && !OPT_ISSET(ops,STOUC(op->o)); op++) ;
659 if(op->o)
660 for(opp = op; (++opp)->o; )
661 if(OPT_ISSET(ops,STOUC(opp->o))) {
662 zwarnnam(name, "incompatible operation selection options");
663 return 1;
665 n = OPT_ISSET(ops,'e') + OPT_ISSET(ops,'v') +
666 OPT_ISSET(ops,'a') + OPT_ISSET(ops,'M');
667 if(!op->selp && n) {
668 zwarnnam(name, "keymap cannot be selected with -%c", op->o);
669 return 1;
671 if(n > 1) {
672 zwarnnam(name, "incompatible keymap selection options");
673 return 1;
676 /* keymap selection */
677 if(op->selp) {
678 if(OPT_ISSET(ops,'e'))
679 kmname = "emacs";
680 else if(OPT_ISSET(ops,'v'))
681 kmname = "viins";
682 else if(OPT_ISSET(ops,'a'))
683 kmname = "vicmd";
684 else if(OPT_ISSET(ops,'M')) {
685 kmname = OPT_ARG(ops,'M');
686 } else
687 kmname = "main";
688 km = openkeymap(kmname);
689 if(!km) {
690 zwarnnam(name, "no such keymap `%s'", kmname);
691 return 1;
693 if(OPT_ISSET(ops,'e') || OPT_ISSET(ops,'v'))
694 linkkeymap(km, "main", 0);
695 } else {
696 kmname = NULL;
697 km = NULL;
700 /* listing is a special case */
701 if(!op->o && (!argv[0] || !argv[1])) {
702 if(OPT_ISSET(ops,'e') || OPT_ISSET(ops,'v'))
703 return 0;
704 return bin_bindkey_list(name, kmname, km, argv, ops, op->o);
707 /* check number of arguments */
708 for(n = 0; argv[n]; n++) ;
709 if(n < op->min) {
710 zwarnnam(name, "not enough arguments for -%c", op->o);
711 return 1;
712 } else if(op->max != -1 && n > op->max) {
713 zwarnnam(name, "too many arguments for -%c", op->o);
714 return 1;
717 /* pass on the work to the operation function */
718 return op->func(name, kmname, km, argv, ops, op->o);
721 /* list the available keymaps */
723 /**/
724 static int
725 bin_bindkey_lsmaps(UNUSED(char *name), UNUSED(char *kmname), UNUSED(Keymap km), UNUSED(char **argv), Options ops, UNUSED(char func))
727 scanhashtable(keymapnamtab, 1, 0, 0, scanlistmaps, OPT_ISSET(ops,'L'));
728 return 0;
731 /**/
732 static void
733 scanlistmaps(HashNode hn, int list)
735 KeymapName n = (KeymapName) hn;
737 if(list) {
738 fputs("bindkey -N ", stdout);
739 if(n->nam[0] == '-')
740 fputs("-- ", stdout);
741 quotedzputs(n->nam, stdout);
742 } else
743 nicezputs(n->nam, stdout);
744 putchar('\n');
747 /* reset all keymaps to the default state */
749 /**/
750 static int
751 bin_bindkey_delall(UNUSED(char *name), UNUSED(char *kmname), UNUSED(Keymap km), UNUSED(char **argv), UNUSED(Options ops), UNUSED(char func))
753 keymapnamtab->emptytable(keymapnamtab);
754 default_bindings();
755 return 0;
758 /* delete named keymaps */
760 /**/
761 static int
762 bin_bindkey_del(char *name, UNUSED(char *kmname), UNUSED(Keymap km), char **argv, UNUSED(Options ops), UNUSED(char func))
764 int ret = 0;
766 do {
767 int r = unlinkkeymap(*argv, 0);
768 if(r == 1)
769 zwarnnam(name, "keymap name `%s' is protected", *argv);
770 else if(r == 2)
771 zwarnnam(name, "no such keymap `%s'", *argv);
772 ret |= !!r;
773 } while(*++argv);
774 return ret;
777 /* link named keymaps */
779 /**/
780 static int
781 bin_bindkey_link(char *name, UNUSED(char *kmname), Keymap km, char **argv, UNUSED(Options ops), UNUSED(char func))
783 km = openkeymap(argv[0]);
784 if(!km) {
785 zwarnnam(name, "no such keymap `%s'", argv[0]);
786 return 1;
787 } else if(linkkeymap(km, argv[1], 0)) {
788 zwarnnam(name, "keymap name `%s' is protected", argv[1]);
789 return 1;
791 return 0;
794 /* create a new keymap */
796 /**/
797 static int
798 bin_bindkey_new(char *name, UNUSED(char *kmname), Keymap km, char **argv, UNUSED(Options ops), UNUSED(char func))
800 KeymapName kmn = (KeymapName) keymapnamtab->getnode(keymapnamtab, argv[0]);
802 if(kmn && (kmn -> flags & KMN_IMMORTAL)) {
803 zwarnnam(name, "keymap name `%s' is protected", argv[0]);
804 return 1;
806 if(argv[1]) {
807 km = openkeymap(argv[1]);
808 if(!km) {
809 zwarnnam(name, "no such keymap `%s'", argv[0]);
810 return 1;
812 } else
813 km = NULL;
814 linkkeymap(newkeymap(km, argv[0]), argv[0], 0);
815 return 0;
818 /* Add standard meta bindings to a keymap. Only sequences currently either *
819 * unbound or bound to self-insert are affected. Note that the use of *
820 * bindkey() is quite necessary: if this function were to go through the *
821 * km->first table itself, it would miss any prefix sequences that should *
822 * be rebound. */
824 /**/
825 static int
826 bin_bindkey_meta(char *name, char *kmname, Keymap km, UNUSED(char **argv), UNUSED(Options ops), UNUSED(char func))
828 char m[3], *str;
829 int i;
830 Thingy fn;
832 if(km->flags & KM_IMMUTABLE) {
833 zwarnnam(name, "keymap `%s' is protected", kmname);
834 return 1;
836 #ifdef MULTIBYTE_SUPPORT
837 zwarnnam(name, "warning: `bindkey -m' disables multibyte support");
838 #endif
839 for(i = 128; i < 256; i++)
840 if(metabind[i - 128] != z_undefinedkey) {
841 m[0] = i;
842 metafy(m, 1, META_NOALLOC);
843 fn = keybind(km, m, &str);
844 if(fn == t_selfinsert || fn == t_undefinedkey)
845 bindkey(km, m, refthingy(Th(metabind[i - 128])), NULL);
847 return 0;
850 /* Change key bindings. func can be: *
851 * 'r' bind sequences to undefined-key *
852 * 's' bind sequneces to specified send-strings *
853 * 0 bind sequences to specified functions *
854 * If the -R option is used, bind to key ranges *
855 * instead of single key sequences. */
857 /**/
858 static int
859 bin_bindkey_bind(char *name, char *kmname, Keymap km, char **argv, Options ops, char func)
861 int ret = 0;
863 if(!func || func == 's') {
864 char **a;
866 for(a = argv+2; *a; a++)
867 if(!*++a) {
868 zwarnnam(name, "even number of arguments required");
869 return 1;
872 if(km->flags & KM_IMMUTABLE) {
873 zwarnnam(name, "keymap `%s' is protected", kmname);
874 return 1;
876 if (func == 'r' && OPT_ISSET(ops,'p')) {
877 char *useq, *bseq;
878 int len;
879 struct remprefstate rps;
880 rps.km = km;
881 while ((useq = *argv++)) {
882 bseq = getkeystring(useq, &len, GETKEYS_BINDKEY, NULL);
883 rps.prefix = metafy(bseq, len, META_USEHEAP);
884 rps.prefixlen = strlen(rps.prefix);
885 scankeymap(km, 0, scanremoveprefix, &rps);
887 return 0;
889 do {
890 char *useq = *argv, *bseq, *seq, *str;
891 int len;
892 Thingy fn;
894 if(func == 'r') {
895 fn = refthingy(t_undefinedkey);
896 str = NULL;
897 } else if(func == 's') {
898 str = getkeystring(*++argv, &len, GETKEYS_BINDKEY, NULL);
899 fn = NULL;
900 str = metafy(str, len, META_HREALLOC);
901 } else {
902 fn = rthingy(*++argv);
903 str = NULL;
905 bseq = getkeystring(useq, &len, GETKEYS_BINDKEY, NULL);
906 seq = metafy(bseq, len, META_USEHEAP);
907 if(OPT_ISSET(ops,'R')) {
908 int first, last;
909 char m[3];
911 if(len < 2 || len > 2 + (bseq[1] == '-') ||
912 (first = STOUC(bseq[0])) > (last = STOUC(bseq[len - 1]))) {
913 zwarnnam(name, "malformed key range `%s'", useq);
914 ret = 1;
915 } else {
916 for(; first <= last; first++) {
917 m[0] = first;
918 metafy(m, 1, META_NOALLOC);
919 bindkey(km, m, refthingy(fn), str);
922 unrefthingy(fn);
923 } else {
924 if(bindkey(km, seq, fn, str)) {
925 zwarnnam(name, "cannot bind to an empty key sequence");
926 unrefthingy(fn);
927 ret = 1;
930 } while(*++argv);
931 return ret;
934 /* Remove bindings for key sequences which have the given (proper) prefix. */
936 /**/
937 static void
938 scanremoveprefix(char *seq, UNUSED(Thingy bind), UNUSED(char *str), void *magic)
940 struct remprefstate *rps = magic;
942 if (strncmp(seq, rps->prefix, rps->prefixlen) || !seq[rps->prefixlen])
943 return;
945 bindkey(rps->km, seq, refthingy(t_undefinedkey), NULL);
948 /* List key bindings. If an argument is given, list just that one *
949 * binding, otherwise list the entire keymap. If the -L option is *
950 * given, list in the form of bindkey commands. */
952 /**/
953 static int
954 bin_bindkey_list(char *name, char *kmname, Keymap km, char **argv, Options ops, UNUSED(char func))
956 struct bindstate bs;
958 bs.flags = OPT_ISSET(ops,'L') ? BS_LIST : 0;
959 bs.kmname = kmname;
960 if(argv[0] && !OPT_ISSET(ops,'p')) {
961 int len;
962 char *seq;
964 seq = getkeystring(argv[0], &len, GETKEYS_BINDKEY, NULL);
965 seq = metafy(seq, len, META_HREALLOC);
966 bs.flags |= BS_ALL;
967 bs.firstseq = bs.lastseq = seq;
968 bs.bind = keybind(km, seq, &bs.str);
969 bs.prefix = NULL;
970 bs.prefixlen = 0;
971 bindlistout(&bs);
972 } else {
973 /* empty prefix is equivalent to no prefix */
974 if (OPT_ISSET(ops,'p') && (!argv[0] || argv[0][0])) {
975 if (!argv[0]) {
976 zwarnnam(name, "option -p requires a prefix string");
977 return 1;
979 bs.prefix = getkeystring(argv[0], &bs.prefixlen, GETKEYS_BINDKEY,
980 NULL);
981 bs.prefix = metafy(bs.prefix, bs.prefixlen, META_HREALLOC);
982 bs.prefixlen = strlen(bs.prefix);
983 } else {
984 bs.prefix = NULL;
985 bs.prefixlen = 0;
987 bs.firstseq = ztrdup("");
988 bs.lastseq = ztrdup("");
989 bs.bind = t_undefinedkey;
990 bs.str = NULL;
991 scankeymap(km, 1, scanbindlist, &bs);
992 bindlistout(&bs);
993 zsfree(bs.firstseq);
994 zsfree(bs.lastseq);
996 return 0;
999 /**/
1000 static void
1001 scanbindlist(char *seq, Thingy bind, char *str, void *magic)
1003 struct bindstate *bs = magic;
1005 if (bs->prefixlen &&
1006 (strncmp(seq, bs->prefix, bs->prefixlen) || !seq[bs->prefixlen]))
1007 return;
1009 if(bind == bs->bind && (bind || !strcmp(str, bs->str)) &&
1010 ztrlen(seq) == 1 && ztrlen(bs->lastseq) == 1) {
1011 int l = bs->lastseq[1] ?
1012 STOUC(bs->lastseq[1]) ^ 32 : STOUC(bs->lastseq[0]);
1013 int t = seq[1] ? STOUC(seq[1]) ^ 32 : STOUC(seq[0]);
1015 if(t == l + 1) {
1016 zsfree(bs->lastseq);
1017 bs->lastseq = ztrdup(seq);
1018 return;
1021 bindlistout(bs);
1022 zsfree(bs->firstseq);
1023 bs->firstseq = ztrdup(seq);
1024 zsfree(bs->lastseq);
1025 bs->lastseq = ztrdup(seq);
1026 bs->bind = bind;
1027 bs->str = str;
1030 /**/
1031 static void
1032 bindlistout(struct bindstate *bs)
1034 int range;
1036 if(bs->bind == t_undefinedkey && !(bs->flags & BS_ALL))
1037 return;
1038 range = strcmp(bs->firstseq, bs->lastseq);
1039 if(bs->flags & BS_LIST) {
1040 int nodash = 1;
1042 fputs("bindkey ", stdout);
1043 if(range)
1044 fputs("-R ", stdout);
1045 if(!bs->bind)
1046 fputs("-s ", stdout);
1047 if(!strcmp(bs->kmname, "main"))
1049 else if(!strcmp(bs->kmname, "vicmd"))
1050 fputs("-a ", stdout);
1051 else {
1052 fputs("-M ", stdout);
1053 quotedzputs(bs->kmname, stdout);
1054 putchar(' ');
1055 nodash = 0;
1057 if(nodash && bs->firstseq[0] == '-')
1058 fputs("-- ", stdout);
1060 printbind(bs->firstseq, stdout);
1061 if(range) {
1062 putchar('-');
1063 printbind(bs->lastseq, stdout);
1065 putchar(' ');
1066 if(bs->bind) {
1067 if (bs->flags & BS_LIST)
1068 quotedzputs(bs->bind->nam, stdout);
1069 else
1070 nicezputs(bs->bind->nam, stdout);
1071 } else
1072 printbind(bs->str, stdout);
1073 putchar('\n');
1076 /****************************/
1077 /* initialisation functions */
1078 /****************************/
1080 /* main initialisation entry point */
1082 /**/
1083 void
1084 init_keymaps(void)
1086 createkeymapnamtab();
1087 default_bindings();
1088 keybuf = (char *)zalloc(keybufsz);
1089 lastnamed = refthingy(t_undefinedkey);
1092 /* cleanup entry point (for unloading the zle module) */
1094 /**/
1095 void
1096 cleanup_keymaps(void)
1098 unrefthingy(lastnamed);
1099 deletehashtable(keymapnamtab);
1100 zfree(keybuf, keybufsz);
1103 static char *cursorptr;
1105 /* utility function for termcap output routine to add to string */
1107 static int
1108 add_cursor_char(int c)
1110 *cursorptr++ = c;
1111 return 0;
1114 /* interrogate termcap for cursor keys and add bindings to keymap */
1116 /**/
1117 static void
1118 add_cursor_key(Keymap km, int tccode, Thingy thingy, int defchar)
1120 char buf[2048];
1121 int ok = 0;
1124 * Be careful not to try too hard with bindings for dubious or
1125 * dysfunctional terminals.
1127 if (tccan(tccode) && !(termflags & (TERM_NOUP|TERM_BAD|TERM_UNKNOWN))) {
1129 * We can use the real termcap sequence. We need to
1130 * persuade termcap to output `move cursor 1 char' and capture it.
1132 cursorptr = buf;
1133 tputs(tcstr[tccode], 1, add_cursor_char);
1134 *cursorptr = '\0';
1137 * Sanity checking. If the cursor key is zero-length (unlikely,
1138 * but this is termcap we're talking about), or it's a single
1139 * character, then we don't bind it.
1141 if (buf[0] && buf[1] && (buf[0] != Meta || buf[2]))
1142 ok = 1;
1144 if (!ok) {
1145 /* Assume the normal VT100-like values. */
1146 sprintf(buf, "\33[%c", defchar);
1148 bindkey(km, buf, refthingy(thingy), NULL);
1151 * If the string looked like \e[? or \eO?, bind the other one, too.
1152 * This is necessary to make cursor keys work on many xterms with
1153 * both normal and application modes.
1155 if (buf[0] == '\33' && (buf[1] == '[' || buf[1] == 'O') &&
1156 buf[2] && !buf[3])
1158 buf[1] = (buf[1] == '[') ? 'O' : '[';
1159 bindkey(km, buf, refthingy(thingy), NULL);
1163 /* Create the default keymaps. For efficiency reasons, this function *
1164 * assigns directly to the km->first array. It knows that there are no *
1165 * prefix bindings in the way, and that it is using a simple keymap. */
1167 /**/
1168 static void
1169 default_bindings(void)
1171 Keymap vmap = newkeymap(NULL, "viins");
1172 Keymap emap = newkeymap(NULL, "emacs");
1173 Keymap amap = newkeymap(NULL, "vicmd");
1174 Keymap smap = newkeymap(NULL, ".safe");
1175 Keymap vimaps[2], kptr;
1176 char buf[3], *ed;
1177 int i;
1179 /* vi insert mode and emacs mode: *
1180 * 0-31 taken from the tables *
1181 * 32-126 self-insert *
1182 * 127 same as entry[8] *
1183 * 128-255 self-insert */
1184 for (i = 0; i < 32; i++) {
1185 vmap->first[i] = refthingy(Th(viinsbind[i]));
1186 emap->first[i] = refthingy(Th(emacsbind[i]));
1188 for (i = 32; i < 256; i++) {
1189 vmap->first[i] = refthingy(t_selfinsert);
1190 emap->first[i] = refthingy(t_selfinsert);
1192 unrefthingy(t_selfinsert);
1193 unrefthingy(t_selfinsert);
1194 vmap->first[127] = refthingy(vmap->first[8]);
1195 emap->first[127] = refthingy(emap->first[8]);
1197 /* vi command mode: *
1198 * 0-127 taken from the table *
1199 * 128-255 undefined-key */
1200 for (i = 0; i < 128; i++)
1201 amap->first[i] = refthingy(Th(vicmdbind[i]));
1202 for (i = 128; i < 256; i++)
1203 amap->first[i] = refthingy(t_undefinedkey);
1205 /* safe fallback keymap:
1206 * 0-255 self-insert, except: *
1207 * '\n' accept-line *
1208 * '\r' accept-line */
1209 for (i = 0; i < 256; i++)
1210 smap->first[i] = refthingy(t_selfinsert);
1211 unrefthingy(t_selfinsert);
1212 unrefthingy(t_selfinsert);
1213 smap->first['\n'] = refthingy(t_acceptline);
1214 smap->first['\r'] = refthingy(t_acceptline);
1216 /* vt100 arrow keys are bound by default, for historical reasons. *
1217 * Both standard and keypad modes are supported. */
1219 vimaps[0] = vmap;
1220 vimaps[1] = amap;
1221 for (i = 0; i < 2; i++) {
1222 kptr = vimaps[i];
1223 /* vi command and insert modes: arrow keys */
1224 add_cursor_key(kptr, TCUPCURSOR, t_uplineorhistory, 'A');
1225 add_cursor_key(kptr, TCDOWNCURSOR, t_downlineorhistory, 'B');
1226 add_cursor_key(kptr, TCLEFTCURSOR, t_vibackwardchar, 'D');
1227 add_cursor_key(kptr, TCRIGHTCURSOR, t_viforwardchar, 'C');
1230 /* emacs mode: arrow keys */
1231 add_cursor_key(emap, TCUPCURSOR, t_uplineorhistory, 'A');
1232 add_cursor_key(emap, TCDOWNCURSOR, t_downlineorhistory, 'B');
1233 add_cursor_key(emap, TCLEFTCURSOR, t_backwardchar, 'D');
1234 add_cursor_key(emap, TCRIGHTCURSOR, t_forwardchar, 'C');
1236 /* emacs mode: ^X sequences */
1237 bindkey(emap, "\30*", refthingy(t_expandword), NULL);
1238 bindkey(emap, "\30g", refthingy(t_listexpand), NULL);
1239 bindkey(emap, "\30G", refthingy(t_listexpand), NULL);
1240 bindkey(emap, "\30\16", refthingy(t_infernexthistory), NULL);
1241 bindkey(emap, "\30\13", refthingy(t_killbuffer), NULL);
1242 bindkey(emap, "\30\6", refthingy(t_vifindnextchar), NULL);
1243 bindkey(emap, "\30\17", refthingy(t_overwritemode), NULL);
1244 bindkey(emap, "\30\25", refthingy(t_undo), NULL);
1245 bindkey(emap, "\30\26", refthingy(t_vicmdmode), NULL);
1246 bindkey(emap, "\30\12", refthingy(t_vijoin), NULL);
1247 bindkey(emap, "\30\2", refthingy(t_vimatchbracket), NULL);
1248 bindkey(emap, "\30s", refthingy(t_historyincrementalsearchforward), NULL);
1249 bindkey(emap, "\30r", refthingy(t_historyincrementalsearchbackward), NULL);
1250 bindkey(emap, "\30u", refthingy(t_undo), NULL);
1251 bindkey(emap, "\30\30", refthingy(t_exchangepointandmark), NULL);
1252 bindkey(emap, "\30=", refthingy(t_whatcursorposition), NULL);
1254 /* emacs mode: ESC sequences, all taken from the meta binding table */
1255 buf[0] = '\33';
1256 buf[2] = 0;
1257 for (i = 0; i < 128; i++)
1258 if (metabind[i] != z_undefinedkey) {
1259 buf[1] = i;
1260 bindkey(emap, buf, refthingy(Th(metabind[i])), NULL);
1263 /* Put the keymaps in the right namespace. The "main" keymap *
1264 * will be linked to the "emacs" keymap, except that if VISUAL *
1265 * or EDITOR contain the string "vi" then it will be linked to *
1266 * the "viins" keymap. */
1267 linkkeymap(vmap, "viins", 0);
1268 linkkeymap(emap, "emacs", 0);
1269 linkkeymap(amap, "vicmd", 0);
1270 linkkeymap(smap, ".safe", 1);
1271 if (((ed = zgetenv("VISUAL")) && strstr(ed, "vi")) ||
1272 ((ed = zgetenv("EDITOR")) && strstr(ed, "vi")))
1273 linkkeymap(vmap, "main", 0);
1274 else
1275 linkkeymap(emap, "main", 0);
1277 /* the .safe map cannot be modified or deleted */
1278 smap->flags |= KM_IMMUTABLE;
1280 /* isearch keymap: initially empty */
1281 isearch_keymap = newkeymap(NULL, "isearch");
1282 linkkeymap(isearch_keymap, "isearch", 0);
1284 /* command keymap: make sure accept-line and send-break are bound */
1285 command_keymap = newkeymap(NULL, "command");
1286 command_keymap->first['\n'] = refthingy(t_acceptline);
1287 command_keymap->first['\r'] = refthingy(t_acceptline);
1288 command_keymap->first['G'&0x1F] = refthingy(t_sendbreak);
1289 linkkeymap(command_keymap, "command", 0);
1292 /*************************/
1293 /* reading key sequences */
1294 /*************************/
1296 /* read a sequence of keys that is bound to some command in a keymap */
1298 /**/
1299 char *
1300 getkeymapcmd(Keymap km, Thingy *funcp, char **strp)
1302 Thingy func = t_undefinedkey;
1303 char *str = NULL;
1304 int lastlen = 0, lastc = lastchar;
1306 keybuflen = 0;
1307 keybuf[0] = 0;
1309 * getkeybuf returns multibyte strings, which may not
1310 * yet correspond to complete wide characters, regardless
1311 * of the locale. This is because we can't be sure whether
1312 * the key bindings and keyboard input always return such
1313 * characters. So we always look up bindings for each
1314 * chunk of string. Intelligence within self-insert tries
1315 * to fix up insertion of real wide characters properly.
1317 * Note that this does not stop the user binding wide characters to
1318 * arbitrary functions, just so long as the string used in the
1319 * argument to bindkey is in the correct form for the locale.
1320 * That's beyond our control.
1322 while(getkeybuf(!!lastlen) != EOF) {
1323 char *s;
1324 Thingy f;
1325 int loc = !!localkeymap;
1326 int ispfx = 0;
1328 if (loc) {
1329 loc = ((f = keybind(localkeymap, keybuf, &s)) != t_undefinedkey);
1330 ispfx = keyisprefix(localkeymap, keybuf);
1332 if (!loc)
1333 f = keybind(km, keybuf, &s);
1334 ispfx |= keyisprefix(km, keybuf);
1336 if (f != t_undefinedkey) {
1337 lastlen = keybuflen;
1338 func = f;
1339 str = s;
1340 lastc = lastchar;
1342 if (!ispfx)
1343 break;
1345 if(!lastlen && keybuflen)
1346 lastlen = keybuflen;
1347 else
1348 lastchar = lastc;
1349 if(lastlen != keybuflen) {
1350 unmetafy(keybuf + lastlen, &keybuflen);
1351 ungetbytes(keybuf+lastlen, keybuflen);
1352 if(vichgflag)
1353 vichgbufptr -= keybuflen;
1354 keybuf[lastlen] = 0;
1356 *funcp = func;
1357 *strp = str;
1358 return keybuf;
1362 * Add a (possibly metafied) byte to the key input so far.
1363 * This handles individual bytes of a multibyte string separately;
1364 * see note in getkeymapcmd. Hence there is no wide character
1365 * support at this level.
1367 * TODO: Need to be careful about whether we return EOF in the
1368 * middle of a wide character. However, I think we're OK since
1369 * EOF and 0xff are distinct and we're reading bytes from the
1370 * lower level, so EOF really does mean something went wrong. Even so,
1371 * I'm worried enough to leave this note here for now.
1374 /**/
1375 static int
1376 getkeybuf(int w)
1378 int c = getbyte((long)w, NULL);
1380 if(c < 0)
1381 return EOF;
1382 if(keybuflen + 3 > keybufsz)
1383 keybuf = realloc(keybuf, keybufsz *= 2);
1384 if(imeta(c)) {
1385 keybuf[keybuflen++] = Meta;
1386 keybuf[keybuflen++] = c ^ 32;
1387 } else
1388 keybuf[keybuflen++] = c;
1389 keybuf[keybuflen] = 0;
1390 return c;
1393 /* Push back the last command sequence read by getkeymapcmd(). *
1394 * Must be executed at most once after each getkeymapcmd(). */
1396 /**/
1397 mod_export void
1398 ungetkeycmd(void)
1400 ungetbytes(keybuf, keybuflen);
1403 /* read a command from the current keymap, with widgets */
1405 /**/
1406 mod_export Thingy
1407 getkeycmd(void)
1409 Thingy func;
1410 int hops = 0;
1411 char *seq, *str;
1413 sentstring:
1414 seq = getkeymapcmd(curkeymap, &func, &str);
1415 if(!*seq)
1416 return NULL;
1417 if(!func) {
1418 int len;
1419 char *pb;
1421 if (++hops == 20) {
1422 zerr("string inserting another one too many times");
1423 hops = 0;
1424 return NULL;
1426 pb = unmetafy(ztrdup(str), &len);
1427 ungetbytes(pb, len);
1428 zfree(pb, strlen(str) + 1);
1429 goto sentstring;
1431 if (func == Th(z_executenamedcmd) && !statusline) {
1432 while(func == Th(z_executenamedcmd))
1433 func = executenamedcommand("execute: ");
1434 if(!func)
1435 func = t_undefinedkey;
1436 else if(func != Th(z_executelastnamedcmd)) {
1437 unrefthingy(lastnamed);
1438 lastnamed = refthingy(func);
1441 if (func == Th(z_executelastnamedcmd))
1442 func = lastnamed;
1443 return func;
1446 /**/
1447 mod_export void
1448 zlesetkeymap(int mode)
1450 Keymap km = openkeymap((mode == VIMODE) ? "viins" : "emacs");
1451 if (!km)
1452 return;
1453 linkkeymap(km, "main", 0);
1456 /**/
1457 mod_export int
1458 readcommand(UNUSED(char **args))
1460 Thingy thingy = getkeycmd();
1462 if (!thingy)
1463 return 1;
1465 setsparam("REPLY", ztrdup(thingy->nam));
1466 return 0;