mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Add support for more keyboard shortcuts (#410)
Add extra key bindings to the emacs and vi modes
This patch adds the following key bindings to the emacs and vi
editing modes:
- Support for Home key sequences ^[[1~ and ^[[7~ as well as End key
sequences ^[[4~ and ^[[8~.
- Support for arrow key sequences ^[OA, ^[OB, ^[OC and ^[OD.
- Support for the following keyboard shortcuts (if the platform
supports the expected escape sequence):
- Ctrl-Left Arrow: Go back one word
- Alt-Left Arrow: Go back one word (Not supported on Haiku)
- Ctrl-Right Arrow: Go forward one word
- Alt-Right Arrow: Go forward one word (Not supported on Haiku)
- Ctrl-G: Cancel reverse search
- Ctrl-Delete: Delete next word (Not supported on Haiku)
- Added a key binding for the Insert key, which differs in the
emacs and vi editing modes:
- In emacs mode, Insert escapes the next character.
- In vi mode, Insert will switch the editor to insert mode (like
in vim).
src/cmd/ksh93/edit/{emacs,vi}.c:
- Add support for the <M-Left> and <M-Right> sequences. Like in
bash and mksh, these shortcuts move the cursor one word backward
or forward (like the <Ctrl-Left> and <Ctrl-Right> shortcuts).
- Only attempt to process these shortcuts if the escape sequence
begins with $'\E[1;'.
src/cmd/ksh93/edit/vi.c:
- If the shell isn't doing a reverse search, insert the bell
character when Ctrl+G is input.
- Add the Ctrl-Delete shortcut as an alias of 'dw'. Calling
ed_ungetchar twice does not work for 'dw', so Ctrl-Delete was
implemented by using a vp->del_word variable.
Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
parent
9c313c7fe3
commit
9a5af738ef
6 changed files with 334 additions and 8 deletions
|
|
@ -780,7 +780,7 @@ static void putstring(Emacs_t* ep,register char *sp)
|
|||
static int escape(register Emacs_t* ep,register genchar *out,int count)
|
||||
{
|
||||
register int i,value;
|
||||
int digit,ch;
|
||||
int digit,ch,c,d;
|
||||
digit = 0;
|
||||
value = 0;
|
||||
while ((i=ed_getchar(ep->ed,0)),digit(i))
|
||||
|
|
@ -827,6 +827,7 @@ static int escape(register Emacs_t* ep,register genchar *out,int count)
|
|||
case 'd': /* M-d == delete word */
|
||||
case 'c': /* M-c == uppercase */
|
||||
case 'f': /* M-f == move cursor forward one word */
|
||||
forward:
|
||||
{
|
||||
i = cur;
|
||||
while(value-- && i<eol)
|
||||
|
|
@ -883,6 +884,7 @@ static int escape(register Emacs_t* ep,register genchar *out,int count)
|
|||
case DELETE :
|
||||
case '\b':
|
||||
case 'h': /* M-h == delete the previous word */
|
||||
backward:
|
||||
{
|
||||
i = cur;
|
||||
while(value-- && i>0)
|
||||
|
|
@ -1079,6 +1081,7 @@ static int escape(register Emacs_t* ep,register genchar *out,int count)
|
|||
return(-1);
|
||||
#endif
|
||||
case '[': /* feature not in book */
|
||||
case 'O': /* after running top <ESC>O instead of <ESC>[ */
|
||||
switch(i=ed_getchar(ep->ed,1))
|
||||
{
|
||||
case 'A':
|
||||
|
|
@ -1131,8 +1134,53 @@ static int escape(register Emacs_t* ep,register genchar *out,int count)
|
|||
/* VT220 End key */
|
||||
ed_ungetchar(ep->ed,cntl('E'));
|
||||
return(-1);
|
||||
case '1':
|
||||
case '7':
|
||||
/*
|
||||
* ed_getchar() can only be run once on each character
|
||||
* and shouldn't be used on non-existent characters.
|
||||
*/
|
||||
ch = ed_getchar(ep->ed,1);
|
||||
if(ch == '~')
|
||||
{ /* Home key */
|
||||
ed_ungetchar(ep->ed,cntl('A'));
|
||||
return(-1);
|
||||
}
|
||||
else if(i == '1' && ch == ';')
|
||||
{
|
||||
c = ed_getchar(ep->ed,1);
|
||||
if(c == '3' || c == '5' || c == '9') /* 3 == Alt, 5 == Ctrl, 9 == iTerm2 Alt */
|
||||
{
|
||||
d = ed_getchar(ep->ed,1);
|
||||
switch(d)
|
||||
{
|
||||
case 'D': /* Ctrl/Alt-Left arrow (go back one word) */
|
||||
ch = 'b';
|
||||
goto backward;
|
||||
case 'C': /* Ctrl/Alt-Right arrow (go forward one word) */
|
||||
ch = 'f';
|
||||
goto forward;
|
||||
}
|
||||
ed_ungetchar(ep->ed,d);
|
||||
}
|
||||
ed_ungetchar(ep->ed,c);
|
||||
}
|
||||
ed_ungetchar(ep->ed,ch);
|
||||
ed_ungetchar(ep->ed,i);
|
||||
return(-1);
|
||||
case '2': /* Insert key */
|
||||
ch = ed_getchar(ep->ed,1);
|
||||
if(ch == '~')
|
||||
{
|
||||
ed_ungetchar(ep->ed, cntl('V'));
|
||||
return(-1);
|
||||
}
|
||||
ed_ungetchar(ep->ed,ch);
|
||||
ed_ungetchar(ep->ed,i);
|
||||
return(-1);
|
||||
case '3':
|
||||
if((ch=ed_getchar(ep->ed,1))=='~')
|
||||
ch = ed_getchar(ep->ed,1);
|
||||
if(ch == '~')
|
||||
{ /*
|
||||
* VT220 forward-delete key.
|
||||
* Since ERASECHAR and EOFCHAR are usually both mapped to ^D, we
|
||||
|
|
@ -1143,6 +1191,47 @@ static int escape(register Emacs_t* ep,register genchar *out,int count)
|
|||
ed_ungetchar(ep->ed,ERASECHAR);
|
||||
return(-1);
|
||||
}
|
||||
else if(ch == ';')
|
||||
{
|
||||
c = ed_getchar(ep->ed,1);
|
||||
if(c == '5')
|
||||
{
|
||||
d = ed_getchar(ep->ed,1);
|
||||
if(d == '~')
|
||||
{
|
||||
/* Ctrl-Delete (delete next word) */
|
||||
ch = 'd';
|
||||
goto forward;
|
||||
}
|
||||
ed_ungetchar(ep->ed,d);
|
||||
}
|
||||
ed_ungetchar(ep->ed,c);
|
||||
}
|
||||
ed_ungetchar(ep->ed,ch);
|
||||
ed_ungetchar(ep->ed,i);
|
||||
return(-1);
|
||||
case '5': /* Haiku terminal Ctrl-Arrow key */
|
||||
ch = ed_getchar(ep->ed,1);
|
||||
switch(ch)
|
||||
{
|
||||
case 'D': /* Ctrl-Left arrow (go back one word) */
|
||||
ch = 'b';
|
||||
goto backward;
|
||||
case 'C': /* Ctrl-Right arrow (go forward one word) */
|
||||
ch = 'f';
|
||||
goto forward;
|
||||
}
|
||||
ed_ungetchar(ep->ed,ch);
|
||||
ed_ungetchar(ep->ed,i);
|
||||
return(-1);
|
||||
case '4':
|
||||
case '8': /* rxvt */
|
||||
ch = ed_getchar(ep->ed,1);
|
||||
if(ch == '~')
|
||||
{
|
||||
ed_ungetchar(ep->ed,cntl('E')); /* End key */
|
||||
return(-1);
|
||||
}
|
||||
ed_ungetchar(ep->ed,ch);
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
|
|
@ -1288,7 +1377,7 @@ static void search(Emacs_t* ep,genchar *out,int direction)
|
|||
goto restore;
|
||||
continue;
|
||||
}
|
||||
if(i == ep->ed->e_intr) /* end reverse search */
|
||||
if(i == ep->ed->e_intr || i == cntl('G')) /* end reverse search */
|
||||
goto restore;
|
||||
if (i==usrkill)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ typedef struct _vi_
|
|||
int U_saved; /* original virtual saved */
|
||||
genchar *U_space; /* used for U command */
|
||||
genchar *u_space; /* used for u command */
|
||||
unsigned char del_word; /* used for Ctrl-Delete */
|
||||
#ifdef FIORDCHK
|
||||
clock_t typeahead; /* typeahead occurred */
|
||||
#else
|
||||
|
|
@ -753,7 +754,7 @@ static int cntlmode(Vi_t *vp)
|
|||
if(mvcursor(vp,c))
|
||||
{
|
||||
sync_cursor(vp);
|
||||
if( c != '[' )
|
||||
if( c != '[' && c != 'O' )
|
||||
vp->repeat = 1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1036,7 +1037,7 @@ static int cntlmode(Vi_t *vp)
|
|||
if(lookahead)
|
||||
{
|
||||
ed_ungetchar(vp->ed,c=ed_getchar(vp->ed,1));
|
||||
if(c=='[')
|
||||
if(c=='[' || c=='O')
|
||||
continue;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
|
@ -1430,6 +1431,10 @@ static void getline(register Vi_t* vp,register int mode)
|
|||
}
|
||||
break;
|
||||
|
||||
case cntl('G'):
|
||||
if(mode!=SEARCH)
|
||||
goto fallback;
|
||||
/* FALLTHROUGH */
|
||||
case UINTR:
|
||||
first_virt = 0;
|
||||
cdelete(vp,cur_virt+1, BAD);
|
||||
|
|
@ -1550,6 +1555,7 @@ static void getline(register Vi_t* vp,register int mode)
|
|||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
fallback:
|
||||
if( mode == REPLACE )
|
||||
{
|
||||
if( cur_virt < last_virt )
|
||||
|
|
@ -1583,7 +1589,7 @@ static void getline(register Vi_t* vp,register int mode)
|
|||
|
||||
static int mvcursor(register Vi_t* vp,register int motion)
|
||||
{
|
||||
register int count;
|
||||
register int count, c, d;
|
||||
register int tcur_virt;
|
||||
register int incr = -1;
|
||||
register int bound = 0;
|
||||
|
|
@ -1612,7 +1618,8 @@ static int mvcursor(register Vi_t* vp,register int motion)
|
|||
tcur_virt = last_virt;
|
||||
break;
|
||||
|
||||
case '[':
|
||||
case '[': /* feature not in book */
|
||||
case 'O': /* after running top <ESC>O instead of <ESC>[ */
|
||||
switch(motion=ed_getchar(vp->ed,-1))
|
||||
{
|
||||
case 'A':
|
||||
|
|
@ -1659,6 +1666,47 @@ static int mvcursor(register Vi_t* vp,register int motion)
|
|||
/* VT220 End key */
|
||||
ed_ungetchar(vp->ed,'$');
|
||||
return(1);
|
||||
case '1':
|
||||
case '7':
|
||||
bound = ed_getchar(vp->ed,-1);
|
||||
if(bound=='~')
|
||||
{ /* Home key */
|
||||
ed_ungetchar(vp->ed,'0');
|
||||
return(1);
|
||||
}
|
||||
else if(motion=='1' && bound==';')
|
||||
{
|
||||
c = ed_getchar(vp->ed,-1);
|
||||
if(c == '3' || c == '5' || c == '9') /* 3 == Alt, 5 == Ctrl, 9 == iTerm2 Alt */
|
||||
{
|
||||
d = ed_getchar(vp->ed,-1);
|
||||
switch(d)
|
||||
{
|
||||
case 'D': /* Ctrl/Alt-Left arrow (go back one word) */
|
||||
ed_ungetchar(vp->ed, 'b');
|
||||
return(1);
|
||||
case 'C': /* Ctrl/Alt-Right arrow (go forward one word) */
|
||||
ed_ungetchar(vp->ed, 'w');
|
||||
return(1);
|
||||
}
|
||||
ed_ungetchar(vp->ed,d);
|
||||
}
|
||||
ed_ungetchar(vp->ed,c);
|
||||
}
|
||||
ed_ungetchar(vp->ed,bound);
|
||||
ed_ungetchar(vp->ed,motion);
|
||||
return(0);
|
||||
case '2':
|
||||
bound = ed_getchar(vp->ed,-1);
|
||||
if(bound=='~')
|
||||
{
|
||||
/* VT220 insert key */
|
||||
ed_ungetchar(vp->ed,'i');
|
||||
return(1);
|
||||
}
|
||||
ed_ungetchar(vp->ed,bound);
|
||||
ed_ungetchar(vp->ed,motion);
|
||||
return(0);
|
||||
case '3':
|
||||
bound = ed_getchar(vp->ed,-1);
|
||||
if(bound=='~')
|
||||
|
|
@ -1667,6 +1715,48 @@ static int mvcursor(register Vi_t* vp,register int motion)
|
|||
ed_ungetchar(vp->ed,'x');
|
||||
return(1);
|
||||
}
|
||||
else if(bound==';')
|
||||
{
|
||||
c = ed_getchar(vp->ed,-1);
|
||||
if(c == '5')
|
||||
{
|
||||
d = ed_getchar(vp->ed,-1);
|
||||
if(d == '~')
|
||||
{
|
||||
/* Ctrl-Delete */
|
||||
vp->del_word = 1;
|
||||
ed_ungetchar(vp->ed,'d');
|
||||
return(1);
|
||||
}
|
||||
ed_ungetchar(vp->ed,d);
|
||||
}
|
||||
ed_ungetchar(vp->ed,c);
|
||||
}
|
||||
ed_ungetchar(vp->ed,bound);
|
||||
ed_ungetchar(vp->ed,motion);
|
||||
return(0);
|
||||
case '5': /* Haiku terminal Ctrl-Arrow key */
|
||||
bound = ed_getchar(vp->ed,-1);
|
||||
switch(bound)
|
||||
{
|
||||
case 'D': /* Ctrl-Left arrow (go back one word) */
|
||||
ed_ungetchar(vp->ed, 'b');
|
||||
return(1);
|
||||
case 'C': /* Ctrl-Right arrow (go forward one word) */
|
||||
ed_ungetchar(vp->ed, 'w');
|
||||
return(1);
|
||||
}
|
||||
ed_ungetchar(vp->ed,bound);
|
||||
ed_ungetchar(vp->ed,motion);
|
||||
return(0);
|
||||
case '4':
|
||||
case '8':
|
||||
bound = ed_getchar(vp->ed,-1);
|
||||
if(bound=='~')
|
||||
{ /* End key */
|
||||
ed_ungetchar(vp->ed,'$');
|
||||
return(1);
|
||||
}
|
||||
ed_ungetchar(vp->ed,bound);
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
|
|
@ -2602,6 +2692,11 @@ chgeol:
|
|||
case 'd': /** delete **/
|
||||
if( mode )
|
||||
c = vp->lastmotion;
|
||||
else if( vp->del_word )
|
||||
{
|
||||
vp->del_word = 0;
|
||||
c = 'w';
|
||||
}
|
||||
else
|
||||
c = getcount(vp,ed_getchar(vp->ed,-1));
|
||||
deleol:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue