From c925a15aa7e0e181e997df078ce06c9b3ce29857 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 13 Mar 2001 15:32:41 +0000 Subject: 13611, 13615: Bind cursor keys using termcap, including in viins. --- ChangeLog | 7 +++++ Doc/Zsh/zle.yo | 18 ++++++++--- Src/Zle/zle_keymap.c | 86 ++++++++++++++++++++++++++++++++++++++++------------ Src/init.c | 3 +- Src/zsh.h | 6 +++- 5 files changed, 95 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2c245ceb9..2892a2307 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2001-03-13 Peter Stephenson + + * 13611, 13615: Doc/Zsh/zle.yo, Src/init.c, Src/zsh.h, + Src/Zle/zle_keymap.c: Use termcap to find cursor sequences to + bind; default to VT100. If ^[[? or ^[O? is being bound, bind + the other one too. Also bind cursor keys in viins keymap. + 2001-03-12 Oliver Kiddle * 13610: INSTALL, README, Completion/Core/compinit, diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 02a828c4f..e0c13da72 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -201,6 +201,16 @@ The following is a list of all the standard widgets, and their default bindings in emacs mode, vi command mode and vi insert mode (the `tt(emacs)', `tt(vicmd)' and `tt(viins)' keymaps, respectively). + +Note that cursor keys are bound to movement keys in all three keymaps; +the shell assumes that the cursor keys send the key sequences reported +by the terminal-handling library (termcap or terminfo). The key sequences +shown in the list are those based on the VT100, common on many modern +terminals, but in fact these are not necessarily bound. In the case of the +tt(viins) keymap, the initial escape character of the sequences serves also +to return to the tt(vicmd) keymap: whether this happens is determined by +the tt(KEYTIMEOUT) parameter, see ifzman(zmanref(zshparam))\ +ifnzman(noderef(Parameters)). startmenu() menu(Movement) menu(History Control) @@ -222,7 +232,7 @@ item(tt(backward-char) (^B ESC-[D) (unbound) (unbound))( Move backward one character. ) tindex(vi-backward-char) -item(tt(vi-backward-char) (unbound) (^H h ^?) (unbound))( +item(tt(vi-backward-char) (unbound) (^H h ^?) (ESC-[D))( Move backward one character, without changing lines. ) tindex(backward-word) @@ -273,7 +283,7 @@ item(tt(forward-char) (^F ESC-[C) (unbound) (unbound))( Move forward one character. ) tindex(vi-forward-char) -item(tt(vi-forward-char) (unbound) (space l) (unbound))( +item(tt(vi-forward-char) (unbound) (space l) (ESC-[C))( Move forward one character. ) tindex(vi-find-next-char) @@ -357,7 +367,7 @@ item(tt(beginning-of-history))( Move to the first event in the history list. ) tindex(down-line-or-history) -item(tt(down-line-or-history) (^N ESC-[B) (j) (unbound))( +item(tt(down-line-or-history) (^N ESC-[B) (j) (ESC-[B))( Move down a line in the buffer, or if already at the bottom line, move to the next event in the history list. ) @@ -546,7 +556,7 @@ item(tt(vi-rev-repeat-search) (unbound) (N) (unbound))( Repeat the last vi history search, but in reverse. ) tindex(up-line-or-history) -item(tt(up-line-or-history) (^P ESC-[A) (k) (unbound))( +item(tt(up-line-or-history) (^P ESC-[A) (k) (ESC-[A))( Move up a line in the buffer, or if already at the top line, move to the previous event in the history list. ) diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index 28203655e..b46c74f91 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -1011,6 +1011,56 @@ cleanup_keymaps(void) zfree(keybuf, keybufsz); } +static char *cursorptr; + +/* utility function for termcap output routine to add to string */ + +static int +add_cursor_char(int c) +{ + *cursorptr++ = c; + return 0; +} + +/* interrogate termcap for cursor keys and add bindings to keymap */ + +/**/ +static void +add_cursor_key(Keymap km, int tccode, Thingy thingy, int defchar) +{ + char buf[2048]; + + /* + * Be careful not to try too hard with bindings for dubious or + * dysfunctional terminals. + */ + if (tccan(tccode) && !(termflags & (TERM_NOUP|TERM_BAD|TERM_UNKNOWN))) { + /* + * We can use the real termcap sequence. We need to + * persuade termcap to output `move cursor 1 char' and capture it. + */ + cursorptr = buf; + tputs(tcstr[tccode], 1, add_cursor_char); + *cursorptr = '\0'; + } else { + /* Assume the normal VT100-like values. */ + sprintf(buf, "\33[%c", defchar); + } + bindkey(km, buf, refthingy(thingy), NULL); + + /* + * If the string looked like \e[? or \eO?, bind the other one, too. + * This is necessary to make cursor keys work on many xterms with + * both normal and application modes. + */ + if (buf[0] == '\33' && (buf[1] == '[' || buf[1] == 'O') && + buf[2] && !buf[3]) + { + buf[1] = (buf[1] == '[') ? 'O' : '['; + bindkey(km, buf, refthingy(thingy), NULL); + } +} + /* Create the default keymaps. For efficiency reasons, this function * * assigns directly to the km->first array. It knows that there are no * * prefix bindings in the way, and that it is using a simple keymap. */ @@ -1023,6 +1073,7 @@ default_bindings(void) Keymap emap = newkeymap(NULL, "emacs"); Keymap amap = newkeymap(NULL, "vicmd"); Keymap smap = newkeymap(NULL, ".safe"); + Keymap vimaps[2], kptr; char buf[3], *ed; int i; @@ -1066,25 +1117,22 @@ default_bindings(void) /* vt100 arrow keys are bound by default, for historical reasons. * * Both standard and keypad modes are supported. */ - /* vi command mode: arrow keys */ - bindkey(amap, "\33[A", refthingy(t_uplineorhistory), NULL); - bindkey(amap, "\33[B", refthingy(t_downlineorhistory), NULL); - bindkey(amap, "\33[C", refthingy(t_viforwardchar), NULL); - bindkey(amap, "\33[D", refthingy(t_vibackwardchar), NULL); - bindkey(amap, "\33OA", refthingy(t_uplineorhistory), NULL); - bindkey(amap, "\33OB", refthingy(t_downlineorhistory), NULL); - bindkey(amap, "\33OC", refthingy(t_viforwardchar), NULL); - bindkey(amap, "\33OD", refthingy(t_vibackwardchar), NULL); - - /* emacs mode: arrow keys */ - bindkey(emap, "\33[A", refthingy(t_uplineorhistory), NULL); - bindkey(emap, "\33[B", refthingy(t_downlineorhistory), NULL); - bindkey(emap, "\33[C", refthingy(t_forwardchar), NULL); - bindkey(emap, "\33[D", refthingy(t_backwardchar), NULL); - bindkey(emap, "\33OA", refthingy(t_uplineorhistory), NULL); - bindkey(emap, "\33OB", refthingy(t_downlineorhistory), NULL); - bindkey(emap, "\33OC", refthingy(t_forwardchar), NULL); - bindkey(emap, "\33OD", refthingy(t_backwardchar), NULL); + vimaps[0] = vmap; + vimaps[1] = amap; + for (i = 0; i < 2; i++) { + kptr = vimaps[i]; + /* vi command and insert modes: arrow keys */ + add_cursor_key(kptr, TCUPCURSOR, t_uplineorhistory, 'A'); + add_cursor_key(kptr, TCDOWNCURSOR, t_downlineorhistory, 'B'); + add_cursor_key(kptr, TCLEFTCURSOR, t_vibackwardchar, 'D'); + add_cursor_key(kptr, TCRIGHTCURSOR, t_viforwardchar, 'C'); + } + + /* emacs mode: arrow keys */ + add_cursor_key(emap, TCUPCURSOR, t_uplineorhistory, 'A'); + add_cursor_key(emap, TCDOWNCURSOR, t_downlineorhistory, 'B'); + add_cursor_key(emap, TCLEFTCURSOR, t_backwardchar, 'D'); + add_cursor_key(emap, TCRIGHTCURSOR, t_forwardchar, 'C'); /* emacs mode: ^X sequences */ bindkey(emap, "\30*", refthingy(t_expandword), NULL); diff --git a/Src/init.c b/Src/init.c index b07ac80d5..a0c06aa63 100644 --- a/Src/init.c +++ b/Src/init.c @@ -497,7 +497,8 @@ init_shout(void) static char *tccapnams[TC_COUNT] = { "cl", "le", "LE", "nd", "RI", "up", "UP", "do", "DO", "dc", "DC", "ic", "IC", "cd", "ce", "al", "dl", "ta", - "md", "so", "us", "me", "se", "ue", "ch" + "md", "so", "us", "me", "se", "ue", "ch", + "ku", "kd", "kl", "kr" }; /* Initialise termcap */ diff --git a/Src/zsh.h b/Src/zsh.h index baafdb0e6..315c1d3bd 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1524,7 +1524,11 @@ struct ttyinfo { #define TCSTANDOUTEND 22 #define TCUNDERLINEEND 23 #define TCHORIZPOS 24 -#define TC_COUNT 25 +#define TCUPCURSOR 25 +#define TCDOWNCURSOR 26 +#define TCLEFTCURSOR 27 +#define TCRIGHTCURSOR 28 +#define TC_COUNT 29 #define tccan(X) (tclen[X]) -- cgit 1.4.1