Apply post-1.20.0 patches, bump version to 1.20.1
[oweals/busybox.git] / libbb / lineedit.c
index 603bbfcae7573299809487b2025de30a1ec26c55..b89748a1c64f4df14e003e2649ac95cd138e479e 100644 (file)
@@ -1352,8 +1352,7 @@ static void load_history(line_input_t *st_parm)
                /* fill temp_h[], retaining only last MAX_HISTORY lines */
                memset(temp_h, 0, sizeof(temp_h));
                idx = 0;
-               if (!ENABLE_FEATURE_EDITING_SAVE_ON_EXIT)
-                       st_parm->cnt_history_in_file = 0;
+               st_parm->cnt_history_in_file = 0;
                while ((line = xmalloc_fgetline(fp)) != NULL) {
                        if (line[0] == '\0') {
                                free(line);
@@ -1361,8 +1360,7 @@ static void load_history(line_input_t *st_parm)
                        }
                        free(temp_h[idx]);
                        temp_h[idx] = line;
-                       if (!ENABLE_FEATURE_EDITING_SAVE_ON_EXIT)
-                               st_parm->cnt_history_in_file++;
+                       st_parm->cnt_history_in_file++;
                        idx++;
                        if (idx == st_parm->max_history)
                                idx = 0;
@@ -1520,8 +1518,10 @@ static void remember_in_history(char *str)
                for (i = 0; i < state->max_history-1; i++)
                        state->history[i] = state->history[i+1];
                /* i == state->max_history-1 */
-               if (ENABLE_FEATURE_EDITING_SAVE_ON_EXIT && state->cnt_history_in_file)
+# if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
+               if (state->cnt_history_in_file)
                        state->cnt_history_in_file--;
+# endif
        }
        /* i <= state->max_history-1 */
        state->history[i++] = xstrdup(str);
@@ -2204,14 +2204,17 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
 #define command command_must_not_be_used
 
        new_settings = initial_settings;
-       new_settings.c_lflag &= ~ICANON;        /* unbuffered input */
-       /* Turn off echoing and CTRL-C, so we can trap it */
-       new_settings.c_lflag &= ~(ECHO | ECHONL | ISIG);
-       /* Hmm, in linux c_cc[] is not parsed if ICANON is off */
+       /* ~ICANON: unbuffered input (most c_cc[] are disabled, VMIN/VTIME are enabled) */
+       /* ~ECHO, ~ECHONL: turn off echoing, including newline echoing */
+       /* ~ISIG: turn off INTR (ctrl-C), QUIT, SUSP */
+       new_settings.c_lflag &= ~(ICANON | ECHO | ECHONL | ISIG);
+       /* reads would block only if < 1 char is available */
        new_settings.c_cc[VMIN] = 1;
+       /* no timeout (reads block forever) */
        new_settings.c_cc[VTIME] = 0;
-       /* Turn off CTRL-C, so we can trap it */
-       new_settings.c_cc[VINTR] = _POSIX_VDISABLE;
+       /* Should be not needed if ISIG is off: */
+       /* Turn off CTRL-C */
+       /* new_settings.c_cc[VINTR] = _POSIX_VDISABLE; */
        tcsetattr_stdin_TCSANOW(&new_settings);
 
 #if ENABLE_USERNAME_OR_HOMEDIR
@@ -2504,6 +2507,44 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
                                vi_cmdmode = 1;
                                input_backward(1);
                        }
+                       /* Handle a few ESC-<key> combinations the same way
+                        * standard readline bindings (IOW: bash) do.
+                        * Often, Alt-<key> generates ESC-<key>.
+                        */
+                       ic = lineedit_read_key(read_key_buffer, timeout);
+                       switch (ic) {
+                               //case KEYCODE_LEFT: - bash doesn't do this
+                               case 'b':
+                                       ctrl_left();
+                                       break;
+                               //case KEYCODE_RIGHT: - bash doesn't do this
+                               case 'f':
+                                       ctrl_right();
+                                       break;
+                               //case KEYCODE_DELETE: - bash doesn't do this
+                               case 'd':  /* Alt-D */
+                               {
+                                       /* Delete word forward */
+                                       int nc, sc = cursor;
+                                       ctrl_right();
+                                       nc = cursor;
+                                       input_backward(cursor - sc);
+                                       while (--nc >= cursor)
+                                               input_delete(1);
+                                       break;
+                               }
+                               case '\b':   /* Alt-Backspace(?) */
+                               case '\x7f': /* Alt-Backspace(?) */
+                               //case 'w': - bash doesn't do this
+                               {
+                                       /* Delete word backward */
+                                       int sc = cursor;
+                                       ctrl_left();
+                                       while (sc-- > cursor)
+                                               input_delete(1);
+                                       break;
+                               }
+                       }
                        break;
 #endif /* FEATURE_COMMAND_EDITING_VI */
 
@@ -2532,9 +2573,11 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
                        input_backward(1);
                        break;
                case KEYCODE_CTRL_LEFT:
+               case KEYCODE_ALT_LEFT: /* bash doesn't do it */
                        ctrl_left();
                        break;
                case KEYCODE_CTRL_RIGHT:
+               case KEYCODE_ALT_RIGHT: /* bash doesn't do it */
                        ctrl_right();
                        break;
                case KEYCODE_HOME: