Що таке еквівалент ZSH від $ PROMPT_COMMAND $ BASH?


24

BASH підтримує $PROMPT_COMMANDзмінну середовища, яка визначає команду, яку потрібно виконати перед будь-яким інтерактивним запитом першого рівня. Я шукаю ZSH, еквівалент цього.

Документація говорить про те, що є функція, яку precmdя можу визначити, щоб досягти цього; однак я не маю уявлення, як це визначити із змінної середовища.

Я розглядав можливість передачі змінної середовища, яка б змусила ZSH прочитати файл, що містить визначення цієї функції, але ZSH , схоже, не підтримує такі речі : він читає лише глобальні файли, а потім файли для кожного користувача. Я можу їх замінити, але не можу додати їх без зміни файлів, чого я не можу зробити.

Тож як я можу визначити попереджувальний гачок у ZSH через змінну середовища, як я б це робив $PROMPT_COMMANDу BASH?


Правду кажучи, мені потрібен гачок після виконання інтерактивних команд-виконання, але жодна оболонка не забезпечує жодного, тому мені доведеться вдаватися до попередньо підкачених гачків - вони здаються настільки ж близькими, наскільки я можу підійти.
Шнацель

1
Гм, мені цікаво, в чому різниця між пост-інтерактивною командою-виконанням та попередньою підказкою . Крім концептуальної різниці, де ви спостерігаєте насправді різницю. ( exitexec;)
Опустимо

@mpy Є різниця при виконанні фонового завдання, оскільки фонові завдання не залежать від послідовності підказок.
Шнацель

1
Гаразд, я зрозумів це. Отже, як щодо чогось подібного: start() { eval "$@"; echo post-command-code }а потім використовувати zle-прив'язку для виконання командного рядка з попередньою startформою?
mpy

1
DEBUGПастка хороша знахідка, але ви все ще є проблема , як визначити його. Я ще раз продовжив свою відповідь, але я залишаю вам, щоб написати власну відповідь щодо рішення DEBUG trap. :)
mpy

Відповіді:


24

Найпростіший підхід до емуляції bash, $PROMPT_COMMANDякий мені спадає на думку, - це використовувати precmdгачок, як ви вже зрозуміли. Визначте це як

precmd() { eval "$PROMPT_COMMAND" }

і ви можете зробити щось подібне:

$ PROMPT_COMMAND='echo Hello, it is now $(date)'
Hello, it is now Mon, Mar 31, 2014 7:08:00 PM
$ whoami      
user
Hello, it is now Mon, Mar 31, 2014 7:08:21 PM     
$

Зверніть увагу, що в цьому прикладі єдина цитата, інакше вона $(date)буде розширена занадто рано, тобто вже при визначенні, $PROMPT_COMMANDа не при виклику перед запитом.


Якщо ви хочете зберегти існуюче визначення (і не хочете змінювати), ви можете використовувати такий підхід:

$ prmptcmd() { eval "$PROMPT_COMMAND" }
$ precmd_functions=(prmptcmd)

При цьому prmptcmdфункції виконуються після існуючої precmd()функції.


Нарешті, ось спосіб, який підходить для використання в програмному пакеті, який не повинен змінювати користувачів або системні файли, а також не може вводити команди інтерактивно.

Прикладом для нерестування баш-сеансу може бути

PROMPT_COMMAND="echo foo" bash

Для нересту zsh можна використовувати

ZDOTDIR=/program/dir zsh

що спричиняє /program/dir/.zshrcджерело. У цьому файлі precmd()гак можна визначити, як пояснено вище. Якщо ви хочете, щоб налаштування користувача додатково включали source $HOME/.zshrcі т.д. в програму .zshrc. Ця настройка є досяжною, оскільки жодні файли поза каталогом програм не змінюються.


Як останнє доповнення, ось доказ концепції, як зберегти нового користувача, також. Використовуйте наступний код у /program/dir/.zshenvфайлі конфігурації rc:

echo define precmd, traps, etc.

autoload -Uz zsh-newuser-install

if [[ ! -e "$HOME/.zshrc" ]]; then
  zsh-newuser-install -f
  mv $ZDOTDIR/.zshrc $HOME/.zshrc
else
  builtin source $HOME/.zshrc
fi

Стільки я зрозумів. Проблема полягає в тому, як я можу визначити гачок precmd через змінну середовища? Чи існує механізм додавання гаків або коду без зміни файлів? Або як це зробити принаймні, не записуючи на глобальний та користувальницький ".zprofile" та подібні файли? Можливо, чи можу я додати власний .zprofile, який не замінить існуючі?
Шнацель

1
Також ваше використання гачка precmd тут замінить будь-які наявні гачки precmd; zsh docs згадую, що я можу створити масив функцій, які будуть співіснувати, але я не маю уявлення, як це зробити.
Шнацель

1
(1) Що ви маєте на увазі, як визначити гачок precmd через змінну середовища? На прикладі, який я представив, працює IMHO як механізм bash. (2) Ви можете додати гачок за допомогою командного рядка, але тоді він не є постійним. У чому проблема з модифікацією вашого .zshrc? (3) Приклад: foo() { echo foo }; bar() { echo bar }; precmd_functions=(foo bar)Це виконується foo()і bar() на додаток до precmd().
mpy

2
Гаразд, це багато що пояснює - мінімальний приклад для bash тоді був би PROMPT_COMMAND="echo foo" bash, правда? Чи є це можливість для нересту zsh : ZDOTDIR=/program/dir zsh. Після цього /program/dir/.zshrcрозміщується на початку, де можна визначити гачок precmd (). Якщо ви хочете, щоб користувач додатково включив source $HOME/.zshrcі т.д. в zshrc програми. Це має бути простим у обслуговуванні, оскільки жодні файли поза програмним редактором не змінюються.
mpy

1
@Shnatsel: Я продовжив свою відповідь. Можливо, ви також можете відредагувати своє запитання, щоб включити додаткову інформацію з ваших коментарів.
mpy

5

Як стверджує @mypy, Zsh precmdпрацює так само, як у Баша PROMPT_COMMAND.

Ось приклад, який працює для Bash або Zsh і не використовує eval:

## ~/myprompt.sh

# 'ZSH_VERSION' only defined in Zsh
# 'precmd' is a special function name known to Zsh

[ ${ZSH_VERSION} ] && precmd() { myprompt; }

# 'BASH_VERSION' only defined in Bash
# 'PROMPT_COMMAND' is a special environment variable name known to Bash

[ ${BASH_VERSION} ] && PROMPT_COMMAND=myprompt

# function called every time shell is about to draw prompt
myprompt() {
  if [ ${ZSH_VERSION} ]; then
    # Zsh prompt expansion syntax
    PS1='%{%F{red}%}%n%{%f%}@%{%F{red}%}%m %{%F{cyan}%}%~ %{%F{white}%}%# %{%f%}'
  elif [ ${BASH_VERSION} ]; then
    # Bash prompt expansion syntax
    PS1='\[\e[31m\]\u\[\e[0m\]@\[\e[31m\]\h \[\e[36m\]\w \[\e[37m\]\$ \[\e[0m\]'
  fi
}

Запустити з скриптів init init:

## ~/.bashrc
. ~/myprompt.sh

і:

## ~/.zshrc
. ~/myprompt.sh

Тут підказки - лише приклади. Однозначно можна зробити набагато складніше.

Докладніше про налаштування функцій підказок див. На веб-сторінці: http://zsh.sourceforge.net/Doc/Release/Functions.html#index-precmd та http://www.gnu.org/software/bash/manual/bashref.html # Друк A-Prompt .

Докладніше про оперативні розширення див. У розділі http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html та http://www.gnu.org/software/bash/manual/bashref.html#Printing-a -Разбійний .

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