When I’m walking the results of :grep
, :lsp-references
and friends, I often want to do another recursive search.
Running :grep
again destroys the old search buffer and with it the context of my original search, which is annoying.
We can rename the *grep*
buffer but that’s a manual step that I might forget to do. Also, it becomes tedious to pick names after multiple levels of recursion.
To make this easier I have each :grep
command push its resulting buffer onto a stack.
When I’m done with the current buffer, I can pop from the stack and return to the state before the latest search.
This allows to do a depth-first search across a code base, without having to keep any context in my head.
Here is the code with some example mappings.
I want to package it (as plugin or in the stdlib) but it currently generates a lot of garbage buffers, I’d like to solve this first. Maybe we can have hidden buffers…
# example mappings to traverse search results:
# temporary dependency on kak-lsp for brevity
map global normal <c-n> %{:lsp-next-location %opt{locations_stack_top}<ret>}
map global normal <c-p> %{:lsp-previous-location %opt{locations_stack_top}<ret>}
map global normal <c-r> %{:locations-pop<ret>}
declare-option -hidden str-list locations_stack
declare-option -hidden str locations_stack_top
hook global WinDisplay \*(?:callees|callers|diagnostics|goto|find|grep|implementations|lint-output|references|symbols)\*(?:-\d+)? %{
locations-push
}
define-command locations-push -docstring "push a new locations buffer onto the stack" %{
evaluate-commands %sh{
eval set -- $kak_quoted_opt_locations_stack
if printf '%s\n' "$@" | grep -Fxq -- "$kak_bufname"; then
exit # already in the stack
fi
# rename to avoid conflict with *grep* etc.
newname=$kak_bufname-$#
echo "try %{ delete-buffer! $newname }"
echo "rename-buffer $newname"
}
set-option -add global locations_stack %val{bufname}
set-option global locations_stack_top %sh{
eval set -- $kak_quoted_opt_locations_stack
eval echo \"\$$#\"
}
}
define-command locations-pop -docstring "pop a locations buffer from the stack and return to previous location" %{
evaluate-commands %sh{
eval set -- $kak_quoted_opt_locations_stack
if [ $# -lt 2 ]; then
echo "fail locations-pop: no locations buffer to pop"
fi
}
delete-buffer %opt{locations_stack_top}
set-option -remove global locations_stack %opt{locations_stack_top}
set-option global locations_stack_top %sh{
eval set -- $kak_quoted_opt_locations_stack
eval echo \"\$$#\"
}
try %{
evaluate-commands -try-client %opt{jumpclient} %{
buffer %opt{locations_stack_top}
grep-jump
}
}
}
define-command locations-clear -docstring "delete locations buffers" %{
evaluate-commands %sh{
eval set -- $kak_quoted_opt_locations_stack
printf 'try %%{ delete-buffer %s }\n' "$@"
}
set-option global locations_stack
}