/ / Comprimi le directory nel prompt di zsh in un modo unico - zsh, prompt, pwd

Comprimi le directory nel prompt di zsh in un modo unico: zsh, prompt, pwd

C'è un modo per comprimere la directory di lavoro corrente nel prompt di zsh in un modo univoco, in modo che io possa copiare e incollarlo su un altro terminale, premere TAB e ottenere il percorso originale?

Diciamo che abbiamo le seguenti directory:

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

Se il prompt è programmato per mostrare il primocaratteri, e io "m in / b / d, quindi è univoco." D'altra parte, / a / d non è univoco, quindi avrei bisogno di / ad / d, / al / de e / al / do. even / ali / ... non appena compare l'utente alex.

E 'possibile hackerarlo direttamente in zsh o devo scrivere uno script, che trovi l'inizio univoco più breve di ogni directory principale?

Grazie per le tue idee!

risposte:

6 per risposta № 1

Non lo so zsh ha una funzione incorporata di questo tipo, ma dovrebbe essere abbastanza facile da scrivere senza ricorrere a una singola subshell oa una pipe 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

Questo script produrrà il percorso più breve necessario affinché il completamento automatico funzioni.

Puoi buttarlo nel tuo .zshrc come una funzione e quindi eseguirlo da qualsiasi directory.

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
}

Ecco un video di esso in azione:

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

O se preferisci, qualche esempio di output:

~/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 per risposta № 2

Sì, è possibile comprimere le directory inun primo percorso con una lettera univoca e avere la Z Shell espandere quel percorso premendo [Tab]. Ho semplicemente usato compinstall (script di utility zsh installato con Zsh) per generare il seguente codice. La parte importante da prendere in considerazione per espandere gli elementi del percorso è su sesto zstyle comando, vicino alla fine, dove la parentesi dei personaggi per separare i punti di completamento include /, che è, ovviamente, il separatore di directory. Con questo, i percorsi unici che hai suggerito si riempiranno completamente con una sola pressione di [Tab] come se fosse il * erano alla fine di ogni percorso-nome lettere univoche.

# 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

Per quanto riguarda la creazione del percorso univoco in primo luogo e l'inserimento nel prompt, è possibile con uno script o una funzione zsh, e quindi dovrebbero essere possibile anche per il compilatore o l'editor di riga, ma semplicemente attenendosi alla richiesta, si aggiungerà una funzione al $precmd_functions array che modifica o aggiunge al PS1 variabile. Questo array speciale è un elenco di nomi di funzioni che vengono eseguiti subito prima di ogni prompt.

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

Per ottenere l'attuale PWD in forma abbreviata, penso che questa funzione sia chiara e facile da seguire, anche se non necessariamente ottimizzata per un uso limitato delle risorse.

#!/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

Si noti che trova percorsi univoci con i nomi delle directory a causa della funzione Zsh (/) alla fine del globbing. Nell'ultima directory (corrente) questo significa che puoi abbinare qualcos'altro se c'è un file con lo stesso nome più un'estensione.