Tiny experiments: buffer-next but related, as a linked list

Hello,

I would like to hear your opinion to switch from a buffer to related buffers with this implementation.

How do you deal with many buffers and switch to the desired one?

# buffer-next but related, as a linked list.
# Usage: Relate buffers together and spam ] until reaching the desired buffer (assuming you mapped ] to relate-next).
provide-module relate %{
  # Internal variables
  declare-option -hidden -docstring 'Next related buffer' str relate_next_buffer
  declare-option -hidden -docstring 'Previous related buffer' str relate_previous_buffer

  # Commands
  # Relate
  define-command relate -params 1 -buffer-completion -docstring 'Relate with the given buffer' %{
    set-option buffer relate_next_buffer %arg{1}
    evaluate-commands -buffer %arg{1} set-option buffer relate_previous_buffer %val{bufname}
  }

  # Relate back
  define-command relate-back -params 1 -buffer-completion -docstring 'Relate back with the given buffer' %{
    relate %arg{1}
    evaluate-commands -buffer %arg{1} relate %val{bufname}
  }

  # Next and previous related buffers
  define-command relate-next -docstring 'Move to the next related buffer' %{
    buffer %opt{relate_next_buffer}
  }

  define-command relate-previous -docstring 'Move to the previous related buffer' %{
    buffer %opt{relate_previous_buffer}
  }
}

# kakrc
require-module relate
alias global r relate
alias global rb relate-back
map -docstring 'relate-next' global normal ']' ': relate-next<ret>'
map -docstring 'relate-previous' global normal '[' ': relate-previous<ret>'
4 Likes

Nice idea. I’ll try this. So far I only used „alternate file“, e.g. for a related buffer that has the unit tests for the file in the current buffer (and back). But you are right, there are other relations than alternate files in everyday use. And there can be more than two buffers total.

Would it be an idea to somehow open linked buffers for the results of a grep or something like that? :thinking: Or is there already a way to go to the next grep file without gaing back to the grep buffer?

I personally find kakoune-buffer-switcher plugin very handy to switch buffers. Especially when mapped to first class key like backspace for example:

def backspace -params 1 %{ eval %sh{[ "$kak_count" = 0 ] && echo "$1" || echo "exec '${kak_count%?}'"} }
map global normal <backspace> ': backspace "eval buffer-switcher"<ret>'
1 Like

You may be interested in :grep-next-match.

1 Like

Hm, maybe @occivink’s idea is better. It is like organizing tabs and therefore doesn’t add an additional concept, so I like it. One thing is I don’t have necessarily one preferred order, depending on what I am doing: editing a lot of models and wanting to be grouped together, or cycling between the source, test and doc. So the relation is not necessarily with a single tab order.

Most languages I work in don’t have the concept of an “alternate” buffer, and definitely don’t have the concept of a string of related buffers, so when I have a bunch of files I’m switching between I usually use the widely-copied :find command so I don’t have to think too hard about which files are open and which aren’t.

Just as aside, for the :relate and :relate-back commands, you might be interested in the -menu switch, which tells Kakoune that the parameter must be one of the completion options, they’re not just suggestions. For commands like these that need the actual name of an actual buffer, this makes them a bit easier to use.

1 Like

A use case is to switch between related *tools* inside toolsclient with following script:

declare-option -hidden str last_tool
hook global BufCreate \
    \*(?:grep|find|make|goto|diagnostics|implementations|symbols|cargo)\* %{
    relate %opt{last_tool}
    set-option global last_tool %val{hook_param}
}

hook global BufClose \
    \*(?:grep|find|make|goto|diagnostics|implementations|symbols|cargo)\* %{
    try %{
        evaluate-commands -buffer %opt{relate_previous_buffer} relate %opt{relate_next_buffer}
    } catch %{
        evaluate-commands -buffer %opt{relate_previous_buffer} unset-option buffer relate_next_buffer
    }
    evaluate-commands %sh{
        if [ "$kak_hook_param" = "$kak_opt_last_tool" ]; then
            printf "set-option global last_tool '%s'\n" "$kak_opt_relate_next_buffer"
            printf "evaluate-commands -buffer '%s' unset-option buffer relate_previous_buffer\n" "$kak_opt_relate_next_buffer"
        fi
    }
}

hook global WinSetOption filetype=(grep|make) %{
    map window normal <left>  ': relate-previous<ret>'
    map window normal <right> ': relate-next<ret>'
}

I didn’t ring the list on purpose, but I think it is possible.

2 Likes

Wow, so if you :grep or :make you can switch between those special buffers *grep* and *make* with :relate-next-buffer?

Yes, next and previous commands do switch between special buffers and if either one is deleted link relations are preserved among the rest.