* Alexander Polakov <polac...@gmail.com> [110721 22:01]: > * Dmitrij D. Czarkoff <czark...@gmail.com> [110721 14:49]: > > Hello! > > > > I tried both documentation and google, and I could only figure out how to > > enable arrow keys in emacs mode of ksh. > > > > Is there a way to enable them in vi mode? Same goes for HOME and END > > buttons. > > Try the patch below. > > You probably wonder why cursor movement is done in such a strange way, > reimplementing both domove() and vi_cmd(), but I couldn't find a better > way to go to "end of line + one".
This one should be a bit better.. diff --git a/edit.c b/edit.c index 36f26ea..5d97dba 100644 --- a/edit.c +++ b/edit.c @@ -27,6 +27,7 @@ static int x_file_glob(int, const char *, int, char ***); static int x_command_glob(int, const char *, int, char ***); static int x_locate_word(const char *, int, int, int *, int *); +int inputq; /* Called from main */ void @@ -117,6 +118,12 @@ x_getc(void) char c; int n; + if (inputq) { + c = inputq; + inputq = 0; + return c; + } + while ((n = blocking_read(STDIN_FILENO, &c, 1)) < 0 && errno == EINTR) if (trap) { x_mode(false); @@ -128,6 +135,26 @@ x_getc(void) return (int) (unsigned char) c; } +int +x_nbgetc(void) +{ + char c; + int n; + int flags; + + if ((flags = fcntl(STDIN_FILENO, F_GETFL, 0)) < 0) + return -1; + flags |= O_NONBLOCK; + if (fcntl(STDIN_FILENO, F_SETFL, flags) < 0) + return -1; + while ((n = read(STDIN_FILENO, &c, 1)) < 0 && errno == EAGAIN) + return -1; + if (n != 1) + return -1; + reset_nonblock(STDIN_FILENO); + return (int) (unsigned char) c; +} + void x_flush(void) { @@ -135,6 +162,12 @@ x_flush(void) } void +x_putback(int c) +{ + inputq = c; +} + +void x_putc(int c) { shf_putc(c, shl_out); diff --git a/edit.h b/edit.h index 258affe..87c52cc 100644 --- a/edit.h +++ b/edit.h @@ -46,7 +46,9 @@ EXTERN X_chars edchars; /* edit.c */ int x_getc(void); +int x_nbgetc(void); void x_flush(void); +void x_putback(int); void x_putc(int); void x_puts(const char *); bool x_mode(bool); diff --git a/vi.c b/vi.c index 0bac6be..5850b50 100644 --- a/vi.c +++ b/vi.c @@ -247,6 +247,47 @@ x_vi(char *buf, size_t len) return es->linelen; } +static int keypad(int ch) { + int cur = 0; + char cmd; + + switch (ch) { + case 'D': /* left */ + cur--; + break; + case 'C': /* right */ + cur++; + break; + case 'A': /* up */ + cmd = 'k'; + vi_cmd(1, &cmd); + break; + case 'B': /* down */ + cmd = 'j'; + vi_cmd(1, &cmd); + break; + case 'H': /* home */ + es->cursor = 0; + break; + case 'F': /* end */ + es->cursor = es->linelen; + break; + default: + return 1; + } + if ((cur += es->cursor) >= 0) { + if (cur > es->linelen && cur != 0) { + cur--; + vi_error(); + } + es->cursor = cur; + } else + vi_error(); + + refresh(0); + return 0; +} + static int vi_hook(int ch) { @@ -559,6 +600,8 @@ static int vi_insert(int ch) { int tcursor; + static int escseq = 0; + int c; if (ch == edchars.erase || ch == Ctrl('h')) { if (insert == REPLACE) { @@ -629,6 +672,14 @@ vi_insert(int ch) return 1; case Ctrl('['): + if ((c = x_nbgetc()) != -1) { + if (c == '[') { + escseq = c; + return 0; + } else + x_putback(c); + } +escmode: expanded = NONE; if (first_insert) { first_insert = 0; @@ -673,6 +724,13 @@ vi_insert(int ch) /* End nonstandard vi commands } */ default: + if (escseq) { + escseq = 0; + if (keypad(ch)) + goto escmode; + return 0; + } + if (es->linelen >= es->cbufsize - 1) return -1; ibuf[inslen++] = ch; -- Alexander Polakov | plhk.ru