zoukankan      html  css  js  c++  java
  • 模糊搜索神器fzf

    前言

    fzf是目前最快的fuzzy finder。使用golang编写。结合其他工具(比如ag和fasd)可以完成非常多的工作。
    让你通过输入模糊的关键词就可以定位文件或文件夹。当你的思维也习惯了模糊匹配后,在工作中可以大幅提高你的工作效率。
    模糊搜索的概念如下,你记得文件名含有con, te, go, 那么你只需要把所有文件送给fzf, 然后在窗口里输入con te go就可以了,不管实现名是test_continus_go还是go_cont_test都会匹配上。

    安装

    使用git

    git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
    ~/.fzf/install
    

    升级

    cd ~/.fzf && git pull && ./install
    

    原生使用

    fzf默认会从STDIN读入数据,然后将结果输出到STDOUT

    find * -type f | fzf > selected
    

    上面命令从find的搜索结果中读入,输出到文件selected中

    fzf里的快捷键

    在finder(输出交换窗口)里,

    • Ctrl-J/Ctrl-K/Ctrl-N/Ctrlk-N可以用来将光标上下移动
    • Enter键用来选中条目, Ctrl-C/Ctrl-G/Esc用来退出
    • 在多选模式下(-m), TAB和Shift-TAB用来多选
    • Mouse: 上下滚动, 选中, 双击; Shift-click或shift-scoll用于多选模式

    布局

    fzf默认全屏模式,你可以定制高度

    vim $(fzf --height 40%)
    

    你可以通过$FZF_DEFAULT_OPTS来设定默认值

    export FZF_DEFAULT_OPTS='--height 40% --reverse --border'
    

    搜索语法

    fzf默认会以“extened-search"模式启动, 这种模式下你可以输入多个以空格分隔的搜索关键词, 如^music .mp3$, sbtrkt !fire.

    Token Match type Description
    sbtrkt fuzzy-match 匹配sbtrkt
    ^music prefix-exact-match 以music开头
    .mp3^ suffix-exact-match 以.mp3结尾
    'wild exact-match(quoted) 精确包含wild
    !fire inverse-exact-match 不包含fire
    !.mp3$ inverse-suffix-exact-match 不以.mp3结尾

    如果你不想用fuzzy match, 可以用fzf -e做精确匹配
    符号"|"可以做or匹配, 比如

    ^core go$|rb$|py$
    

    表示以core开头,以go或rb或py结尾的

    环境变量

    • FZF_DEFAULT_ COMMAND
      • 设定默认输入
      • 比如`export FZF_DEFAULT_ COMMAND='ag -g ""'
    • FZF_DEFAULT_OPTS
      • 设定默认选项
      • 比如`export FZF_DEFAULT_OPTS="--reverse --inline-info"

    命令行下的快捷键

    CTRL-T

    在命令行下按下ctrl-t会打开fzf窗口,如果你选中某个条目并按下Enter, 选中的条目会被拷贝到命令行上
    如果想同时预览文件内容,可以使用--preview选项

    export FZF_CTRL_T_OPTS="--preview '(highlight -O ansi -l {} 2> /dev/null || cat {} || tree -C {}) 2> /dev/null | head -200'"
    

    也可以用--select-1--exit-0
    前者是如果只有一个条目,那么自动选中并退出fzf
    后者是如果条目为空,自动退出
    上面两个选项对ALT-C也有用

    CTRL-R

    在命令行下按下ctrl-r, fzf会列出history命令,选中条目并离开fzf的话, 选中条目会被拷到命令行上
    在zsh下可以使用下面的方法来按下C-XC-R来直接执行

    fzf-history-widget-accept() {
      fzf-history-widget
      zle accept-line
    }
    zle    -N    fzf-history-widget-accept
    bindkey '^X^R' fzf-history-widget-accept
    

    ALT-C

    在命令行上按下alt-c, 会列出当前文件夹下的目录,选中条目会自动进入到相应目录

    命令行下的模糊完成

    默认可以通过**来触发文件或目录的自动完成

    COMMAND [DIRECTORY/][FUZZY_PATTERN]**<TBA>
    

    比如

    vim **<TAB>
    vim ../mult**<TAB>
    cd ~/github/fzf**<TBA>
    

    预览窗口

    如果使用--preview选项, fzf会自动用外部程序打开现在条目的文件, {}会被fzf选中行内容代替

    fzf --preview 'cat {}'
    

    建议安装rougify(先安装ruby, 然后gem intall rouge)
    然后在.zshrc里用函数或别名

    fzfp() {
    fzf --preview '[[ $(file --mime {}) =~ binary ]] && echo {} is a binary file || (rougify {}  || highlight -O ansi -l {} || coderay {} || cat {}) 2> /dev/null | head -500'
    alias tt='fzf --preview '"'"'[[ $(file --mime {}) =~ binary ]] && echo {} is a binary file || (rougify {}  || highlight -O ansi -l {} || coderay {} || cat {}) 2> /dev/null | head -500'"'"
    

    函数是更好的方式, 用alias的话,为了绕开'的问题,需要用一个双引号加一个间引号再加一个双引号才能生成一个单引号

    上图左侧是文件列表,右侧是rougify生成的预览窗口,可以用鼠标上下滚动,遗憾的是用键盘没法移动光标到右侧窗口进行上下滚动。

    fzf示例

    interactive cd

    安装

    wget https://github.com/changyuheng/zsh-interactive-cd/blob/master/zsh-interactive-cd.plugin.zsh
    cp zsh-interactive-cd.plugin.zsh ~/.fzf/shell
    echo 'source ~/.fzf/shell/zsh-interactive-cd.plugin.zsh' >> ~/.zshrc
    

    cd后按ctrl-i就会打开fzf finder窗口

    z

    # fasd & fzf change directory - jump using `fasd` if given argument, filter output of `fasd` using `fzf` else
    z() {
        [ $# -gt 0 ] && fasd_cd -d "$*" && return
        local dir
        dir="$(fasd -Rdl "$1" | fzf -1 -0 --no-sort +m)" && cd "${dir}" || return 1
    }
    

    changing directory

    # fd - cd to selected directory
    fd() {
      local dir
      dir=$(find ${1:-.} -path '*/.*' -prune 
                      -o -type d -print 2> /dev/null | fzf +m) &&
      cd "$dir"
    }
    
    # fda - including hidden directories
    fda() {
      local dir
      dir=$(find ${1:-.} -type d 2> /dev/null | fzf +m) && cd "$dir"
    }
    
    # fdr - cd to selected parent directory
    fdr() {
      local declare dirs=()
      get_parent_dirs() {
        if [[ -d "${1}" ]]; then dirs+=("$1"); else return; fi
        if [[ "${1}" == '/' ]]; then
          for _dir in "${dirs[@]}"; do echo $_dir; done
        else
          get_parent_dirs $(dirname "$1")
        fi
      }
      local DIR=$(get_parent_dirs $(realpath "${1:-$PWD}") | fzf-tmux --tac)
      cd "$DIR"
    }
    
    # cf - fuzzy cd from anywhere
    # ex: cf word1 word2 ... (even part of a file name)
    # zsh autoload function
    cf() {
      local file
    
      file="$(locate -Ai -0 $@ | grep -z -vE '~$' | fzf --read0 -0 -1)"
    
      if [[ -n $file ]]
      then
        if [[ -d $file ]]
        then
            cd -- $file
        else
            cd -- ${file:h}
        fi
      fi
    }
    

    v

    # fasd & fzf change directory - open best matched file using `fasd` if given argument, filter output of `fasd` using `fzf` else
    v() {
        [ $# -gt 0 ] && fasd -f -e ${EDITOR} "$*" && return
        local file
        file="$(fasd -Rfl "$1" | fzf -1 -0 --no-sort +m)" && vi "${file}" || return 1
    }
    

    fzf的vim插件

    在.vimrc里用vunble安装

    set rtp+=/home/harriszh/.fzf/
    ...
    Plugin 'junegunn/fzf.vim'
    ...
    

    然后FZF等命令就可以使用了
    建议要安装ag,并把FZF_DEFAULT_COMMAND改成ag

    后言

    fzf是非常强大的胶水工具,利用它和ag, fasd及shell command可以实现非常绚烂的功能。更多例子见wiki
    如果上文有错误的地方,欢迎联系作者

  • 相关阅读:
    除草第一季 1 简单日常心得
    [搬家from qzone] 读书笔记 人间情味.半成品
    [搬家from qzone] 读书笔记 最好的告别
    [搬家from qzone] 读书笔记 爱是一种选择
    [搬家from qzone] 读书笔记 童年的王国
    [搬家from qzone] 我不是一个很好的学长,所以毕业前,给学习学妹们写写自己犯的错误吧
    博客重新开张 第一篇灌水
    我眼中的vim
    linux启动kdump失败
    centos7 minimal安装之后要做的事情
  • 原文地址:https://www.cnblogs.com/harriszh/p/7616966.html
Copyright © 2011-2022 走看看