/ / Contraer directorios en el indicador zsh de una manera única: zsh, prompt, pwd

Contraer directorios en el indicador zsh de una manera única: zsh, prompt, pwd

¿Hay alguna manera de contraer el directorio de trabajo actual en el indicador de zsh de una manera única, para poder copiarlo y pegarlo en otra terminal, presionar TAB y obtener la ruta original?

Digamos que tenemos los siguientes directorios:

/adam/devl
/alice/devl
/alice/docs
/bob/docs

Si el aviso está programado para mostrar el primercaracteres, y yo estoy en / b / d, entonces es único. Por otro lado, / a / d no es único, entonces necesitaría / ad / d, / al / de y / al / do. incluso / ali / ... tan pronto como aparezca el usuario alex.

¿Es posible hackear esto directamente en zsh o tengo que escribir un script que encuentre el comienzo único más corto de cada directorio padre?

¡Gracias por tus ideas!

Respuestas

6 para la respuesta № 1

No soy consciente de eso zsh tiene una función incorporada de este tipo, pero debería ser bastante fácil de crear sin recurrir a una única subcapa o tubería lenta:

#!/bin/zsh

paths=(${(s:/:)PWD})

cur_path="/"
cur_short_path="/"
for directory in ${paths[@]}
do
cur_dir=""
for (( i=0; i<${#directory}; i++ )); do
cur_dir+="${directory:$i:1}"
matching=("$cur_path"/"$cur_dir"*/)
if [[ ${#matching[@]} -eq 1 ]]; then
break
fi
done
cur_short_path+="$cur_dir/"
cur_path+="$directory/"
done

printf %q "${cur_short_path: : -1}"
echo

Este script generará la ruta más corta necesaria para que la autocompletación funcione.

Puedes tirarlo en tu .zshrc como una función y luego ejecutarlo desde cualquier directorio.

function spwd {
paths=(${(s:/:)PWD})

cur_path="/"
cur_short_path="/"
for directory in ${paths[@]}
do
cur_dir=""
for (( i=0; i<${#directory}; i++ )); do
cur_dir+="${directory:$i:1}"
matching=("$cur_path"/"$cur_dir"*/)
if [[ ${#matching[@]} -eq 1 ]]; then
break
fi
done
cur_short_path+="$cur_dir/"
cur_path+="$directory/"
done

printf %q "${cur_short_path: : -1}"
echo
}

Aquí hay un video de eso en acción:

https://asciinema.org/a/0TyL8foqvQ8ec5ZHS3c1mn5LH

O si lo prefiere, algunos ejemplos de salida:

~/t $ ls
adam  alice  bob  getshortcwd.zsh

~/t $ ls adam
devl

~/t $ ls alice
devl  docs

~/t $ spwd
/h/v/t

~/t $ cd adam/devl

~/t/adam/devl $ spwd
/h/v/t/ad/d

~/t/adam/devl $ cd ../../alice/devl

~/t/alice/devl $ spwd
/h/v/t/al/de

~/t/alice/devl $ cd ../docs

~/t/alice/docs $ spwd
/h/v/t/al/do

~/t/alice/docs $ `spwd` [TAB]
~/t/alice/docs $ /h/v/t/al/do [TAB]
~/t/alice/docs $ /home/vsimonian/t/alice/docs

0 para la respuesta № 2

Sí, es posible colapsar los directoriosuna primera ruta de una sola letra y hacer que la Z Shell expanda esa ruta al presionar [Tab]. Simplemente usé compinstall (script de utilidad zsh instalado con Zsh) para generar el siguiente código. La parte importante a tener en cuenta para expandir los elementos de ruta se encuentra en sexto zstyle comando, cerca del final, donde el corchete de caracteres para separar los puntos de culminación incluye el /, que es, por supuesto, el separador de directorio. Con esto, las rutas exclusivas que sugirió completarán por completo con solo una [Pestaña] presionar como si * estaban al final de cada nombre de ruta letras únicas.

# The following lines were added by compinstall

zstyle ":completion:*" add-space true
zstyle ":completion:*" completer _list _expand _complete _ignored _match _correct _approximate _prefix
zstyle ":completion:*" completions 1
zstyle ":completion:*" list-colors ${(s.:.)LS_COLORS}
zstyle ":completion:*" matcher-list "m:{[:lower:]}={[:upper:]} r:|[._-]=* r:|=*" "m:{[:lower:]}={[:upper:]} m:{[:lower:][:upper:]}={[:upper:][:lower:]} r:|[._-]=* r:|=*" "r:|[._-/]=* r:|=*" "l:|=* r:|=*"
zstyle ":completion:*" match-original both
zstyle :compinstall filename "/home/micah/.zsh/.zshrc"

autoload -Uz compinit
compinit
# End of lines added by compinstall

En cuanto a la creación de la ruta única en primer lugar y su inserción en el aviso, es posible con un script o función zsh, y por lo tanto debería ser posible para el completer o el editor de línea también, pero simplemente siguiendo el mensaje, agregaría una función al $precmd_functions matriz que modifica o agrega a la PS1 variable. Esta matriz especial es una lista de nombres de funciones que se ejecutan justo antes de cada solicitud.

function precmd_unique_pwd {
local pwd_string="$(upwd)"
PS1="%B%n@%m $pwd_string => %b"
}
precmd_functions+=( precmd_unique_pwd )

Para obtener la PWD actual en forma abreviada, creo que esta función es clara y fácil de seguir, aunque no necesariamente optimizada para un bajo uso de recursos.

#!/bin/zsh
function upwd {
emulate -LR zsh -o nullglob
local dir Path
local -a newpwd tmp stack
local -i length=1 Flag=0
newpwd=( ${(s./.)PWD} )
foreach dir ( $newpwd )
(( length=0, Flag=0 ))
repeat $#dir
do
(( length += 1 ))
tmp=( ${(j.*/.)~stack}/$dir[1,$length]*(/) )
if
(( $#tmp == 1 ))
then
Path=$Path/$dir[1,$length]
stack+=( /$dir )
(( Flag=1 ))
break
fi
done
if
(( Flag ))
then
continue
else
Path=$Path/$dir
fi
end
print -- $Path
}
upwd

Tenga en cuenta que encuentra rutas únicas con nombres de directorio debido a la función Zsh (/) al final del globbing. En el último directorio (actual) esto significa que puede coincidir con otra cosa si hay un archivo con el mismo nombre más una extensión.