Make REPL key bindings more similar to those on GNU readline.

* I deleted Alt-H and Alt-L because Ctrl-F and Ctrl-B serve the same
roles.
* Ctrl-W, Alt-D, Alt-F, and Alt-B behave more similarly to the same
key bindings on GNU readline.
* Improved documentation of REPL keybindings on man page.
* Home and End keys now work on more terminal environments.
* Removed bindings for `Esc OH` and `Esc OF` because andrewchambers
doesn't need those bindings and the bindings don't seem to make much
sense for Home and End. `Esc O` is Single Shift Select of G3 Character
Set in xterm. https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
This commit is contained in:
crocket 2020-01-22 09:45:13 +09:00
parent 01c6ffe1d5
commit 8162c64ca3
2 changed files with 91 additions and 75 deletions

88
janet.1
View File

@ -29,68 +29,88 @@ most new platforms.
.SH REPL KEY-BINDINGS .SH REPL KEY-BINDINGS
.TP 16 .TP 16
.BR Home/Ctrl\-A .BR Home
Move cursor to the beginning of input line Move cursor to the beginning of input line.
.TP 16 .TP 16
.BR End .BR End
Move cursor to the end of input line Move cursor to the end of input line.
.TP 16 .TP 16
.BR Left/Right .BR Left/Right
Move cursor in input line Move cursor in input line.
.TP 16 .TP 16
.BR Up/Down .BR Up/Down
Go backwards and forwards through history. Go backwards and forwards through history.
.TP 16
.BR Ctrl\-,
Go to earliest item in history
.TP 16
.BR Ctrl\-.
Go to last item in history
.TP 16 .TP 16
.BR Tab .BR Tab
Complete current symbol, or show available completion Complete current symbol, or show available completions.
.TP 16
.BR Delete
Delete one character after the cursor.
.TP 16
.BR Backspace
Delete one character before the cursor.
.TP 16
.BR Ctrl\-A
Move cursor to the beginning of input line.
.TP 16
.BR Ctrl\-B
Move cursor one character to the left.
.TP 16
.BR Ctrl\-E
Move cursor to the end of input line.
.TP 16
.BR Ctrl\-F
Move cursor one character to the right.
.TP 16 .TP 16
.BR Ctrl\-H .BR Ctrl\-H
Delete one character behind the cursor. Delete one character before the cursor.
.TP 16
.BR Ctrl\-K
Delete everything after the cursor on the input line.
.TP 16 .TP 16
.BR Ctrl\-L .BR Ctrl\-L
Clear the screen. Clear the screen.
.TP 16
.BR Ctrl\-N/Ctrl\-P
Go forwards and backwards through history.
.TP 16
.BR Ctrl\-U
Delete everything before the cursor on the input line.
.TP 16 .TP 16
.BR Ctrl\-W .BR Ctrl\-W
Delete a word behind the cursor Delete one word before the cursor.
.TP 16 .TP 16
.BR Alt\-A .BR Alt\-B/Alt\-F
Move cursor forward one word. Move cursor backwards and forwards one word.
.TP 16
.BR Alt\-B
Move cursor backwards one word.
.TP 16
.BR Delete
Delete character on cursor.
.TP 16
.BR Alt\-H
Move cursor one character to the left.
.TP 16
.BR Alt\-L
Move cursor one character to the right.
.TP 16 .TP 16
.BR Alt\-D .BR Alt\-D
Delete word at cursor. Delete one word after the cursor.
.TP 16
.BR Alt\-,
Go to earliest item in history.
.TP 16
.BR Alt\-.
Go to last item in history.
.LP .LP

View File

@ -377,20 +377,20 @@ static void kdelete(int draw) {
} }
static void kbackspacew(void) { static void kbackspacew(void) {
while (gbl_pos && !isspace(gbl_buf[gbl_pos - 1])) { while (gbl_pos && isspace(gbl_buf[gbl_pos - 1])) {
kbackspace(0); kbackspace(0);
} }
while (gbl_pos && isspace(gbl_buf[gbl_pos - 1])) { while (gbl_pos && !isspace(gbl_buf[gbl_pos - 1])) {
kbackspace(0); kbackspace(0);
} }
refresh(); refresh();
} }
static void kdeletew(void) { static void kdeletew(void) {
while (gbl_pos < gbl_len && !isspace(gbl_buf[gbl_pos])) { while (gbl_pos < gbl_len && isspace(gbl_buf[gbl_pos])) {
kdelete(0); kdelete(0);
} }
while (gbl_pos < gbl_len && isspace(gbl_buf[gbl_pos])) { while (gbl_pos < gbl_len && !isspace(gbl_buf[gbl_pos])) {
kdelete(0); kdelete(0);
} }
refresh(); refresh();
@ -584,11 +584,9 @@ static int line() {
if (write(STDOUT_FILENO, gbl_prompt, gbl_plen) == -1) return -1; if (write(STDOUT_FILENO, gbl_prompt, gbl_plen) == -1) return -1;
for (;;) { for (;;) {
char c; char c;
int nread;
char seq[3]; char seq[3];
nread = read(STDIN_FILENO, &c, 1); if (read(STDIN_FILENO, &c, 1) <= 0) return -1;
if (nread <= 0) return -1;
switch (c) { switch (c) {
default: default:
@ -625,6 +623,11 @@ static int line() {
kshowcomp(); kshowcomp();
refresh(); refresh();
break; break;
case 11: /* ctrl-k */
gbl_buf[gbl_pos] = '\0';
gbl_len = gbl_pos;
refresh();
break;
case 12: /* ctrl-l */ case 12: /* ctrl-l */
clear(); clear();
refresh(); refresh();
@ -638,11 +641,17 @@ static int line() {
case 16: /* ctrl-p */ case 16: /* ctrl-p */
historymove(1); historymove(1);
break; break;
case 21: /* ctrl-u */ case 21: { /* ctrl-u */
gbl_buf[0] = '\0'; char *temp = sdup(&gbl_buf[gbl_pos]);
gbl_pos = gbl_len = 0; memcpy(temp, &gbl_buf[gbl_pos], sizeof(char) * (gbl_len - gbl_pos));
memcpy(gbl_buf, temp, sizeof(char) * (gbl_len - gbl_pos));
free(temp);
gbl_buf[gbl_len - gbl_pos] = '\0';
gbl_len = gbl_len - gbl_pos;
gbl_pos = 0;
refresh(); refresh();
break; break;
}
case 23: /* ctrl-w */ case 23: /* ctrl-w */
kbackspacew(); kbackspacew();
break; break;
@ -657,6 +666,7 @@ static int line() {
* Use two calls to handle slow terminals returning the two * Use two calls to handle slow terminals returning the two
* chars at different times. */ * chars at different times. */
if (read(STDIN_FILENO, seq, 1) == -1) break; if (read(STDIN_FILENO, seq, 1) == -1) break;
// Esc[ = Control Sequence Introducer (CSI)
if (seq[0] == '[') { if (seq[0] == '[') {
if (read(STDIN_FILENO, seq + 1, 1) == -1) break; if (read(STDIN_FILENO, seq + 1, 1) == -1) break;
if (seq[1] >= '0' && seq[1] <= '9') { if (seq[1] >= '0' && seq[1] <= '9') {
@ -664,9 +674,17 @@ static int line() {
if (read(STDIN_FILENO, seq + 2, 1) == -1) break; if (read(STDIN_FILENO, seq + 2, 1) == -1) break;
if (seq[2] == '~') { if (seq[2] == '~') {
switch (seq[1]) { switch (seq[1]) {
case '1': /* Home */
gbl_pos = 0;
refresh();
break;
case '3': /* delete */ case '3': /* delete */
kdelete(1); kdelete(1);
break; break;
case '4': /* End */
gbl_pos = gbl_len;
refresh();
break;
default: default:
break; break;
} }
@ -676,10 +694,10 @@ static int line() {
/* Single escape sequences */ /* Single escape sequences */
default: default:
break; break;
case 'A': case 'A': /* Up */
historymove(1); historymove(1);
break; break;
case 'B': case 'B': /* Down */
historymove(-1); historymove(-1);
break; break;
case 'C': /* Right */ case 'C': /* Right */
@ -688,11 +706,11 @@ static int line() {
case 'D': /* Left */ case 'D': /* Left */
kleft(); kleft();
break; break;
case 'H': case 'H': /* Home */
gbl_pos = 0; gbl_pos = 0;
refresh(); refresh();
break; break;
case 'F': case 'F': /* End */
gbl_pos = gbl_len; gbl_pos = gbl_len;
refresh(); refresh();
break; break;
@ -703,41 +721,19 @@ static int line() {
switch (seq[0]) { switch (seq[0]) {
default: default:
break; break;
case 'O': { case 'd': // Alt-d
if (read(STDIN_FILENO, seq + 1, 1) == -1) break;
switch (seq[1]) {
default:
break;
case 'H':
gbl_pos = 0;
refresh();
break;
case 'F':
gbl_pos = gbl_len;
refresh();
break;
}
break;
}
case 'h':
kleft();
break;
case 'l':
kright();
break;
case 'd':
kdeletew(); kdeletew();
break; break;
case 'b': case 'b': // Alt-b
kleftw(); kleftw();
break; break;
case 'f': case 'f': // Alt-f
krightw(); krightw();
break; break;
case ',': case ',': // Alt-,
historymove(JANET_HISTORY_MAX); historymove(JANET_HISTORY_MAX);
break; break;
case '.': case '.': // Alt-.
historymove(-JANET_HISTORY_MAX); historymove(-JANET_HISTORY_MAX);
break; break;
} }