скажіть, чи остання команда була порожньою в PROMPT_COMMAND


12

В bash, зсередини PROMPT_COMMAND, чи є спосіб сказати, чи користувач просто натиснув "return" і не ввів команду?

Відповіді:


7

Перевірте, чи збільшено номер історії. Скасований запит або підказка, коли користувач щойно натиснув Enter, не збільшуватиме номер історії.

Номер історії доступний у змінній HISTCMD, але це недоступно в PROMPT_COMMAND(тому, що ви там хочете, це насправді номер історії попередньої команди; команда, яка PROMPT_COMMANDсама виконує, не має номера історії). Ви можете отримати номер на виході fc.

prompt_command () {
  HISTCMD_previous=$(fc -l -1); HISTCMD_previous=${HISTCMD_previous%%$'[\t ]'*}
  if [[ -z $HISTCMD_before_last ]]; then
    # initial prompt
  elif [[ $HISTCMD_before_last = "$HISTCMD_previous" ]]; then
    # cancelled prompt
  else
    # a command was run
  fi
  HISTCMD_before_last=$HISTCMD_previous
}
PROMPT_COMMAND='prompt_command'

Зауважте, що якщо ви ввімкнули стискання дублікатів в історії ( HISTCONTROL=ignoredupsабо HISTCONTROL=erasedups), це помилково повідомить про порожню команду після послідовного запуску двох однакових команд.


Спасибі, Жилле. Я чогось тут пропускаю. Це, здається, ніколи не працює, оскільки поставити "ехо-привіт" на перший рядок буквальної функції не працює, хоча PROMPT_COMMAND = 'echo hello ". Я думав, що це може бути проблема HISTCMD_previous проти HISTCMD_PREVIOUS, але без кісток. Я буду продовжувати мотати, але я коментую, як ваш баш-фу явно виходить за межі мого.
користувач

@user Я зафіксував більше помилок, зокрема, ${HISTCMD_previous%%$'[\t ]'*}біт відсутній $'…'і закінчив обрізання після `, t` або пробілу замість після вкладки чи пробілу, але bash друкує вкладку.
Жил "ТАК - перестань бути злим"

1
Це рішення засноване на припущенні, що дублікати зберігаються в історії (що для мене ВИМКНЕНО). Отже, це рішення не працює, як очікувалося, для повторних команд, поки дублікати не зберігаються в історії.
schlimmchen

4

Існує рішення, але воно має деякі вимоги:

Потрібно встановити $HISTCONTROLдля збереження ВСІХ команд, а також дублікатів та пробілів. Так встановлено:

HISTCONTROL=

Тепер визначте функцію для виклику як $PROMPT_COMMAND:

isnewline () {
  # read the last history number
  prompt_command__isnewline__last="$prompt_command__isnewline__curr"
  # get the current history number
  prompt_command__isnewline__curr="$(history 1 | grep -oP '^\ +\K[0-9]+')"
  [ "$prompt_command__isnewline__curr" = "$prompt_command__isnewline__last" ] && \
    echo "User hit return"
}

Тепер встановіть $PROMPT_COMMANDзмінну:

PROMPT_COMMAND="isnewline"

Дивіться вихід:

user@host:~$ true
user@host:~$ <return>
User hit return
user@host:~$ <space><return>
user@host:~$ 

Я не розумію, чому ви тут використовуєте тимчасовий файл. Змінна lastзберігається від одного виклику isnewlineдо наступного (виберіть лише менш загальне ім'я, як prompt_command__isnewline__lastщоб уникнути зіткнень).
Жиль "ТАК - перестань бути злим"

@Gilles Ви маєте рацію, я змінив це, дякую за вашу пропозицію
хаос

Спасибі, хаос. Я використовував ту саму ідею для наступного, що трохи простіше розібратися. HISTCONTROL="" function last_was_blank { local last_command="$(history 1)" if [[ "$last_was_blank_PREVIOUS_LINE" = "$last_command" ]] ; then echo "true" else echo "false" fi export last_was_blank_PREVIOUS_LINE="$last_command" } PROMPT_COMMAND=last_was_blank
користувач

1

Я не знаю спосіб зробити це, самі по собі . Але такий же ефект можна отримати, використовуючи

пастка some_command_or_function налагодження

Це призведе some_command_or_functionдо виклику кожного разу, коли ви запускаєте команду. Справа в тому, що він не буде викликаний, якщо ви просто натиснете Enter- якщо у вас не визначено PROMPT_COMMAND, у цьому випадку натискання Enterвикликає PROMPT_COMMAND, що, в свою чергу, запускає пастку.

Мабуть, найпростіший спосіб досягти бажаного результату - це визначити функцію пастки налагодження замість використання PROMPT_COMMAND. Але я не можу сказати, тому що я не знаю, якого результату ви хочете. Якщо ви хочете, щоб щось траплялося, коли ви просто натискаєте Enter, і щось друге / додаткове трапляється, коли ви вводите команду, тоді (AFAIK) вам потрібно використовувати пастку налагодження та PROMPT_COMMAND. Дивіться цю відповідь, і  це - спосіб змусити два механізми гарно грати разом.


0

(Це був би коментар до прийнятої відповіді, якби мені дозволили додати коментарі ...) @schlimmen, ви можете встановити HISTTIMEFORMATщось на кшталт, HISTTIMEFORMAT='%F %T 'а потім зберегти та порівняти history 1. Причиною цього є те, що при видаленні часу принаймні часова мітка (можливо повторювана) остання команда змінюється щоразу --- і при HISSTIMEFORMATналежному встановленні history 1буде відображати часову позначку (на відміну від цього fc) і, таким чином, відрізнятися навіть між повторними командами.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.