Завершение первого аргумента cd OLD NEW

22

В zshкоманде cdкоманда имеет форму с двумя аргументами: cd OLD NEWизменяется на ${PWD/OLD/NEW}. С системой завершения в новом стиле zsh может выполнить NEW: второй аргумент завершается на основе того, что OLDможно заменить, чтобы получить существующий каталог. Но первый аргумент дополняется только для существующих каталогов.

Как заставить zsh предлагать дополнения, которые являются возможными значениями OLD, в дополнение к заполнению существующих каталогов?

Например, если текущий каталог есть /path/to/fooи есть также каталоги /also/to/fooи /path/to/foo/prime, то cd pTabзавершается pдо prime. Если я собираюсь запустить, cd path alsoто я хотел бы, чтобы zsh также предлагал pathв качестве завершения. Как?

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

Жиль "ТАК - перестань быть злым"
источник
Ваш пример завершения с двумя аргументами будет:, cd p also <Tab>или cd p also <left arrow x 5> <Tab>?
Джефф Шаллер
@JeffSchaller Пример, чувствительный ко второму аргументу cd p also<Left*5><Tab>: если я нажму, <Tab>когда курсор находится внутри also, я ожидаю, alsoчто будет завершено, а не p.
Жиль "ТАК - перестань быть злым"
Если вы печатаете, cd t<tab>он должен предложить th/to/foo/primeи to/foo/prime? Или это должно просто ограничиться границами каталога?
Бармар
@ Barmar Я думаю, что ограничение границ каталога будет наиболее удобным.
Жиль "ТАК - перестань быть злым"
Интересный вопрос ...
wogsland

Ответы:

1

Я полагаю, что вы могли бы добавить компоненты $PWDв cdсписок завершения, хотя это, кажется, требует возиться с _cd; то есть настроенная версия _cdдолжна появиться первой в $fpath.

% cd && mkdir zcomp
% cp $fpath[-1]/_cd zcomp
% fpath=(~/zcomp $fapth)

Затем наверху ~/zcomp/_cdдобавить функцию

_our_pwd() {
  _values ourpwd ${(ps:/:)PWD}
}

а затем непосредственно перед _alternativeстрокой добавить то, что возвращается в список альтернатив

  ...
  alt=("$service-options:$service option:_cd_options" "$alt[@]")
fi

alt=(ourpwd:pwd:_our_pwd "$alt[@]")

_alternative "$alt[@]" && ret=0

return ret
...

хотя это всегда будет добавлять pwdкомпоненты к cdдополнениям:

% cd
Users    jdoe    Applications/  Desktop/  Documents/  Downloads/  Library/
...

с дополнительной логикой вы можете добавлять $PWDкомпоненты только тогда, когда уже есть второй аргумент вместо всегда.

Тем не мение! Это всегда портит cdзавершение и требует, чтобы мы исправили _cdзавершение восходящего потока . Другой вариант - создать новое имя для функции, предоставляемой двумя аргументами cd, возможно, вызванной cdsub, и PWDдля этого появятся только завершенные компоненты. Добавьте это к~/.zshrc

function cdsub { builtin cd "$@" }

И затем потрошенное _cd завершение для_cdsub размещения где-то в $fpath:

#compdef cdsub
#
# Modified version of _cd from ZSH 5.3.1 with specific support for the
# `cd old new` form whereby PWD elements are provided for completion.

_cd_options() {
  _arguments -s \
  '-q[quiet, no output or use of hooks]' \
  '-s[refuse to use paths with symlinks]' \
  '(-P)-L[retain symbolic links ignoring CHASE_LINKS]' \
  '(-L)-P[resolve symbolic links as CHASE_LINKS]'
}

setopt localoptions nonomatch

local expl ret=1 curarg
integer argstart=2 noopts

if (( CURRENT > 1 )); then
  # if not in command position, may have options.
  # Careful: -<-> is not an option.
  while [[ $words[$argstart] = -* && argstart -lt CURRENT ]]; do
    curarg=$words[$argstart]
    [[ $curarg = -<-> ]] && break
    (( argstart++ ))
    [[ $curarg = -- ]] && noopts=1 && break
  done
fi

if [[ CURRENT -eq $((argstart+1)) ]]; then
  # cd old new: look for old in $PWD and see what can replace it
  local rep
  # Get possible completions using word in position 2
  rep=(${~PWD/$words[$argstart]/*}~$PWD(-/))
  # Now remove all the common parts of $PWD and the completions from this
  rep=(${${rep#${PWD%%$words[$argstart]*}}%${PWD#*$words[$argstart]}})
  (( $#rep )) && _wanted -C replacement strings expl replacement compadd -a rep
else
  _values ourpwd ${(ps:/:)PWD} && ret=0
  return ret
fi
thrig
источник