以独特的方式在 zsh 提示符下折叠目录
Collapse directories in zsh prompt in a unique way
有没有办法以一种独特的方式在 zsh 提示符下折叠当前工作目录,以便我可以将其复制并粘贴到另一个终端,按 TAB 键并获取原始路径?
假设我们有以下目录:
/adam/devl
/alice/devl
/alice/docs
/bob/docs
如果提示被编程为显示第一个字符,而我在 /b/d,那么它是唯一的。另一方面,/a/d 不是唯一的,所以我需要 /ad/d、/al/de 和 /al/do。甚至 /ali/... 一旦用户 alex 出现。
是否可以直接在 zsh 中解决这个问题,或者我是否需要编写一个脚本来找到每个父目录的最短唯一开头?
谢谢你的想法!
我不知道 zsh
有这种内置函数,但编写脚本应该很容易,而无需借助单个子 shell 或慢速管道:
#!/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
此脚本将输出自动完成工作所需的最短路径。
您可以将它作为函数放入 .zshrc
,然后从任何目录 运行。
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
}
这是一个实际操作视频:
https://asciinema.org/a/0TyL8foqvQ8ec5ZHS3c1mn5LH
或者,如果您愿意,可以提供一些示例输出:
~/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
是的,可以将目录折叠到第一个唯一字母路径,并让 Z Shell 在按 [Tab] 时展开该路径。我简单地使用了 compinstall(与 Zsh 一起安装的 zsh 实用程序脚本)来生成以下代码。扩展路径元素需要注意的重要部分是 第六个 zstyle
命令,靠近末尾 ,其中用于分隔完成点的字符括号包括 /
,当然是目录分隔符。有了这个,您建议的唯一路径将完全填写一个 [Tab] 按下,就好像 *
位于每个路径名称唯一字母的末尾一样。
# 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
至于首先创建唯一路径并将其插入到提示符中,可以使用 zsh 脚本或函数,因此 应该 可以完成或行编辑器,但只要坚持提示,您将向 $precmd_functions
数组添加一个函数,该函数修改或添加到 PS1
变量。这个特殊的数组是函数名称的列表,这些函数名称 运行 就在每个提示之前。
function precmd_unique_pwd {
local pwd_string="$(upwd)"
PS1="%B%n@%m $pwd_string => %b"
}
precmd_functions+=( precmd_unique_pwd )
为了以缩写形式获取当前 PWD,我认为此函数清晰易懂,但不一定针对低资源使用率进行了优化。
#!/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
请注意,由于 Zsh 特性 (/)
在 globbing 的末尾,它会找到具有目录名称的唯一路径。在最后一个目录(当前)上,这意味着如果有一个具有相同名称和扩展名的文件,您可能会匹配其他内容。
有没有办法以一种独特的方式在 zsh 提示符下折叠当前工作目录,以便我可以将其复制并粘贴到另一个终端,按 TAB 键并获取原始路径?
假设我们有以下目录:
/adam/devl
/alice/devl
/alice/docs
/bob/docs
如果提示被编程为显示第一个字符,而我在 /b/d,那么它是唯一的。另一方面,/a/d 不是唯一的,所以我需要 /ad/d、/al/de 和 /al/do。甚至 /ali/... 一旦用户 alex 出现。
是否可以直接在 zsh 中解决这个问题,或者我是否需要编写一个脚本来找到每个父目录的最短唯一开头?
谢谢你的想法!
我不知道 zsh
有这种内置函数,但编写脚本应该很容易,而无需借助单个子 shell 或慢速管道:
#!/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
此脚本将输出自动完成工作所需的最短路径。
您可以将它作为函数放入 .zshrc
,然后从任何目录 运行。
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
}
这是一个实际操作视频:
https://asciinema.org/a/0TyL8foqvQ8ec5ZHS3c1mn5LH
或者,如果您愿意,可以提供一些示例输出:
~/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
是的,可以将目录折叠到第一个唯一字母路径,并让 Z Shell 在按 [Tab] 时展开该路径。我简单地使用了 compinstall(与 Zsh 一起安装的 zsh 实用程序脚本)来生成以下代码。扩展路径元素需要注意的重要部分是 第六个 zstyle
命令,靠近末尾 ,其中用于分隔完成点的字符括号包括 /
,当然是目录分隔符。有了这个,您建议的唯一路径将完全填写一个 [Tab] 按下,就好像 *
位于每个路径名称唯一字母的末尾一样。
# 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
至于首先创建唯一路径并将其插入到提示符中,可以使用 zsh 脚本或函数,因此 应该 可以完成或行编辑器,但只要坚持提示,您将向 $precmd_functions
数组添加一个函数,该函数修改或添加到 PS1
变量。这个特殊的数组是函数名称的列表,这些函数名称 运行 就在每个提示之前。
function precmd_unique_pwd {
local pwd_string="$(upwd)"
PS1="%B%n@%m $pwd_string => %b"
}
precmd_functions+=( precmd_unique_pwd )
为了以缩写形式获取当前 PWD,我认为此函数清晰易懂,但不一定针对低资源使用率进行了优化。
#!/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
请注意,由于 Zsh 特性 (/)
在 globbing 的末尾,它会找到具有目录名称的唯一路径。在最后一个目录(当前)上,这意味着如果有一个具有相同名称和扩展名的文件,您可能会匹配其他内容。