Running Shell Command Pipelines From Your Text Editor
What? Why!?
Modern text editors provide lots of commands for manipulating text. Unix shell pipelines also combine into text manipulation utilities, and of course both overlap sometimes. Sorting lines of text is a common first-class command in both environments.
My own approach to editing text changed through using aoeui (asdfg really), a terminal-based editor that eschews many builtin commands in of favor supporting the use of shell pipelines and does so without offering a special mechanism for entering these.
Quoting the documentation:
^E
brings all the power of UNIX text processing commands into your editing session, including your own programs and scripts. This is the best way to customize your editor.^E
executes the shell command pipeline that is the current selection, using the content of the clip buffer as its standard input. The selection is replaced with the command's standard output.
Ever since then I've relied on this feature in every editor I've used, Shell command pipelines are a and flexible editor-independent toolkit that let us replicate many builtin or missing features, and I'm comfortable assembling them.
This document collects ways to run arbitrary shell command pipelines in different text editors.
The main point of differentiation between them is whether we enter the commands in the same text area as the text they operate on. The advantage in using the same area for both is that we can use the same mechanisms to operate on both, and prepare commands independently of when we want to run them. Using a different area on the other hand lets the editor provide additional mechanisms for writing the commands, like completion or an interactive history, and leaves the main text area to care about a single consistent document without arbitrary shell commands in it.
Some good hints about writing unix tools that are always good to reference: Hints for writing Unix tools
Editors
Acme
Acme supports shell commands by selecting them with mouse button 2.
To work as a pipeline they must be prefixed with |
.
Commands can be entered anywhere, it's all text.
If you are unfamiliar with acme I recommend Russ Cox's tour of it.
Aoeui
...and asdfg
Aoeui supports shell pipelines with the keyboard shortcut Control-E
while asfdg uses Control-R
.
Commands are entered in the main text area.
Emacsen
All emacsen I have used,
like GNU Emacs or OpenBSD Mg,
support shell pipelines through shell-command-on-region
,
which is often bound to Meta-|
.
Commands are entered in the minibuffer.
Gedit
Gedit supports shell pipelines with the help of the "External Tools" plugin. Enable the plugin, then in "Manage External Tools…" create a tool with a script like
#!/bin/sh
cmd="$(cat)"
wl-paste | sh -c "$cmd"
Set input to "Current selection" and output to "Replace current selection".
Done this way commands are entered in the main text area, an alternate version could bypass the clipboard, read stdin from the document and the commands in a separate dialog.
Helix
Helix supports shell pipelines through the pipe
command
invoked with |
in normal mode.
Lite
Lite supports shell pipelines through the Exec: Replace
command
from the exec plugin.
Commands are entered in a command line.
Lite XL probably supports the same plugin.
Micro
Micro supports shell pipelines through textfilter
.
Commands are entered after the textfilter
command
on the command line (Ctrl-E
),
and we may want to bind a key to "command-edit:textfilter "
.
Nano
Nano supports shell pipelines through execute
(Control-T
).
Commands are entered in a command line
and must be prefixed with |
to work as a pipeline,
which we can enter ourselves or toggle with flippipe
(Meta-|
).
Sam
Sam supports shell commands through the |
command.
Commands are entered in the command window.
TextMate
TextMate was the first editor I built support for this for, but unless I find a backup of that it's now lost to time. The script was essentially the same as the one for gedit though.
Vi
Vi and its descendants
like vim or nvi
support shell pipelines through the ex command :!
.
Commands are entered in the ex command line.
Visual Studio Code
VSCode supports shell pipelines with the Edit with Shell Command extension
and its EditWithShell: Run command
command.
Commands are entered in a command line
or selected from history.
Zed
Zed supports running shell pipelines by using Tasks.
You can run the task: spawn
command
(Alt-Shift-T
in the default keymap)
and enter your pipeline in the dialog that appears.
To read the selection, you'll have to manually prefix your command with echo "$ZED_SELECTED_TEXT" |
every time,
and you'll also have to find the output in the terminal pane that pops up and copy it manually.
Alternatively you can define a global task like this:
{
"label": "Filter clipboard using selection",
"command": "wl-paste | sh -c \"$ZED_SELECTED_TEXT\""
}
Invoke it using task: spawn
and selecting it from the dialog.
Using this task means that your input must be on the clipboard
and the shell pipeline selected in your editor buffer.
Output will once again be in a terminal pane.