• fzf 命令行模糊搜索神器


    fzf是一款使用 GO 语言编写的交互式的 Unix 命令行工具。
    可以用来查找任何 列表内容、文件、历史命令、 本机绑定的host、 进程、 Git 分支、进程 等。所有的命令行工具可以生成列表输出的都可以再通过管道 pipe 到 fzf 上进行搜索和查找

    项目地址:https://github.com/junegunn/fzf

    fzf 使用

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

    find * -type f | fzf 
    

    使用更快的fd

    fd --type f | fzf
    

    fzf默认环境变量

    • 环境变量:如下表所示:
    name description example
    FZF_DEFAULT_COMMAND 输入为 tty 时的默认命令 export FZF_DEFAULT_COMMAND='fd --type f'
    FZF_DEFAULT_OPTS 设置默认选项 export FZF_DEFAULT_OPTS="--height 80% --layout=reverse --inline-info"
    FZF_CTRL_T_COMMAND 按键映射<CTRL-T>行为设置
    FZF_CTRL_T_OPTS 按键映射<CTRL-T>选项设置
    FZF_CTRL_R_OPTS 按键映射<CTRL-R>选项设置
    FZF_ALT_C_COMMAND 按键映射<CTRL-C>行为设置
    FZF_ALT_C_OPTS 按键映射<CTRL-C>选项设置
    • 按键绑定:如下表所示:

    fzf的安装脚本会为 bash,zsh 和 fish 终端设置以下按键绑定:

    按键 描述
    CTRL-T 命令行打印选中内容
    CTRL-R 命令行历史记录搜索,并打印输出
    ALT-C 模糊搜索目录,并进入(cd

    以zsh为例,.zshrc

    source /usr/share/fzf/key-bindings.zsh
    

    预览窗口

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

    fzf --preview 'cat {}'
    

    高亮输出:

    fzf --preview '[[ $(file --mime {}) =~ binary ]] && echo {} is a binary file || (bat --style=numbers --color=always{} || (ccat --color=always {} || highlight -O ansi -l {} || coderay {} || cat {}) 2> /dev/null | head -500'
    }
    
    export FZF_CTRL_T_OPTS="--preview '(highlight -O ansi -l {} 2> /dev/null || cat {} || tree -C {}) 2> /dev/null | head -200'"
    

    实用脚本

    以下脚本添加到fzf.zsh文件,.zshrc中引用

    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"
    }
    
    # cda - including hidden directories 
    cda() {
      local dir
      dir=$(find ${1:-.} -type d 2> /dev/null | fzf +m) && cd "$dir"
    }
    
    # cdf - cd into the directory of the selected file
    cdf() {
       local file
       local dir
       file=$(fzf +m -q "$1") && dir=$(dirname "$file") && 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
    }
    

    Command history

    # fh - repeat history
    fh() {
      eval $( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed -E 's/ *[0-9]*\*? *//' | sed -E 's/\\/\\\\/g')
    }
    
    # fh - repeat history
    fh() {
      print -z $( ([ -n "$ZSH_NAME" ] && fc -l 1 || history) | fzf +s --tac | sed -E 's/ *[0-9]*\*? *//' | sed -E 's/\\/\\\\/g')
    }
    

    Replacing eval with print -z will push the arguments onto the editing buffer stack, allowing you to edit the command before running it. It also means the command you run will appear in your history rather than just fh

    Processes

    # fkill - kill process
    fkill() {
      local pid
      pid=$(ps -ef | sed 1d | fzf -m | awk '{print $2}')
    
      if [ "x$pid" != "x" ]
      then
        echo $pid | xargs kill -${1:-9}
      fi
    }
    
    # fkill - kill processes - list only the ones you can kill. Modified the earlier script.
    fkill() {
        local pid 
        if [ "$UID" != "0" ]; then
            pid=$(ps -f -u $UID | sed 1d | fzf -m | awk '{print $2}')
        else
            pid=$(ps -ef | sed 1d | fzf -m | awk '{print $2}')
        fi  
    
        if [ "x$pid" != "x" ]
        then
            echo $pid | xargs kill -${1:-9}
        fi  
    }
    

    Interactive cd

    Suggested by @mgild Like normal cd but opens an interactive navigation window when called with no arguments. For ls, use -FG instead of --color=always on osx.

    function cdi() {
        if [[ "$#" != 0 ]]; then
            builtin cd "$@";
            return
        fi
        while true; do
            local lsd=$(echo ".." && ls -p | grep '/$' | sed 's;/$;;')
            local dir="$(printf '%s\n' "${lsd[@]}" |
                fzf --reverse --preview '
                    __cd_nxt="$(echo {})";
                    __cd_path="$(echo $(pwd)/${__cd_nxt} | sed "s;//;/;")";
                    echo $__cd_path;
                    echo;
                    ls -p --color=always "${__cd_path}";
            ')"
            [[ ${#dir} != 0 ]] || return 0
            builtin cd "$dir" &> /dev/null
        done
    }
    

    fzf + zsh

    配置文件.zshrc

    # fzf
    source /usr/share/fzf/key-bindings.zsh
    source ~/.config/fzf/fzf.zsh
    export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git -E .cache'
    export FZF_DEFAULT_OPTS='--height 80% --layout=reverse --preview-window down,30%,border-horizontal --preview "[[ $(file --mime {}) =~ binary ]] && echo {} is a binary file || (ccat --color=always {} || (bat --style=numbers --color=always{} || highlight -O ansi -l {} || cat {}) 2> /dev/null | head -500"'
    #export FZF_CTRL_T_COMMAND=$FZF_DEFAULT_COMMAND
    export FZF_CTRL_T_COMMAND='fd --type f -t d --hidden --follow --exclude .git -E .cache'
    export FZF_ALT_C_COMMAND="fd --type d --hidden --follow"
    

    fzf + ranger

    ranger配置文件commands.py

    • 方法一:
    class fzf_select(Command):
        """
        :fzf_select
        Find a file using fzf.
        With a prefix argument to select only directories.
    
        See: https://github.com/junegunn/fzf
        """
    
        def execute(self):
            import subprocess
            import os
            from ranger.ext.get_executables import get_executables
    
            if 'fzf' not in get_executables():
                self.fm.notify('Could not find fzf in the PATH.', bad=True)
                return
    
            fd = None
            if 'fdfind' in get_executables():
                fd = 'fdfind'
            elif 'fd' in get_executables():
                fd = 'fd'
    
            if fd is not None:
                hidden = ('--hidden' if self.fm.settings.show_hidden else '')
                exclude = "--no-ignore-vcs --exclude '.git' --exclude '*.py[co]' --exclude '__pycache__'"
                only_directories = ('--type directory' if self.quantifier else '')
                fzf_default_command = '{} --follow {} {} {} --color=always'.format(
                    fd, hidden, exclude, only_directories
                )
            else:
                hidden = ('-false' if self.fm.settings.show_hidden else r"-path '*/\.*' -prune")
                exclude = r"\( -name '\.git' -o -iname '\.*py[co]' -o -fstype 'dev' -o -fstype 'proc' \) -prune"
                only_directories = ('-type d' if self.quantifier else '')
                fzf_default_command = 'find -L . -mindepth 1 {} -o {} -o {} -print | cut -b3-'.format(
                    hidden, exclude, only_directories
                )
    
            env = os.environ.copy()
            env['FZF_DEFAULT_COMMAND'] = fzf_default_command
            env['FZF_DEFAULT_OPTS'] = '--height=80% --layout=reverse --ansi --preview-window down,30% --preview="{}"'.format('''
                (
                    batcat --color=always {} ||
                    bat --color=always {} ||
                    cat {} ||
                    tree -ahpCL 3 -I '.git' -I '*.py[co]' -I '__pycache__' {}
                ) 2>/dev/null | head -n 100
            ''')
    
            fzf = self.fm.execute_command('fzf --no-multi', env=env,
                                          universal_newlines=True, stdout=subprocess.PIPE)
            stdout, _ = fzf.communicate()
            if fzf.returncode == 0:
                selected = os.path.abspath(stdout.strip())
                if os.path.isdir(selected):
                    self.fm.cd(selected)
                else:
                    self.fm.select_file(selected)
    
    • 方法二:
    # fzf
    lass fzf_select(Command):
        """
        :fzf_select
        Find a file using fzf.
        With a prefix argument select only directories.
        See: https://github.com/junegunn/fzf
        """
        def execute(self):
            import subprocess
            import os.path
            if self.quantifier:
                # match only directories
                command="find -L . \( -path '*/\.*' -o -fstype 'dev' -o -fstype 'proc' \) -prune \
                -o -type d -print 2> /dev/null | sed 1d | cut -b3- | fzf +m"
            else:
                # match files and directories
                command="find -L . \( -path '*/\.*' -o -fstype 'dev' -o -fstype 'proc' \) -prune \
                -o -print 2> /dev/null | sed 1d | cut -b3- | fzf +m"
            fzf = self.fm.execute_command(command, universal_newlines=True, stdout=subprocess.PIPE)
            stdout, stderr = fzf.communicate()
            if fzf.returncode == 0:
                fzf_file = os.path.abspath(stdout.rstrip('\n'))
                if os.path.isdir(fzf_file):
                    self.fm.cd(fzf_file)
                else:
                    self.fm.select_file(fzf_file)
    

    ranger配置文件rc.conf设置快捷键

    # fzf
    map <C-f> fzf_select
    
    ✎﹏键落惊风雨,码成泣鬼神~~
  • 相关阅读:
    从 Qt 的 delete 说开来
    Qt信号槽的一些事
    Qt 线程基础(QThread、QtConcurrent等)
    QThread使用——关于run和movetoThread的区别
    重点:怎样正确的使用QThread类(注:包括推荐使用QThread线程的新方法QObject::moveToThread)
    重要:C/C++变量的自动初始化
    C++中基类的析构函数为什么要用virtual虚析构函数
    如何打印Qt中的枚举所对应的字符串
    用route命令解决多出口的问题
    C/C++预处理指令
  • 原文地址:https://www.cnblogs.com/wonux/p/15720035.html
Copyright © 2020-2023  润新知