Определение псевдонимов git на основе gitconfig в zsh

Определение псевдонимов git на основе gitconfig в zsh

У меня в файле есть следующие строки ~/.aliases:

function __function_exists() {
    declare -f -F $1 > /dev/null
    return $?
}

# git aliases (need to have git bash completion installed)
for al in `__git_aliases`; do
    alias g$al="git $al"

    complete_func=_git_$(__git_aliased_command $al)
    __function_exists $complete_fnc && __git_complete g$al $complete_func
done

А у меня ~/.gitconfigв наличии:

[alias]
    # one-line log
    l = log --pretty=format:"%C(yellow)%h\\ %ad%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --date=short

    a = add
    ap = add -p
    c = commit --verbose
    ca = commit -a --verbose
    cm = commit -m
    cam = commit -a -m
    m = commit --amend --verbose

    d = diff
    ds = diff --stat
    dc = diff --cached

    s = status -s
    co = checkout
    cob = checkout -b
    # list branches sorted by last modified
    b = "!git for-each-ref --sort='-authordate' --format='%(authordate)%09%(objectname:short)%09%(refname)' refs/heads | sed -e 's-refs/heads/--'"

    # list aliases
    la = "!git config -l | grep alias | cut -c 7-"

И в моем ~/.zshrc:

zstyle :compinstall filename '/home/giuliani/.zshrc'
autoload -Uz compinit
compinit
[[ -f $HOME/.aliases ]] && source "$HOME/.aliases"

Итак, для каждого псевдонима в моем gitconfig я определю псевдоним оболочки, например glfor git logи так далее.

Пытаюсь перенести это на zsh, но у меня возникла проблема: autoloadвстроенная функция zsh загружает файл только /usr/share/zsh/functions/Completion/Unix/_gitв первый раз, когда я пытаюсь выполнить какую-то команду git.

Я попытался вызвать/загрузить _gitфайл напрямую из , .zshrcно после нескольких предупреждений это не сработало.

Как правильно получить ту же функциональность, что и в bash, используя zsh?

решение1

На самом деле, вызов _gitиз вашего .zshrcдействительно работает, поскольку он определяет _gitи сопутствующие ему функции, включая __git_aliases, и пытается выполнить какое-то завершение, но терпит неудачу (даже без сообщения об ошибке в данном конкретном случае).Это работает с большинством функций завершения.. Это нужно сделать после compinitтого, как _gitи его вспомогательные функции будут отмечены для автозагрузки.

% zsh -f
darkstar% autoload compinit          
darkstar% compinit
darkstar% _git 
darkstar% __git_aliases 
_tags:comptags:36: can only be called from completion function
_tags:comptry:55: can only be called from completion function
_tags:comptags:60: can only be called from completion function
_tags:comptags:67: can only be called from completion function

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

Поскольку вы в любом случае погружаетесь глубоко в _gitфайл завершения, вызовите __git_extract_aliasesвместо __git_aliases. __git_extract_aliasesзапихивает информацию в переменную aliasesтаким образом, чтобы ее было легко извлечь. (Примечание: я написал этот ответ для zsh 5.4.2, которая является версией в Ubuntu 18.04. Другие версии zsh могут иметь другую структуру в _git.)

_git 2>/dev/null
define_git_aliases () {
  local -a aliases; local al
  __git_extract_aliases
  for al in ${aliases%%:*}; do
    alias g$al="git $al"
  done
}
define_git_aliases

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

for al in ${${${(0)"$(git config -z --get-regexp '^alias.')"}%%$'\n'*}#alias.}; do
  alias g$al="git $al"
done

Связанный контент