Skip to content
Bob edited this page Jun 9, 2023 · 27 revisions

Find

You can define the following command to act as a simple fuzzy file picker from the command line:

def find -params 1 -shell-script-candidates %{ find . -type f } %{ edit %arg{1} }

Then :find on the command line will find fuzzy matches to the first argument as you type.

From Kakoune 2022.10.31, the switches for providing command completion are discouraged in favor of the complete-command command. The recommended way is now:

define-command find -docstring "find files" -params 1 %{ edit %arg{1} }
complete-command find shell-script-candidates %{ find . -type f }

Recursive file search under %opt{path} option

This command replicates Vim behavior when path option contains ** item. find will search for file recursively, and if several files found it will prompt you a list of files to choose. This is smart function, so it tries to find match as fast as possible before going full recursive.

define-command -docstring \
"find <filename>: search for file recusively under path option: %opt{path}" \
find -params 1 %{ evaluate-commands %sh{
    file=$1
    eval "set -- $kak_buflist"
    while [ $# -gt 0 ]; do            # Check if buffer with this
        if [ "$file" = "$1" ]; then   # file already exists. Basically
            printf "%s\n" "buffer $1" # emulating what edit command does
            exit
        fi
        shift
    done
    if [ -e "$file" ]; then                     # Test if file exists under
        printf "%s\n" "edit -existing %{$file}" # servers' working directory
        exit                                    # this is last resort until
    fi                                          # we start recursive searchimg

    # if everthing  above fails - search for file under path
    eval "set -- $kak_opt_path"
    while [ $# -gt 0 ]; do
        case $1 in                        # Since we want to check fewer places
            ./) path=${kak_buffile%/*} ;; # I've swapped ./ and %/ because
            %/) path=$PWD ;;              # %/ usually has smaller scope. So
            *)  path=$1 ;;                # this trick is a speedi-up hack.
        esac
        if [ -z "${file##*/*}" ]; then # test if filename contains path
            if [ -e "$path/$file" ]; then
                printf "%s\n" "edit -existing %{$path/$file}"
                exit
            fi
        else # build list of candidates or automatically select if only one found
            for candidate in $(find -L $path -mount -type f -name "$file"); do
                if [ -n "$candidate" ]; then
                    candidates="$candidates %{$candidate} %{evaluate-commands %{edit -existing %{$candidate}}}"
                fi
            done
            if [ -n "$candidates" ]; then
                printf "%s\n" "menu -auto-single $candidates"
                exit
            fi
        fi
        shift
    done
    printf "%s\n" "echo -markup %{{Error}unable to find file '$file'}"
}}

This command can also be mapped to gf keeping old behavior with gAlt+f:

map -docstring "file non-recursive" global goto '<a-f>' '<esc>gf'
map -docstring "file" global goto 'f' '<esc>: find %val{selection}<ret>'

Git

def git-edit -params 1 -shell-script-candidates %{ git ls-files } %{ edit %arg{1} }

Again, the recommended way is now:

define-command git-edit -params 1 %{ edit %arg{1} }
complete-command git-edit shell-script-candidates %{ git ls-files }

FZF

fzf is a basic fuzzy finder tool used to interactively filter large lists of data in a shell.

In the following snippets, a tmux pane is opened with fzf ready to filter a list of files and a list of current buffers.

Other kakoune lists could be filtered this way, taking fzf.vim as inspiration.

define-command -docstring 'Invoke fzf to open a file' -params 0 fzf-edit %{
    evaluate-commands %sh{
        if [ -z "${kak_client_env_TMUX}" ]; then
            printf 'fail "client was not started under tmux"\n'
        else
            file="$(find . -type f |TMUX="${kak_client_env_TMUX}" fzf-tmux -d 15)"
            if [ -n "$file" ]; then
                printf 'edit "%s"\n' "$file"
            fi
        fi
    }
}

# the original version no longer works since kak_buflist is no longer ":" separated.
# this one works even you have single quote or newline in file names.

define-command -docstring 'Invoke fzf to select a buffer' fzf-buffer %{
    evaluate-commands %sh{
        BUFFER=$(
            (
                eval "set -- $kak_buflist"
                while [ $# -gt 0 ]; do
                    printf "%s\0" "$1"
                    shift
                done
            ) |
            fzf-tmux -d 15 --read0
        )
        BUFFER=${BUFFER/\'/\'\'}
        if [ -n "$BUFFER" ]; then
            printf "buffer '%s'" "${BUFFER}"
        fi
    }
}

fzf.kak

There's also a fzf.kak plugin, that includes such features:

  • Supports both x11 and tmux
  • Opening files with find, fd, rg, ag
  • Previewing file contents with syntax highlighting, backed by bat, coderay, highlight, rogue
  • Switching buffers
  • Automatic detection of your VCS to list project files. Supports:
    • Git
    • GNU Bazaar
    • Subversion
    • Mercurial
  • Searching tags with universal-ctags
    • Filtering tags by kinds for all ctags supported languages
  • Searching current buffer contents
  • Changing server's working directory

Skim

Use terminal, fd with skim to open a interactively fuzzy file finder in a new terminal window.

define-command find -docstring "Find a file to open" -params .. %{
    terminal sk -c "fd -tf %arg{@}" --bind %exp{enter:execute(echo eval -verbatim -client %val{client} edit '"{}"' | kak -p %val{session})+abort}
}

Rofi

Select an open buffer using Rofi

define-command rofi-buffers \
-docstring 'Select an open buffer using Rofi' %{ evaluate-commands %sh{
    BUFFER=$(printf "%s\n" "${kak_buflist}" | tr " " "\n" | rofi -dmenu | tr -d \')
    if [ -n "$BUFFER" ]; then
        printf "%s\n" "buffer ${BUFFER}"
    fi
} }

Using Ag + Rofi to select files in your project directory.

define-command rofi-files \
-docstring 'Select files in project using Ag and Rofi' %{nop %sh{
    FILE=$(ag -g "" | rofi -dmenu)
    if [ -n "$FILE" ]; then
        printf 'eval -client %%{%s} edit %%{%s}\n' "${kak_client}" "${FILE}" | kak -p "${kak_session}"
    fi
} }

Fast file finder: fasd integration

Add function k () kak `fasd -f $1` to your .zshrc to open frecent files with k filename

Clone this wiki locally