Calling `fzf` command from user script

I’ve defined my command named go-decls, which calls fzf command internally. fzf command is part of fzf plugin by @andreyorst.
Now when I call my command for the very first time, like :go-decls<ret>, it says no such command: fzf.
I figured out that I need first run any of fzf plugin’s command, then my command works.
I suppose fzf module should be loaded first, before I can call fzf command in my script.
How do I augment my command, so it works regardless?

just prepend require-module fzf before call. If module is already required there’s no significant overhead of calling require-module again.

If you 100% want to avoid calling require-module every time, you probably can override command inside command like so:

define-command fzf-go-decl %{
    require-module fzf
    fzf ...
    define-command -override fzf-go-decl %{
        fzf ...
    }
}

But this is much code duplication here, so I would just do:

define-command fzf-go-decl %{
    require-module fzf
    fzf-go-decl-impl
    define-command -override fzf-go-decl %{
        fzf-go-decl-impl
    }
}

define-command fzf-go-decl-impl %{
    fzf ...
}

If you’re using mappings to call it from fzf-user-mode, it’s easier, because you can put your command to the list of mappings of fzf, and you will be able to call it from here without requiring:

hook global ModuleLoaded fzf %§
    map global fzf -docstring "Go declarations" 'G' '<esc>: fzf-go-decl<ret>'
    define-command fzf-go-decl %{
        fzf ...
    }
§

Doing it through mapping is a recommended way to extend fzf.kak, because by doing this, you’re deferring your configuration in a proper way.

By requiring module too early you can break the rest of fzf modules. That is, if you require module fzf after fzf.kak and your function was sourced and called, but the rest of files weren’t sourrced yet. I guess this is hard to achieve, if you’re using plug.kak but if sourcing plugin manually or via autoload this is possible.

1 Like

Thank you! It works now.

I was thinking to map it to fzf menu with ModuleLoaded hook, but it is specific to go filetype.
Can I have fzf menu item available on specific filetype only?

PS: I do use plug.kak

This is what I got, after your recommendation:

define-command go-decls %{
    require-module fzf
    go-decls-impl
    define-command -override go-decls %{
        go-decls-impl
    }
}

define-command -hidden go-decls-impl %{ evaluate-commands %sh{
    output=$(mktemp ${TMPDIR:-/tmp}/kak-go-decls.XXXXXX)
    motion -mode decls -include func,type -file ${kak_bufname} | jq -c '[.decls[]]' > ${output}

    filter='.[] | "\(.filename):\(.line):\(.col):\t\(.keyword) \(.ident)"'
    items_command="cat $output | jq -r '${filter}' | nl -b a -n ln"
    pcmd=$(printf 'n=$(echo {} | cut -f 1); cat %s | jq -r .[$(($n-1))].full | gofmt' "$output")
    preview="--preview '${pcmd}'"
    # echo "echo -debug items_command: $items_command"
    # echo "echo -debug preview: ${preview}"

    printf "%s\n" "fzf -kak-cmd %{fzf-sk-grep-handler} -items-cmd %{$items_command} -preview -preview-cmd %{$preview} -fzf-args %{--expect $kak_opt_fzf_window_map} -filter %{cut -f 2,3} -post-action %{buffer %opt{fzf_sk_first_file}}"
}}

I really like this functionality to outline go file. It may be not perfect in terms of implementation, but seems to work well.

This is bit trickier. I guess you should go for command overriding, like you did in the answer above this reply, and wrap it to the go module loaded hook. But again, calling require-module should not add overhead if module was loaded, so you can skip the overriding part and just always call reuire-module in your command.

I Guess you sould go for hook ModuleLoaded go which will try to require-module fzf and define-command fzf-go-decls and catch possible error on requiring fzf.

If this code will be evaluated after fzf.kak it will work fine. If not, it will throw an error which you’ll be able to see.