web-dev-qa-db-ja.com

cd OLD NEWの最初の引数の補完

zshでは、cdコマンドには2つの引数形式があります。cd OLD NEW${PWD/OLD/NEW}に変わります。新しいスタイルの補完システムでは、zshはNEWを補完できます。2番目の引数は、既存のディレクトリを取得するためにOLDを置き換えることができるものに基づいて補完されます。ただし、最初の引数は既存のディレクトリに対してのみ完了します。

既存のディレクトリを補完することに加えて、OLDの可能な値である補完をzshに提供させるにはどうすればよいですか?

たとえば、現在のディレクトリが/path/to/fooであり、ディレクトリ/also/to/fooおよび/path/to/foo/primeもある場合、cd pTabpからprimeを完了します。 cd path alsoを実行する場合は、zshでpathも補完として提供したいと思います。どうやって?

2番目の引数の入力済みの値を使用して最初の引数の可能性を制限することはプラスですが、最初の引数を個別に完了することも問題ありません。

$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/
...

追加のロジックを使用すると、常にではなく、すでに2番目の引数が存在する場合にのみ、$PWDコンポーネントを追加できます。

しかしながら!これは常にcd完了をめちゃくちゃにするので、上流の_cd完了にモンキーパッチを適用する必要があります。別のオプションは、おそらくcdと呼ばれる2つの引数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
1
thrig