Ohmyzsh: завершение git не выполняется, если установлена ​​опция complete_aliases

Созданный на 2 янв. 2014  ·  40Комментарии  ·  Источник: ohmyzsh/ohmyzsh

Я запускаю zsh 5.0.4 на OS X 10.8 с oh-my-zsh a38af27 с плагином git . Когда я набираю gco <TAB> , я получаю следующий результат:

% gco zsh:12: command not found: __git-checkout_main
extegco
file
MIT-LICENSE.txt  custom/          log/             plugins/         themes/
README.textile   lib/             oh-my-zsh.sh     templates/       tools/

Я обнаружил, что виноват вариант complete_aliases . Как только я его выключаю, все работает как положено.

Что дает? Есть ли вариант коллизии? Я давно не менял свои .zshrc , и у меня всегда были complete_aliases .

Мне эта опция особо не нужна, но, думаю, здесь есть какая-то ошибка.

Самый полезный комментарий

Проблема здесь в том, что официальное завершение Git не было подготовлено для 'complete_aliases', я внес исправление:

https://github.com/felipec/git/commit/aaafa76

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

compdef _git gco=git_checkout

Однако, если вы хотите использовать формат zsh: gco=git-checkout и чтобы он работал в распространяемой в настоящее время версии Git, вы можете сделать это:

alias __git-checkout_main=_git_checkout

Все 40 Комментарий

: +1: Точно такая же проблема ... очень озадачивающая.

Интересно.

Для ленивых вот что говорится в руководстве Zsh о complete_aliases :

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

Однако, поскольку 57f55e69ed967e93c0fd44a6a7e470781eb38029 и 2e9492969b0ea90932ad3f4298330b75ef8cf2ce, псевдонимы из подключаемого модуля git имеют собственный набор завершения и gco перенаправляются на соответствующую подкоманду git 1, включая gco . Так что эта проблема _не должна_ возникать. Кто-нибудь знает, почему до сих пор?

Наконец, я не могу воспроизвести проблему с Zsh 5.0.2 на Mac 10.9.2: complete_aliases вообще не изменяет поведение завершения на gco , даже если я очищаю завершение кеш.

@slhck @mecampbellsoup Можете ли вы попробовать с шаблоном .zshrc и посмотреть, происходит ли это по-прежнему?

Также @mecampbellsoup, можете ли вы опубликовать конфигурацию вашей системы и версию Zsh?

@mcornella @simonweil (мои счастливые помощники = D) вы можете попытаться воспроизвести проблему?

Сейчас я использую Zsh 5.0.5 с oh-my-zsh eafd5f3 . Если я использую шаблон .zshrc проблем нет. Конечно, потому что там нет опции complete_aliases .

Как только я включаю setopt complete_aliases , нажатие Tab после gco вызывает ту же старую ошибку.

@ncanceill Конечно, вот и все:

⇒  zsh --version
zsh 5.0.5 (x86_64-apple-darwin13.0.0)⇒  zsh --version
zsh 5.0.5 (x86_64-apple-darwin13.0.0)

Мои полные конфигурации .zshrc и zsh можно найти здесь: https://github.com/mecampbellsoup/dotfiles/tree/master/zsh

Версия oh-my-zsh тоже eafd5f3 .

Понятия не имею .. может быть ошибка compinit cache? Если да, попробуйте удалить файлы .zcompdump* в каталоге $ HOME.

@mcornella К сожалению, это не помогло.

@slhck Думаю, нам стоит начать проверять предыдущие zsh коммиты, чтобы увидеть, сможем ли мы найти ошибку ...?

@mecampbellsoup да, это может быть полезно! Я рекомендую использовать git-bisect .


Невоспроизводимость проблемы предполагает, что она имеет какое-то отношение к вашей конфигурации, а тот факт, что она все еще происходит с шаблоном .zshrc указывает на то, что она не связана с вашей конфигурацией OMZ.

Давайте начнем с определения того, что должен делать оператор compdef . Прочитав руководство по

#compdef names... [ -[pP] patterns... [ -N names... ] ]
Каждое имя также может иметь форму «_cmd = service_». При завершении команды _cmd_ функция обычно ведет себя так, как если бы вместо этого выполнялась команда (или специальный контекст) _service_. Это дает возможность изменить поведение функций, которые могут выполнять множество различных операций. Это реализуется установкой параметра $service при вызове функции; функция может интерпретировать это так, как она хочет, а более простые функции, вероятно, проигнорируют это.

compdef [ -ane ] function names... [ -[pP] patterns... [ -N names... ] ]
Первая форма определяет _function_ для вызова завершения в заданных контекстах, как описано для тега #compdef выше.
В качестве альтернативы все аргументы могут иметь форму «_cmd = service_». Здесь _service_ уже должен был быть определен строками '_cmd1 = service_' в файлах #compdef , как описано выше. Аргумент для _cmd_ будет заполнен так же, как _service_.

Но затем я взглянул на завершение Zsh git (с количеством строк 6661), и git-checkout не указано в операторе #compdef , а $service тоже не проверяется. Так что я понятия не имею, почему работает compdef _git gco=git-checkout но это действительно работает!

@pielgrzym не могли бы вы рассказать нам о 2e9492969b0ea90932ad3f4298330b75ef8cf2ce?

Приятно копать @ncanceill!

$service тоже не проверяется. Так что я понятия не имею, почему compdef _git gco=git-checkout работает - но это действительно работает!

Это действительно проверено внутри функции _git() , CTRL + F показывает, что это простой if-else:

if [[ $service == git ]]; then
    [...]
else
    _call_function ret _$service
fi

поэтому он затем вызывает _git-checkout , который также определен, но только если он не был ранее определен :

(( $+functions[_git-checkout] )) ||
_git-checkout () { [...] }

Может быть, у них обоих есть специальная функция _git-checkout определенная где-то еще, которая запускает это поведение?
Кроме того, в сообщении об ошибке отображается __git-checkout_main (_с двумя знаками подчеркивания_), а затем extegco\n file . Мне кажется, что сообщение перезаписано, как будто zle как-то связано с этим ..

Кстати, источник, который вы связали, был из основной ветки, вот как 5.0.4, так и 5.0.5

Спасибо @mcornella , я нашел чек на $service == git но тупо проигнорировал условие else ! И я не нашел в себе смелости поиграть с программой просмотра SF git (у которой, кстати, нет номеров строк!), Чтобы найти конкретный момент в истории, ленив меня!

Мне нравится ваш намек о том, что _git-checkout не определен, потому что он находится в другом месте. @slhck @mecampbellsoup можно запустить which _git-checkout чтобы проверить правильность работы?

Что касается странного вывода, я видел, как zle делал много странных вещей, поэтому я не слишком удивлен. Но меня сбивает с толку __git-checkout_main как и вам.

И последнее: использование git checkout вместо gco должно показывать такое же поведение.

@ncanceill @mcornella Итак, вот некоторые результаты для вас, оба берутся после попытки завершения табуляции:

matthewcampbell@Matthews-MacBook-Air:~/Sites/code/stack-builders/seo_platform|69220108_adjust_keyword_editing_on_dealer⚡
⇒  gco ......zsh:12: command not found: __git-checkout_main
⇒  git checkout
67061970_notify_sidekiq_hangs                            origin/67061970_notify_sidekiq_hangs                     production
67394702_track_keywords_change                           origin/67394702_track_keywords_change                    production_2014-04-21

(PS Это то же самое, что и результат, когда у меня просто alias gco=git checkout active и я использую gco , т.е. после того, как я закомментировал setopt complete_aliases в моем .zshrc файле )

И когда я спрашиваю о which _git-checkout (а также о which __git-checkout ):

⇒  which _git-checkout
_git-checkout not found
⇒  which __git-checkout
__git-checkout not found

Попробуй это:

autoload -Uz _git-checkout && _git-checkout
which _git-checkout

Извините, но не выяснилось, возникла ли проблема с использованием всего git checkout <TAB> вместо gco <TAB> ..

Также попробуйте полностью отключить OMZ: то есть использовать пустой файл .zshrc . Завершение Git должно сохраниться, и проблема тоже

И последнее: происходит ли то же самое в другом репозитории git?

@mcornella Больше результатов для тебя ':

⇒  autoload -Uz _git-checkout && _git-checkout
zsh: _git-checkout: function definition file not found
⇒  which _git-checkout
_git-checkout () {
    # undefined
    builtin autoload -XUz
}

Похоже, что в основном все мои функции завершения Git, кстати, не работают (мне нужно дважды <TAB> чтобы появились ошибки):

⇒  ga ......zsh:12: command not found: __git-add_main
⇒  gco ......zsh:12: command not found: __git-checkout_main
⇒  gd ......zsh:12: command not found: __git-diff_main
⇒  gst ......zsh:12: command not found: __git-status_main

Я в полном недоумении. Сообщите мне, чем еще я могу помочь.

@mcornella Еще одна очень странная вещь, происходящая в моей настройке, - это результаты моей функции where :

⇒  where ruby
ruby: aliased to bundled_ruby
/Users/matthewcampbell/.rbenv/shims/ruby
/Users/matthewcampbell/.rbenv/shims/ruby
/usr/bin/ruby
⇒  where coqc
/usr/local/bin/coqc
/usr/local/bin/coqc
/usr/local/bin/coqc
/usr/local/bin/coqc

Почему ZSH возвращал мне один и тот же результат 4 раза ?!

Хорошо, потерпите меня, в последний раз:

autoload -Uz _git && _git
which _git-checkout

а также

echo '$fpath = ('$fpath')'
echo '$path = ('$path')'

Также попробуйте то, что я упоминал об использовании пустого файла .zshrc

⇒  autoload -Uz _git && _git
zsh:12: command not found: ___main
_default:compcall:12: can only be called from completion function
⇒  which _git-checkout
_git-checkout not found
⇒  echo '$fpath = ('$fpath')'
$fpath = (/Users/matthewcampbell/.oh-my-zsh/plugins/gem /Users/matthewcampbell/.oh-my-zsh/plugins/brew /Users/matthewcampbell/.oh-my-zsh/plugins/bundler /Users/matthewcampbell/.oh-my-zsh/plugins/git /Users/matthewcampbell/.oh-my-zsh/functions /Users/matthewcampbell/.oh-my-zsh/completions /Users/matthewcampbell/.dotfiles/zsh /Users/matthewcampbell/.dotfiles/xcode /Users/matthewcampbell/.dotfiles/vim /Users/matthewcampbell/.dotfiles/tmux /Users/matthewcampbell/.dotfiles/system /Users/matthewcampbell/.dotfiles/sublime2 /Users/matthewcampbell/.dotfiles/script /Users/matthewcampbell/.dotfiles/ruby /Users/matthewcampbell/.dotfiles/python /Users/matthewcampbell/.dotfiles/osx /Users/matthewcampbell/.dotfiles/macvim /Users/matthewcampbell/.dotfiles/homebrew /Users/matthewcampbell/.dotfiles/git /Users/matthewcampbell/.dotfiles/functions /Users/matthewcampbell/.dotfiles/ctags /Users/matthewcampbell/.dotfiles/cloudapp /Users/matthewcampbell/.dotfiles/bin /Users/matthewcampbell/.dotfiles/functions /usr/local/share/zsh/site-functions /usr/local/Cellar/zsh/5.0.5/share/zsh/functions)
⇒  echo '$path = ('$path')'
$path = (/Users/matthewcampbell/.rbenv/shims /usr/local/opt/coreutils/libexec/gnubin /usr/local/bin /Users/matthewcampbell/.cabal/bin /Applications/Postgres93.app/Contents/MacOS/bin /usr/local/bin /usr/local/heroku/bin ./bin /Users/matthewcampbell/.rbenv/shims /usr/local/bin /usr/local/sbin /Users/matthewcampbell/.sfs /Users/matthewcampbell/.dotfiles/bin /usr/bin /bin /usr/sbin /sbin /usr/local/bin /opt/X11/bin /usr/local/go/bin /usr/local/MacGPG2/bin /Users/matthewcampbell/.rbenv/shims /usr/local/opt/coreutils/libexec/gnubin /Users/matthewcampbell/.cabal/bin /Applications/Postgres93.app/Contents/MacOS/bin /usr/local/heroku/bin ./bin /usr/local/sbin /Users/matthewcampbell/.sfs /Users/matthewcampbell/.dotfiles/bin /usr/local/Cellar/go/1.2.1/bin /usr/local/Cellar/go/1.2.1/bin)

Также попробуйте полностью отключить OMZ: то есть использовать пустой файл .zshrc . Завершение Git должно сохраниться, и проблема тоже

Matthews-MacBook-Air% autoload -Uz _git-checkout && _git-checkout
zsh: _git-checkout: function definition file not found
Matthews-MacBook-Air% gd
zsh: command not found: gd
Matthews-MacBook-Air% gst
zsh: command not found: gst
Matthews-MacBook-Air% gco
zsh: command not found: gco

Похоже, завершение не сохраняется ...

⇒ автозагрузка -Uz _git && _git
zsh: 12 : команда не найдена: ___main

Это подтверждает, что проблема возникает при каждом завершении git, я думаю, что-то не так с _git() . Пожалуйста, опубликуйте результат which _git

Похоже, завершение не сохраняется ...

Когда вы используете zsh без oh-my-zsh, используйте не псевдонимы, а полную команду git, поскольку псевдонимы не определяются без oh-my-zsh. Вы можете перейти в репозиторий git и ввести любую команду git (например, git checkout <TAB> ) с setopt completealiases и без него; Завершение git включено по умолчанию.

Кроме того, похоже, что в вашем пути $ есть повторяющиеся записи; для обеспечения уникальных значений добавьте команду typeset -U path в конец вашего .zshrc (после добавления всех записей пути)

Спасибо @mcornella , мне очень помогло.

⇒  which _git
_git () {
        local _ret=1
        local cur cword prev
        cur=${words[CURRENT]}
        prev=${words[CURRENT-1]}
        let cword=CURRENT-1
        if (( $+functions[__${service}_zsh_main] ))
        then
                __${service}_zsh_main
        else
                emulate ksh -c __${service}_main
        fi
        let _ret && _default && _ret=0
        return _ret
}

Когда вы используете zsh без oh-my-zsh, используйте не псевдонимы, а полную команду git, поскольку псевдонимы не определяются без oh-my-zsh.

Когда я использую полные команды git С АКТИВНЫМ OMZ, поведение немного отличается от того, что я имел раньше с псевдонимами ... взгляните:

⇒  git checkout <TAB>
64879538_fix_li_elements                             master                                               origin/master
64908958_center_products_text_in_div                 next_ror_post                                        origin/next_ror_post
64916916_fix_contact_emails                          origin/64879538_fix_li_elements                      origin/oss_contrib_blog_post
64919128_override_fonts                              origin/64908958_center_products_text_in_div          origin/production
65271680_fix_map_resizing                            origin/64916916_fix_contact_emails                   origin/sprites
65753620_translate_navigation_bar                    origin/64919128_override_fonts                       origin/title-update-final

Раньше при использовании gco <TAB> в качестве параметров отображались только локальные ветки. В приведенном выше выводе отображаются все ветки на удаленном origin .

Вот результат, когда я отключил OMZ и запустил те же команды git :

Matthews-MacBook-Air% git checkout README.md
Procfile                 Setup.hs                 circle.yml               dist/                    node_modules/            stackbuilders.com.cabal
README.md                assets/                  client_session_key.aes   news/                    src/                     tests/

Кажется, что он сломан, что имеет смысл, поскольку я отключил плагин git поскольку он включен в моем .zshrc .

Хорошо, теперь мы знаем, откуда берутся эти _git-checkout_main . Ваша функция _git() испорчена, но я не знаю почему. Я предполагаю, что у вас есть setopt completealiases в вашем .zshrc . Идите дальше и отключите это, а затем снова запустите which _git .
Также опубликуйте файл /usr/local/Cellar/zsh/5.0.5/share/zsh/functions/Completion/Unix/_git по сути

Это с отключенным setopt complete_aliases :

⇒  which _git
_git () {
    # undefined
    builtin autoload -XUz
}

Похоже, у меня нет этого пути к файлу - у меня есть до /functions но не /Completion и более ... (далее партии опущены):

matthewcampbell@Matthews-MacBook-Air:~|
⇒  vim /usr/local/Cellar/zsh/5.0.5/share/zsh/functions/
VCS_INFO_adjust                _dmidecode                     _matlab                        _snoop                         _zpty
VCS_INFO_bydir_detect          _domains                       _md5sum                        _socket                        _zsh-mime-handler
VCS_INFO_check_com             _dpatch-edit-patch             _mdadm                         _sockstat                      _zstyle
VCS_INFO_detect_bzr            _dpkg                          _members                       _softwareupdate                _ztodo
VCS_INFO_detect_cdv            _dpkg-buildpackage             _mencal                        _sort                          _zypper

Хорошо, путь к файлу должен быть /usr/local/Cellar/zsh/5.0.5/functions/Completion/Unix/_git

Что касается _git() , вам нужно попробовать выполнить автозаполнение некоторой команды git перед запуском which _git

Все еще не могу найти этот путь к файлу, брат ... вот Gist с выводом tree из моего каталога ZSH : https://gist.github.com/mecampbellsoup/1065d4228b143140ac69

Вот which _git после запуска функции автозаполнения (в частности, я пробовал ga , gd и gc ):

⇒  which _git
_git () {
    local _ret=1
    local cur cword prev
    cur=${words[CURRENT]}
    prev=${words[CURRENT-1]}
    let cword=CURRENT-1
    if (( $+functions[__${service}_zsh_main] ))
    then
        __${service}_zsh_main
    else
        emulate ksh -c __${service}_main
    fi
    let _ret && _default && _ret=0
    return _ret
}

Хорошо, теперь я понимаю, как Homebrew устанавливает zsh , спасибо за tree gist! Таким образом, ваш файл завершения _git находится в /usr/local/Cellar/zsh/5.0.5/functions/_git . Пожалуйста, опубликуйте это.

Я начинаю думать, что это проблема с вашей домашней установкой zsh. Может, стоит удалить его и снова установить заново .. Или спросите ребят из @Homebrew ?

https://gist.github.com/80a00d7af3766c1ad6dc

@mcornella Как вы думаете, это может иметь какое-то отношение к точечным файлам, которые я установил не так давно? Это @holman ... https://github.com/mecampbellsoup/dotfiles/blob/master/zsh/config.zsh

Что ж, вы правильно установили zsh. Кажется, что у вас есть другое место, которое переопределяет ваше завершение git, потому что ваш which _git и функция _git() определенная в файле _git указанном в сути, очень разные.

Как вы думаете, это может иметь какое-то отношение к точечным файлам, которые я установил не так давно?

Может быть, да. В этом файле находится файл завершения, проверьте его для меня, пожалуйста, и спасибо : cat $(brew --prefix)/share/zsh/site-functions/_git

@slhck , это может быть та же проблема, у вас тоже есть точечные файлы @holman?

Да, виноват этот файл. Определение функции _git () находится внизу файла, вы увидите, что оно совпадает с выводом which _git который вы получаете.

Я не знаю, как тебе теперь действовать. Вы можете переименовать файл, который вы только что указали, чтобы ваш dotfiles не нашел его, или полностью удалите dotfiles , или просто удалите dotfiles/git/completion.zsh из вилки (но тогда у вас будут конфликты слияния при обновлении точечных файлов).

@mcornella Извините, а как вы конкретно объясните такое поведение? Я немного запутался: /

⇒  which _git
_git () {
    # undefined
    builtin autoload -XUz
}
matthewcampbell@Matthews-MacBook-Air:~/.dotfiles|master⚡
⇒  ga
Nothing specified, nothing added.
Maybe you wanted to say 'git add .'?
matthewcampbell@Matthews-MacBook-Air:~/.dotfiles|master⚡
⇒  which _git
_git () {
    local _ret=1
    local cur cword prev
    cur=${words[CURRENT]}
    prev=${words[CURRENT-1]}
    let cword=CURRENT-1
    if (( $+functions[__${service}_zsh_main] ))
    then
        __${service}_zsh_main
    else
        emulate ksh -c __${service}_main
    fi
    let _ret && _default && _ret=0
    return _ret
}

Под _это поведение_ вы имеете в виду разный вывод обоих which _git ? Если да, то это потому, что завершение _autoloaded_, как вы видите в первом which _git . Это означает, что определение загружается только при первой необходимости, поэтому в первый раз, когда вы запрашиваете завершение команды git, это когда функция _git загружает определение.

И правильное поведение, вероятно, в какой-то момент будет перезаписано, вероятно, чем-то в моем config.zsh ?

Да, файл, который загружает старое завершение, и есть этот файл в ваших точечных файлах . Если вы удалите его, вы получите правильное завершение.

Это очень похоже на brew install hub . Взгляните на этот комментарий и на этот выпуск: # 1727.
Следуя совету по последнему, это исправит.

@slhck, вы найдете свое исправление в этом комментарии: https://github.com/robbyrussell/oh-my-zsh/issues/2800#issuecomment -43694975

@mcornella Извините за поздний ответ. У меня не было доступа к машине, обнаружившей проблему.

Бег

brew uninstall --force git && brew install git --without-completions

действительно решил проблему.

Большое спасибо за ваше расследование.

Проблема здесь в том, что официальное завершение Git не было подготовлено для 'complete_aliases', я внес исправление:

https://github.com/felipec/git/commit/aaafa76

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

compdef _git gco=git_checkout

Однако, если вы хотите использовать формат zsh: gco=git-checkout и чтобы он работал в распространяемой в настоящее время версии Git, вы можете сделать это:

alias __git-checkout_main=_git_checkout

найдите .zshrc и удалите комментарий

Примеры псевдонимов

псевдоним zshconfig = "st ~ / .zshrc"

здесь

псевдоним ohmyzsh = "приятель ~ / .oh-my-zsh"

псевдоним gco = "git checkout"

Может ли кто-нибудь помочь мне отладить, почему у меня возникает эта проблема? Это происходит с установленным complete_aliases и без него. Кроме того, удаление файлов .zcompdump* не исправляет. Мои плагины просто установлены на plugins=(git gitfast) , однако я получаю эти проблемы с завершением функций (что расстраивает, потому что в идеале я бы использовал свою собственную настроенную функцию gco вместо gco плагина git.
ggl _git:12: command not found: __git-checkout_main
gdv _git:12: command not found: __git-diff_main

Я использую Powerlevel10k на oh-my-zsh 173d4ca68f1ff4b04e9f3fd783244c309d848092, с zsh 5.8 (x86_64-apple-darwin19.3.0) и git версии 2.26.1. К сожалению, brew uninstall --force git && brew install git --without-completions больше не подходит для git.

Вот мое определение _git .

❯ which _git
_git () {
    local _ret=1
    local cur cword prev
    cur=${words[CURRENT]}
    prev=${words[CURRENT-1]}
    let cword=CURRENT-1
    if (( $+functions[__${service}_zsh_main] ))
    then
        __${service}_zsh_main
    else
        emulate ksh -c __${service}_main
    fi
    let _ret && _default && _ret=0
    return _ret
}

@jessrosenfield Это потому, что вам не хватает патча. Я не уверен, что вы используете последнюю версию ohmyzsh, но было некоторое несоответствие, и мой патч был отменен:

завершение: zsh: улучшить выбор основной функции

@felipec Я обновился, но все еще не работает (моя текущая проблема № 9018 немного отличается)

Была ли эта страница полезной?
0 / 5 - 0 рейтинги