9

Is there a way to collapse the current working directory in the zsh prompt in a unique way, so that I could copy and paste it to another terminal, hit TAB and get the original path?

Let's say we have following directories:

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

If the prompt is programmed to show the first characters, and I'm in /b/d, then it is unique. On the other hand, /a/d is not unique, so I would need /ad/d, /al/de and /al/do. And even /ali/… as soon as the user alex appears.

Is it possible to hack this directly in zsh or do I need to write a script, that finds the shortest unique beginning of each parent directory?

Thank you for your ideas!

4

2 回答 2

11

我不知道它zsh有这种内置功能,但它应该很容易编写脚本,而无需求助于单个子外壳或慢速管道:

#!/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
于 2017-07-26T19:41:38.060 回答
0

是的,可以将目录折叠到第一个唯一字母路径,并在按下 [Tab] 时让 Z Shell 展开该路径。我只是使用 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

(/)请注意,由于globbing 末尾的Zsh 功能,它会找到具有目录名称的唯一路径。在最后一个目录(当前)上,这意味着如果有同名文件加上扩展名,您可能会匹配其他内容。

于 2017-07-30T18:46:03.543 回答