diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | Doc/Zsh/contrib.yo | 27 | ||||
-rw-r--r-- | Doc/Zsh/zle.yo | 12 | ||||
-rw-r--r-- | Functions/Misc/zed | 33 | ||||
-rw-r--r-- | Src/Zle/zle_keymap.c | 21 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 133 |
6 files changed, 147 insertions, 86 deletions
diff --git a/ChangeLog b/ChangeLog index c2223ad1b..a96d5da92 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2004-04-06 Peter Stephenson <pws@csr.com> + + * 19733 (with improved documentation): Doc/Zsh/contrib.yo, + Doc/Zsh/zle.yo, Functions/Misc/zed, Src/Zle/zle_keymap.c, + Src/Zle/zle_main.c: vared -M and -m allow you to provide + main and alternate keymap; zed will use keymaps zed and zed-vicmd. + 2004-04-05 Peter Stephenson <pws@csr.com> * 19728: Doc/Zsh/expn.yo: explain that (^F) (from 19717) diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 2648fd6c8..56eb62cfb 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1312,12 +1312,7 @@ See the comments in the function for a few extra tips. ) findex(zed) item(tt(zed) [ tt(-f) ] var(name))( -This function uses the ZLE editor to edit a file or function. It rebinds -the return key to insert a line break, and adds bindings for `tt(^X^W)' in -the tt(emacs) keymap and `tt(ZZ)' in the tt(vicmd) keymap to accept (and -therefore write, in the case of a file) the edited file or function. -Keybindings are otherwise the standard ones; completion is available, and -styles may be set with the context prefix `tt(:completion:zed)'. +This function uses the ZLE editor to edit a file or function. Only one var(name) argument is recognized (additional arguments are ignored). If the tt(-f) option is given, the name is taken to be that of @@ -1328,6 +1323,26 @@ autoload file. Without tt(-f), var(name) is the path name of the file to edit, which need not exist; it is created on write, if necessary. + +While editing, the function sets the main keymap to tt(zed) and the +vi command keymap to tt(zed-vicmd). These will be copied from the existing +tt(main) and tt(vicmd) keymaps if they do not exist the first time tt(zed) +is run. They can be used to provide special key bindings used only in zed. + +If it creates the keymap, tt(zed) rebinds the return key to insert a line +break and `tt(^X^W)' to accept the edit in the tt(zed) keymap, and binds +`tt(ZZ)' to accept the edit in the tt(zed-vicmd) keymap. If the tt(zed) +keymap is created by hand, the user will need to bind: + +example(zle -M zed '^M' self-insert-unmeta +zle -M zed '^X^W' accept-line) + +for this behaviour, and if tt(zed-vicmd) is created by hand, + +example(zle -M zed-vicmd 'ZZ' accept-line) + +Completion is available, and styles may be set with the context prefix +`tt(:completion:zed)'. ) findex(zcp) findex(zln) diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 0ebbb2739..2976cc6b5 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -265,7 +265,8 @@ by `tt(bindkey -m)'. findex(vared) cindex(parameters, editing) cindex(editing parameters) -item(tt(vared) [ tt(-Aache) ] [ tt(-p) var(prompt) ] [ tt(-r) var(rprompt) ] var(name))( +xitem(tt(vared) [ tt(-Aache) ] [ tt(-p) var(prompt) ] [ tt(-r) var(rprompt) ]) +item( [ -M var(main-keymap) ] [ -m var(vicmd-keymap) ] var(name))( The value of the parameter var(name) is loaded into the edit buffer, and the line editor is invoked. When the editor exits, var(name) is set to the string value returned by the editor. @@ -289,9 +290,16 @@ created automatically, even without tt(-c). If the tt(-p) flag is given, the following string will be taken as the prompt to display at the left. If the tt(-r) flag is given, the following string gives the prompt to display at the right. If the -tt(-h) flag is specified, the history can be accessed from ZLE. If the +tt(-h) flag is specified, the history can be accessed from ZLE. If the tt(-e) flag is given, typing tt(^D) (Control-D) on an empty line causes tt(vared) to exit immediately with a non-zero return value. + +The tt(-M) option gives a keymap to link to the tt(main) keymap during +editing, and the tt(-m) option gives a keymap to link to the tt(vicmd) +keymap during editing. For vi-style editing, this allows a pair of keymaps +to override tt(viins) and tt(vicmd). For emacs-style editing, only tt(-M) +is normally needed but the tt(-m) option may still be used. On exit, the +previous keymaps will be restored. ) findex(zle) cindex(widgets, rebinding) diff --git a/Functions/Misc/zed b/Functions/Misc/zed index 3cee176a1..eef8ee218 100644 --- a/Functions/Misc/zed +++ b/Functions/Misc/zed @@ -10,7 +10,7 @@ # compctl -f -x 'w[1,-f]' -F -- zed # -local var fun cleanup +local var fun # We do not want timeout while we are editing a file integer TMOUT=0 @@ -24,20 +24,27 @@ local curcontext=zed::: zstyle -m ":completion:zed:*" insert-tab '*' || zstyle ":completion:zed:*" insert-tab yes -# catch interrupts -cleanup="$(bindkey -L "^M"; bindkey -L -M emacs "^X^W"; bindkey -aL "ZZ" - echo "trap - INT EXIT"; trap)" -trap "return 130" INT -trap "$cleanup" EXIT +if ! bindkey -M zed >&/dev/null; then + # Make the zed keymap a copy of the current main. + bindkey -N zed main + + # Assign some default keys. + # Depending on your stty's, you may be able to use ^J as accept-line, else: + + # The following isn't useful if we are copying viins, but that's + # a nicety. + bindkey -M zed '^x^w' accept-line + bindkey -M zed '^M' self-insert-unmeta +fi +if ! bindkey -M zed-vicmd >&/dev/null; then + bindkey -N zed-vicmd vicmd + + bindkey -M zed-vicmd "ZZ" accept-line +fi # don't mangle !'s setopt localoptions nobanghist -bindkey "^M" self-insert-unmeta -# Depending on your stty's, you may be able to use ^J as accept-line, else: -bindkey -M emacs "^X^W" accept-line -bindkey -a "ZZ" accept-line - if ((fun)) then var="$(functions $1)" # If function is undefined but autoloadable, load it @@ -55,10 +62,10 @@ $(<$dir/$1) var="$1() { }" fi - vared var && eval "$cleanup ;" function "$var" + vared -M zed -m zed-vicmd var && eval function "$var" else [[ -f $1 ]] && var="$(<$1)" - while vared var + while vared -M zed -m zed-vicmd var do (print -r -- "$var" >| $1) && break echo -n -e '\a' diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index f28dec775..7e5fd02ee 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -169,8 +169,7 @@ freekeymapnamnode(HashNode hn) KeymapName kmn = (KeymapName) hn; zsfree(kmn->nam); - if(!--kmn->keymap->rc) - deletekeymap(kmn->keymap); + unrefkeymap(kmn->keymap); zfree(kmn, sizeof(*kmn)); } @@ -355,8 +354,7 @@ linkkeymap(Keymap km, char *name, int imm) return 1; if(n->keymap == km) return 0; - if(!--n->keymap->rc) - deletekeymap(n->keymap); + unrefkeymap(n->keymap); n->keymap = km; } else { n = makekeymapnamnode(km); @@ -364,10 +362,23 @@ linkkeymap(Keymap km, char *name, int imm) n->flags |= KMN_IMMORTAL; keymapnamtab->addnode(keymapnamtab, ztrdup(name), n); } - km->rc++; + refkeymap(km); return 0; } +/**/ +void refkeymap(Keymap km) +{ + km->rc++; +} + +/**/ +void unrefkeymap(Keymap km) +{ + if (!--km->rc) + deletekeymap(km); +} + /* Select a keymap as the current ZLE keymap. Can optionally fall back * * on the guaranteed safe keymap if it fails. */ diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 38552cef4..0e1b2983a 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -987,6 +987,45 @@ handleprefixes(void) initmodifier(&zmod); } +/**/ +static int +savekeymap(char *cmdname, char *oldname, char *newname, Keymap *savemapptr) +{ + Keymap km = openkeymap(newname); + + if (km) { + *savemapptr = openkeymap(oldname); + /* I love special cases */ + if (*savemapptr == km) + *savemapptr = NULL; + else { + /* make sure this doesn't get deleted. */ + if (*savemapptr) + refkeymap(*savemapptr); + linkkeymap(km, oldname, 0); + } + return 0; + } else { + zwarnnam(cmdname, "no such keymap: %s", newname, 0); + return 1; + } +} + +/**/ +static void +restorekeymap(char *cmdname, char *oldname, char *newname, Keymap savemap) +{ + if (savemap) { + linkkeymap(savemap, oldname, 0); + /* we incremented the reference count above */ + unrefkeymap(savemap); + } else if (newname) { + /* urr... can this happen? */ + zwarnnam(cmdname, + "keymap %s was not defined, not restored", oldname, 0); + } +} + /* this exports the argument we are currently vared'iting if != NULL */ /**/ @@ -1002,9 +1041,10 @@ bin_vared(char *name, char **args, Options ops, int func) struct value vbuf; Value v; Param pm = 0; - int create = 0, ifl; + int ifl; int type = PM_SCALAR, obreaks = breaks, haso = 0; - char *p1 = NULL, *p2 = NULL; + char *p1, *p2, *main_keymapname, *vicmd_keymapname; + Keymap main_keymapsave = NULL, vicmd_keymapsave = NULL; FILE *oshout = NULL; if ((interact && unset(USEZLE)) || !strcmp(term, "emacs")) { @@ -1016,61 +1056,23 @@ bin_vared(char *name, char **args, Options ops, int func) return 1; } - /* all options are handled as arguments */ - while (*args && **args == '-') { - while (*++(*args)) - switch (**args) { - case 'c': - /* -c option -- allow creation of the parameter if it doesn't - yet exist */ - create = 1; - break; - case 'a': - type = PM_ARRAY; - break; - case 'A': - type = PM_HASHED; - break; - case 'p': - /* -p option -- set main prompt string */ - if ((*args)[1]) - p1 = *args + 1, *args = "" - 1; - else if (args[1]) - p1 = *(++args), *args = "" - 1; - else { - zwarnnam(name, "prompt string expected after -%c", NULL, - **args); - return 1; - } - break; - case 'r': - /* -r option -- set right prompt string */ - if ((*args)[1]) - p2 = *args + 1, *args = "" - 1; - else if (args[1]) - p2 = *(++args), *args = "" - 1; - else { - zwarnnam(name, "prompt string expected after -%c", NULL, - **args); - return 1; - } - break; - case 'h': - /* -h option -- enable history */ - ops->ind['h'] = 1; - break; - case 'e': - /* -e option -- enable EOF */ - ops->ind['e'] = 1; - break; - default: - /* unrecognised option character */ - zwarnnam(name, "unknown option: %s", *args, 0); - return 1; - } - args++; + if (OPT_ISSET(ops,'A')) + { + if (OPT_ISSET(ops, 'a')) + { + zwarnnam(name, "specify only one of -a and -A", NULL, 0); + return 1; + } + type = PM_HASHED; } - if (type && !create) { + else if (OPT_ISSET(ops,'a')) + type = PM_ARRAY; + p1 = OPT_ARG_SAFE(ops,'p'); + p2 = OPT_ARG_SAFE(ops,'r'); + main_keymapname = OPT_ARG_SAFE(ops,'M'); + vicmd_keymapname = OPT_ARG_SAFE(ops,'m'); + + if (type != PM_SCALAR && !OPT_ISSET(ops,'c')) { zwarnnam(name, "-%s ignored", type == PM_ARRAY ? "a" : "A", 0); } @@ -1082,9 +1084,9 @@ bin_vared(char *name, char **args, Options ops, int func) /* handle non-existent parameter */ s = args[0]; queue_signals(); - v = fetchvalue(&vbuf, &s, (!create || type == PM_SCALAR), + v = fetchvalue(&vbuf, &s, (!OPT_ISSET(ops,'c') || type == PM_SCALAR), SCANPM_WANTKEYS|SCANPM_WANTVALS|SCANPM_MATCHMANY); - if (!v && !create) { + if (!v && !OPT_ISSET(ops,'c')) { unqueue_signals(); zwarnnam(name, "no such variable: %s", args[0], 0); return 1; @@ -1156,6 +1158,13 @@ bin_vared(char *name, char **args, Options ops, int func) /* edit the parameter value */ zpushnode(bufstack, s); + if (main_keymapname && + savekeymap(name, "main", main_keymapname, &main_keymapsave)) + main_keymapname = NULL; + if (vicmd_keymapname && + savekeymap(name, "vicmd", vicmd_keymapname, &vicmd_keymapsave)) + vicmd_keymapname = NULL; + varedarg = *args; ifl = isfirstln; if (OPT_ISSET(ops,'h')) @@ -1167,6 +1176,10 @@ bin_vared(char *name, char **args, Options ops, int func) hend(NULL); isfirstln = ifl; varedarg = ova; + + restorekeymap(name, "main", main_keymapname, main_keymapsave); + restorekeymap(name, "vicmd", vicmd_keymapname, vicmd_keymapsave); + if (haso) { fclose(shout); /* close(SHTTY) */ shout = oshout; @@ -1182,7 +1195,7 @@ bin_vared(char *name, char **args, Options ops, int func) if (t[strlen(t) - 1] == '\n') t[strlen(t) - 1] = '\0'; /* final assignment of parameter value */ - if (create) { + if (OPT_ISSET(ops,'c')) { unsetparam(args[0]); createparam(args[0], type); } @@ -1353,7 +1366,7 @@ zleaftertrap(Hookdef dummy, void *dat) static struct builtin bintab[] = { BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaM:ldDANmrsLRp", NULL), - BUILTIN("vared", 0, bin_vared, 1, 7, 0, NULL, NULL), + BUILTIN("vared", 0, bin_vared, 1, 7, 0, "aAchM:m:p:r:", NULL), BUILTIN("zle", 0, bin_zle, 0, -1, 0, "aAcCDFgGIKlLmMNRU", NULL), }; |