Как добавить хук zle-init-line, не заменяя существующий хук?

Вопрос или проблема

Я хотел бы запустить некоторый код, когда zle становится активным.

Единственный способ, который я знаю, как это сделать:

zle-init-line() {
    echo hi
}

zle -N zle-init-line

Но, насколько я знаю, это заменит любые потенциальные существующие хуки zle-init-line.

Как я могу либо добавить к существующим хукам (как в случае с precmd, который имеет массив precmd_functions), либо восстановить предыдущее состояние zle-init-line после выполнения моей функции?

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

functions[zle-line-init]+='
    echo hi
'

Если вам нужно запустить код после кода, который определяет zle-line-init, не полагаясь на его простоту, вы можете переименовать существующую функцию и вызвать её.

functions[zle-line-init-before-me]=$functions[zle-line-init]
function zle-line-init {
  zle-line-init-before-me
  echo hi
}

Чтобы сделать это более надежным, структурируйте это как список хуков. Пусть любой существующий код будет одним из элементов списка.

zle_line_init_functions=()
if [[ -v functions[zle-line-init] ]]; then
  functions[zle-line-init-before-me]=$functions[zle-line-init]
  zle_line_init_functions+=zle-line-init-before-me
fi
function zle-line-init {
  local f
  for f in $zle_line_init_functions[@]; do
    $f $@[@] || return $?
  done
}

Ответ или решение

Добавление хуков в Zsh может быть вызвано необходимостью выполнить пользовательский код каждый раз, когда активируется функция zle (Zsh Line Editor). Однако, проблема в том, что использование:

zle-init-line() {
    echo hi
}

zle -N zle-init-line

заменяет любые существующие хуки zle-init-line, что может быть нежелательным. В этой статье мы рассмотрим несколько решений, которые помогут вам добавить новый функционал без замены существующих хуков, сохраняя их в целостности.

Использование простого добавления к существующему хуку

Если вы уверены, что zle-init-line не использует команду return, вы можете просто добавить свою команду непосредственно в уже существующий хук:

functions[zle-line-init]+='
    echo hi
'

Этот метод прост и эффективен, однако он ограничен: использование return в существующей функции zle-line-init приведет к тому, что ваша команда будет пропущена.

Переименование существующей функции и создание новой

Если вам нужно гарантировать, что ваш код будет выполнен после выполнения существующих команд, без зависимости от их структуры, лучше переименовать существующий хук и вызвать его внутри нового хука:

functions[zle-line-init-before-me]=$functions[zle-line-init]
function zle-line-init {
    zle-line-init-before-me
    echo hi
}

Этот подход позволяет сохранить оригинальный функционал и добавляет ваш собственный код.

Более устойчивый вариант: структура в виде списка хуков

Для более комплексных сценариев хорошим вариантом будет создание списка хуков, который позволяет управлять порядком выполнения функций:

zle_line_init_functions=()
if [[ -v functions[zle-line-init] ]]; then
    functions[zle-line-init-before-me]=$functions[zle-line-init]
    zle_line_init_functions+=zle-line-init-before-me
fi

function zle-line-init {
    local f
    for f in "${zle_line_init_functions[@]}"; do
        $f "$@" || return $?
    done
    echo hi  # Ваш код
}

В данном примере мы проверяем, существует ли функция zle-line-init. Если да, мы сохраняем её в новом именованном хуке zle-line-init-before-me, после чего добавляем его в массив zle_line_init_functions. Затем, при выполнении нового хука zle-line-init, мы проходимся по всем функциям в массиве и вызываем их. Ваш собственный код выполняется в конце, обеспечивая выполнение всех предшествующих инструкций.

Заключение

Используя описанные выше методы, вы можете добавить новый код при активации zle, не заменяя существующие хуки. В зависимости от ваших потребностей, вы можете выбрать наиболее подходящий подход: от простого добавления к более сложной и безопасной структуре с использованием массивов хуков. Применяя эти методы, вы можете гибко управлять функциями вашего окружения Zsh, минимизируя риски нарушения существующего функционала вашей оболочки.

Оцените материал
Добавить комментарий

Капча загружается...