* Alexander Polakov <[email protected]> [110721 22:01]:
> * Dmitrij D. Czarkoff <[email protected]> [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