tmux: window move should insert, not swap #1
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type
Bug
Lineage
standalone — discovered during tmux daily use
Repo
ldraney/tmux-custom(GitHub)What Broke
tmux-pain-controlplugin bindsprefix + <andprefix + >toswap-window -d -t -1/swap-window -d -t +1. This swaps two windows' positions rather than inserting and shifting. Creating a new window (position 5) and pressing<to move it to position 1 causes window 1 to teleport to position 5 — disrupting the entire window order.Repro Steps
[1:mail, 2:code, 3:logs, 4:ssh]5:newprefix + <repeatedly to move window 5 to position 1Expected Behavior
prefix + <should bubble the current window left one position at a time via adjacent swap. Windows not directly involved in the swap should remain in their original order. Result:[NEW, mail, code, logs, ssh]— everything shifts right by one.Environment
~/tmux-custom/.tmux.confAcceptance Criteria
prefix + <moves current window left one position without displacing non-adjacent windowsprefix + >moves current window right one position without displacing non-adjacent windows-r) — mash key to slide through multiple positionsrenumber-windows on(line 72 in config)Related
dotfiles— projecttmux-pain-control— upstream plugin providing the bindings being overriddenScope Review: NEEDS_REFINEMENT
Review note:
review-358-2026-03-25Ticket scope is solid on context and acceptance criteria but missing two sections critical for agent execution.
~/tmux-custom/.tmux.confAFTER the TPM init line (line 95), and must NOT modify the plugin file directly.run '~/.tmux/plugins/tpm/tpm'will be silently clobbered by tmux-pain-control. This must be documented explicitly.Scope Refinement (from review-358-2026-03-25)
Adding the two sections flagged by ticket review:
File Targets
~/tmux-custom/.tmux.conf— add override bindings after line 95 (run '~/.tmux/plugins/tpm/tpm')Constraints
run '~/.tmux/plugins/tpm/tpm'line. Any keybindings defined before this line that conflict with plugin bindings will be silently overwritten. The</>overrides MUST come after the TPMrunline to take effect.set -g automatic-rename off). New bindings should follow this pattern.Scope Review: READY
Review note:
review-358-2026-03-25-v2Re-review after scope refinement. Both File Targets and Constraints sections verified against codebase -- all line references accurate. Ticket is agent-executable.
~/tmux-custom/.tmux.confline 95 (TPM init), line 98 (post-TPM block) -- both verified exact matchrunline confirmed necessaryCode Review: Lines 100-104 of
.tmux.confDOMAIN REVIEW (tmux configuration)
Change under review (lines 100-104):
What pain-control does (lines 30-31 of
pain_control.tmux):The
-dflag in pain-control means "don't follow the moved window." After a swap, focus stays at the original index rather than following the window to its new position. This breaks repeat behavior: pressing<twice in a row swaps the window at the original index twice, which swaps it left then back right -- a no-op. The override correctly removes-dso focus follows the window, making successive presses bubble the window further in one direction.ACCEPTANCE CRITERIA VERIFICATION
prefix + <moves window left one positionswap-window -t -1swaps with the window at index-1prefix + >moves window right one positionswap-window -t +1swaps with the window at index+1-r)-rflag present on both bindings. Without-d, focus follows the window, so repeat key presses continue moving in the same direction.renumber-windows on(line 72)renumber-windowsonly triggers on window creation/destruction, not onswap-window. Index swaps are direct and unaffected.PLACEMENT
Correctly placed after TPM init at line 95. This is necessary because pain-control's
window_move_bindings()runs during TPM plugin initialization. Bindings defined beforerun '~/.tmux/plugins/tpm/tpm'would be overwritten by the plugin. Lines 97-98 and 100-104 are both post-plugin overrides, grouped with the explanatory comment at line 97.BLOCKERS
None.
NITS
Comment accuracy: The comment says "bubble-sort behavior" which is technically correct (pairwise adjacent swaps are the core operation of bubble sort). The term could be confusing to someone unfamiliar with the algorithm. Consider "slide" or "shift" as a more intuitive label, but this is purely cosmetic.
Issue title vs. implementation: The issue says "insert, not swap" but the implementation uses
swap-window. This is not a bug -- swapping with the adjacent window IS insertion for a single-step move, and repeated swaps produce insertion-slide behavior. The distinction only matters for multi-position jumps (e.g., moving window 5 to position 1 in one command), which is not what these keybindings do. Worth noting in the issue close message for future reference.Edge case -- boundary behavior: When the current window is already at the leftmost position,
swap-window -t -1wraps around (swaps with the highest-indexed window). Same for rightmost with+1. This is default tmux behavior and may be surprising. Not a regression from pain-control (same behavior), but worth documenting if users report unexpected wrapping.SOP COMPLIANCE
This is a dotfiles repo, so full SOP (branch naming, PR template, plan slug) does not strictly apply. Reviewing as a direct config change:
PROCESS OBSERVATIONS
Small, surgical change. Low change-failure risk. The override pattern (post-TPM-init rebinding) is clean and maintainable. If more plugin overrides accumulate, consider grouping them under a dedicated section header.
VERDICT: APPROVED
The change correctly satisfies all four acceptance criteria. The removal of
-dfrom pain-control's default bindings is the correct fix, the placement after TPM init is necessary, andrenumber-windows oncompatibility is confirmed. No blockers.