zsh 函数与 fzf 选择需要 Enter

zsh 函数与 fzf 选择需要 Enter

dirs-stack我编写了一个简单的 zsh 函数,它允许我从via中进行选择fzf

我的.zshrc样子

DIRSTACKSIZE='99'    
setopt PUSHD_IGNORE_DUPS

# change to directory from the dirs stack
fzf-change-dirstack () {
    cd "$(dirs -lv | cut -f2 | fzf )" 
}

zle -N fzf-change-dirstack
bindkey '^[p' fzf-change-dirstack   # shortcut ALT+P

即使需要进行一些改进,它也能正常工作。唯一对我来说非常烦人的是,当我使用键绑定时,我必须输入Enter两次才能更改到目录。

如何cd立即修改脚本而无需再次输入两次Enter

答案1

fzf-change-dirstack () {
  local dir
  print -rNC1 -- $dirstack |
    fzf --read0 --print0 |
    IFS= read -rd '' dir &&
    cd -- $dir &&
    zle -I
}

zle -N fzf-change-dirstack
bindkey '^[p' fzf-change-dirstack  # shortcut ALT+P

要点是当当前工作目录更改时zle -I使I提示无效,其余部分修复代码中的一些其他问题,以便它可以使用任意目录名称。

尤其:

  • dirs -lv | cut -f2如果这些目录名称中的任何一个包含换行符或制表符,则会失败。更一般地,文件路径可以是任何非空字节序列。因此,要传递给fzf,您需要使用它--read0并提供一个空分隔列表(此处print为olumn上的raw Null-delimited )。1 C
  • 如果您忘记了--,那么任何以 开头的目录-都会出现问题(如果没有之前的错误,通常不会发生)。忘记它print甚至会引入命令注入漏洞
  • 不要忘记错误处理!

cd +Tab 另请注意,当您完成或只是~+Tab完成 dirstack 元素作为任何命令的参数(而不仅仅是cd/ pushd)时,zsh 已经有自己的 dirstack 完成器。

例如,尝试cd +TabTab以下操作:

zstyle ':completion:*' format 'Completing %d'
zstyle ':completion:*' menu select=2
autoload compinit
compinit

并使用箭头键导航。

(您通常使用这种设置进行调整compinstall


cd不幸的是,For--并不能解决所有问题。-,,+1比如-1仍然受到特殊对待cd。这些不会作为 的元素出现,但可能作为like after$dirstack的输出中某行的第二个制表符分隔字段出现。dirs -lvcd $'foo\nx\t+1\twhatever'

相关内容