From 005513f8fa5235230da88b74cc38886ef22cfc5b Mon Sep 17 00:00:00 2001 From: christos Date: Thu, 13 Aug 2015 08:55:30 +0000 Subject: [PATCH 1/7] Fix the word boundary handling of vi-eword (which uses c_eword()) to be consistent with c_next_word() when VImode is set in the latter, using the word class definition from c_to_class(). Previously c_eword() used isword() which honors $wordchars. (Luke Mewburn) --- ed.chared.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/ed.chared.c b/ed.chared.c index c0bd41b..fc62bc5 100644 --- a/ed.chared.c +++ b/ed.chared.c @@ -290,7 +290,7 @@ c_preword(Char *p, Char *low, int n, Char *delim) /* * c_to_class() returns the class of the given character. * - * This is used to make the c_prev_word() and c_next_word() functions + * This is used to make the c_prev_word(), c_next_word() and c_eword() functions * work like vi's, which classify characters. A word is a sequence of * characters belonging to the same class, classes being defined as * follows: @@ -828,15 +828,24 @@ c_eword(Char *p, Char *high, int n) p++; while (n--) { - while ((p < high) && Isspace(*p)) - p++; + int c_class; - if (isword(*p)) - while ((p < high) && isword(*p)) - p++; - else - while ((p < high) && !(Isspace(*p) || isword(*p))) - p++; + if (p >= high) + break; + + /* scan until end of current word (may be all whitespace!) */ + c_class = c_to_class(*p); + while ((p < high) && c_class == c_to_class(*p)) + p++; + + /* if this was a non_whitespace word, we're ready */ + if (c_class != C_CLASS_WHITE) + continue; + + /* otherwise, move to the end of the word just found */ + c_class = c_to_class(*p); + while ((p < high) && c_class == c_to_class(*p)) + p++; } p--; -- 2.5.5 From c7619a43032fcc923382a540a364232ce1a92103 Mon Sep 17 00:00:00 2001 From: christos Date: Thu, 13 Aug 2015 09:04:07 +0000 Subject: [PATCH 2/7] Provide shell variable $vimode to control VImode. Set by bindkey -v Unset by bindkey -e If explicitly set or unset by the user, changes VImode appropriately. (Luke Mewburn) --- Fixes | 1 + ed.defns.c | 4 ++++ sh.set.c | 5 +++++ tc.const.c | 1 + 4 files changed, 11 insertions(+) diff --git a/Fixes b/Fixes index 811e67c..71e2c72 100644 --- a/Fixes +++ b/Fixes @@ -1,3 +1,4 @@ + 6. expose VImode in $vimode (Luke Mewburn) 5. display what the compiled in editor is in bindkey -d (Luke Mewburn) 4. run-fg-editor improvements and documentation (Luke Mewburn) 3. Fix parsing of 'if (cond)then' (Fridolin Pokorny) diff --git a/ed.defns.c b/ed.defns.c index c3de4be..ff4202f 100644 --- a/ed.defns.c +++ b/ed.defns.c @@ -1889,6 +1889,7 @@ ed_InitVIMaps(void) int i; VImode = 1; + setNS(STRvimode); ResetXmap(); for (i = 0; i < NT_NUM_KEYS; i++) { CcKeyMap[i] = CcViMap[i]; @@ -1910,6 +1911,9 @@ ed_InitEmacsMaps(void) cstr.len = 2; VImode = 0; + if (adrof(STRvimode)) + unsetv(STRvimode); + ResetXmap(); for (i = 0; i < NT_NUM_KEYS; i++) { CcKeyMap[i] = CcEmacsMap[i]; diff --git a/sh.set.c b/sh.set.c index 1a19713..abb0236 100644 --- a/sh.set.c +++ b/sh.set.c @@ -165,6 +165,9 @@ update_vars(Char *vp) noediting = 0; /* PWP: add more stuff in here later */ } + else if (eq(vp, STRvimode)) { + VImode = 1; + } else if (eq(vp, STRshlvl)) { tsetenv(STRKSHLVL, varval(vp)); } @@ -792,6 +795,8 @@ unset(Char **v, struct command *c) SetKillRing(0); if (did_edit && noediting && adrof(STRedit) == 0) noediting = 0; + if (adrof(STRvimode) == 0) + VImode = 0; if (did_roe && adrof(STRrecognize_only_executables) == 0) tw_cmd_free(); if (adrof(STRhistory) == 0) diff --git a/tc.const.c b/tc.const.c index f4969ff..06ddd2b 100644 --- a/tc.const.c +++ b/tc.const.c @@ -86,6 +86,7 @@ Char STRMACHTYPE[] = { 'M', 'A', 'C', 'H', 'T', 'Y', 'P', 'E', '\0' }; Char STROSTYPE[] = { 'O', 'S', 'T', 'Y', 'P', 'E', '\0' }; Char STRedit[] = { 'e', 'd', 'i', 't', '\0' }; Char STReditors[] = { 'e', 'd', 'i', 't', 'o', 'r', 's', '\0' }; +Char STRvimode[] = { 'v', 'i', 'm', 'o', 'd', 'e', '\0' }; Char STRaddsuffix[] = { 'a', 'd', 'd', 's', 'u', 'f', 'f', 'i', 'x', '\0' }; Char STRcsubstnonl[] = { 'c', 's', 'u', 'b', 's', 't', 'n', 'o', 'n', 'l', -- 2.5.5 From 8a6d8efbc62e4d52d4121015c5eb97934b687ee2 Mon Sep 17 00:00:00 2001 From: christos Date: Thu, 13 Aug 2015 09:05:21 +0000 Subject: [PATCH 3/7] If VImode=1, use "_" as the default for $wordchars, to match vi's default. Provide a separate STR_WORD_CHARS_VI global for the default for vi. Provide update_wordchars() to be called if VImode is changed to change word_char if necessary. --- Fixes | 1 + ed.defns.c | 3 +++ sh.c | 1 + sh.decls.h | 1 + sh.h | 7 +++++-- sh.set.c | 10 ++++++++++ 6 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Fixes b/Fixes index 71e2c72..0481286 100644 --- a/Fixes +++ b/Fixes @@ -1,3 +1,4 @@ + 7. more correct $wordchars for vimode (Luke Mewburn) 6. expose VImode in $vimode (Luke Mewburn) 5. display what the compiled in editor is in bindkey -d (Luke Mewburn) 4. run-fg-editor improvements and documentation (Luke Mewburn) diff --git a/ed.defns.c b/ed.defns.c index ff4202f..2b2abff 100644 --- a/ed.defns.c +++ b/ed.defns.c @@ -1890,6 +1890,8 @@ ed_InitVIMaps(void) VImode = 1; setNS(STRvimode); + update_wordchars(); + ResetXmap(); for (i = 0; i < NT_NUM_KEYS; i++) { CcKeyMap[i] = CcViMap[i]; @@ -1913,6 +1915,7 @@ ed_InitEmacsMaps(void) VImode = 0; if (adrof(STRvimode)) unsetv(STRvimode); + update_wordchars(); ResetXmap(); for (i = 0; i < NT_NUM_KEYS; i++) { diff --git a/sh.c b/sh.c index b941bf7..8d219d3 100644 --- a/sh.c +++ b/sh.c @@ -345,6 +345,7 @@ main(int argc, char **argv) # endif #endif STR_WORD_CHARS = SAVE(WORD_CHARS); + STR_WORD_CHARS_VI = SAVE(WORD_CHARS_VI); HIST = '!'; HISTSUB = '^'; diff --git a/sh.decls.h b/sh.decls.h index 2c29732..78bbed9 100644 --- a/sh.decls.h +++ b/sh.decls.h @@ -399,6 +399,7 @@ extern void autoset_dspmbyte (const Char *); #if defined(AUTOSET_KANJI) extern void autoset_kanji (void); #endif +extern void update_wordchars (void); /* * sh.time.c diff --git a/sh.h b/sh.h index 75de557..51d3f3b 100644 --- a/sh.h +++ b/sh.h @@ -1161,12 +1161,14 @@ extern struct mesg { const char *pname; /* print name */ } mesg[]; -/* word_chars is set by default to WORD_CHARS but can be overridden by - the worchars variable--if unset, reverts to WORD_CHARS */ +/* word_chars is set by default to WORD_CHARS (or WORD_CHARS_VI) but can + be overridden by the wordchars variable--if unset, reverts to + WORD_CHARS (or WORD_CHARS_VI) */ EXTERN Char *word_chars; #define WORD_CHARS "*?_-.[]~=" /* default chars besides alnums in words */ +#define WORD_CHARS_VI "_" /* default chars besides alnums in words */ EXTERN Char *STR_SHELLPATH; @@ -1174,6 +1176,7 @@ EXTERN Char *STR_SHELLPATH; EXTERN Char *STR_BSHELL; #endif EXTERN Char *STR_WORD_CHARS; +EXTERN Char *STR_WORD_CHARS_VI; EXTERN Char **STR_environ IZERO; extern int dont_free; /* Tell free that we are in danger if we free */ diff --git a/sh.set.c b/sh.set.c index abb0236..52602f0 100644 --- a/sh.set.c +++ b/sh.set.c @@ -167,6 +167,7 @@ update_vars(Char *vp) } else if (eq(vp, STRvimode)) { VImode = 1; + update_wordchars(); } else if (eq(vp, STRshlvl)) { tsetenv(STRKSHLVL, varval(vp)); @@ -808,6 +809,7 @@ unset(Char **v, struct command *c) #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) update_dspmbyte_vars(); #endif + update_wordchars(); #ifdef NLS_CATALOGS nlsclose(); nlsinit(); @@ -1316,3 +1318,11 @@ autoset_kanji(void) } #endif #endif + +void +update_wordchars(void) +{ + if ((word_chars == STR_WORD_CHARS) || (word_chars == STR_WORD_CHARS_VI)) { + word_chars = (VImode ? STR_WORD_CHARS_VI : STR_WORD_CHARS); + } +} -- 2.5.5 From 11d982273f8b12271363b530cd0c674b6ce87817 Mon Sep 17 00:00:00 2001 From: christos Date: Thu, 13 Aug 2015 09:06:33 +0000 Subject: [PATCH 4/7] Modify c_to_class() to use isword(); this matches alnum + $wordchars rather than just alnum + "_". Rename C_CLASS_ALNUM to C_CLASS_WORD. (Luke Mewburn) --- ed.chared.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ed.chared.c b/ed.chared.c index fc62bc5..800f3ed 100644 --- a/ed.chared.c +++ b/ed.chared.c @@ -93,7 +93,7 @@ RCSID("$tcsh$") * from: Gert-Jan Vons */ #define C_CLASS_WHITE 1 -#define C_CLASS_ALNUM 2 +#define C_CLASS_WORD 2 #define C_CLASS_OTHER 3 static Char *InsertPos = InputBuf; /* Where insertion starts */ @@ -305,8 +305,8 @@ c_to_class(Char ch) if (Isspace(ch)) return C_CLASS_WHITE; - if (Isdigit(ch) || Isalpha(ch) || ch == '_') - return C_CLASS_ALNUM; + if (isword(ch)) + return C_CLASS_WORD; return C_CLASS_OTHER; } -- 2.5.5 From 675e8d9b6b26e8f6b2c70b58a928faceb7db10dd Mon Sep 17 00:00:00 2001 From: christos Date: Wed, 19 Aug 2015 14:29:55 +0000 Subject: [PATCH 5/7] rename e_capitolcase ->e_capitalcase (Luke Mewburn) --- ed.chared.c | 2 +- ed.decls.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ed.chared.c b/ed.chared.c index 800f3ed..1277e53 100644 --- a/ed.chared.c +++ b/ed.chared.c @@ -3034,7 +3034,7 @@ e_uppercase(Char c) /*ARGSUSED*/ CCRETVAL -e_capitolcase(Char c) +e_capitalcase(Char c) { Char *cp, *end; diff --git a/ed.decls.h b/ed.decls.h index a2dd671..defb558 100644 --- a/ed.decls.h +++ b/ed.decls.h @@ -142,7 +142,7 @@ extern CCRETVAL e_wordfwd (Char); extern CCRETVAL v_wordbegnext (Char); extern CCRETVAL e_uppercase (Char); extern CCRETVAL e_lowercase (Char); -extern CCRETVAL e_capitolcase (Char); +extern CCRETVAL e_capitalcase (Char); extern CCRETVAL e_cleardisp (Char); extern CCRETVAL e_complete (Char); extern CCRETVAL e_correct (Char); -- 2.5.5 From ee37323a0e2cfc912801350b9d1a8b063b6338a6 Mon Sep 17 00:00:00 2001 From: christos Date: Thu, 20 Aug 2015 07:56:41 +0000 Subject: [PATCH 6/7] Various improvements from Luke Mewburn: * Document vimode state changed by bindkey -e and -d, with manual override. * Document wordchars default changing based on vimode state. * Use "emacs(1)" instead of "GNU Emacs". * Use "...\-style" instead of "...-like" when referring to editor behavior. * Note which key bindings have different word boundary or cursor behavior depending on whether vimode is set or not. --- tcsh.man | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 13 deletions(-) diff --git a/tcsh.man b/tcsh.man index 80c14b6..0a35405 100644 --- a/tcsh.man +++ b/tcsh.man @@ -256,13 +256,13 @@ Finally, \fBEditor commands\fR lists and describes the editor commands specific to the shell and their default bindings. .SS "The command-line editor (+)" Command-line input can be edited using key sequences much like those used in -GNU Emacs or \fIvi\fR(1). +\fIemacs\fR(1) or \fIvi\fR(1). The editor is active only when the \fBedit\fR shell variable is set, which it is by default in interactive shells. The \fIbindkey\fR builtin can display and change key bindings. -Emacs-style key bindings are used by default +\fIemacs\fR(1)\-style key bindings are used by default (unless the shell was compiled otherwise; see the \fBversion\fR shell variable), -but \fIbindkey\fR can change the key bindings to \fIvi\fR-style bindings en masse. +but \fIbindkey\fR can change the key bindings to \fIvi\fR(1)\-style bindings en masse. .PP The shell always binds the arrow keys (as defined in the \fBTERMCAP\fR environment variable) to @@ -289,10 +289,12 @@ One can set the arrow key escape sequences to the empty string with \fIsettc\fR to prevent these bindings. The ANSI/VT100 sequences for arrow keys are always bound. .PP -Other key bindings are, for the most part, what Emacs and \fIvi\fR(1) +Other key bindings are, for the most part, what \fIemacs\fR(1) and \fIvi\fR(1) users would expect and can easily be displayed by \fIbindkey\fR, so there is no need to list them here. Likewise, \fIbindkey\fR can list the editor commands with a short description of each. +Certain key bindings have different behavior depending if \fIemacs\fR(1) or \fIvi\fR(1) +style bindings are being used; see \fBvimode\fR for more information. .PP Note that editor commands do not have the same notion of a ``word'' as does the shell. The editor delimits words with any non-alphanumeric characters not in @@ -553,6 +555,26 @@ on terminals without a meta key. Case counts, but commands that are bound to letters by default are bound to both lower- and uppercase letters for convenience. .TP 8 +.B backward-char \fR(^B, left) +Move back a character. +Cursor behavior modified by \fBvimode\fR. +.TP 8 +.B backward-delete-word \fR(M-^H, M-^?) +Cut from beginning of current word to cursor \- saved in cut buffer. +Word boundary behavior modified by \fBvimode\fR. +.TP 8 +.B backward-word \fR(M-b, M-B) +Move to beginning of current word. +Word boundary and cursor behavior modified by \fBvimode\fR. +.TP 8 +.B beginning-of-line \fR(^A, home) +Move to beginning of line. +Cursor behavior modified by \fBvimode\fR. +.TP 8 +.B capitalize-word \fR(M-c, M-C) +Capitalize the characters from cursor to end of current word. +Word boundary behavior modified by \fBvimode\fR. +.TP 8 .B complete-word \fR(tab) Completes a word as described under \fBCompletion and listing\fR. .TP 8 @@ -570,6 +592,7 @@ Like \fIcomplete-word\fR, but ignores user-defined completions. .B copy-prev-word \fR(M-^_) Copies the previous word in the current line into the input buffer. See also \fIinsert-last-word\fR. +Word boundary behavior modified by \fBvimode\fR. .TP 8 .B dabbrev-expand \fR(M-/) Expands the current word to the most recent preceding one for which @@ -582,11 +605,13 @@ much like \fIhistory-search-backward\fR does. .B delete-char \fR(not bound) Deletes the character under the cursor. See also \fIdelete-char-or-list-or-eof\fR. +Cursor behavior modified by \fBvimode\fR. .TP 8 .B delete-char-or-eof \fR(not bound) Does \fIdelete-char\fR if there is a character under the cursor or \fIend-of-file\fR on an empty line. See also \fIdelete-char-or-list-or-eof\fR. +Cursor behavior modified by \fBvimode\fR. .TP 8 .B delete-char-or-list \fR(not bound) Does \fIdelete-char\fR if there is a character under the cursor @@ -601,14 +626,26 @@ See also those three commands, each of which does only a single action, and \fIdelete-char-or-eof\fR, \fIdelete-char-or-list\fR and \fIlist-or-eof\fR, each of which does a different two out of the three. .TP 8 +.B delete-word \fR(M-d, M-D) +Cut from cursor to end of current word \- save in cut buffer. +Word boundary behavior modified by \fBvimode\fR. +.TP 8 .B down-history \fR(down-arrow, ^N) Like \fIup-history\fR, but steps down, stopping at the original input line. .TP 8 +.B downcase-word \fR(M-l, M-L) +Lowercase the characters from cursor to end of current word. +Word boundary behavior modified by \fBvimode\fR. +.TP 8 .B end-of-file \fR(not bound) Signals an end of file, causing the shell to exit unless the \fBignoreeof\fR shell variable (q.v.) is set to prevent this. See also \fIdelete-char-or-list-or-eof\fR. .TP 8 +.B end-of-line \fR(^E, end) +Move cursor to end of line. +Cursor behavior modified by \fBvimode\fR. +.TP 8 .B expand-history \fR(M-space) Expands history substitutions in the current word. See \fBHistory substitution\fR. @@ -627,6 +664,14 @@ expands history substitutions in each word in the input buffer. Expands the variable to the left of the cursor. See \fBVariable substitution\fR. .TP 8 +.B forward-char \fR(^F, right) +Move forward one character. +Cursor behavior modified by \fBvimode\fR. +.TP 8 +.B forward-word \fR(M-f, M-F) +Move forward to end of current word. +Word boundary and cursor behavior modified by \fBvimode\fR. +.TP 8 .B history-search-backward \fR(M-p, M-P) Searches backwards through the history list for a command beginning with the current contents of the input buffer up to the cursor and copies it @@ -675,12 +720,13 @@ Any other character not bound to \fIself-insert-command\fR terminates the search, leaving the current line in the input buffer, and is then interpreted as normal input. In particular, a carriage return causes the current line to be executed. -Emacs mode only. See also \fIi-search-fwd\fR and \fIhistory-search-backward\fR. +Word boundary behavior modified by \fBvimode\fR. .RE .TP 8 .B i-search-fwd \fR(not bound) Like \fIi-search-back\fR, but searches forward. +Word boundary behavior modified by \fBvimode\fR. .TP 8 .B insert-last-word \fR(M-_) Inserts the last word of the previous input line (`!$') into the input buffer. @@ -786,6 +832,18 @@ Copies the previous entry in the history list into the input buffer. If \fBhistlit\fR is set, uses the literal form of the entry. May be repeated to step up through the history list, stopping at the top. .TP 8 +.B upcase-word \fR(M-u, M-U) +Uppercase the characters from cursor to end of current word. +Word boundary behavior modified by \fBvimode\fR. +.TP 8 +.B vi-beginning-of-next-word \fR(not bound) +Vi goto the beginning of next word. +Word boundary and cursor behavior modified by \fBvimode\fR. +.TP 8 +.B vi-eword \fR(not bound) +Vi move to the end of the current word. +Word boundary behavior modified by \fBvimode\fR. +.TP 8 .B vi-search-back \fR(?) Prompts with `?' for a search string (which may be a glob-pattern, as with \fIhistory-search-backward\fR), searches for it and copies it into the @@ -2179,17 +2237,20 @@ Options include: Lists all editor commands and a short description of each. .TP 4 .B \-d -Binds all keys to the standard bindings for the default editor. +Binds all keys to the standard bindings for the default editor, +as per \fB-e\fR and \fB-v\fR below. .TP 4 .B \-e -Binds all keys to the standard GNU Emacs-like bindings. +Binds all keys to \fIemacs\fR(1)\-style bindings. +Unsets \fBvimode\fR. .TP 4 .B \-v -Binds all keys to the standard \fIvi\fR(1)-like bindings. +Binds all keys to \fIvi\fR(1)\-style bindings. +Sets \fBvimode\fR. .TP 4 .B \-a Lists or changes key-bindings in the alternative key map. -This is the key map used in \fIvi\fR command mode. +This is the key map used in \fBvimode\fR command mode. .TP 4 .B \-b \fIkey\fR is interpreted as @@ -4675,7 +4736,7 @@ nd `.' is omitted from \fBpath\fR for security .TP 6 vi -\fIvi\fR-style editing is the default rather than \fIemacs\fR +\fIvi\fR(1)\-style editing is the default rather than \fIemacs\fR(1)\-style .TP 6 dtr Login shells drop DTR when exiting @@ -4713,6 +4774,23 @@ An administrator may enter additional strings to indicate differences in the local version. .RE .TP 8 +.B vimode \fR(+) +.RS +8 +If unset, various key bindings change behavior to be more \fBemacs\fR(1)\-style: +word boundaries are determined by \fBwordchars\fR versus other characters. +.PP +If set, various key bindings change behavior to be more \fBvi\fR(1)\-style: +word boundaries are determined by \fBwordchars\fR versus whitespace +versus other characters; +cursor behavior depends upon current vi mode (command, delete, insert, replace). +.PP +This variable is unset by \fIbindkey\fR \fB-e\fR and +set by \fIbindkey\fR \fB-v\fR. +.B vimode +may be explicitly set or unset by the user after those \fIbindkey\fR +operations if required. +.RE +.TP 8 .B visiblebell \fR(+) If set, a screen flash is used rather than the audible bell. See also \fBnobeep\fR. @@ -4777,7 +4855,9 @@ which don't store the remote hostname. .B wordchars \fR(+) A list of non-alphanumeric characters to be considered part of a word by the \fIforward-word\fR, \fIbackward-word\fR etc., editor commands. -If unset, `*?_\-.[]~=' is used. +If unset, the default value is determined based on the state of \fBvimode\fR: +if \fBvimode\fR is unset, `*?_\-.[]~=' is used as the default; +if \fBvimode\fR is set, `_' is used as the default. .SH ENVIRONMENT .TP 8 .B AFSUSER \fR(+) @@ -5100,8 +5180,9 @@ This manual describes \fItcsh\fR as a single entity, but experienced \fIcsh\fR(1) users will want to pay special attention to \fItcsh\fR's new features. .PP -A command-line editor, which supports GNU Emacs or \fIvi\fR(1)-style -key bindings. See \fBThe command-line editor\fR and \fBEditor commands\fR. +A command-line editor, which supports \fIemacs\fR(1)\-style +or \fIvi\fR(1)\-style key bindings. +See \fBThe command-line editor\fR and \fBEditor commands\fR. .PP Programmable, interactive word completion and listing. See \fBCompletion and listing\fR and the \fIcomplete\fR and \fIuncomplete\fR -- 2.5.5 From 660f11b691b66eb991fd03c644a8b93908b8d844 Mon Sep 17 00:00:00 2001 From: kim Date: Mon, 24 Aug 2015 20:08:24 +0000 Subject: [PATCH 7/7] Fix e_capitolcase to e_capitalcase --- ed.defns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ed.defns.c b/ed.defns.c index 2b2abff..60ef193 100644 --- a/ed.defns.c +++ b/ed.defns.c @@ -151,7 +151,7 @@ PFCmd CcFuncTbl[] = { /* table of available commands */ #define F_CASEUPPER 54 e_lowercase, #define F_CASELOWER 55 - e_capitolcase, + e_capitalcase, #define F_CASECAPITAL 56 v_zero, #define V_ZERO 57 -- 2.5.5