aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-05-13 13:43:13 +0100
committerLibravatar sommerfeld <sommerfeld@sommerfeld.dev>2026-05-13 13:43:13 +0100
commitbcb3792e45de4b880013cc2ed0f4c2bfccb1671c (patch)
treed6d82842a5e5cc9e26b5d2fd9f209e4bc692210d
parent38220f5fbb12fd4327e9515a7040d7a7ac0d55c7 (diff)
downloaddotfiles-bcb3792e45de4b880013cc2ed0f4c2bfccb1671c.tar.gz
dotfiles-bcb3792e45de4b880013cc2ed0f4c2bfccb1671c.tar.bz2
dotfiles-bcb3792e45de4b880013cc2ed0f4c2bfccb1671c.zip
feat(zsh): add Alt-Shift-Y widget to copy last command output
Zellij has no native "copy last command output" feature, and ghostty's jump_to_prompt (Ctrl+Shift+J/K, via OSC 133) can't work inside zellij because zellij sits between the shell and the terminal emulator. Build it ourselves: a zle widget runs 'zellij action dump-screen --full', finds the last two lines matching the prompt prefix (user@host:), and pipes everything between them to wl-copy. Bound to Alt+Shift+Y. Requires running inside zellij and at least two prompts in the scrollback.
-rw-r--r--KEYBINDS.md1
-rw-r--r--dot_config/zsh/dot_zshrc39
2 files changed, 40 insertions, 0 deletions
diff --git a/KEYBINDS.md b/KEYBINDS.md
index 18129da..99ae335 100644
--- a/KEYBINDS.md
+++ b/KEYBINDS.md
@@ -243,6 +243,7 @@ Emacs mode (`bindkey -e`) is the base.
| `Ctrl-X Ctrl-R` | fzf history search + execute |
| `Ctrl-T` | fzf file picker (built-in) |
| `Alt-C` | fzf cd (built-in) |
+| `Alt-Shift-Y` | Copy last command's output (zellij only) |
## Ghostty
diff --git a/dot_config/zsh/dot_zshrc b/dot_config/zsh/dot_zshrc
index c7d5e90..db9fa85 100644
--- a/dot_config/zsh/dot_zshrc
+++ b/dot_config/zsh/dot_zshrc
@@ -241,6 +241,45 @@ alias sub='subliminal download -l en'
# Use `| wlc` to copy AND see the output.
wlc() { tee >(wl-copy "$@"); }
+# Copy the *last* command's output to the clipboard, retroactively.
+# Works only inside zellij — uses `zellij action dump-screen --full` and
+# locates prompt boundaries by matching the prompt prefix `user@host:`.
+# Bound to Alt+Shift+Y as a zle widget.
+copy-last-output() {
+ emulate -L zsh
+ if [[ -z $ZELLIJ ]]; then
+ zle -M "copy-last-output: not inside a zellij session"
+ return 1
+ fi
+ local dump
+ dump=$(zellij action dump-screen --full 2>/dev/null) || {
+ zle -M "copy-last-output: dump-screen failed"
+ return 1
+ }
+ local prompt_re='^[[:alnum:]_-]+@[[:alnum:]_-]+:'
+ local -a lines
+ lines=("${(@f)dump}")
+ local -a prompt_idx
+ local i
+ for (( i = 1; i <= ${#lines}; i++ )); do
+ [[ ${lines[i]} =~ $prompt_re ]] && prompt_idx+=($i)
+ done
+ if (( ${#prompt_idx} < 2 )); then
+ zle -M "copy-last-output: need at least 2 prompts in scrollback"
+ return 1
+ fi
+ local start=$(( ${prompt_idx[-2]} + 1 ))
+ local end=$(( ${prompt_idx[-1]} - 1 ))
+ if (( start > end )); then
+ zle -M "copy-last-output: previous command produced no output"
+ return 0
+ fi
+ printf '%s\n' "${lines[start,end]}" | wl-copy
+ zle -M "copied $((end - start + 1)) line(s) of last command output"
+}
+zle -N copy-last-output
+bindkey '^[Y' copy-last-output # Alt+Shift+Y
+
# Neovim
alias n='nvim'
alias ndiff='nvim -d'