declare-option str-list harpoon_files define-command harpoon-add -docstring "harpoon-add: Add the current file to the list of harpoons" %{ evaluate-commands %sh{ eval set -- "$kak_quoted_opt_harpoon_files" index=0 while [ $# -gt 0 ]; do index=$(($index + 1)) if [ "$1" = "$kak_bufname" ]; then echo "fail %{$kak_quoted_bufname is already harpooned at index $index}" exit fi shift done index=$(($index + 1)) printf "%s\\n" " set-option -add global harpoon_files $kak_quoted_bufname echo '$index: $kak_bufname' " } } define-command harpoon-nav -params 1 -docstring "harpoon-nav : navigate to the harpoon at " %{ evaluate-commands %sh{ index=$1 eval set -- "$kak_quoted_opt_harpoon_files" eval "bufname=\${$index}" if [ -n "$bufname" ]; then echo "edit '$bufname'" echo "echo '$index: $bufname'" else echo "fail 'No harpoon at index $index'" fi } } define-command harpoon-show-list -docstring "harpoon-show-list: show all harpoons in the *harpoons* buffer" %{ evaluate-commands -save-regs dquote %{ try %{ set-register dquote %opt{harpoon_files} edit -scratch *harpoon* execute-keys -draft '%"_daI#: gjxd' } try %{ execute-keys ggghwl } catch %{ delete-buffer *harpoon* fail "No harpoons are set" } } } define-command -hidden harpoon-update-from-list %{ evaluate-commands -save-regs dquote %{ try %{ execute-keys -draft -save-regs '' '%^\d*:;wly' set-option global harpoon_files %reg{dquote} harpoon-show-list } catch %{ set-option global harpoon_files } echo "Updated harpoons" } } define-command harpoon-add-bindings -docstring "Add convenient keybindings for navigating harpoons" %{ map global normal ":harpoon-nav 1" map global normal ":harpoon-nav 2" map global normal ":harpoon-nav 3" map global normal ":harpoon-nav 4" map global normal ":harpoon-nav 5" map global normal ":harpoon-nav 6" map global normal ":harpoon-nav 7" map global normal ":harpoon-nav 8" map global normal ":harpoon-nav 9" map global user h ":harpoon-add" -docstring "add harpoon" map global user H ":harpoon-show-list" -docstring "show harpoons" } hook global BufCreate \*harpoon\* %{ map buffer normal ':harpoon-nav %val{cursor_line}' map buffer normal ':delete-buffer *harpoon*' alias buffer write harpoon-update-from-list alias buffer w harpoon-update-from-list add-highlighter buffer/harpoon-indices regex ^\d: 0:function } # State saving - save by PWD and git branch, if any declare-option str harpoon_state_file define-command -hidden harpoon-load %{ evaluate-commands %sh{ if [ -f "$kak_opt_harpoon_state_file" ]; then printf "set-option global harpoon_files " cat "$kak_opt_harpoon_state_file" fi } } define-command -hidden harpoon-save %{ evaluate-commands %sh{ if [ -z "$kak_opt_harpoon_state_file" ]; then exit fi if [ -z "$kak_quoted_opt_harpoon_files" ]; then rm -f "$kak_opt_harpoon_state_file" exit fi printf "$kak_quoted_opt_harpoon_files" > "$kak_opt_harpoon_state_file" } } define-command -hidden harpoon-check %{ evaluate-commands %sh{ git_branch=$(git -C "${kak_buffile%/*}" rev-parse --abbrev-ref HEAD 2>/dev/null) state_file=$(printf "%s" "$PWD-$git_branch" | sed -e 's|_|__|g' -e 's|/|_-|g') state_dir=${XDG_STATE_HOME:-~/.local/state}/kak/harpoon state_path="$state_dir/$state_file" if [ "$state_path" != "$kak_opt_harpoon_state_file" ]; then mkdir -p "$state_dir" printf "%s\\n" " harpoon-save set-option global harpoon_state_file '$state_path' harpoon-load " fi } } hook global FocusIn .* harpoon-check hook global WinDisplay .* harpoon-check hook global KakEnd .* harpoon-save