diff --git a/bin/omarchy-menu-tmux-keybindings b/bin/omarchy-menu-tmux-keybindings index a06d7c5d..a72f1dae 100755 --- a/bin/omarchy-menu-tmux-keybindings +++ b/bin/omarchy-menu-tmux-keybindings @@ -1,6 +1,6 @@ #!/bin/bash -# omarchy:summary=Display Tmux keybindings defined in your configuration using an interactive search menu. +# omarchy:summary=Display annotated Tmux keybindings using an interactive search menu. # omarchy:args=[--print|-p] [--config ] print_only=false @@ -34,197 +34,21 @@ if [[ ! -f $config_file ]]; then fi fi -output_keybindings() { - awk ' -function trim(value) { - gsub(/^[ \t]+|[ \t]+$/, "", value) - return value -} - -function key_part_text(part, is_modifier, part_count) { - gsub(/^\\/, "", part) - - if (is_modifier && part == "C") return "CTRL" - if (is_modifier && part == "M") return "ALT" - if (is_modifier && part == "S") return "SHIFT" - if (part == "Space") return "SPACE" - if (part == "BSpace") return "BACKSPACE" - if (part == "BTab") return "SHIFT + TAB" - if (part == "PPage") return "PAGE UP" - if (part == "NPage") return "PAGE DOWN" - if (part == "DC") return "DELETE" - if (part == "IC") return "INSERT" - if (part_count == 1 && part ~ /^[a-z]$/) return part - - return toupper(part) -} - -function key_text(key, parts, count, i, part, text) { - gsub(/\\/, "", key) - count = split(key, parts, "-") - text = "" - - for (i = 1; i <= count; i++) { - part = key_part_text(parts[i], i < count, count) - text = text (text == "" ? "" : " + ") part - } - - return text -} - -function table_text(table) { - if (table == "copy-mode-vi") return "COPY MODE" - if (table == "copy-mode") return "COPY MODE" - if (table == "prefix") return "PREFIX" - - gsub(/-/, " ", table) - return toupper(table) -} - -function pretty_command(command) { - gsub(/\\;/, ";", command) - gsub(/[{}]/, "", command) - gsub(/^[ \t]+|[ \t]+$/, "", command) - gsub(/[ \t]+/, " ", command) - return command -} - -function command_action(command, normalized, target) { - normalized = pretty_command(command) - - if (normalized ~ /omarchy-menu-tmux-keybindings/) return "Show Tmux keybindings" - if (normalized ~ /^send(-keys)? -X begin-selection/) return "Begin selection" - if (normalized ~ /^send(-keys)? -X copy-selection-and-cancel/) return "Copy selection" - if (normalized ~ /^send-prefix/) return "Send prefix" - if (normalized ~ /^source-file/) return "Reload config" - if (normalized ~ /^split-window -v/) return "Split pane vertically" - if (normalized ~ /^split-window -h/) return "Split pane horizontally" - if (normalized ~ /^kill-pane/) return "Kill pane" - if (normalized ~ /^select-pane -L/) return "Focus pane left" - if (normalized ~ /^select-pane -R/) return "Focus pane right" - if (normalized ~ /^select-pane -U/) return "Focus pane up" - if (normalized ~ /^select-pane -D/) return "Focus pane down" - if (normalized ~ /^resize-pane -L/) return "Resize pane left" - if (normalized ~ /^resize-pane -R/) return "Resize pane right" - if (normalized ~ /^resize-pane -U/) return "Resize pane up" - if (normalized ~ /^resize-pane -D/) return "Resize pane down" - if (normalized ~ /^swap-pane -t "?left-of"?/) return "Move pane left" - if (normalized ~ /^swap-pane -t "?right-of"?/) return "Move pane right" - if (normalized ~ /^swap-pane -t "?up-of"?/) return "Move pane up" - if (normalized ~ /^swap-pane -t "?down-of"?/) return "Move pane down" - if (normalized ~ /^swap-pane -U/) return "Move pane left" - if (normalized ~ /^swap-pane -D/) return "Move pane right" - if (normalized ~ /rename-window/) return "Rename window" - if (normalized ~ /^new-window/) return "New window" - if (normalized ~ /^kill-window/) return "Kill window" - - if (match(normalized, /^select-window -t ([^ ;]+)/, target)) { - gsub(/^:=?/, "", target[1]) - - if (target[1] == "-1") return "Previous window" - if (target[1] == "+1") return "Next window" - - return "Switch to window " target[1] - } - - if (normalized ~ /^swap-window -t -1/) return "Move window left" - if (normalized ~ /^swap-window -t \+1/) return "Move window right" - if (normalized ~ /rename-session/) return "Rename session" - if (normalized ~ /^new-session/) return "New session" - if (normalized ~ /^kill-session/) return "Kill session" - if (normalized ~ /^switch-client -p/) return "Previous session" - if (normalized ~ /^switch-client -n/) return "Next session" - - return normalized -} - -function add_record(combo, action) { - records[++record_count] = sprintf("%-32s → %s", combo, action) -} - -function parse_bind(line, words, count, i, table, global, key, command, combo, action) { - count = split(line, words, /[ \t]+/) - i = 2 - table = "prefix" - global = 0 - - while (i <= count && words[i] ~ /^-/) { - if (words[i] == "-n") { - global = 1 - i++ - } else if (words[i] == "-T") { - table = words[i + 1] - i += 2 - } else if (words[i] == "-r") { - i++ - } else { - i++ - } - } - - key = words[i] - i++ - - command = "" - for (; i <= count; i++) { - command = command (command == "" ? "" : " ") words[i] - } - - if (key == "" || command == "") return - - if (global) { - combo = key_text(key) - } else if (table == "prefix") { - combo = "PREFIX + " key_text(key) - } else { - combo = table_text(table) " + " key_text(key) - } - - action = command_action(command) - add_record(combo, action) -} - -BEGIN { - prefix = "C-b" - prefix2 = "" -} - -{ - line = trim($0) - - if (line == "") next - if (line ~ /^#/) next - - if (line ~ /^(set|set-option|setw|set-window-option)[ \t]/) { - word_count = split(line, words, /[ \t]+/) - - for (i = 2; i <= word_count; i++) { - if (words[i] == "prefix") prefix = words[i + 1] - if (words[i] == "prefix2") prefix2 = words[i + 1] - } - - next - } - - if (line ~ /^(bind|bind-key)[ \t]/) parse_bind(line) -} - -END { - prefix_description = key_text(prefix) - - if (prefix2 != "" && prefix2 != "None") { - prefix_description = prefix_description " / " key_text(prefix2) - } - - printf "%-32s → %s\n", "PREFIX", prefix_description - - add_record("PREFIX + {", "Move pane left") - add_record("PREFIX + }", "Move pane right") - - for (i = 1; i <= record_count; i++) print records[i] -} -' "$config_file" -} +output_keybindings() ( + set -o pipefail + socket_dir=$(mktemp -d) + socket="$socket_dir/tmux" + trap 'tmux -S "$socket" kill-server >/dev/null 2>&1 || true; rm -f "$socket"; rmdir "$socket_dir" 2>/dev/null || true' EXIT + tmux -S "$socket" -f /dev/null start-server \; \ + unbind-key -a -T prefix \; \ + unbind-key -a -T root \; \ + unbind-key -a -T copy-mode \; \ + unbind-key -a -T copy-mode-vi \; \ + source-file "$config_file" \; \ + list-keys -aN -T prefix \; \ + list-keys -aN -T root -P "" \; \ + list-keys -aN -T copy-mode-vi -P "copy-mode-vi" | sed 's/^ //' +) if [[ $print_only == "true" ]]; then output_keybindings diff --git a/config/tmux/tmux.conf b/config/tmux/tmux.conf index 11c75203..d73c42ea 100644 --- a/config/tmux/tmux.conf +++ b/config/tmux/tmux.conf @@ -1,65 +1,65 @@ # Prefix set -g prefix C-Space set -g prefix2 C-b -bind C-Space send-prefix +bind -N "Send prefix" C-Space send-prefix # Config and help -bind q source-file ~/.config/tmux/tmux.conf \; display "Configuration reloaded" -bind ? display-popup -E -w 80% -h 70% -T "Tmux keybindings" "omarchy-menu-tmux-keybindings --print | less -R" +bind -N "Reload configuration" q source-file ~/.config/tmux/tmux.conf \; display "Configuration reloaded" +bind -N "Show Tmux keybindings" ? display-popup -E -w 80% -h 70% -T "Tmux keybindings" "omarchy-menu-tmux-keybindings --print | less -R" # Vi mode for copy setw -g mode-keys vi -bind -T copy-mode-vi v send -X begin-selection -bind -T copy-mode-vi y send -X copy-selection-and-cancel +bind -N "Begin selection" -T copy-mode-vi v send -X begin-selection +bind -N "Copy selection" -T copy-mode-vi y send -X copy-selection-and-cancel # Pane Controls -bind -n M-Enter split-window -v -c "#{pane_current_path}" -bind -n M-S-Enter split-window -h -c "#{pane_current_path}" -bind -n M-Escape kill-pane +bind -N "Split pane vertically" -n M-Enter split-window -v -c "#{pane_current_path}" +bind -N "Split pane horizontally" -n M-S-Enter split-window -h -c "#{pane_current_path}" +bind -N "Kill pane" -n M-Escape kill-pane -bind h split-window -v -c "#{pane_current_path}" -bind v split-window -h -c "#{pane_current_path}" -bind x kill-pane +bind -N "Split pane vertically" h split-window -v -c "#{pane_current_path}" +bind -N "Split pane horizontally" v split-window -h -c "#{pane_current_path}" +bind -N "Kill pane" x kill-pane -bind -n C-M-Left select-pane -L -bind -n C-M-Right select-pane -R -bind -n C-M-Up select-pane -U -bind -n C-M-Down select-pane -D +bind -N "Focus pane left" -n C-M-Left select-pane -L +bind -N "Focus pane right" -n C-M-Right select-pane -R +bind -N "Focus pane up" -n C-M-Up select-pane -U +bind -N "Focus pane down" -n C-M-Down select-pane -D -bind -n C-M-S-Left resize-pane -L 5 -bind -n C-M-S-Down resize-pane -D 5 -bind -n C-M-S-Up resize-pane -U 5 -bind -n C-M-S-Right resize-pane -R 5 +bind -N "Resize pane left" -n C-M-S-Left resize-pane -L 5 +bind -N "Resize pane down" -n C-M-S-Down resize-pane -D 5 +bind -N "Resize pane up" -n C-M-S-Up resize-pane -U 5 +bind -N "Resize pane right" -n C-M-S-Right resize-pane -R 5 # Window navigation -bind r command-prompt -I "#W" "rename-window -- '%%'" -bind c new-window -c "#{pane_current_path}" -bind k kill-window +bind -N "Rename window" r command-prompt -I "#W" "rename-window -- '%%'" +bind -N "Create window" c new-window -c "#{pane_current_path}" +bind -N "Kill window" k kill-window -bind -n M-1 select-window -t 1 -bind -n M-2 select-window -t 2 -bind -n M-3 select-window -t 3 -bind -n M-4 select-window -t 4 -bind -n M-5 select-window -t 5 -bind -n M-6 select-window -t 6 -bind -n M-7 select-window -t 7 -bind -n M-8 select-window -t 8 -bind -n M-9 select-window -t 9 +bind -N "Switch to window 1" -n M-1 select-window -t 1 +bind -N "Switch to window 2" -n M-2 select-window -t 2 +bind -N "Switch to window 3" -n M-3 select-window -t 3 +bind -N "Switch to window 4" -n M-4 select-window -t 4 +bind -N "Switch to window 5" -n M-5 select-window -t 5 +bind -N "Switch to window 6" -n M-6 select-window -t 6 +bind -N "Switch to window 7" -n M-7 select-window -t 7 +bind -N "Switch to window 8" -n M-8 select-window -t 8 +bind -N "Switch to window 9" -n M-9 select-window -t 9 -bind -n M-Left select-window -t -1 -bind -n M-Right select-window -t +1 -bind -n M-S-Left swap-window -t -1 \; select-window -t -1 -bind -n M-S-Right swap-window -t +1 \; select-window -t +1 +bind -N "Previous window" -n M-Left select-window -t -1 +bind -N "Next window" -n M-Right select-window -t +1 +bind -N "Move window left" -n M-S-Left swap-window -t -1 \; select-window -t -1 +bind -N "Move window right" -n M-S-Right swap-window -t +1 \; select-window -t +1 # Session controls -bind R command-prompt -I "#S" "rename-session -- '%%'" -bind C new-session -c "#{pane_current_path}" -bind K kill-session -bind P switch-client -p -bind N switch-client -n +bind -N "Rename session" R command-prompt -I "#S" "rename-session -- '%%'" +bind -N "Create session" C new-session -c "#{pane_current_path}" +bind -N "Kill session" K kill-session +bind -N "Previous session" P switch-client -p +bind -N "Next session" N switch-client -n -bind -n M-Up switch-client -p -bind -n M-Down switch-client -n +bind -N "Previous session" -n M-Up switch-client -p +bind -N "Next session" -n M-Down switch-client -n # General set -g default-terminal "tmux-256color"