mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-15 04:32:24 +00:00
emacs, vi: Support repeat parameters to VT220 keys (re: f2a3f4e3
)
In the vi and emacs line editors, repeat count parameters can now
also be used for the arrow keys and the forward-delete key. E.g.,
in emacs mode, <ESC> 7 <left-arrow> will now move the cursor seven
positions to the left. In vi control mode, this would be entered
as: 7 <left-arrow>.
src/cmd/ksh93/edit/emacs.c:
- ed_emacsread(): Upon getting ^[ (ESC), save current repeat count
in a new variable; restore and reset it upon the next character.
- escape(): Minor bugfix: when processing a ^[[x sequence where 'x'
is a character other than '~' (which would be DEL), also reinsert
the final character into the buffer so scripts can detect them.
src/cmd/ksh93/edit/vi.c:
- cntlmode(): Do not reset the repeat count if the command is '[',
the character following ESC in VT220 escape sequences.
- mvcursor():
* Do not use getcount() to get the character following '[', as
that was parsing repetition parameters in the wrong place.
There wouldn't be any, so this would reset the repeat count.
* After that, no more need for the special-casing of ^[[3~ (DEL)
introduced in f2a3f4e3
. Move it to within the 'switch' block.
* When handling left and right arrows and Home and End keys, do
not modify cursor directly but ed_ungetchar() the corresponding
traditional command keys as with the rest. Otherwise a repeat
count parameter would now wrongly survive those keys.
src/cmd/ksh93/sh.1:
- Document control character notation used for vi mode docs.
- Since vi control mode beeps and aborts on ESC except if a
subsequent [ is already in the input buffer upon receiving ESC,
document that VT220 escape sequences only preserve repeat counts
when entered into the input buffer all at once.
- Don't skip the initial ESC in the documentation of the VT220
escape sequences. In control mode, skipping the initial ESC still
works as before, but that is now undocumented, as it's really
nothing more than an artefact of VT220 escape processing.
- Move the two long paragraphs on '-o viraw' and canonical (i.e.
line-based) input processing from the vi editor introduction to
the options section under 'viraw'. It is much too arcane for the
intro, and besides, ksh 93u+ (and hence also 93u+m) has
SHOPT_VIRAW enabled by default, so the shell is compiled to force
this option on at all times, making it even less relevant for
most users.
This commit is contained in:
parent
c24c3dc0af
commit
13c3fb21e9
5 changed files with 106 additions and 58 deletions
7
NEWS
7
NEWS
|
@ -3,6 +3,13 @@ For full details, see the git log at: https://github.com/ksh93/ksh
|
||||||
|
|
||||||
Any uppercase BUG_* names are modernish shell bug IDs.
|
Any uppercase BUG_* names are modernish shell bug IDs.
|
||||||
|
|
||||||
|
2020-09-17:
|
||||||
|
|
||||||
|
- In the vi and emacs line editors, repeat count parameters can now also be
|
||||||
|
used for the arrow keys and the forward-delete key. E.g., in emacs mode,
|
||||||
|
<ESC> 7 <left-arrow> will now move the cursor seven positions to the left.
|
||||||
|
In vi control mode, this would be entered as: 7 <left-arrow>.
|
||||||
|
|
||||||
2020-09-14:
|
2020-09-14:
|
||||||
|
|
||||||
- Corrected rounding of floating point values by ksh's printf %f formatting
|
- Corrected rounding of floating point values by ksh's printf %f formatting
|
||||||
|
|
|
@ -184,6 +184,7 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
|
||||||
register int count;
|
register int count;
|
||||||
register Emacs_t *ep = ed->e_emacs;
|
register Emacs_t *ep = ed->e_emacs;
|
||||||
int adjust,oadjust;
|
int adjust,oadjust;
|
||||||
|
int vt220_save_repeat = 0;
|
||||||
char backslash;
|
char backslash;
|
||||||
genchar *kptr;
|
genchar *kptr;
|
||||||
char prompt[PRSIZE];
|
char prompt[PRSIZE];
|
||||||
|
@ -313,6 +314,11 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit)
|
||||||
killing = 0;
|
killing = 0;
|
||||||
#endif
|
#endif
|
||||||
oadjust = count = adjust;
|
oadjust = count = adjust;
|
||||||
|
if(vt220_save_repeat)
|
||||||
|
{
|
||||||
|
count = vt220_save_repeat;
|
||||||
|
vt220_save_repeat = 0;
|
||||||
|
}
|
||||||
if(count<0)
|
if(count<0)
|
||||||
count = 1;
|
count = 1;
|
||||||
adjust = -1;
|
adjust = -1;
|
||||||
|
@ -607,6 +613,7 @@ update:
|
||||||
ep->ed->e_nocrnl = 0;
|
ep->ed->e_nocrnl = 0;
|
||||||
continue;
|
continue;
|
||||||
case cntl('[') :
|
case cntl('[') :
|
||||||
|
vt220_save_repeat = oadjust;
|
||||||
do_escape:
|
do_escape:
|
||||||
adjust = escape(ep,out,oadjust);
|
adjust = escape(ep,out,oadjust);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1067,6 +1074,7 @@ static int escape(register Emacs_t* ep,register genchar *out,int count)
|
||||||
switch(i=ed_getchar(ep->ed,1))
|
switch(i=ed_getchar(ep->ed,1))
|
||||||
{
|
{
|
||||||
case 'A':
|
case 'A':
|
||||||
|
/* VT220 up arrow */
|
||||||
#if SHOPT_EDPREDICT
|
#if SHOPT_EDPREDICT
|
||||||
if(!ep->ed->hlist && cur>0 && eol==cur && (cur<(SEARCHSIZE-2) || ep->prevdirection == -2))
|
if(!ep->ed->hlist && cur>0 && eol==cur && (cur<(SEARCHSIZE-2) || ep->prevdirection == -2))
|
||||||
#else
|
#else
|
||||||
|
@ -1094,23 +1102,28 @@ static int escape(register Emacs_t* ep,register genchar *out,int count)
|
||||||
ed_ungetchar(ep->ed,cntl('P'));
|
ed_ungetchar(ep->ed,cntl('P'));
|
||||||
return(-1);
|
return(-1);
|
||||||
case 'B':
|
case 'B':
|
||||||
|
/* VT220 down arrow */
|
||||||
ed_ungetchar(ep->ed,cntl('N'));
|
ed_ungetchar(ep->ed,cntl('N'));
|
||||||
return(-1);
|
return(-1);
|
||||||
case 'C':
|
case 'C':
|
||||||
|
/* VT220 right arrow */
|
||||||
ed_ungetchar(ep->ed,cntl('F'));
|
ed_ungetchar(ep->ed,cntl('F'));
|
||||||
return(-1);
|
return(-1);
|
||||||
case 'D':
|
case 'D':
|
||||||
|
/* VT220 left arrow */
|
||||||
ed_ungetchar(ep->ed,cntl('B'));
|
ed_ungetchar(ep->ed,cntl('B'));
|
||||||
return(-1);
|
return(-1);
|
||||||
case 'H':
|
case 'H':
|
||||||
|
/* VT220 Home key */
|
||||||
ed_ungetchar(ep->ed,cntl('A'));
|
ed_ungetchar(ep->ed,cntl('A'));
|
||||||
return(-1);
|
return(-1);
|
||||||
case 'F':
|
case 'F':
|
||||||
case 'Y':
|
case 'Y':
|
||||||
|
/* VT220 End key */
|
||||||
ed_ungetchar(ep->ed,cntl('E'));
|
ed_ungetchar(ep->ed,cntl('E'));
|
||||||
return(-1);
|
return(-1);
|
||||||
case '3':
|
case '3':
|
||||||
if(ed_getchar(ep->ed,1)=='~')
|
if((ch=ed_getchar(ep->ed,1))=='~')
|
||||||
{ /*
|
{ /*
|
||||||
* VT220 forward-delete key.
|
* VT220 forward-delete key.
|
||||||
* Since ERASECHAR and EOFCHAR are usually both mapped to ^D, we
|
* Since ERASECHAR and EOFCHAR are usually both mapped to ^D, we
|
||||||
|
@ -1121,6 +1134,7 @@ static int escape(register Emacs_t* ep,register genchar *out,int count)
|
||||||
ed_ungetchar(ep->ed,ERASECHAR);
|
ed_ungetchar(ep->ed,ERASECHAR);
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
ed_ungetchar(ep->ed,ch);
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
default:
|
default:
|
||||||
ed_ungetchar(ep->ed,i);
|
ed_ungetchar(ep->ed,i);
|
||||||
|
|
|
@ -762,6 +762,7 @@ static int cntlmode(Vi_t *vp)
|
||||||
if(mvcursor(vp,c))
|
if(mvcursor(vp,c))
|
||||||
{
|
{
|
||||||
sync_cursor(vp);
|
sync_cursor(vp);
|
||||||
|
if( c != '[' )
|
||||||
vp->repeat = 1;
|
vp->repeat = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1053,11 +1054,8 @@ static int cntlmode(Vi_t *vp)
|
||||||
{
|
{
|
||||||
ed_ungetchar(vp->ed,c=ed_getchar(vp->ed,1));
|
ed_ungetchar(vp->ed,c=ed_getchar(vp->ed,1));
|
||||||
if(c=='[')
|
if(c=='[')
|
||||||
{
|
|
||||||
vp->repeat = 1;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
ringbell:
|
ringbell:
|
||||||
ed_ringbell();
|
ed_ringbell();
|
||||||
|
@ -1606,7 +1604,6 @@ static int mvcursor(register Vi_t* vp,register int motion)
|
||||||
register int tcur_virt;
|
register int tcur_virt;
|
||||||
register int incr = -1;
|
register int incr = -1;
|
||||||
register int bound = 0;
|
register int bound = 0;
|
||||||
int c;
|
|
||||||
|
|
||||||
switch(motion)
|
switch(motion)
|
||||||
{
|
{
|
||||||
|
@ -1633,16 +1630,10 @@ static int mvcursor(register Vi_t* vp,register int motion)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '[':
|
case '[':
|
||||||
c = ed_getchar(vp->ed,-1);
|
switch(motion=ed_getchar(vp->ed,-1))
|
||||||
if(c=='3' && ed_getchar(vp->ed,-1)=='~')
|
|
||||||
{
|
|
||||||
/* VT220 forward-delete key */
|
|
||||||
ed_ungetchar(vp->ed,'x');
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
switch(motion=getcount(vp,c))
|
|
||||||
{
|
{
|
||||||
case 'A':
|
case 'A':
|
||||||
|
/* VT220 up arrow */
|
||||||
#if SHOPT_EDPREDICT
|
#if SHOPT_EDPREDICT
|
||||||
if(!vp->ed->hlist && cur_virt>=0 && cur_virt<(SEARCHSIZE-2) && cur_virt == last_virt)
|
if(!vp->ed->hlist && cur_virt>=0 && cur_virt<(SEARCHSIZE-2) && cur_virt == last_virt)
|
||||||
#else
|
#else
|
||||||
|
@ -1665,22 +1656,36 @@ static int mvcursor(register Vi_t* vp,register int motion)
|
||||||
ed_ungetchar(vp->ed,'k');
|
ed_ungetchar(vp->ed,'k');
|
||||||
return(1);
|
return(1);
|
||||||
case 'B':
|
case 'B':
|
||||||
|
/* VT220 down arrow */
|
||||||
ed_ungetchar(vp->ed,'j');
|
ed_ungetchar(vp->ed,'j');
|
||||||
return(1);
|
return(1);
|
||||||
case 'C':
|
case 'C':
|
||||||
motion = last_virt;
|
/* VT220 right arrow */
|
||||||
incr = 1;
|
ed_ungetchar(vp->ed,'l');
|
||||||
goto walk;
|
return(1);
|
||||||
case 'D':
|
case 'D':
|
||||||
motion = first_virt;
|
/* VT220 left arrow */
|
||||||
goto walk;
|
ed_ungetchar(vp->ed,'h');
|
||||||
|
return(1);
|
||||||
case 'H':
|
case 'H':
|
||||||
tcur_virt = 0;
|
/* VT220 Home key */
|
||||||
break;
|
ed_ungetchar(vp->ed,'0');
|
||||||
|
return(1);
|
||||||
case 'F':
|
case 'F':
|
||||||
case 'Y':
|
case 'Y':
|
||||||
tcur_virt = last_virt;
|
/* VT220 End key */
|
||||||
break;
|
ed_ungetchar(vp->ed,'$');
|
||||||
|
return(1);
|
||||||
|
case '3':
|
||||||
|
bound = ed_getchar(vp->ed,-1);
|
||||||
|
if(bound=='~')
|
||||||
|
{
|
||||||
|
/* VT220 forward-delete key */
|
||||||
|
ed_ungetchar(vp->ed,'x');
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
ed_ungetchar(vp->ed,bound);
|
||||||
|
/* FALLTHROUGH */
|
||||||
default:
|
default:
|
||||||
ed_ungetchar(vp->ed,motion);
|
ed_ungetchar(vp->ed,motion);
|
||||||
return(0);
|
return(0);
|
||||||
|
|
|
@ -17,4 +17,4 @@
|
||||||
* David Korn <dgk@research.att.com> *
|
* David Korn <dgk@research.att.com> *
|
||||||
* *
|
* *
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
#define SH_RELEASE "93u+m 2020-09-14"
|
#define SH_RELEASE "93u+m 2020-09-17"
|
||||||
|
|
|
@ -4598,7 +4598,7 @@ Neither the `RETURN' nor the `LINE FEED' key is
|
||||||
entered after edit commands except when noted.
|
entered after edit commands except when noted.
|
||||||
.PP
|
.PP
|
||||||
The \fBM-[\fR multi-character commands below are DEC VT220 escape sequences
|
The \fBM-[\fR multi-character commands below are DEC VT220 escape sequences
|
||||||
generated by keys on modern PC/Mac keyboards, such as the arrow keys.
|
generated by special keys on standard PC keyboards, such as the arrow keys.
|
||||||
You could type them directly but they are meant to recognize the keys
|
You could type them directly but they are meant to recognize the keys
|
||||||
in question, which are indicated in parentheses.
|
in question, which are indicated in parentheses.
|
||||||
.PP
|
.PP
|
||||||
|
@ -4899,9 +4899,9 @@ The commands that accept a parameter are
|
||||||
.BR M-d ,
|
.BR M-d ,
|
||||||
.BR M-f ,
|
.BR M-f ,
|
||||||
.BR M-h ,
|
.BR M-h ,
|
||||||
.B M-l
|
.BR M-l ,
|
||||||
and
|
.BR M-^H ,
|
||||||
.BR M-^H .
|
and the arrow keys and forward-delete key.
|
||||||
.PP
|
.PP
|
||||||
.TP 10
|
.TP 10
|
||||||
.BI M- letter
|
.BI M- letter
|
||||||
|
@ -5027,25 +5027,27 @@ Most control commands accept an optional repeat
|
||||||
.I count
|
.I count
|
||||||
prior to the command.
|
prior to the command.
|
||||||
.PP
|
.PP
|
||||||
When in
|
The notation for control characters used below is
|
||||||
.B vi
|
.B ^
|
||||||
mode on most systems,
|
followed by a character. For instance,
|
||||||
canonical processing is initially enabled and the
|
.B ^H
|
||||||
command will be echoed again if the speed is 1200 baud or greater and it
|
is entered by holding down the Control key and pressing H.
|
||||||
contains any control characters or less than one second has elapsed
|
.B ^[
|
||||||
since the prompt was printed.
|
(Control+\fB[\fR) is equivalent to the ESC key.
|
||||||
The ESC character terminates canonical processing for the remainder of the command
|
The notation for escape sequences is
|
||||||
and the user can then modify the command line.
|
.B ^[
|
||||||
This scheme has the advantages of canonical processing with the type-ahead
|
followed by one or more characters.
|
||||||
echoing of raw mode.
|
|
||||||
.PP
|
.PP
|
||||||
If the option
|
The \fB^[[\fR (ESC \fB[\fR) multi-character commands below are DEC VT220 escape
|
||||||
.B viraw
|
sequences generated by special keys on standard PC keyboards, such as the arrow
|
||||||
is also set, the terminal will always have canonical processing
|
keys, which are indicated in parentheses. When in
|
||||||
disabled.
|
.I input\^
|
||||||
This mode is implicit for systems that do not support two
|
mode, these keys will switch you to
|
||||||
alternate end of line delimiters,
|
.I control\^
|
||||||
and may be helpful for certain terminals.
|
mode before performing the associated action.
|
||||||
|
These sequences can use preceding repeat count parameters, but only when the
|
||||||
|
\fB^[\fR and the subsequent \fB[\fR are entered into the input buffer at the
|
||||||
|
same time, such as when pressing one of those keys.
|
||||||
.SS "\ \ \ \ \ Input Edit Commands"
|
.SS "\ \ \ \ \ Input Edit Commands"
|
||||||
.PP
|
.PP
|
||||||
.RS
|
.RS
|
||||||
|
@ -5110,8 +5112,8 @@ These commands will move the cursor.
|
||||||
[\f2count\fP]\f3l\fP
|
[\f2count\fP]\f3l\fP
|
||||||
Cursor forward (right) one character.
|
Cursor forward (right) one character.
|
||||||
.TP 10
|
.TP 10
|
||||||
[\f2count\fP]\f3[C\fP
|
[\f2count\fP]\f3^[[C\fP
|
||||||
Cursor forward (right) one character.
|
(Right arrow) Same as \f3l\fP.
|
||||||
.TP 10
|
.TP 10
|
||||||
[\f2count\fP]\f3w\fP
|
[\f2count\fP]\f3w\fP
|
||||||
Cursor forward one alpha-numeric word.
|
Cursor forward one alpha-numeric word.
|
||||||
|
@ -5128,8 +5130,8 @@ Cursor to end of the current blank delimited word.
|
||||||
[\f2count\fP]\f3h\fP
|
[\f2count\fP]\f3h\fP
|
||||||
Cursor backward (left) one character.
|
Cursor backward (left) one character.
|
||||||
.TP 10
|
.TP 10
|
||||||
[\f2count\fP]\f3[D\fP
|
[\f2count\fP]\f3^[[D\fP
|
||||||
Cursor backward (left) one character.
|
(Left arrow) Same as \f3h\fP.
|
||||||
.TP 10
|
.TP 10
|
||||||
[\f2count\fP]\f3b\fP
|
[\f2count\fP]\f3b\fP
|
||||||
Cursor backward one word.
|
Cursor backward one word.
|
||||||
|
@ -5178,17 +5180,20 @@ times.
|
||||||
.B 0
|
.B 0
|
||||||
Cursor to start of line.
|
Cursor to start of line.
|
||||||
.TP 10
|
.TP 10
|
||||||
.B ^
|
.B ^[[H
|
||||||
Cursor to start of line.
|
(Home) Same as \f30\fP.
|
||||||
.TP 10
|
.TP 10
|
||||||
.B [H
|
.B ^
|
||||||
Cursor to first non-blank character in line.
|
Cursor to first non-blank character in line.
|
||||||
.TP 10
|
.TP 10
|
||||||
.B $
|
.B $
|
||||||
Cursor to end of line.
|
Cursor to end of line.
|
||||||
.TP 10
|
.TP 10
|
||||||
.B [Y
|
.B ^[[F
|
||||||
Cursor to end of line.
|
(End) Same as \f3$\fP.
|
||||||
|
.TP 10
|
||||||
|
.B ^[[Y
|
||||||
|
Same as \f3$\fP.
|
||||||
.TP 10
|
.TP 10
|
||||||
.B %
|
.B %
|
||||||
Moves to balancing
|
Moves to balancing
|
||||||
|
@ -5218,11 +5223,12 @@ the previous command back in time is accessed.
|
||||||
Equivalent to
|
Equivalent to
|
||||||
.BR k .
|
.BR k .
|
||||||
.TP 10
|
.TP 10
|
||||||
[\f2count\fP]\f3[A\fP
|
[\f2count\fP]\f3^[[A\fP
|
||||||
|
(Up arrow)
|
||||||
If cursor is at the end of the line it is equivalent to
|
If cursor is at the end of the line it is equivalent to
|
||||||
.B /
|
.B /
|
||||||
with
|
with
|
||||||
.I string^\
|
.I string\^
|
||||||
set to the contents of the current line.
|
set to the contents of the current line.
|
||||||
Otherwise, it is equivalent to
|
Otherwise, it is equivalent to
|
||||||
.BR k .
|
.BR k .
|
||||||
|
@ -5238,7 +5244,8 @@ the next command forward in time is accessed.
|
||||||
Equivalent to
|
Equivalent to
|
||||||
.BR j .
|
.BR j .
|
||||||
.TP 10
|
.TP 10
|
||||||
[\f2count\fP]\f3[B\fP
|
[\f2count\fP]\f3^[[B\fP
|
||||||
|
(Down arrow)
|
||||||
Equivalent to
|
Equivalent to
|
||||||
.BR j .
|
.BR j .
|
||||||
.TP 10
|
.TP 10
|
||||||
|
@ -5356,6 +5363,9 @@ and advance the cursor.
|
||||||
[\f2count\fP]\f3x\fP
|
[\f2count\fP]\f3x\fP
|
||||||
Delete current character.
|
Delete current character.
|
||||||
.TP 10
|
.TP 10
|
||||||
|
[\f2count\fP]\f3^[[3~\fP
|
||||||
|
(Forward delete) Same as \f3x\fP.
|
||||||
|
.TP 10
|
||||||
[\f2count\fP]\f3X\fP
|
[\f2count\fP]\f3X\fP
|
||||||
Delete preceding character.
|
Delete preceding character.
|
||||||
.TP 10
|
.TP 10
|
||||||
|
@ -7118,6 +7128,18 @@ Each character is processed as it is typed
|
||||||
in
|
in
|
||||||
.I vi\^
|
.I vi\^
|
||||||
mode.
|
mode.
|
||||||
|
The shell may have been compiled to force this option on at all times.
|
||||||
|
Otherwise, canonical processing (line-by-line input) is initially enabled
|
||||||
|
and the command line will be echoed again if the speed is 1200 baud or
|
||||||
|
greater and it contains any control characters or less than one second has
|
||||||
|
elapsed since the prompt was printed. The ESC character terminates canonical
|
||||||
|
processing for the remainder of the command and the user can then modify the
|
||||||
|
command line. This scheme has the advantages of canonical processing with
|
||||||
|
the type-ahead echoing of raw mode. If the
|
||||||
|
.B viraw
|
||||||
|
option is set, the terminal will always have canonical processing disabled.
|
||||||
|
This mode is implicit for systems that do not support two alternate end of
|
||||||
|
line delimiters, and may be helpful for certain terminals.
|
||||||
.TP 8
|
.TP 8
|
||||||
.B xtrace
|
.B xtrace
|
||||||
Same as
|
Same as
|
||||||
|
|
Loading…
Reference in a new issue