Equivalent of vim's :read command?

Hi, folks. I’d like to insert the content from a file after the current selection, similar to vim’s :read command. How does one do this in Kakoune? I tried a few dozen keywords and didn’t find anything in the existing documentation.

Many many thanks.

# https://neovim.io/doc/user/insert.html#:read
define-command read -params 1 -docstring 'Insert the file [name] below the cursor' %{
  set-register dquote %sh(cat "$1")
  execute-keys p
}
2 Likes

Thank you! I tried to use the ! keystroke (" insert command output before selection"), but that didn’t do what I expected. Do you know what it does that differs from what you offered here? I expected this to work:

!cat <filename>

@jbrains Actually just:

<a-!>cat [file]

! inserts and the Alt version appends.

1 Like

This didn’t seem to work for me, but then I realized that my file name had a space in it.

Oops.

Thank you again.

That looks like a job for the rarely used file expansion

def -file-completion -params 1 read %{
    eval -- reg dquote "%%file{%arg{1}}"
    exec p
}

The <a-!> solution is better tho

1 Like

Coming back into Kakoune, what exactly would be the way to abstract the use of <a-!> here into a command? Because execute-keys <a-!>cat %arg{1}<ret> won’t work, will it?

# https://neovim.io/doc/user/insert.html#:read
define-command read -params 1.. -docstring 'Insert the file [name...] below the cursor' %{
  # Execute the commands in a temporary context,
  # where the registers will be restored.
  evaluate-commands -save-regs 'a|' %{
    # Store arguments into the `a` register.
    set-register a %arg{@}

    # Set the shell command to concatenate the files.
    set-register | %{
      # Set the arg-list with the `a` register.
      eval "set -- $kak_quoted_reg_a"

      # Concatenate the files.
      cat "$@"
    }

    # Paste the output of the shell command.
    execute-keys '<a-!>' '<ret>'
  }
}

The more polished, the more ugly it gets. >:/

1 Like

I feel like it might be necessary to abstract ! or <a-!>[some commandline command] as a…well “function,” but you get what I mean, in these cases. Because there might be other commands one might want to insert or append the output of. I think using %sh{} would get even messier, maybe.

At least with %sh{ ... } we can access the arg-list with:

... %sh{
  cat "$@"
}

without dealing with the escaping.

I ran into this again today. It would be nice if, when <!> or <Alt+!> can’t get output from the command, it yelled loudly.

I requested a feature to make this easier for users. insert-output should complain loudly when the output-producing command fails? · Issue #4302 · mawww/kakoune · GitHub

The eval -- "%%EXPANSION{%arg{1}}" trick is awesome — with %file, %sh{}, %opt{}. The only problem is that the content inside %EXPANSION{} must balance braces (and in correct order too).

For %file, I would recommend eval -- reg dquote "%%file<%arg{1}>" — and then the filename needs to balance angular brackets instead. Those are unlikely to appear in filenames.

I’m doing this in k9s0ke-shlib / Kakoune commands (k9s0ke-file2reg, k9s0ke-file2opt, def-sh-with-prelude-cmd).