完成cd OLD NEW的第一个参数


22

在中zshcd命令具有两个参数的形式:cd OLD NEW更改为${PWD/OLD/NEW}。使用新式的完成系统,zsh能够完成NEW:第二个参数根据OLD可以替换为现有目录的内容完成。但是第一个参数仅在现有目录中完成。

OLD除了完成现有目录之外,zsh如何让zsh提供可能的值?

例如,如果当前目录是,/path/to/foo并且还有目录/also/to/foo/path/to/foo/prime,则cd pTab完成pprime。如果我打算运行,cd path also那么我希望zsh也可以path作为补充。怎么样?

使用第二个参数的已经输入的值来限制第一个参数的可能性是一个加号,但是独立完成第一个参数也可以。


您的2参数完成示例是:cd p also <Tab>还是cd p also <left arrow x 5> <Tab>
杰夫·谢勒

@JeffSchaller第二个参数敏感的示例是cd p also<Left*5><Tab>:如果<Tab>在光标处于位置时按,则also希望also完成,而不是p
吉尔斯(Gilles)'所以

如果输入cd t<tab>,它应该提供th/to/foo/primeto/foo/prime?还是应该只将自己限制在目录边界?
巴马尔

@Barmar我认为限制目录边界将是最方便的。
吉尔斯(Gilles)'所以

有趣的问题……
wogsland

Answers:


1

我想您可以将的组件添加$PWDcd完成列表中,尽管这似乎需要摆弄_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完成。另一种选择是为two-arg提供的功能创建一个新名称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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.