diff --git a/src/core.go b/src/core.go index 35a143fe..aaf1cf0d 100644 --- a/src/core.go +++ b/src/core.go @@ -379,7 +379,8 @@ func Run(opts *Options) (int, error) { // Change nth and clear caches nth = *val.nth patternCache = make(map[string]*Pattern) - inputRevision.bumpMajor() + cache.Clear() + inputRevision.bumpMinor() } if command != nil { useSnapshot = val.sync diff --git a/src/item.go b/src/item.go index c07d7fff..6b91d069 100644 --- a/src/item.go +++ b/src/item.go @@ -6,10 +6,17 @@ import ( "github.com/junegunn/fzf/src/util" ) +type transformed struct { + // Because nth can be changed dynamically by change-nth action, we need to + // keep the nth value at the time of transformation. + nth []Range + tokens []Token +} + // Item represents each input line. 56 bytes. type Item struct { text util.Chars // 32 = 24 + 1 + 1 + 2 + 4 - transformed *[]Token // 8 + transformed *transformed // 8 origText *[]byte // 8 colors *[]ansiOffset // 8 } diff --git a/src/pattern.go b/src/pattern.go index 11bed5f9..9a386280 100644 --- a/src/pattern.go +++ b/src/pattern.go @@ -393,12 +393,24 @@ func (p *Pattern) extendedMatch(item *Item, withPos bool, slab *util.Slab) ([]Of func (p *Pattern) transformInput(item *Item) []Token { if item.transformed != nil { - return *item.transformed + transformed := *item.transformed + if len(transformed.nth) == len(p.nth) { + same := true + for idx, rangeItem := range transformed.nth { + if rangeItem != p.nth[idx] { + same = false + break + } + } + if same { + return transformed.tokens + } + } } tokens := Tokenize(item.text.ToString(), p.delimiter) ret := Transform(tokens, p.nth) - item.transformed = &ret + item.transformed = &transformed{p.nth, ret} return ret } diff --git a/src/pattern_test.go b/src/pattern_test.go index 9f105f6a..1487d704 100644 --- a/src/pattern_test.go +++ b/src/pattern_test.go @@ -135,12 +135,12 @@ func TestOrigTextAndTransformed(t *testing.T) { chunk.items[0] = Item{ text: util.ToChars([]byte("junegunn")), origText: &origBytes, - transformed: &trans} + transformed: &transformed{pattern.nth, trans}} pattern.extended = extended matches := pattern.matchChunk(&chunk, nil, slab) // No cache if !(matches[0].item.text.ToString() == "junegunn" && string(*matches[0].item.origText) == "junegunn.choi" && - reflect.DeepEqual(*matches[0].item.transformed, trans)) { + reflect.DeepEqual((*matches[0].item.transformed).tokens, trans)) { t.Error("Invalid match result", matches) } @@ -148,7 +148,7 @@ func TestOrigTextAndTransformed(t *testing.T) { if !(match.item.text.ToString() == "junegunn" && string(*match.item.origText) == "junegunn.choi" && offsets[0][0] == 0 && offsets[0][1] == 5 && - reflect.DeepEqual(*match.item.transformed, trans)) { + reflect.DeepEqual((*match.item.transformed).tokens, trans)) { t.Error("Invalid match result", match, offsets, extended) } if !((*pos)[0] == 4 && (*pos)[1] == 0) { diff --git a/src/terminal.go b/src/terminal.go index 88c2b4a0..d7ca89b6 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -1626,6 +1626,10 @@ func (t *Terminal) adjustMarginAndPadding() (int, int, [4]int, [4]int) { return screenWidth, screenHeight, marginInt, paddingInt } +func (t *Terminal) forceRerenderList() { + t.prevLines = make([]itemLine, len(t.prevLines)) +} + func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) { t.forcePreview = forcePreview screenWidth, screenHeight, marginInt, paddingInt := t.adjustMarginAndPadding() @@ -4639,6 +4643,7 @@ func (t *Terminal) Loop() error { if len(tokens) > 1 { a.a = strings.Join(append(tokens[1:], tokens[0]), "|") } + t.forceRerenderList() case actChangeQuery: t.input = []rune(a.a) t.cx = len(t.input) @@ -5101,7 +5106,7 @@ func (t *Terminal) Loop() error { req(reqList) case actToggleHscroll: // Force re-rendering of the list - t.prevLines = make([]itemLine, len(t.prevLines)) + t.forceRerenderList() t.hscroll = !t.hscroll req(reqList) case actTrackCurrent: diff --git a/test/test_go.rb b/test/test_go.rb index b40bfb42..6a7f2ce4 100755 --- a/test/test_go.rb +++ b/test/test_go.rb @@ -3721,10 +3721,12 @@ class TestGoFZF < TestBase def test_change_nth input = [ + *[''] * 1000, 'foo bar bar bar bar', 'foo foo bar bar bar', 'foo foo foo bar bar', - 'foo foo foo foo bar' + 'foo foo foo foo bar', + *[''] * 1000 ] writelines(input) tmux.send_keys %(#{FZF} -qfoo -n1 --bind 'space:change-nth:2|3|4|5|' < #{tempname}), :Enter