How to access current selection by reference in shell?

I’m editing a document with paragraph numbers and cross references. I’ve written an awk script to maintain the numbers and references as paragraphs are added or deleted. As far as I can tell this requires reading the document once to establish the index and a second time to update the indices.

The bash shell will only pass stdin to awk ONCE. In the shell the solution is awk filename filename, i.e. pass the filename (reference) twice to awk.

Under Kakoune the pipe commands will also pass the current selection to the script by reference only ONCE. I can’t find the syntax to pass the current selection to the script explicitly by reference to allow me to do it twice. $kak_reg_dot expands to the VALUE of the selection, not a REFERENCE. e.g.
:echo %sh{echo $kak_reg_dot}
works. My standard shell solution to pass by reference
:echo %sh{cat <(echo $kak_reg_dot)}
leads Kakoune to seem to object to <(echo $kak_reg_dot)
Am I missing something basic?

There are workarounds like

  • passing variables to awk by value
  • saving the buffer and passing the filename twice to awk as in the shell
  • splitting the script into two pipe steps and passing the index between the 2 scripts in a temp file or named pipe

This is mostly to help me and others understand the fine points of the Kakoune design for communication with the shell.

you can use the value multiple times

nop %sh{
  printf %s "$kak_selection" | foo
  printf %s "$kak_selection" | bar
}

%sh{cat <(echo $kak_reg_dot)}

process substitutions are not (yet?) POSIX so this may depend on which shell you’re using

Great catch!
According to ps -p $$, bash is running at the terminal command prompt
However :echo %sh{ps -p $$} shows sh running under Kakoune.
man sh indicates it is dash and the process substitution error also occurs at a dash prompt outside kakoune.

:echo %sh{echo “cat <(echo hello)”|bash}
successfully returns hello which is a workaround

Unlinking /bin/sh and /usr/bin/sh results in Kakoune refusing to start because it can’t find a Posix compliant shell. Kakoune did start with /bin/sh and /usr/bin/sh symlinked to bash and process substitution ran successfully under Kakoune, but I assume that is unsupported. I understand that it might be difficult to support the multitude of *nix shells. If I were better at C++ I would try running bash to find out what breaks…

I will split the script into two Posix compliant steps. The first step will rewrite stdin to the second step as well as writing the change indexes to a named pipe for step 2 to also process. This also has the benefit of playing nice with the Kakoune pipe commands.

Now I know to test Kakoune scripts under dash. thanks

When bash is started as sh (such as via a symlink) it tries to start up in a POSIX-compatible mode, and many Linux distributions do use bash as /bin/sh, so it’s supported by bash and probably by other tools too.

However, if your /bin/sh defaults to dash, you’re probably on a Debian-derived distribution, and tinkering with /bin/sh is not supported by Debian.

Kakoune will use the $KAKOUNE_POSIX_SHELL environment variable to locate a POSIX shell, if it’s set, so you can try Kakoune with different shells without having to mess with system-managed parts of the filesystem.

Yes, Debian 12 Bookworm. I see the warnings on Reddit etc about tampering with /bin/sh Thanks for the heads up.

1 Like