How can I pass the project root variable from kak-lsp into a shell command

Hello I wanted to make it easier to open files in the current project. Right now I am using a one program one job Unix philosophy workflow using Hyprland as the tiling system, ranger as an in terminal file explorer, and obviously Kakoune and Kak-Lsp as the text editor. I wanted to make opening files in new windows of the same projects easier since I have to do it so much and figured the best way would be to open a new window with ranger opened to the root directory of the project. It is pretty easy to do this with the command: hyrpctl dispatch exec kitty ranger ${insert filepath to project root here} The only thing that I cannot figure out is how to get the project root of the current buffer with an lsp open from kak-lsp. Since kak-lsp is added into the configuration through eval %sh{kak-lsp} I tried to search the output of the kak-lsp command to see what it was doing and I did find a declare-option -hidden str lsp_project_root which I throught is what I need but when I opened a cpp file where the lsp was working and ran debug options to see if it was working I only got * lsp_project_root: '' where the project root doesn’t seem to be set at all despite the lsp clearly working and finding all includes. So my question is simply what is the proper way to get the project root from kak-lsp so I can pass it into a command called by a keybinding. In case the set up of the project is important most my projects look exactly like this:

  • “Project name” directory
    • “.git” directory
    • “debug” CMake debug build directory
    • “release” CMake release build directory
    • “include” include directory
    • “src” source directory
    • “CMakeLists.txt” only cmake file in the project
    • “compile_commands.json” A symbolic link to the compile commands that CMake generates in the debug build directory.

For finding git project root I use this shell expansion:

%sh{git rev-parse --show-toplevel}

Personally I don’t use LSP but it should be able to provide you the project root.
Though as far as I recall, it depends on both the LSP server and LSP client to support the workspace feature.

Hello thank you for your response what I want is this exact behavior (to walk up the parent directory and return the first match but for all of the entrys in the lsp servers “root_globs” variables so that it would work for projects which I don’t have git(which I have a lot of) I tried to make a script to find it (which is why I took so long to respond) but can’t figure out how to walk up the file directory without cding. And if anyone does know the lsp, I found a lsp_send command but I don’t know how to get information back from it and it is not documented on the kak-lsp github. Thank you for your time.

Yeah this is indeed not currently exposed by LSP.

It would be fairly easy and probably reasonable to have kak-lsp set the lsp_project_root option for all LSP-enabled buffers… though a naive implementation would leave it intermittently stale.

(In theory we could also expose this as kak-lsp --project-root $kak_quoted_opt_lsp_servers $kak_quoted_buffile, so it’s “usable” outside the editor but that seems ugly and out-of-place.
kak-lsp is not meant to be called from outside Kakoune, so the preferred mode of interaction is via Kakoune commands/options.)

For now, if you want to use the exact LSP root-globs semantics (as opposed to jj workspace root || git rev-parse --show-toplevel),
I recommend copying the logic that kakoune-lsp uses. Try this:

find_root() {
    project_root=$(dirname "$kak_buffile")
    if [ "$project_root" = . ]; then
        exit # Ignore scratch buffers.
    fi
    until cd "$project_root" 2>/dev/null; do
        project_root=${project_root%/*}
        project_root=/${project_root#/}
    done
    for glob; do
        until [ "$(pwd -P)" = / ]; do
            set -- $glob
            if [ -e "$1" ]; then
                break 2
            fi
            cd ..
        done
        cd "$project_root"
    done
    printf %s "$PWD"
}
# The subshell means that the working-directory changes won't affect the parent shell
root=$( find_root CMakeLists.txt 'compile_commands.*' .git )
do-something-with "$root"

I’ve moved away from ranger (they still didn’t merge the fix preventing glitches on focus notification sequences, which are requested by Kakoune). Instead I mostly use this:

define-command -override my-find-edit -params 1 %{edit -- %arg{@}}
complete-command -menu my-find-edit shell-script-candidates %{ find -type f | sed s,^./,, }
define-command -override my-git-edit -params 1 %{
	edit -existing -- %arg{@}
}
complete-command -menu my-git-edit shell-script-candidates %{ git ls-files || jj --ignore-working-copy file list }
define-command -override my-git-edit-root -params 1 %{
	edit -existing -- %arg{@}
}
complete-command -menu my-git-edit-root shell-script-candidates %{ git ls-files "$(project-root)" || (cd "$(project-root)" && jj --ignore-working-copy file list) }