go-fuzzyfinder: github.com/ktr0731/go-fuzzyfinder Index | Examples | Files | Directories

package fuzzyfinder

import "github.com/ktr0731/go-fuzzyfinder"

Package fuzzyfinder provides terminal user interfaces for fuzzy-finding.

Note that, all functions are not goroutine-safe.



Package Files

fuzzyfinder.go mock.go option.go tcell.go


const (
    // ModeSmart enables a smart matching. It is the default matching mode.
    // At the beginning, matching mode is ModeCaseInsensitive, but it switches
    // over to ModeCaseSensitive if an upper case character is inputted.
    ModeSmart mode = iota
    // ModeCaseSensitive enables a case-sensitive matching.
    // ModeCaseInsensitive enables a case-insensitive matching.


var (
    // ErrAbort is returned from Find* functions if there are no selections.
    ErrAbort = errors.New("abort")

func Find Uses

func Find(slice interface{}, itemFunc func(i int) string, opts ...Option) (int, error)

Find displays a UI that provides fuzzy finding against to the passed slice. The argument slice must be a slice type. If it is not a slice, Find returns an error. itemFunc is called by the length of slice. previewFunc is called when the cursor which points the current selected item is changed. If itemFunc is nil, Find returns an error.

itemFunc receives an argument i. It is the index of the item currently selected.

Find returns ErrAbort if a call of Find is finished with no selection.


slice := []struct {
    id   string
    name string
    {"id1", "foo"},
    {"id2", "bar"},
    {"id3", "baz"},
idx, _ := fuzzyfinder.Find(slice, func(i int) string {
    return fmt.Sprintf("[%s] %s", slice[i].id, slice[i].name)
fmt.Println(slice[idx]) // The selected item.


slice := []struct {
    id   string
    name string
    {"id1", "foo"},
    {"id2", "bar"},
    {"id3", "baz"},
    func(i int) string {
        return fmt.Sprintf("[%s] %s", slice[i].id, slice[i].name)
    fuzzyfinder.WithPreviewWindow(func(i, width, _ int) string {
        if i == -1 {
            return "no results"
        s := fmt.Sprintf("%s is selected", slice[i].name)
        // As an example of using width, if the window width is less than
        // the length of s, we returns the name directly.
        if width < len([]rune(s)) {
            return slice[i].name
        return s

func FindMulti Uses

func FindMulti(slice interface{}, itemFunc func(i int) string, opts ...Option) ([]int, error)

FindMulti is nearly same as the Find. The only one difference point from Find is the user can select multiple items at once by tab key.


slice := []struct {
    id   string
    name string
    {"id1", "foo"},
    {"id2", "bar"},
    {"id3", "baz"},
idxs, _ := fuzzyfinder.FindMulti(slice, func(i int) string {
    return fmt.Sprintf("[%s] %s", slice[i].id, slice[i].name)
for _, idx := range idxs {

type Option Uses

type Option func(*opt)

Option represents available fuzzy-finding options.

func WithHotReload Uses

func WithHotReload() Option

WithHotReload reloads the passed slice automatically when some entries are appended. The caller must pass a pointer of the slice instead of the slice itself.

func WithMode Uses

func WithMode(m mode) Option

WithMode specifies a matching mode. The default mode is ModeSmart.

func WithPreviewWindow Uses

func WithPreviewWindow(f func(i, width, height int) string) Option

WithPreviewWindow enables to display a preview for the selected item. The argument f receives i, width and height. i is the same as Find's one. width and height are the size of the terminal so that you can use these to adjust a preview content. Note that width and height are calculated as a rune-based length.

If there is no selected item, previewFunc passes -1 to previewFunc.

If f is nil, the preview feature is disabled.

func WithPromptString Uses

func WithPromptString(s string) Option

WithPromptString changes the prompt string. The default value is "> ".

type TerminalMock Uses

type TerminalMock struct {
    // contains filtered or unexported fields

TerminalMock is a mocked terminal for testing. Most users should use it by calling UseMockedTerminal.


keys := func(str string) []termbox.Event {
    s := []rune(str)
    e := make([]termbox.Event, 0, len(s))
    for _, r := range s {
        e = append(e, termbox.Event{Type: termbox.EventKey, Ch: r})
    return e

// Initialize a mocked terminal.
term := fuzzyfinder.UseMockedTerminal()
// Set the window size and events.
term.SetSize(60, 10)
    termbox.Event{Type: termbox.EventKey, Key: termbox.KeyEsc})...)

// Call fuzzyfinder.Find.
slice := []string{"foo", "bar", "baz"}
fuzzyfinder.Find(slice, func(i int) string { return slice[i] })

// Write out the execution result to a temp file.
// We can test it by the golden files testing pattern.
// See https://speakerdeck.com/mitchellh/advanced-testing-with-go?slide=19
res := term.GetResult()
ioutil.WriteFile("ui.out", []byte(res), 0644)

func UseMockedTerminal Uses

func UseMockedTerminal() *TerminalMock

UseMockedTerminal switches the terminal, which is used from this package to a mocked one.

func (*TerminalMock) GetResult Uses

func (m *TerminalMock) GetResult() string

GetResult returns a flushed string that is displayed to the actual terminal. It contains all escape sequences such that ANSI escape code.

func (*TerminalMock) SetEvents Uses

func (m *TerminalMock) SetEvents(e ...termbox.Event)

SetEvents sets all events, which are fetched by pollEvent. A user of this must set the EscKey event at the end.

func (*TerminalMock) SetSize Uses

func (m *TerminalMock) SetSize(w, h int)

SetSize changes the pseudo-size of the window. Note that SetSize resets added cells.


matchingPackage matching provides matching features that find appropriate strings by using a passed input string.
scoringPackage scoring provides APIs that calculates similarity scores between two strings.

Package fuzzyfinder imports 15 packages (graph) and is imported by 5 packages. Updated 2020-06-19. Refresh now. Tools for package owners.