In kakoune (vim-like editor) I can press pipe, type a command, press enter, and it will run the command using the current selection as input, and replace that selection with the output of the command ran.
For example, |jq<ret>
, where <ret>
is the Enter key, will format a json selection.
Sometimes though, I’d rather have the selection used as part of the command, instead of as the input. For example if I want to use cat
to replace a file name with its content. Within Kakoune there’s a handy shortcut to paste the current selection in the command prompt, but it doesn’t work with multi-selection (running the same command multiple times with different i/o).
The solution I settled for is to expand the stdin using $(cat)
. For the previous example, I would press |cat $(cat)<ret>
.
This use of $(cat)
seems to rely on the specific (and degenerate?) way bash handles expansions and sub-process. For example, it doesn’t work on zsh or fish where the expansion happens immediately and the input of cat
is the output of the terminal, or I guess of whatever launched the command. Instead, in bash, the input of cat
is the output of the command before the pipe.
I use this pattern outside of kakoune as well, for example:
pgrep code | ps -p $(cat) -O [options]
to use pgrep to search processes and use ps to format the informations I want to display (better than with pgrep -a
), but kakoune pipe command is the one use case where I cannot use the more robust and maybe more idiomatic:
ps -p $(pgrep code) -O [option]
Kakoune defaults to sh
which most often means bash or dash, so I’m fine, but since I primarily use fish as my interactive shell, I am still very curious about achieving something similar in fish. Namely:
How to expand stdin from a previously piped command, or how to generate and execute a command depending on stdin ?
I’m also curious about cleaner ways in bash.
One thing I love aobut interactive shell languages (as opposed to most programming language, or even to Nu) is the flexibility in the flow of information. For example, because I used to do them separately and in that order, pgrep code | ps -p $(cat)
makes some sense to me, more than starting with ps
, and I love having the choice. As for kak, short of writing down scripts or writing to temporary files, the pipe command does impose a constraint, which turns out rather strong despite being very reasonable.