Можно ли использовать сценарий завершения табуляции Bash в zsh?

87

У меня есть сценарий завершения вкладки Bash для Apache Hadoop. Обычно я использую zsh как свою повседневную оболочку. Он имеет тенденцию быть довольно похожим на bash, когда мне это нужно, но похоже, что системы завершения табуляции радикально отличаются между ними. Есть ли простой способ «преобразовать» существующие определения завершения bash-tab для работы в zsh? Я не хочу тратить на это кучу времени, но если это будет легко, я сэкономлю умеренное количество усилий.

Кодерер
источник

Ответы:

39

На этой странице (от 01.01.2010 г.):

Zsh может обрабатывать функции завершения bash. В последней разрабатываемой версии zsh есть функция bashcompinit, которая при запуске позволяет zsh читать спецификации и функции завершения bash. Это описано на странице руководства zshcompsys. Чтобы использовать это, все, что вам нужно сделать, это запустить bashcompinit в любое время после compinit. Он будет определять функции complete и compgen, соответствующие встроенным командам bash.

Приостановлено до дальнейшего уведомления.
источник
Хорошие новости: я думаю, это должно сработать, поэтому большое спасибо. Плохая новость: по какой-то причине система, на которой я пытаюсь это сделать, не загружает / etc / zshrc, когда я вхожу в систему через SSH. Я недостаточно знаю о процессе входа в систему, чтобы объяснить, почему это так. Может, пора задать еще один вопрос ...
Coderer
1
@Coderer: Прежде всего, вы говорите "/ etc / zshrc". В моей системе это /etc/zsh/zshrc. Кроме того , проверьте следующие файлы в обратном порядке (перечислены в порядке их соерсед при ЗШ запуске): /etc/zsh/zshenv, $ZDOTDIR/.zshenv, /etc/zsh/zprofileи $ZDOTDIR/.zprofile(возможно ~/.zprofile) , чтобы увидеть , если RCSпеременная не установлена. Если это так, то это предотвратит получение следующих файлов после файла, в котором он не установлен. Наконец, проверьте оболочку для пользователя /etc/passwdи убедитесь, zshчто она не имеет -fаргументов.
Приостановлено до дальнейшего уведомления.
Спасибо за все отзывы - я прибег к классическому способу программирования №1, «отладке stdout» (эхо-выражения в каждом сценарии запуска) и обнаружил проблему. По какой-то причине наш / etc / zprofile получал различные сценарии /etc/profile.d, которые затем снова загружались в / etc / zshrc. Простое перемещение операторов автозагрузки в начало / etc / zprofile решило проблему.
Coderer
157
autoload bashcompinit
bashcompinit
source /path/to/your/bash_completion_file
фристайлер
источник
10
Это лучший ответ, поскольку в нем рассказывается, как использовать bashcompinit. Хорошая работа.
pyrospade
5
Спасибо, отличный ответ, к сожалению, это не сработает, если сценарий использует команду _init_completion bash.
0fnt
6
У меня это не сработало. Я все еще получал complete:13: command not found: compdefошибку.
Джатин Кумар
Если не работает, проверьте скрипт (дох :)) - возможно, if is-bashвверху есть галочка.
olejorgenb 02
Это не работает для некоторых скриптов, использование _get_comp_words_by_refкоторых не определено bashcompinit. Однако большинство доработок не используют эту функцию.
Франклин Ю,
39
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source /path/to/your/bash_completion_script

Я использую zsh zsh 5.0.2 (x86_64-apple-darwin13.0) без ~ / .zshrc и приведенная выше последовательность работала в только что созданной оболочке zsh.

Спасибо скрипту git-Completion.bash за подсказку: D


Читайте подробнее о трех строках выше:

Bash имеет потрясающую встроенную поддержку автозаполнения, но скрипты автозаполнения bash не работают напрямую zsh, поскольку в среде zsh нет основных вспомогательных функций автозаполнения bash, таких как compgen,complete . Это делается для того, чтобы сессия zsh оставалась быстрой.

В наши дни zsh поставляется с соответствующими сценариями завершения, такими как compinitиbashcompinit которые имеют необходимые функции для поддержки сценариев автозаполнения bash.

autoload <func_name>: Обратите внимание, что автозагрузка определяется в zsh, а не в bash. autoloadищет файл с именем в пути к каталогам, возвращаемым fpathкомандой, и отмечает функцию для загрузки при первом вызове.

  • -U: игнорировать любые псевдонимы при загрузке такой функции, как compinit или bashcompinit
  • + X: просто загрузите названную функцию fow и не выполняйте ее

Например , на моей системе echo $fpathвозвратов /usr/share/zsh/site-functionsи /usr/share/zsh/5.0.5/functionsи как compinitи bashcompinitдоступны в /usr/share/zsh/5.0.5/functions.

Кроме того, для большинства людей , может быть только autoload -U +X bashcompinit && bashcompinitтребуется потому , что какой -либо другой сценарий , как мерзавца автозаполнения или их собственные ~/.zshrcможет делать autoload -U +X compinit && compinit, но это безопасно просто запустить их обоих.

Джатин Кумар
источник
Что -Uи +Xдля чего?
jmk
Обновленный ответ с более подробной информацией.
Джатин Кумар
6
В этом все еще мало смысла; на странице руководства описывается суть +X fooвыполнения той же автоматической загрузки, что и при вызове foo, но без его немедленного выполнения… так что autoload +X foo && fooкажется полностью излишним. Вы можете объяснить, почему вы выбрали этот узор?
ELLIOTTCABLE
2
@ELLIOTTCABLE Смысл в autoload -U +X bashcompinit && bashcompinitтом, что (из-за &&) он выполнит bashcompinitIFF, модуль действительно найден. Нормальный autoload fooвсегда возвращает истину. Позже, когда вы пытаетесь запустить foo, то ЗШ наконец говорит вам «файл определение функции не найден». С autoload +Xвами получите ошибку немедленно.
FeRD
1
Мне кажется, что справочная страница все еще несколько неясна: autoload +Xзагружает функцию, не выполняя ее - а это больше, чем autoloadработает без +X. Без +Xавтозагрузки даже функция не загружается; Он просто отмечает имя как ссылку на функцию, которая будет загружена позже. Фактическая загрузка не выполняется до первого вызова функции. Если вы хотите определить, успешно ли загружается названная функция , вам нужно использовать +Xдля немедленного выполнения шага загрузки.
FeRD
4

Для zshиспользования:

  • compdef
  • compadd

Мой пример:

# bash completion for bxrun (/home/ecuomo/projects/bashx/bxrun)
_bxrun_methods() {
    grep "^\s*\(function\s\+\)\?__.\+()\s*{.*$" "${1}" | while read line ; do
        echo "$line" | sed "s/()\s*{.*//g" | sed "s/\s*\(function\s\+\)\?__//g"
    done
}
_bxrun_lst() {
    if [ -d "/home/ecuomo/projects/bashx/src/actions" ]; then
        for f in /home/ecuomo/projects/bashx/src/actions/* ; do
            if [ -f "${f}" ]; then
                basename "${f}" | sed 's/\..*$//g'
            fi
        done
    fi
    _bxrun_methods "/home/ecuomo/projects/bashx/bxrun"
    _bxrun_methods "/home/ecuomo/projects/bashx/src/bashx.sh"
}
_bxrun() {
    local cur
    COMPREPLY=()
    cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $( compgen -W '$( _bxrun_lst )' -- $cur  ) )
}
_bxrun_zsh() {
    compadd `_bxrun_lst`
}
if type complete >/dev/null 2>/dev/null; then
    # bash
    complete -F _bxrun bxrun
else if type compdef >/dev/null 2>/dev/null; then
    # zsh
    compdef _bxrun_zsh bxrun
fi; fi

Источник: Мой код https://github.com/reduardo7/bashx

Эдуардо Куомо
источник
1
Вы должны сообщить, что являетесь автором связанного фреймворка bashx.
Бен
4

Я запускаю Antigen как менеджер плагинов Oh-My-Zsh. У меня было несколько сценариев завершения bash, написанных коллегами, которые я хотел загрузить в Zsh с помощью простогоsource /path/to/completion .

У меня были проблемы, потому что похоже, что Antigen или OMZ (трудно сказать) заботятся только о загрузке скриптов завершения из своих плагинов. Я наконец-то обошел это путем автозагрузки bashcompinit и compinit после antigen apply. Одной автозагрузки bashcompinitбыло недостаточно.

source ~/.antigen/antigen.zsh
antigen use oh-my-zsh
antigen apply

autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit

source /path/to/bash_completion

Antigen создает свой .zcompdumpфайл, в $ANTIGEN_COMPDUMPкотором у меня был~/.antigen/.zcompdump

Повторный вызов compinit и bashcompinit создает второй .zcompdump в $HOME/.zcompdump

Это кажется всем удается, потому что я могу использовать дополнение , настроенное /path/to/bash_completion. Я удалил оба файла .zcompdump несколько раз, чтобы убедиться, что они восстановлены и работают.

Мне приходилось перезагружать файлы .zcompdump несколько раз после перезагрузки компьютера из-за ошибок, возникающих при попытке завершения вкладки, но я не уверен, связано ли это с этой настройкой или чем-то еще. rm ~/.zcompdump && rm $ANTIGEN_COMPDUMPи новая оболочка исправляет это для меня.

Версии, использованные на момент написания:

Antigen = v2.2.3 = d3d4ee0
Oh-my-zsh = c3b072e
Zsh = 5.3
Уолтер Уилфингер
источник
0

Ответ @ JatinKumar направил меня на правильный путь, но мне пришлось использовать completeвместо source. Итак все вместе:

autoload -Uz compinit && compinit
autoload -U +X bashcompinit && bashcompinit

complete -C /usr/local/bin/terraform terraform
complete -C /usr/local/aws/bin/aws_completer aws
complete -C /usr/local/bin/az az
jschmitter
источник