Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new finder primitive #677

Closed
wants to merge 11 commits into from
9 changes: 9 additions & 0 deletions demos/finder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
![Screenshot](screenshot.png)

The finder primitive is inspired by [go-fuzzyfinder](https://github.com/ktr0731/go-fuzzyfinder) but is more
configurable in terms of appearance.

In contrast to `go-fuzzyfinder`, this implementation does not use a fuzzy search algorithm. It will just
search for and highlight the first substring that matches the entered text.

If you want to perform a more elaborate search, you can also provide a custom matcher function (see example `customatcher`).
55 changes: 55 additions & 0 deletions demos/finder/customatcher/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package main

import (
"github.com/rivo/tview"
"regexp"
)

func main() {

app := tview.NewApplication()

items := []string{
"foo",
"bar",
"foo bar foo",
"baz",
"baz two",
"lorem ipsum",
}

// Don't use the default matcher (which will just return the first substring indices and uses a fixed score of 0).
// This custom implementation uses a regex expression and returns all matching substring indices.
// Moreover, it uses the number of matches for each item as score value (the default matcher assumes score 0 for
// every item). Thus, items with more matches will be sorted before items with fewer matches (e.g. when searching
// for "foo", item "foo bar foo" will be sorted before "foo".
matcher := func(item string, filter string) ([][2]int, int, bool) {

re := regexp.MustCompile(filter)

matchedIndices := re.FindAllStringSubmatchIndex(item, -1)
if matchCount := len(matchedIndices); matchCount > 0 {
matches := make([][2]int, matchCount)
for i := range matchedIndices {
matches[i] = [2]int{matchedIndices[i][0], matchedIndices[i][1]}
}
return matches, len(matchedIndices), true
}

// no match
return [][2]int{}, 0, false
}

finder := tview.NewFinder().
SetItems(len(items), func(index int) string {
return items[index]
}).
SetDoneFunc(func(index int) {
app.Stop()
}).
SetMatcherFunc(matcher)

if err := app.SetRoot(finder, true).Run(); err != nil {
panic(err)
}
}
64 changes: 64 additions & 0 deletions demos/finder/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Demo code for the finder primitive.
package main

import (
"fmt"
"github.com/rivo/tview"
)

type Item struct {
Title string
}

func (i *Item) preview() string {
return fmt.Sprintf("\033[1;33;4;44mTitle: %s\033[0m", i.Title)
}

func main() {

app := tview.NewApplication()

items := []*Item{
{Title: "foo"},
{Title: "bar"},
{Title: "foo foo"},
{Title: "baz one - this is a very long item which should overflow horizontally at some point"},
{Title: "baz two"},
{Title: "lorem ipsum"},
}

selectedView := tview.NewTextView()
selectedView.SetBorder(true)
selectedView.SetTitle("Selected item")
selectedView.SetDynamicColors(true)

finder := tview.NewFinder().
SetItems(len(items), func(index int) string {
return items[index].Title
}).
SetDoneFunc(func(index int) {
app.Stop()
fmt.Printf("Selected index: %d", index)
}).
SetChangedFunc(func(index int) {
if index >= 0 {
selectedView.SetText("")
writer := tview.ANSIWriter(selectedView)
_, _ = writer.Write([]byte(items[index].preview()))
} else {
selectedView.SetText("")
}
})

finder.
SetBorder(true).
SetTitle("Pick an item")

flex := tview.NewFlex().SetDirection(tview.FlexColumn).
AddItem(finder, 0, 1, true).
AddItem(selectedView, 0, 1, false)

if err := app.SetRoot(flex, true).Run(); err != nil {
panic(err)
}
}
Binary file added demos/finder/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading