From b389616030a76e8bffe9be597fd118787d6f7088 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Mon, 26 Jan 2026 11:16:59 +0900 Subject: [PATCH] Fix track-current unset after a combined movement action Fix #4649 Close #4663 --- src/options.go | 28 +++++++++++++++++++++++----- src/terminal.go | 25 ++++++++++++------------- test/test_core.rb | 24 ++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/src/options.go b/src/options.go index 9faa7a92..1c7de52d 100644 --- a/src/options.go +++ b/src/options.go @@ -292,14 +292,32 @@ func defaultMargin() [4]sizeSpec { return [4]sizeSpec{} } -type trackOption int +type trackOption struct { + enabled bool + index int32 +} -const ( - trackDisabled trackOption = iota - trackEnabled - trackCurrent +var ( + trackDisabled = trackOption{false, minItem.Index()} + trackEnabled = trackOption{true, minItem.Index()} ) +func (t trackOption) Disabled() bool { + return !t.enabled +} + +func (t trackOption) Global() bool { + return t.enabled && t.index == minItem.Index() +} + +func (t trackOption) Current() bool { + return t.enabled && t.index != minItem.Index() +} + +func trackCurrent(index int32) trackOption { + return trackOption{true, index} +} + type windowPosition int const ( diff --git a/src/terminal.go b/src/terminal.go index 1ef745f9..e996dbfc 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -1816,7 +1816,7 @@ func (t *Terminal) UpdateList(result MatchResult) { if i >= 0 { t.cy = i t.offset = t.cy - pos - } else if t.track == trackCurrent { + } else if t.track.Current() { t.track = trackDisabled t.cy = pos t.offset = 0 @@ -2886,10 +2886,9 @@ func (t *Terminal) printInfoImpl() { output += " -S" } } - switch t.track { - case trackEnabled: + if t.track.Global() { output += " +T" - case trackCurrent: + } else if t.track.Current() { output += " +t" } if t.multi > 0 { @@ -5471,11 +5470,11 @@ func (t *Terminal) Loop() error { case reqList: t.printList() currentIndex := t.currentIndex() - focusChanged := focusedIndex != currentIndex - if focusChanged && focusedIndex >= 0 && t.track == trackCurrent { + if t.track.Current() && t.track.index != currentIndex { t.track = trackDisabled info = true } + focusChanged := focusedIndex != currentIndex if (t.hasFocusActions || t.infoCommand != "") && focusChanged && currentIndex != t.lastFocus { t.lastFocus = currentIndex t.eventChan <- tui.Focus.AsEvent() @@ -6550,11 +6549,10 @@ func (t *Terminal) Loop() error { } req(reqInfo) case actToggleTrackCurrent: - switch t.track { - case trackCurrent: + if t.track.Current() { t.track = trackDisabled - case trackDisabled: - t.track = trackCurrent + } else if t.track.Disabled() { + t.track = trackCurrent(t.currentIndex()) } req(reqInfo) case actShowHeader: @@ -6602,12 +6600,13 @@ func (t *Terminal) Loop() error { } req(reqList, reqInfo, reqPrompt, reqHeader) case actTrackCurrent: - if t.track == trackDisabled { - t.track = trackCurrent + // Global tracking has higher priority + if !t.track.Global() { + t.track = trackCurrent(t.currentIndex()) } req(reqInfo) case actUntrackCurrent: - if t.track == trackCurrent { + if t.track.Current() { t.track = trackDisabled } req(reqInfo) diff --git a/test/test_core.rb b/test/test_core.rb index 697133dd..2802c933 100644 --- a/test/test_core.rb +++ b/test/test_core.rb @@ -1588,14 +1588,16 @@ class TestCore < TestInteractive end def test_track_action - tmux.send_keys "seq 1000 | #{FZF} --query 555 --bind t:track", :Enter + tmux.send_keys "seq 1000 | #{FZF} --pointer x --query 555 --bind t:track,T:up+track", :Enter tmux.until do |lines| assert_equal 1, lines.match_count + assert_includes lines, 'x 555' assert_includes lines, '> 555' end tmux.send_keys :BSpace tmux.until do |lines| assert_equal 28, lines.match_count + assert_includes lines, 'x 55' assert_includes lines, '> 55' end tmux.send_keys :t @@ -1605,7 +1607,8 @@ class TestCore < TestInteractive tmux.send_keys :BSpace tmux.until do |lines| assert_equal 271, lines.match_count - assert_includes lines, '> 55' + assert_includes lines, 'x 55' + assert_includes lines, '> 5' end # Automatically disabled when the tracking item is no longer visible @@ -1617,16 +1620,33 @@ class TestCore < TestInteractive tmux.send_keys :BSpace tmux.until do |lines| assert_equal 271, lines.match_count + assert_includes lines, 'x 52' assert_includes lines, '> 5' end tmux.send_keys :t tmux.until do |lines| assert_includes lines[-2], '+t' end + + # Automatically disabled when the focus has moved tmux.send_keys :Up tmux.until do |lines| + assert_includes lines, 'x 53' refute_includes lines[-2], '+t' end + + # Should work even when combined with a focus moving actions + tmux.send_keys 'T' + tmux.until do |lines| + assert_includes lines, 'x 54' + assert_includes lines[-2], '+t' + end + + tmux.send_keys 'T' + tmux.until do |lines| + assert_includes lines, 'x 55' + assert_includes lines[-2], '+t' + end end def test_one_and_zero