fzf-like fuzzy-finder as a Go library

go-fuzzyfinder

PkgGoDev GitHub Actions codecov

go-fuzzyfinder is a Go library that provides fuzzy-finding with an fzf-like terminal user interface.

Installation

$ go get github.com/ktr0731/go-fuzzyfinder

Usage

go-fuzzyfinder provides two functions, Find and FindMulti. FindMulti can select multiple lines. It is similar to fzf -m.

This is an example of FindMulti.

type Track struct {
    Name      string
    AlbumName string
    Artist    string
}

var tracks = []Track{
    {"foo", "album1", "artist1"},
    {"bar", "album1", "artist1"},
    {"foo", "album2", "artist1"},
    {"baz", "album2", "artist2"},
    {"baz", "album3", "artist2"},
}

func main() {
    idx, err := fuzzyfinder.FindMulti(
        tracks,
        func(i int) string {
            return tracks[i].Name
        },
        fuzzyfinder.WithPreviewWindow(func(i, w, h int) string {
            if i == -1 {
                return ""
            }
            return fmt.Sprintf("Track: %s (%s)\nAlbum: %s",
                tracks[i].Name,
                tracks[i].Artist,
                tracks[i].AlbumName)
        }))
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("selected: %v\n", idx)
}

The execution result prints selected item's indexes.

Motivation

Fuzzy-finder command-line tools such that fzf, fzy, or skim are very powerful to find out specified lines interactively. However, there are limits to deal with fuzzy-finder's features in several cases.

First, it is hard to distinguish between two or more entities that have the same text. In the example of ktr0731/itunes-cli, it is possible to conflict tracks such that same track names, but different artists. To avoid such conflicts, we have to display the artist names with each track name. It seems like the problem has been solved, but it still has the problem. It is possible to conflict in case of same track names, same artists, but other albums, which each track belongs to. This problem is difficult to solve because pipes and filters are row-based mechanisms, there are no ways to hold references that point list entities.

The second issue occurs in the case of incorporating a fuzzy-finder as one of the main features in a command-line tool such that enhancd or itunes-cli. Usually, these tools require that it has been installed one fuzzy-finder as a precondition. In addition, to deal with the fuzzy-finder, an environment variable configuration such that export TOOL_NAME_FINDER=fzf is required. It is a bother and complicated.

go-fuzzyfinder resolves above issues. Dealing with the first issue, go-fuzzyfinder provides the preview-window feature (See an example in Usage). Also, by using go-fuzzyfinder, built tools don't require any fuzzy-finders.

See Also

Owner
ktr
application engineer & digital painter
ktr
Comments
  • Add option to use custom item view

    Add option to use custom item view

    Summary

    This change adds another option in option.go file that allows user to render item views (think descriptions/titles).

    This API is similar to the concept of post processing in fzf: https://github.com/junegunn/fzf/wiki/Examples-(completion)

    However, this library already provides means to postprocess items via itemFunc. All that's left to replicate fzf functionality is the above mentioned change that allows to process items in order to extract view from them.

  • [retry] Replace termbox to tcell

    [retry] Replace termbox to tcell

    related: #32

    Hello.

    Finally, tcell announced the fix of lost key problem officially. https://github.com/gdamore/tcell/issues/194#issuecomment-782751304

    So, we can avoid the workaround which causes the cgo problem!

    I could confirm that this program work well in local.

  • Ansi color in preview mode

    Ansi color in preview mode

    Describe the bug

    I want to display text with Ansi colors (provided by github.com/logrusorgru/aurora). It's not possible, or it's not make sense?

    To reproduce

    	projects, err := hbtn.GetProjects()
    		if err != nil {
    			log.Fatal(err)
    		}
    
    		idx, err := fuzzyfinder.FindMulti(
    			projects,
    			func(i int) string {
    				return projects[i].Title
    			},
    			fuzzyfinder.WithPreviewWindow(func(i, w, h int) string {
    				if i == -1 {
    					return ""
    				}
    
    				return fmt.Sprintf("Track: %s (%s)\nAlbum: %s",
    					Green(projects[i].Title),
    					projects[i].Tasks,
    					projects[i].ID)
    			}))
    		if err != nil {
    			log.Fatal(err)
    		}
    		fmt.Printf("selected: %v\n", idx)
    

    Expected behavior

    Screenshots

    image

    Environment

    • OS: Arch linux
    • Terminal: Tilix
    • go-fuzzyfinder version: Latest

    Additional context

  • Feature request: find from a channel of entries

    Feature request: find from a channel of entries

    Hello,

    First, thank you for this great library.

    it is possible to feed fzf's stdin with the output of a running command. The possible choices then appear progressively to the user.

    Similarly, I'd like to have a Find() function that takes a channel of entries instead of a slice.

    Is that difficult to implement ?

  • the code is blocked on the function FindMulti  in case go-fuzzyfinder/_example/track

    the code is blocked on the function FindMulti in case go-fuzzyfinder/_example/track

    Hello, when I run the example in Usage, the code is blocked on the function FindMulti.

    go env: set GOARCH=amd64 set GOBIN= set GOCACHE=C:\Users\smile\AppData\Local\go-build set GOEXE=.exe set GOFLAGS= set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOOS=windows set GOPATH=C:\Users\smile\go set GOPROXY= set GORACE= set GOROOT=c:\go set GOTMPDIR= set GOTOOLDIR=c:\go\pkg\tool\windows_amd64 set GCCGO=gccgo set CC=gcc set CXX=g++ set CGO_ENABLED=1 set GOMOD= set CGO_CFLAGS=-g -O2 set CGO_CPPFLAGS= set CGO_CXXFLAGS=-g -O2 set CGO_FFLAGS=-g -O2 set CGO_LDFLAGS=-g -O2 set PKG_CONFIG=pkg-config set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\smile\AppData\Local\Temp\go-build410240270=/tmp/go-build -gno-record-gcc-switches

  • Replace to tcell from termbox

    Replace to tcell from termbox

    Related Issue: #15

    Thanks great library! This PR is intended to replace completely from termbox to tcell.

    I think this migration has two merits.

    1. It is stated that termbox will not be maintained anymore (ref). So, migrate to maintained tcell, make this product more stable.

    2. tcell has a lot of useful features. For example, #29 can solve easily by using code used in tview etc (ref).


    The problem reported in #17, can solve by using workaround(ref).

    I could confirm the code(reproduce the problem) work well in local.

  • hotreload has data race

    hotreload has data race

    There is data race detected by go run -race

    when fuzzyfinder.WithHotReload() is enabled. e.g. in the example/hotreload/main.go

    To reproduce

    cd example/hotreload
    cat main.go | go run -race main.go
    

    Expected behavior

    It can finish without data race.

    Screenshots

    image

    Environment

    • OS: MacOS
    • Terminal: iTerm2
    • go-fuzzyfinder version: commit 81ff9cb dated 2022-01-10
  • Bump github.com/golangci/golangci-lint from 1.37.1 to 1.38.0

    Bump github.com/golangci/golangci-lint from 1.37.1 to 1.38.0

    Bumps github.com/golangci/golangci-lint from 1.37.1 to 1.38.0.

    Release notes

    Sourced from github.com/golangci/golangci-lint's releases.

    v1.38.0

    Changelog

    5698d46e Add ForceTypeAssert linter (#1789) 012559c5 Add linter wastedassign (#1651) 66fc7797 Add nilerr linter. (#1788) f00da2c0 Add stringintconv and ifaceassert to govet (#1360) a1e3749a Bump github.com/Djarvur/go-err113 to HEAD (#1760) 495a74f6 Bump github.com/timakin/bodyclose to HEAD (#1758) b7aac3b1 Bump wsl to v3.2.0 (#1750) 251b205f Deprecate Interfacer linter (#1755) 42ff682f Deprecate maligned, add govet fieldalignment as replacement (#1765) 92d38e52 Exclude PR about doc dependencies from release changelog. (#1752) 89315e00 Fix go-header usage (#1785) 05836e48 Integrate ImportAs linter (#1783) cdaf03d1 Remove outdated CVEs from .nancy-ignore (#1791) 856ffd16 Support RelatedInformation for analysis Diagnostic (#1773) 507703b4 Update Docs and Assets Github Actions (#1460) 5dcc3eaf Update dependencies that dependabot cannot (#1790) 2e7c389d Update staticcheck to v0.1.2 (2020.2.2) (#1756) b77118fd Use errcheck from main repo instead of golangci-lint fork (#1319) 1a906bc1 Use go v1.14 in go.mod file (#1803) 34e46c74 Using a version instead of commit id for goconst (#1786) 747e3aea add doc for the profiling arguments (#1761) dac2059e build(deps): bump github.com/kulti/thelper from 0.3.1 to 0.4.0 (#1764) 326d715b build(deps): bump github.com/sirupsen/logrus from 1.7.0 to 1.8.0 (#1763) 067cfac3 build(deps): bump golangci/golangci-lint-action from v2.4.0 to v2.5.1 (#1798) d6db13d7 build(deps): bump sonatype-nexus-community/nancy-github-action (#1762) 2880d89b bump durationcheck from 0.0.4 to 0.0.6 (#1757) 5ca29739 fix: use same default linter as go vet. (#1793) eefb9743 ineffassign: use upstrea instead of golangci fork (#1780) b407bb8f revive: add rule name in message. (#1772)

    Commits
    • 507703b Update Docs and Assets Github Actions (#1460)
    • d4ee818 build(deps): bump gatsby-source-filesystem in /docs (#1806)
    • c77b82f build(deps): bump gatsby-plugin-manifest from 2.12.0 to 2.12.1 in /docs (#1807)
    • 7516c37 build(deps): bump gatsby-plugin-offline from 3.10.0 to 3.10.2 in /docs (#1801)
    • 01a6238 build(deps): bump gatsby-transformer-remark in /docs (#1805)
    • 38ad382 build(deps): bump gatsby from 2.32.3 to 2.32.8 in /docs (#1804)
    • 5925964 build(deps): bump prism-react-renderer from 1.1.1 to 1.2.0 in /docs (#1802)
    • 2c5a421 build(deps): bump gatsby-plugin-mdx from 1.10.0 to 1.10.1 in /docs (#1800)
    • 1a906bc Use go v1.14 in go.mod file (#1803)
    • d22c64e build(deps): bump puppeteer from 7.0.1 to 8.0.0 in /docs (#1796)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • Bump github.com/golangci/golangci-lint from 1.37.1 to 1.38.0

    Bump github.com/golangci/golangci-lint from 1.37.1 to 1.38.0

    Bumps github.com/golangci/golangci-lint from 1.37.1 to 1.38.0.

    Release notes

    Sourced from github.com/golangci/golangci-lint's releases.

    v1.38.0

    Changelog

    5698d46e Add ForceTypeAssert linter (#1789) 012559c5 Add linter wastedassign (#1651) 66fc7797 Add nilerr linter. (#1788) f00da2c0 Add stringintconv and ifaceassert to govet (#1360) a1e3749a Bump github.com/Djarvur/go-err113 to HEAD (#1760) 495a74f6 Bump github.com/timakin/bodyclose to HEAD (#1758) b7aac3b1 Bump wsl to v3.2.0 (#1750) 251b205f Deprecate Interfacer linter (#1755) 42ff682f Deprecate maligned, add govet fieldalignment as replacement (#1765) 92d38e52 Exclude PR about doc dependencies from release changelog. (#1752) 89315e00 Fix go-header usage (#1785) 05836e48 Integrate ImportAs linter (#1783) cdaf03d1 Remove outdated CVEs from .nancy-ignore (#1791) 856ffd16 Support RelatedInformation for analysis Diagnostic (#1773) 507703b4 Update Docs and Assets Github Actions (#1460) 5dcc3eaf Update dependencies that dependabot cannot (#1790) 2e7c389d Update staticcheck to v0.1.2 (2020.2.2) (#1756) b77118fd Use errcheck from main repo instead of golangci-lint fork (#1319) 1a906bc1 Use go v1.14 in go.mod file (#1803) 34e46c74 Using a version instead of commit id for goconst (#1786) 747e3aea add doc for the profiling arguments (#1761) dac2059e build(deps): bump github.com/kulti/thelper from 0.3.1 to 0.4.0 (#1764) 326d715b build(deps): bump github.com/sirupsen/logrus from 1.7.0 to 1.8.0 (#1763) 067cfac3 build(deps): bump golangci/golangci-lint-action from v2.4.0 to v2.5.1 (#1798) d6db13d7 build(deps): bump sonatype-nexus-community/nancy-github-action (#1762) 2880d89b bump durationcheck from 0.0.4 to 0.0.6 (#1757) 5ca29739 fix: use same default linter as go vet. (#1793) eefb9743 ineffassign: use upstrea instead of golangci fork (#1780) b407bb8f revive: add rule name in message. (#1772)

    Commits
    • 507703b Update Docs and Assets Github Actions (#1460)
    • d4ee818 build(deps): bump gatsby-source-filesystem in /docs (#1806)
    • c77b82f build(deps): bump gatsby-plugin-manifest from 2.12.0 to 2.12.1 in /docs (#1807)
    • 7516c37 build(deps): bump gatsby-plugin-offline from 3.10.0 to 3.10.2 in /docs (#1801)
    • 01a6238 build(deps): bump gatsby-transformer-remark in /docs (#1805)
    • 38ad382 build(deps): bump gatsby from 2.32.3 to 2.32.8 in /docs (#1804)
    • 5925964 build(deps): bump prism-react-renderer from 1.1.1 to 1.2.0 in /docs (#1802)
    • 2c5a421 build(deps): bump gatsby-plugin-mdx from 1.10.0 to 1.10.1 in /docs (#1800)
    • 1a906bc Use go v1.14 in go.mod file (#1803)
    • d22c64e build(deps): bump puppeteer from 7.0.1 to 8.0.0 in /docs (#1796)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.

    If all status checks pass Dependabot will automatically merge this pull request.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot badge me will comment on this PR with code to add a "Dependabot enabled" badge to your readme

    Additionally, you can set the following in the .dependabot/config.yml file in this repo:

    • Update frequency
    • Automerge options (never/patch/minor, and dev/runtime dependencies)
    • Out-of-range updates (receive only lockfile updates, if desired)
    • Security updates (receive only security updates, if desired)
  • Bump actions/setup-go from 2.1.5 to 2.2.0

    Bump actions/setup-go from 2.1.5 to 2.2.0

    Bumps actions/setup-go from 2.1.5 to 2.2.0.

    Release notes

    Sourced from actions/setup-go's releases.

    Add check-latest input

    In scope of this release we add the check-latest input. If check-latest is set to true, the action first checks if the cached version is the latest one. If the locally cached version is not the most up-to-date, a Go version will then be downloaded from go-versions repository. By default check-latest is set to false. Example of usage:

    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-go@v2
        with:
          go-version: '1.16'
          check-latest: true
      - run: go version
    

    Moreover, we updated @actions/core from 1.2.6 to 1.6.0

    Commits
    • bfdd357 Implement "check-latest" flag to check if pre-cached version is latest one (#...
    • 44e2214 Replace 'ubuntu-16.04' -> 'ubuntu-latest' (#180)
    • See full diff in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • revert the chages which migrates terminal library from nsf/termbox-go to gdamore/tcell

    revert the chages which migrates terminal library from nsf/termbox-go to gdamore/tcell

    I'm sorry for @tjmtmmnk, but I decided to revert a Pull Request which migrates the terminal library from nsf/termbox-go to gdamore/tcell. gdamore/tcell has a known bug that causes https://github.com/ktr0731/go-fuzzyfinder/issues/17 and https://github.com/ktr0731/go-fuzzyfinder/issues/46. A workaround is proposed in https://github.com/gdamore/tcell/issues/194#issuecomment-478209769, but it requires a Cgo dependency and it doesn't reproduce in the latest macOS version (I don't know the detailed cause...).

    Also, I think that go-fuzzyfinder shouldn't depend on Cgo dependencies because it is designed to use from various platforms such as macOS, Linux, and Windows, etc. Multi-compile is one of the greatest features of Go, so we want to continue to support multi-platform compile.

    So, I revert the changes and I'm going to wait for terminal library migration until gdamore/tcell will be fixed the bug officially.

  • Maximum Height Option

    Maximum Height Option

    I'm really interesting to use your module for tagging purpose.

    I usually do something like:

    # display img
    # display some details
    # run fzf with maximum height of 30% of the screen
    fzf --multi --height 30% --border --layout reverse -e --bind esc:clear-query < $TAG > "$TAG_SELECT"
    

    I can't use the window function to display the information I need, because I need to show the picture of what I want to tag, and it doesn't work in the window preview.

    Can you add an option to limit the height of the selection? Instead of filling the terminal, we fill a part of it.

Twitter ID Finder For Golang

Twitter ID Finder n文字の全数IDを探せます Usage $ make go build -o main main.go $ ./main Twitter ID Finder Creator: @_m_vt Digits: 2 Target IDs: 100 Really? [

Dec 12, 2021
Dedugo - Simple duplicate image finder for golang

Dedugo Image Duplicate Finder De-duplicate in Go (get it?) Summary This simple p

Dec 27, 2022
GoFind - Concurrent file finder in Golang

GoFind How to Run? Clona la repository. Setta il tuo GOPATH dalla root della rep

Feb 17, 2022
Software for archiving my digital stuff like tweets

rsms's memex Software for managing my digital information, like tweets. Usage First check out the source and build. You'll need Make and Go installed.

Nov 17, 2022
A simple Go utility to display track information from, and send commands to, spotifyd from Tiling Window Managers like Sway and i3
A simple Go utility to display track information from, and send commands to, spotifyd from Tiling Window Managers like Sway and i3

Untitled Spotifyd Controller A simple Go utility to display track information from, and send commands to, spotifyd from Tiling Window Managers like Sw

Mar 8, 2022
DND-magic-item-Generator - D&D magic item generator like in Diablo

DND-magic-item-Generator D&D magic item generator like in Diablo Legendary items

Mar 28, 2022
Nvote - Decentralized, vote-driven community similar to services like Reddit and HackerNews. Built on nostr

NVote Nvote is a decentralized, vote-driven community similar to services like R

Jan 4, 2023
Service that wrap up different movies-related APIs like IMDB and match it to streaming services
Service that wrap up different movies-related APIs like IMDB and match it to streaming services

Service that wrap up different movies-related APIs like IMDB and match it to streaming services. That way you can check in which platforms you can find your favorite movies.

Feb 10, 2022
Prig is for Processing Records In Go. Like AWK, but snobbish.

Prig: the snobbish AWK Prig is for Processing Records In Go. It's like AWK, but snobbish (Go! static typing!). It's also faster to execute, and if you

Sep 20, 2022
GoBatch is a batch processing framework in Go like Spring Batch in Java
GoBatch is a batch processing framework in Go like Spring Batch in Java

GoBatch English|中文 GoBatch is a batch processing framework in Go like Spring Batch in Java. If you are familiar with Spring Batch, you will find GoBat

Dec 25, 2022
Go Client Library for Amazon Product Advertising API

go-amazon-product-advertising-api Go Client Library for Amazon Product Advertising API How to Use go get -u github.com/ngs/go-amazon-product-advertisi

Sep 27, 2022
A Go client library for the Twitter 1.1 API

Anaconda Anaconda is a simple, transparent Go package for accessing version 1.1 of the Twitter API. Successful API queries return native Go structs th

Jan 1, 2023
Go library for http://www.brewerydb.com/ API

brewerydb brewerydb is a Go library for accessing the BreweryDB API usage import "github.com/naegelejd/brewerydb" Construct a new Client using your Br

Sep 27, 2022
Go(lang) client library for Cachet (open source status page system).

cachet Go(lang) client library for Cachet (open source status page system). Features Full API support Components Incidents Metrics Subscribers Various

Sep 27, 2022
Go library for interacting with CircleCI

go-circleci Go library for interacting with CircleCI's API. Supports all current API endpoints allowing you do do things like: Query for recent builds

Nov 26, 2022
Clarifai library for Go

Clarifai Golang Library Library for our v1 API. Disclaimer This API client only supports Clarifai v1 API. Stay tuned for the v2 support. Usage go get

Sep 27, 2022
Go library for accessing the Codeship API v2

Codeship API v2 Client for Go Codeship API v2 client for Go. Documentation https://godoc.org/github.com/codeship/codeship-go Usage go get -u github.co

Sep 27, 2022
Go client library for interacting with Coinpaprika's API

Coinpaprika API Go Client Usage This library provides convenient way to use coinpaprika.com API in Go. Coinpaprika delivers full market data to the wo

Dec 8, 2022