Чи можна використовувати скрипт завершення вкладки Bash у zsh?


87

У мене є скрипт завершення вкладки Bash для Hadoop від Apache. Зазвичай я використовую zsh як свою щоденну оболонку. Це, як правило, досить схоже на баш, коли мені це потрібно, але схоже, що системи заповнення вкладок кардинально відрізняються між собою. Чи існує простий спосіб "перетворити" існуючі визначення завершення bash-tab на роботу в zsh? Я не хочу вкладати в це тону часу, але якщо це легко, я заощаджу помірні зусилля.

Відповіді:


39

З цієї сторінки (від 05.01.2010):

Zsh може обробляти функції завершення bash. Остання версія розробника zsh має функцію bashcompinit, яка при запуску дозволить zsh читати специфікації та функції завершення bash. Це задокументовано на керівництві zshcompsys. Для його використання потрібно лише запустити bashcompinit у будь-який час після складання. Він визначатиме повні функції та функції 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. Хороша робота.
піроспада

5
Дякую, чудова відповідь, на жаль, це не працює, якщо сценарій використовує команду _init_completion bash.
0fnt

6
Це не спрацювало для мене. Я все ще отримував complete:13: command not found: compdefпомилку.
Ятін Кумар

Якщо це не спрацює, перевірте сценарій (doh :)) - він може мати 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-complete.bash для підказки: D


Прочитайте, щоб отримати докладнішу інформацію над 3 рядками:

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

Оновлена ​​відповідь із більш детальною інформацією.
Jatin Kumar

6
Це все ще мало сенсу; manpage описує пункт, +X fooяк робити те саме автоматичне завантаження, яке тільки fooвикликає, але без негайного його виконання ... так autoload +X foo && fooздається абсолютно зайвим. Чи можете ви пояснити, чому обрали саме цей шаблон?
ELLIOTTCABLE

2
@ELLIOTTCABLE Сенс цього autoload -U +X bashcompinit && bashcompinitполягає в тому, що (завдяки &&) він буде виконувати bashcompinitIFF, який фактично знайдено. Звичайне autoload fooзавжди повертає істину. Пізніше, коли ви спробуєте запустити foo, тоді zsh нарешті скаже вам "файл визначення функції не знайдений". З 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

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