add built-in fzf (playlist)

This commit is contained in:
raziman 2020-08-18 00:26:28 +08:00
parent 91b8eeecda
commit c6e0af6f4a
7 changed files with 136 additions and 3 deletions

1
config
View File

@ -14,3 +14,4 @@ general:
popup_timeout: 5s
volume: 100
emoji: true
fzf: false

1
go.mod
View File

@ -15,6 +15,7 @@ require (
github.com/pelletier/go-toml v1.8.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/tview v0.0.0-20200712113419-c65badfc3d92
github.com/sahilm/fuzzy v0.1.0
github.com/spf13/afero v1.3.4 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect

2
go.sum
View File

@ -207,6 +207,8 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=

View File

@ -25,6 +25,7 @@ type Gomu struct {
popupBg tcell.Color
textColor tcell.Color
accentColor tcell.Color
bgColor tcell.Color
panels []Panel
isSuspend bool
mu sync.Mutex
@ -36,6 +37,7 @@ func newGomu() *Gomu {
gomu := &Gomu{
popupBg: tcell.GetColor(viper.GetString("color.popup")),
textColor: tcell.GetColor(viper.GetString("color.foreground")),
bgColor: tcell.GetColor(viper.GetString("color.background")),
accentColor: tcell.GetColor(viper.GetString("color.accent")),
}

View File

@ -217,11 +217,32 @@ func newPlaylist(args Args) *Playlist {
case '/':
err := playlist.fuzzyFind()
if err != nil {
logError(err)
if viper.GetBool("general.fzf") {
err := playlist.fuzzyFind()
if err != nil {
logError(err)
}
return e
}
files := make([]string, len(playlist.getAudioFiles()))
for i, file := range playlist.getAudioFiles() {
files[i] = file.name
}
searchPopup(files, func(text string) {
audio, err := playlist.findAudioFile(sha1Hex(text))
if err != nil {
logError(err)
}
playlist.setHighlight(audio.node)
})
}
return e

View File

@ -5,10 +5,12 @@ package main
import (
"fmt"
"regexp"
"strings"
"time"
"github.com/gdamore/tcell"
"github.com/rivo/tview"
"github.com/sahilm/fuzzy"
"github.com/spf13/viper"
)
@ -361,3 +363,98 @@ func exitConfirmation(args Args) {
}
})
}
func searchPopup(stringsToMatch []string, handler func(selected string)) {
list := tview.NewList().ShowSecondaryText(false)
list.SetSelectedBackgroundColor(gomu.accentColor)
list.SetHighlightFullLine(true)
for _, v := range stringsToMatch {
list.AddItem(v, v, 0, nil)
}
input := tview.NewInputField()
input.SetFieldBackgroundColor(gomu.bgColor).
SetLabel("[red]>[-] ")
input.SetChangedFunc(func(text string) {
list.Clear()
// list all item if input is empty
if len(text) == 0 {
for _, v := range stringsToMatch {
list.AddItem(v, v, 0, nil)
}
return
}
pattern := input.GetText()
matches := fuzzy.Find(pattern, stringsToMatch)
const highlight = "[red]%s[-]"
for _, match := range matches {
var text strings.Builder
for i := 0; i < len(match.Str); i++ {
currChar := string(match.Str[i])
if contains(i, match.MatchedIndexes) {
text.WriteString(fmt.Sprintf(highlight, currChar))
} else {
text.WriteString(currChar)
}
}
list.AddItem(text.String(), match.Str, 0, nil)
}
})
input.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
switch e.Key() {
case tcell.KeyCtrlN:
currIndx := list.GetCurrentItem()
// if last index
if currIndx == list.GetItemCount()-1 {
currIndx = 0
} else {
currIndx++
}
list.SetCurrentItem(currIndx)
case tcell.KeyCtrlP:
currIndx := list.GetCurrentItem()
if currIndx == 0 {
currIndx = list.GetItemCount() - 1
} else {
currIndx--
}
list.SetCurrentItem(currIndx)
case tcell.KeyEnter:
if list.GetItemCount() > 0 {
_, selected := list.GetItemText(list.GetCurrentItem())
handler(selected)
gomu.pages.RemovePage("search-input-popup")
gomu.popups.pop()
}
case tcell.KeyEscape:
gomu.pages.RemovePage("search-input-popup")
gomu.popups.pop()
}
return e
})
popup := tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(input, 2, 1, true).
AddItem(list, 0, 1, false)
popup.SetBorder(true).
SetBackgroundColor(gomu.popupBg).
SetBorderPadding(1, 1, 2, 2).
SetTitle(" Find In Playlist ")
gomu.pages.AddPage("search-input-popup", center(popup, 70, 40), true, true)
gomu.popups.push(popup)
}

View File

@ -206,3 +206,12 @@ func validateHexColor(color string) bool {
reg := regexp.MustCompile(`^#([A-Fa-f0-9]{6})$`)
return reg.MatchString(color)
}
func contains(needle int, haystack []int) bool {
for _, i := range haystack {
if needle == i {
return true
}
}
return false
}