Finalización para el primer argumento de cd OLD NEW

22

En zsh, el cdcomando tiene una forma de dos argumentos: cd OLD NEWcambios a ${PWD/OLD/NEW}. Con el sistema de finalización de nuevo estilo, zsh es capaz de completar NEW: el segundo argumento se completa en función de lo que OLDse puede sustituir para obtener un directorio existente. Pero el primer argumento solo se completa en los directorios existentes.

¿Cómo puedo hacer que zsh ofrezca terminaciones que son valores posibles para OLD, además de completar directorios existentes?

Por ejemplo, si el directorio actual es /path/to/fooy también hay directorios /also/to/fooy /path/to/foo/prime, entonces cd pTabcompleta pa prime. Si tengo la intención de ejecutar cd path also, me gustaría que zsh también se ofrezca pathcomo una finalización. ¿Cómo?

Usar valores ya escritos del segundo argumento para limitar las posibilidades del primer argumento sería una ventaja, pero completar el primer argumento de forma independiente también estaría bien.

Gilles 'SO- deja de ser malvado'
fuente
¿Sería su ejemplo de finalización de 2 argumentos: cd p also <Tab>o cd p also <left arrow x 5> <Tab>?
Jeff Schaller
@JeffSchaller El ejemplo sensible al segundo argumento sería cd p also<Left*5><Tab>: si presiono <Tab>mientras el cursor está presionado also, espero alsoque se complete, no p.
Gilles 'SO- deja de ser malvado'
Si escribe, ¿ cd t<tab>debería ofrecer th/to/foo/primey to/foo/prime? ¿O debería limitarse a los límites del directorio?
Barmar
@Barmar Creo que limitar los límites del directorio sería lo más conveniente.
Gilles 'SO- deja de ser malvado'
Pregunta interesante ...
wogsland

Respuestas:

1

Supongo que podría agregar los componentes de $PWDa la cdlista de finalización, aunque esto parece requerir jugar con _cd; es decir, una versión personalizada de _cddebe aparecer primero en $fpath.

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

Luego arriba en la parte superior de ~/zcomp/_cdagregar una función

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

y justo antes de la _alternativelínea agregue lo que eso devuelve a la lista de alternativas

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

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

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

return ret
...

aunque esto siempre agregará los pwdcomponentes a las cdterminaciones:

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

con lógica adicional, solo puede agregar los $PWDcomponentes cuando ya hay un segundo argumento presente en lugar de siempre.

¡Sin embargo! Esto siempre arruina la cdfinalización y requiere que apliquemos parches a la _cdfinalización aguas arriba . Otra opción sería crear un nuevo nombre para la función proporcionada por los dos argumentos cd, quizás llamado cdsub, y solo PWDpara que aparezca la finalización de los componentes. Agregue esto a~/.zshrc

function cdsub { builtin cd "$@" }

Y luego una _cd terminación_cdsub destripada para ser colocado en algún lugar de $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
fuente