tmux: fold tmux-copy into tmux-grab
The whitespace-token pass in tmux-grab already captures whole URLs as
candidates, so the only missing piece was an open action. Add ctrl-o
alongside enter (insert) and ctrl-y (copy), then retire tmux-copy and
its C-y binding now that tmux-grab covers all three actions.
Assisted-by: Claude Sonnet 5 via Claude Code
diff --git a/.config/tmux/tmux.conf b/.config/tmux/tmux.conf
index a0d6ac6a..d2ad5c53 100644
--- a/.config/tmux/tmux.conf
+++ b/.config/tmux/tmux.conf
@@ -101,7 +101,6 @@ bind Tab new-pane -x 80% -y 60% -X 10% -Y 20% -e IN_TMUX_FLOAT=1 -- "~/.dotfiles
# bind -Tfzf-git C-h send-keys C-g h
# bind -Troot C-g switch-client -Tfzf-git
-bind C-y run -b ~/.dotfiles/bin/,tmux-copy
bind r source-file ~/.config/tmux/tmux.conf \; display-message "tmux.conf reloaded"
if-shell "[[ -e ~/.config/tmux/tmux.conf.local ]]" "source-file ~/.config/tmux/tmux.conf.local"
diff --git a/bin/,tmux-copy b/bin/,tmux-copy
deleted file mode 100755
index 701824da..00000000
--- a/bin/,tmux-copy
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/env ruby
-# frozen_string_literal: true
-
-# https://github.com/junegunn/tmux-fzf-url
-
-require 'English'
-require 'shellwords'
-
-def executable(*commands)
- commands.find do |c|
- `command -v #{c.split.first}`.empty?.!
- end
-end
-
-def halt(message)
- system "tmux display-message #{Shellwords.escape(message)}"
- exit
-end
-
-def with(command)
- io = IO.popen(command, 'r+')
- begin
- stdout = $stdout
- $stdout = io
- begin
- yield
- rescue Errno::EPIPE
- nil
- end
- ensure
- $stdout = stdout
- end
- io.close_write
- io.readlines.map(&:chomp)
-end
-
-# TODO: Keep it simple for now
-def extract_urls(line)
- line.scan(%r{(?:https?|file)://[-a-zA-Z0-9@:%_+.~#?&/=]+[-a-zA-Z0-9@%_+.~#?&/=!]+}x)
-end
-
-lines = `tmux capture-pane -J -p -S -99999`
-urls = lines.each_line.map(&:strip).reject(&:empty?)
- .flat_map { |l| extract_urls(l) }.reverse.uniq
-halt 'No URLs found' if urls.empty?
-
-header = 'Press CTRL-Y to copy URL to clipboard'
-max_size = `tmux display-message -p "\#{client_width} \#{client_height}"`.split.map(&:to_i)
-size = [[*urls, header].map(&:length).max + 7, urls.length + 5].zip(max_size).map(&:min).join(',')
-opts = ['--tmux', size, '--multi', '--no-margin', '--no-padding', '--wrap',
- '--expect', 'ctrl-y',
- '--header', header,
- '--highlight-line', '--header-first', '--info', 'inline-right',
- '--border-label', ' URLs '].map(&:shellescape).join(' ')
-selected = with("fzf #{opts}") do
- puts urls
-end
-exit if selected.length < 2
-
-if selected.first == 'ctrl-y'
- # https://superuser.com/questions/288320/whats-like-osxs-pbcopy-for-linux
- copier = executable('reattach-to-user-namespace pbcopy',
- 'pbcopy',
- 'xsel --clipboard --input',
- 'xclip -selection clipboard')
- halt 'No command to control clipboard with' unless copier
- with(copier) do
- print selected.drop(1).join($RS).strip
- end
- halt 'Copied to clipboard'
-end
-
-opener = executable('open', 'xdg-open')
-opener = 'nohup xdg-open' if opener == 'xdg-open'
-halt 'No command to open URL with' unless opener
-selected.drop(1).each do |url|
- system "#{opener} #{Shellwords.escape(url)} &> /dev/null"
-end
diff --git a/bin/,tmux-grab b/bin/,tmux-grab
index ca3abfa0..5deb8fd3 100755
--- a/bin/,tmux-grab
+++ b/bin/,tmux-grab
@@ -38,8 +38,8 @@ main() {
local tmux_opts=(--tmux "80%,60%")
[[ -n "${IN_TMUX_FLOAT:-}" ]] && tmux_opts=()
- # --expect ctrl-y reports which key completed the selection: it's the
- # first line of output, empty unless ctrl-y was the trigger, with the
+ # --expect reports which key completed the selection: it's the first
+ # line of output, empty unless ctrl-y/ctrl-o was the trigger, with the
# selected token on the following line.
local result
result=$(printf '%s\n' "$tokens" | FZF_DEFAULT_OPTS='' fzf --no-multi --select-1 --no-margin --no-padding \
@@ -47,8 +47,8 @@ main() {
--layout reverse \
--height 100% \
--highlight-line --info inline-right \
- --header 'enter: insert ctrl-y: copy' --header-first \
- --expect ctrl-y \
+ --header 'enter: insert ctrl-y: copy ctrl-o: open' --header-first \
+ --expect ctrl-y,ctrl-o \
--border-label ' grab ') || exit 0
[[ -n "$result" ]] || exit 0
@@ -57,12 +57,18 @@ main() {
selection=$(tail -n +2 <<<"$result")
[[ -n "$selection" ]] || exit 0
- if [[ "$key" == "ctrl-y" ]]; then
- printf '%s' "$selection" | pbcopy
- tmux display-message 'Copied to clipboard'
- else
- tmux send-keys -l -t "$pane_id" -- "$selection"
- fi
+ case "$key" in
+ ctrl-y)
+ printf '%s' "$selection" | pbcopy
+ tmux display-message 'Copied to clipboard'
+ ;;
+ ctrl-o)
+ open -- "$selection"
+ ;;
+ *)
+ tmux send-keys -l -t "$pane_id" -- "$selection"
+ ;;
+ esac
}
main "$@"