mirror of
https://github.com/Llewellynvdm/fzf.git
synced 2025-01-23 07:08:27 +00:00
Add --track option to track the current selection
Close #3186 Related #1890
This commit is contained in:
parent
ae745d9397
commit
1c7534f009
@ -3,6 +3,13 @@ CHANGELOG
|
||||
|
||||
0.39.0
|
||||
------
|
||||
- Added `--track` option that makes fzf track the current selection when the
|
||||
result list is updated. This can be useful when browsing logs using fzf with
|
||||
sorting disabled.
|
||||
```sh
|
||||
git log --oneline --graph --color=always | nl |
|
||||
fzf --ansi --track --no-sort --layout=reverse-list
|
||||
```
|
||||
- If you use `--listen` option without a port number fzf will automatically
|
||||
allocate an available port and export it as `$FZF_PORT` environment
|
||||
variable.
|
||||
|
@ -92,6 +92,16 @@ interface rather than a "fuzzy finder". You can later enable the search using
|
||||
.B "+s, --no-sort"
|
||||
Do not sort the result
|
||||
.TP
|
||||
.B "--track"
|
||||
Make fzf track the current selection when the result list is updated.
|
||||
This can be useful when browsing logs using fzf with sorting disabled.
|
||||
|
||||
.RS
|
||||
e.g.
|
||||
\fBgit log --oneline --graph --color=always | nl |
|
||||
fzf --ansi --track --no-sort --layout=reverse-list\fR
|
||||
.RE
|
||||
.TP
|
||||
.B "--tac"
|
||||
Reverse the order of the input
|
||||
|
||||
|
@ -17,6 +17,7 @@ type Merger struct {
|
||||
tac bool
|
||||
final bool
|
||||
count int
|
||||
pass bool
|
||||
}
|
||||
|
||||
// PassMerger returns a new Merger that simply returns the items in the
|
||||
@ -26,7 +27,8 @@ func PassMerger(chunks *[]*Chunk, tac bool) *Merger {
|
||||
pattern: nil,
|
||||
chunks: chunks,
|
||||
tac: tac,
|
||||
count: 0}
|
||||
count: 0,
|
||||
pass: true}
|
||||
|
||||
for _, chunk := range *mg.chunks {
|
||||
mg.count += chunk.count
|
||||
@ -58,6 +60,19 @@ func (mg *Merger) Length() int {
|
||||
return mg.count
|
||||
}
|
||||
|
||||
// FindIndex returns the index of the item with the given item index
|
||||
func (mg *Merger) FindIndex(itemIndex int32) int {
|
||||
if mg.pass {
|
||||
return int(itemIndex)
|
||||
}
|
||||
for i := 0; i < mg.count; i++ {
|
||||
if mg.Get(i).item.Index() == itemIndex {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Get returns the pointer to the Result object indexed by the given integer
|
||||
func (mg *Merger) Get(idx int) Result {
|
||||
if mg.chunks != nil {
|
||||
|
@ -33,6 +33,7 @@ const usage = `usage: fzf [options]
|
||||
field index expressions
|
||||
-d, --delimiter=STR Field delimiter regex (default: AWK-style)
|
||||
+s, --no-sort Do not sort the result
|
||||
--track Track the current selection when the result is updated
|
||||
--tac Reverse the order of the input
|
||||
--disabled Do not perform search
|
||||
--tiebreak=CRI[,..] Comma-separated list of sort criteria to apply
|
||||
@ -266,6 +267,7 @@ type Options struct {
|
||||
WithNth []Range
|
||||
Delimiter Delimiter
|
||||
Sort int
|
||||
Track bool
|
||||
Tac bool
|
||||
Criteria []criterion
|
||||
Multi int
|
||||
@ -338,6 +340,7 @@ func defaultOptions() *Options {
|
||||
WithNth: make([]Range, 0),
|
||||
Delimiter: Delimiter{},
|
||||
Sort: 1000,
|
||||
Track: false,
|
||||
Tac: false,
|
||||
Criteria: []criterion{byScore, byLength},
|
||||
Multi: 0,
|
||||
@ -1562,6 +1565,10 @@ func parseOptions(opts *Options, allArgs []string) {
|
||||
opts.Sort = optionalNumeric(allArgs, &i, 1)
|
||||
case "+s", "--no-sort":
|
||||
opts.Sort = 0
|
||||
case "--track":
|
||||
opts.Track = true
|
||||
case "--no-track":
|
||||
opts.Track = false
|
||||
case "--tac":
|
||||
opts.Tac = true
|
||||
case "--no-tac":
|
||||
|
@ -183,6 +183,7 @@ type Terminal struct {
|
||||
multi int
|
||||
sort bool
|
||||
toggleSort bool
|
||||
track bool
|
||||
delimiter Delimiter
|
||||
expect map[tui.Event]string
|
||||
keymap map[tui.Event][]*action
|
||||
@ -599,6 +600,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
|
||||
multi: opts.Multi,
|
||||
sort: opts.Sort > 0,
|
||||
toggleSort: opts.ToggleSort,
|
||||
track: opts.Track,
|
||||
delimiter: opts.Delimiter,
|
||||
expect: opts.Expect,
|
||||
keymap: opts.Keymap,
|
||||
@ -904,6 +906,10 @@ func (t *Terminal) UpdateProgress(progress float32) {
|
||||
// UpdateList updates Merger to display the list
|
||||
func (t *Terminal) UpdateList(merger *Merger, reset bool) {
|
||||
t.mutex.Lock()
|
||||
var prevIndex int32 = -1
|
||||
if !reset && t.track && t.merger.Length() > 0 {
|
||||
prevIndex = t.merger.Get(t.cy).item.Index()
|
||||
}
|
||||
t.progress = 100
|
||||
t.merger = merger
|
||||
if reset {
|
||||
@ -914,6 +920,18 @@ func (t *Terminal) UpdateList(merger *Merger, reset bool) {
|
||||
t.triggerLoad = false
|
||||
t.eventChan <- tui.Load.AsEvent()
|
||||
}
|
||||
if prevIndex >= 0 {
|
||||
pos := t.cy - t.offset
|
||||
count := t.merger.Length()
|
||||
i := t.merger.FindIndex(prevIndex)
|
||||
if i >= 0 {
|
||||
t.cy = i
|
||||
t.offset = t.cy - pos
|
||||
} else if t.cy > count {
|
||||
// Try to keep the vertical position when the list shrinks
|
||||
t.cy = count - util.Min(count, t.maxItems()) + pos
|
||||
}
|
||||
}
|
||||
t.mutex.Unlock()
|
||||
t.reqBox.Set(reqInfo, nil)
|
||||
t.reqBox.Set(reqList, nil)
|
||||
|
@ -2679,6 +2679,29 @@ class TestGoFZF < TestBase
|
||||
OUTPUT
|
||||
tmux.until { assert_block(expected, _1) }
|
||||
end
|
||||
|
||||
def test_track
|
||||
tmux.send_keys "seq 1000 | #{FZF} --query 555 --track", :Enter
|
||||
tmux.until do |lines|
|
||||
assert_equal 1, lines.match_count
|
||||
assert_includes lines, '> 555'
|
||||
end
|
||||
tmux.send_keys :BSpace
|
||||
index = tmux.until do |lines|
|
||||
assert_equal 28, lines.match_count
|
||||
assert_includes lines, '> 555'
|
||||
end.index('> 555')
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until do |lines|
|
||||
assert_equal 271, lines.match_count
|
||||
assert_equal '> 555', lines[index]
|
||||
end
|
||||
tmux.send_keys :BSpace
|
||||
tmux.until do |lines|
|
||||
assert_equal 1000, lines.match_count
|
||||
assert_equal '> 555', lines[index]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module TestShell
|
||||
|
Loading…
x
Reference in New Issue
Block a user