Skip to content

Commit

Permalink
add initial query and select one options (#185)
Browse files Browse the repository at this point in the history
Co-authored-by: William Snyders <wsnyders@flexera.com>
  • Loading branch information
wsny and William Snyders authored Nov 27, 2023
1 parent 8d345ee commit 09200ef
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 0 deletions.
12 changes: 12 additions & 0 deletions fuzzyfinder.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ func (f *finder) initFinder(items []string, matched []matching.Matched, opt opt)
f.drawTimer.Stop()
}
f.eventCh = make(chan struct{}, 30) // A large value

if opt.query != "" {
f.state.input = []rune(opt.query)
f.state.cursorX = runewidth.StringWidth(opt.query)
f.state.x = len(opt.query)
f.filter()
}

return nil
}

Expand Down Expand Up @@ -736,6 +744,10 @@ func (f *finder) find(slice interface{}, itemFunc func(i int) string, opts []Opt

close(inited)

if opt.selectOne && len(f.state.matched) == 1 {
return []int{f.state.matched[0].Idx}, nil
}

go func() {
for {
select {
Expand Down
107 changes: 107 additions & 0 deletions fuzzyfinder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,113 @@ func TestFind_withContext(t *testing.T) {
})
}

func TestFind_WithQuery(t *testing.T) {
t.Parallel()
var (
things = []string{"one", "three2one"}
thingFunc = func(i int) string {
return things[i]
}
events = append(runes("one"), key(input{tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone}))
)

t.Run("no initial query", func(t *testing.T) {
f, term := fuzzyfinder.NewWithMockedTerminal()
term.SetEventsV2(events...)

assertWithGolden(t, func(t *testing.T) string {
idx, err := f.Find(things, thingFunc)
if err != nil {
t.Fatalf("Find must not return an error, but got '%s'", err)
}
if idx != 0 {
t.Errorf("expected index: 0, but got %d", idx)
}
res := term.GetResult()
return res
})
})

t.Run("has initial query", func(t *testing.T) {
f, term := fuzzyfinder.NewWithMockedTerminal()
term.SetEventsV2(events...)

assertWithGolden(t, func(t *testing.T) string {
idx, err := f.Find(things, thingFunc, fuzzyfinder.WithQuery("three2"))

if err != nil {
t.Fatalf("Find must not return an error, but got '%s'", err)
}
if idx != 1 {
t.Errorf("expected index: 1, but got %d", idx)
}
res := term.GetResult()
return res
})
})
}

func TestFind_WithSelectOne(t *testing.T) {
t.Parallel()

cases := map[string]struct {
things []string
moreOpts []fuzzyfinder.Option
expected int
abort bool
}{
"only one option": {
things: []string{"one"},
expected: 0,
},
"more than one": {
things: []string{"one", "two"},
abort: true,
},
"has initial query": {
things: []string{"one", "two"},
moreOpts: []fuzzyfinder.Option{
fuzzyfinder.WithQuery("two"),
},
expected: 1,
},
}

for name, c := range cases {
c := c

t.Run(name, func(t *testing.T) {
t.Parallel()
f, term := fuzzyfinder.NewWithMockedTerminal()
term.SetEventsV2(key(input{tcell.KeyEsc, rune(tcell.KeyEsc), tcell.ModNone}))

assertWithGolden(t, func(t *testing.T) string {
idx, err := f.Find(
c.things,
func(i int) string {
return c.things[i]
},
append(c.moreOpts, fuzzyfinder.WithSelectOne())...,
)
if c.abort {
if !errors.Is(err, fuzzyfinder.ErrAbort) {
t.Fatalf("Find must return ErrAbort, but got '%s'", err)
}
} else {
if err != nil {
t.Fatalf("Find must not return an error, but got '%s'", err)
}
if idx != c.expected {
t.Errorf("expected index: %d, but got %d", c.expected, idx)
}
}
res := term.GetResult()
return res
})
})
}
}

func TestFind_error(t *testing.T) {
t.Parallel()

Expand Down
16 changes: 16 additions & 0 deletions option.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ type opt struct {
header string
beginAtTop bool
context context.Context
query string
selectOne bool
}

type mode int
Expand Down Expand Up @@ -127,3 +129,17 @@ func WithContext(ctx context.Context) Option {
o.context = ctx
}
}

// WithQuery enables to set the initial query.
func WithQuery(s string) Option {
return func(o *opt) {
o.query = s
}
}

// WithQuery enables to set the initial query.
func WithSelectOne() Option {
return func(o *opt) {
o.selectOne = true
}
}
11 changes: 11 additions & 0 deletions testdata/fixtures/testfind_withquery-has_initial_query.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@







> three2one
1/2
> three2one█

11 changes: 11 additions & 0 deletions testdata/fixtures/testfind_withquery-no_initial_query.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@






three2one
> one
2/2
> one█

11 changes: 11 additions & 0 deletions testdata/fixtures/testfind_withselectone-has_initial_query.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@











11 changes: 11 additions & 0 deletions testdata/fixtures/testfind_withselectone-more_than_one.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@






two
> one
2/2
> █

11 changes: 11 additions & 0 deletions testdata/fixtures/testfind_withselectone-only_one_option.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@












0 comments on commit 09200ef

Please sign in to comment.