Archived: this was a fun project, but these days I make this happen by composing individual commands instead. E.g. I have this script bound to a key in tmux:
#!/usr/bin/env fish
set file (mktemp)
set mode (tmux display-message -p "#{pane_mode}")
if test $mode = "copy-mode"
set start (math -1 x (tmux display-message -p "#{scroll_position}"))
set offset (tmux display-message -p "#{pane_height}")
# An additional offset of 1 is necessary, probably to remove the border at the top.
set end (math $start + $offset - 1)
tmux capture-pane -pJ -S $start -E $end > $file
else
tmux capture-pane -pJ > $file
end
tmux new-window -n "<extract>" "cat $file | rg -o '(http|https)://\\S+[\\S&&[^\'\"]]' | sort | uniq | sk | vipe | <some command here>; rm $file"Extract a regex, invoke a command on it.
The canonical use (that I wrote this for) is to extract URLs from stdout on the command line, and then automatically copy them to clipboard or open them in a web browser.
cargo install --locked --git https://github.com/patrick-kidger/exvoker
You'll also need to create a ~/.config/exvoker/exvoker.toml file specifying what regexes to extract, and what command to run on them. For example, here's mine:
extract = '''(http|https)://\S+'''
invoke = 'tmux set-buffer -w'This extracts most URLs, and copies the selected item to my tmux clipboard.
(This URL-matching is deliberately simplistic, and you can try other more complicated regexes if you want to.)
exvoker reads from stdin and parses out items that match the regex. Using the URL regex above, then this:
echo "https://github.com foo bar http://google.com qux https://twitter.com" | exvoker
produces:
▓ ❯ https://github.com http://google.com https://twitter.com
This menu can be navigated (keys listed below), and also has a fuzzy search prompt on the first line:
go▓ ❯ http://google.com https://github.com
Once you're happy with your choice, then press Space to select the item, which will run your invoke command on it. (Passed as $invoke $selection.)
Alternatively, press Enter to edit the item before invoking a command on it.
Esc/Control-C: quit (and do nothing)Up/Shift-Tab: move selection upDown/Tab: move selection downHome/End/Left/Right/letters/numbers/punctuation/etc.: edit fuzzy selectionSpace: select itemEnter: select item and edit it (using the same interface as fuzzy selection). Then press eitherSpaceorEnteragain to select the edited version.
I have bind e run tmux-exvoker in my tmux configuration file, and the executable file tmux-evoker on my $PATH (make sure it's executable: chmod +x tmux-exvoker), with contents:
#!/usr/bin/env fish
set file (mktemp -p /dev/shm)
tmux capture-pane -pJ > $file
tmux new-window -n "<exvoker>" "cat $file | exvoker"(you may need to adapt this if you use other shells, e.g. bash or zsh)
This will call exvoker on the currently-visible contents of your pane, when you press <prefix> e.
To open the selected link in a web browser, include this in exvoker.toml:
invoke = 'xdg-open'Depends exactly what is meant by "system" clipboard, but on many Linux distros that frequently means using the X clipboard:
invoke = 'xsel -ib'In exvoker.toml:
invoke = 'tmux set-buffer -w'In this example, we additionally match strings of the form Index <number>, and rewrite them to https://example.org/index/<number>, and then invoke our final command.
In exvoker.toml:
extract = '''((http|https)://\S+|Index [0-9]+)'''
invoke = 'exvoker-invoke'And in an file exvoker-invoke somewhere on your $PATH (make sure it's executable: chmod +x exvoker-invoke):
#!/usr/bin/env fish
if test (count $argv) -ne 1
echo "Can only invoke with a single argment"
exit 1
end
set --function arg $argv[1]
if test (string match --regex '^Index [0-9]+' "$arg")
set --function arg (string replace 'Index ' 'https://example.org/index/' "$arg")
end
tmux set-buffer -w $arg # Or whatever else your final command isThe above uses the fish shell, but you could construct something equivalent if you're a bash/zsh/etc. user.
The basic functionality of copying URLs from stdout to clipboard was inspired by the venerable urlview. This is intended as a personal replacement for that. I didn't really like urlview enough (or any of its derivatives), mostly because they involved too many keypresses. For example extracting a URL via urlview involves three keypresses, to select item -> edit item -> close menu. In contrast exvoker only requires a single keypress to select an item.
The command line interface is adapted from dialoguer, which honestly does most of the heavy lifting here.