Как включить клавиши со стрелками вверх / вниз для отображения предыдущих вводов при использовании `read`?

Я ожидая ввода пользователя (с помощью 'read') в бесконечном цикле и хотел бы иметь историю команд, которая позволяет отображать предыдущие вводимые данные, которые уже были введены, с помощью клавиш со стрелками вверх и вниз вместо получения ^ [[A и ^ [[B. Возможно ли это?


Спасибо @ l0b0 за ваш ответ. Это привело меня в правильное русло. Поиграв с ней некоторое время, я понял, что мне также нужны следующие две функции, но мне еще не удалось их получить:

  • Если я нажму и добавлю что-то к предыдущей команде, я бы хотел, чтобы в истории сохранено все, а не только дополнение. Пример

    $ ./up_and_down
    Введите команду: hello
    ENTER
    Введите команду:
    Вверх
    Введите команду: привет
    ENTER
    Введите команду:
    Вверх
    Введите команду: вы
    (вместо «привет»)

  • Если я не могу продолжать движение вверх, потому что я нахожусь в конце массива истории, я не хочу, чтобы курсор перемещался на предыдущую строку, вместо этого я хочу, чтобы он оставаться на месте.

Это то, что у меня есть (up_and_down):

#!/usr/bin/env bash
set -o nounset -o errexit -o pipefail

read_history() {
    local char
    local string
    local esc=$'\e'
    local up=$'\e[A'
    local down=$'\e[B'
    local clear_line=$'\r\e[K'


    local history=()
    local -i history_index=0

    # Read one character at a time
    while IFS="" read -p "Enter command:" -n1 -s char ; do
        if [[ "$char" == "$esc" ]]; then 
            # Get the rest of the escape sequence (3 characters total)
            while read -n2 -s rest ; do
                char+="$rest"
                break
            done
        fi

        if [[ "$char" == "$up" && $history_index > 0 ]] ; then
            history_index+=-1
            echo -ne $clear_line${history[$history_index]}
        elif [[ "$char" == "$down" && $history_index < $((${#history[@]} - 1)) ]] ; then
            history_index+=1
            echo -ne $clear_line${history[$history_index]}
        elif [[ -z "$char" ]]; then # user pressed ENTER
            echo
            history+=( "$string" )
            string=
            history_index=${#history[@]}
        else
            echo -n "$char"
            string+="$char"
        fi
    done
}
read_history
13
задан nachocab 2 September 2015 в 14:51
поделиться