Piped command information on file started from

I was trying to destinguish the behaviour of a command run on a selection (using |snip) based on the type of file the selection was made on. I checked the environment variables availabe to the snip program, but none seem to be set by kakoune. Is it possible to at least pass on the filename, either as environment variable.

An extra commandline option (like --file abc.ext) added to the invocation of snip would work as well, but I would not like to have that added to every command invocation.

See :doc expansions shell-expansions for all the environment variables that Kakoune can set for external commands - although by default it doesn’t set any unless it sees them mentioned in the command line.

I’m not familiar with this snip program or what environment variables it might consult.

snip is a in-house program that finds a code snippet based on the argument you give it. I can modify it to look at any environment variable.

If I knew the filename or the full path based on any environment variable I could select e.g. Python only snipppets when the filename ends in .py.

I currently dump all environment variables that snip receives to a log file, and I don’t see any difference when adding # kak_session on the commandline as suggested in the doc you refer to.

If I launch Kakoune with kak -n (to prevent it from loading any configuration or the standard library), and then press:

%|env # kak_session

…and hit Enter, then I get a list of environment variables, and $kak_session is in the list. Does that not work for you? What version of Kakoune are you using?

Yes this works. Thanks for the pointers, that helped me progress. I originally tried the full echo … example and that doesn’t work in |.
There was another problem with my snip command getting the comment # kakoune and not working properly because of that.
And I realise I might have typed fgrep out of habit (instead of plain grep) and then ^kak_ will of course not match. I should switch to the recommended grep -F instead of using fgrep at all, but 40 years of musclememory is not easily erased.

I am going to look into how to use define-command to create a snip command that invokes the external utiltiy and has some env. variable names in its body.
Thanks again

rc/tools/format.kak in the Kakoune repo uses this pattern:

define-command snip %{
	evaluate-commands -save-regs | %{
		set-register '|' %{
			# kak_buffile
			# kak_opt_filetype
		execute-keys -draft |<ret>

@krobelus That looked promising, and when I added -params 2, executing :snip would require two parameters. But I couldn’t get these parameters passed on to the external program:

define-command snip -params 2 %{
    evaluate-commands -save-regs | %{
        set-register '|' %{
            # kak_buffile
            # kak_opt_filetype
            snip $1 $2
        execute-keys -draft |<ret>

I tried quoting ( "$1" ) inserting curly braces (${1}), which didn’t get me the parameters in the program, and quoting the whole ("snip $1 $2"), resulted in command not found (as seen in debug`.

I checked out the source for kakoune to see if there were slightly more complicated set-register '|' examples that also set parameters but couldn’t find any so far.

The filename and file type do get passed on nicely.

That’s an open issue that only comes up seldomly. Not sure if we should change it.
A workaround is to use an option or a register as intermediary:

evaluate-commands -save-regs |a %{
  set-register a %arg{1}
  set-register | %{
      snip "$kak_reg_a"

You probably also want to define completions for your command, using something like

complete-command -menu snip shell-script-candidates %{
set -- $(snip --list-possible-arguments)
    printf '%s\n' "$@"

For even tighter integration, there are snippet plugins (like kak-lsp) that expose snippets as autocompletions. When a completion is accepted, the snippet is expanded. That’s a bit more involved but probably still well simpler than in other editors.

1 Like

The set-register trick worked. I was not sure if I needed to set a different register for each argument or could combine the two, but the latter worked ( set-register %arg{1} %arg{2} ).

The completion would be nice, the utility already has a --list option to list such possible completions. But I haven’t got that work yet.

/Users/anthon/.config/kak/kakrc:76:1: 'complete-command': no such command
/opt/homebrew/Cellar/kakoune/2021.11.08/share/kak/kakrc:29:1: 'evaluate-commands': 131:1: 'source': 76:1: 'complete-command': no such command
error while parsing kakrc:
    1:1: 'source': 29:1: 'evaluate-commands': 131:1: 'source': 76:1: 'complete-command': no such command

(note that instead of set-register a %arg{1} %arg{2} you can write set-register a %arg{@})
FYI there’s a hidden gotcha with passing both arguments in a single register. If one of them contains a space, you need special quoting to break them apart again (POSIX sh doesn’t really have arrays except “$@”). Here’s the customary pattern:

set-register a arg 'arg   with   spaces'
execute-keys %{!eval set -- "$kak_quoted_reg_a"; printf '[%s]\n' "$@"<ret>}


[arg   with   spaces]

‘complete-command’: no such command

sorry this is not yet in the released version. I think mawww wants to tag a release soon.
You can use the equivalent define-command -shell-script-candidates switch to define shell completions (or you can update to latest git master, also a good choice).