diff options
| -rw-r--r-- | .pik/web/deploy.sh (renamed from .pik/web/web.sh) | 0 | ||||
| -rw-r--r-- | README.md | 12 | ||||
| -rw-r--r-- | completion/completion.sh | 13 | ||||
| -rw-r--r-- | go.mod | 36 | ||||
| -rw-r--r-- | go.sum | 28 | ||||
| -rw-r--r-- | main.go | 7 | ||||
| -rw-r--r-- | menu/input.go | 47 | ||||
| -rw-r--r-- | menu/model.go | 33 | ||||
| -rw-r--r-- | menu/search.go | 11 | ||||
| -rw-r--r-- | menu/target.go | 9 | ||||
| -rw-r--r-- | runner/shell/shell.go | 4 |
11 files changed, 175 insertions, 25 deletions
diff --git a/.pik/web/web.sh b/.pik/web/deploy.sh index 543142c..543142c 100644 --- a/.pik/web/web.sh +++ b/.pik/web/deploy.sh @@ -21,7 +21,7 @@ if you were already using `pik`, `pik install` would suffice! thankfully you can `pik` yourself: * `bash .pik/install.sh` -wow! you just learned about `pik`s most obvious usage! +wow! you just learned about `pik`s simplest usage! ## getting started @@ -58,8 +58,6 @@ pik reads the first comment line from your targets and informs you in the tui! * `--at` to run the target in an arbitrary location * target tags in filenames which trigger flag behaviours * aliases to sources through the `.alias` file -* tui for viewing and running targets - * descriptions for targets based on first comment in a target * y/n confirmation with yes as default * will be used if we have an uncertain target guess * `--yes` to automatically confirm y/n prompts @@ -70,6 +68,13 @@ pik reads the first comment line from your targets and informs you in the tui! * env files are reread for every trigger, meaning you can have a pre-trigger fetch credentials and save it in .env * create any kind of target: high-level support for shell and python, and arbitrary shells with the shebang. +### tui +* tui for viewing and running targets +* descriptions for targets based on first comment in a target +* external targets will also show up in the tui +* search with `/` and `?`, scroll results with `n` and `N` + + ### supported external runners * `just` @@ -89,7 +94,6 @@ attach to these features. * adding descriptions to external targets * expand tui: * support for categories and ordering of targets through the `.order` file - * search * more hotkeys (filter jumping, toggle all, etc.) * git pre-commit and pre-push triggers * linking sources together by `.include` and `.wants` files diff --git a/completion/completion.sh b/completion/completion.sh new file mode 100644 index 0000000..9cbd52c --- /dev/null +++ b/completion/completion.sh @@ -0,0 +1,13 @@ +#/usr/bin/env bash +_pik_completions() +{ + QUERY="" + for word in COMP_WORDS ; do + if [[ query != "-*" ]] ; then + QUERY="$QUERY $WORD" + fi + done + COMPREPLY=($(compgen -W "$(pik --list)" "${QUERY}")) +} + +complete -F _pik_completions pik
\ No newline at end of file @@ -3,31 +3,39 @@ module github.com/ewy1/pik go 1.26.1 require ( - github.com/adrg/xdg v0.5.3 // indirect + github.com/adrg/xdg v0.5.3 + github.com/charmbracelet/bubbletea v1.3.10 + github.com/charmbracelet/lipgloss v1.1.0 + github.com/charmbracelet/x/term v0.2.2 + github.com/joho/godotenv v1.5.1 + github.com/pelletier/go-toml/v2 v2.3.0 + github.com/spf13/pflag v1.0.10 + github.com/stretchr/testify v1.11.1 +) + +require ( + github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/charmbracelet/bubbletea v1.3.10 // indirect - github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect - github.com/charmbracelet/lipgloss v1.1.0 // indirect - github.com/charmbracelet/x/ansi v0.10.1 // indirect - github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect - github.com/charmbracelet/x/term v0.2.1 // indirect + github.com/charmbracelet/bubbles v1.0.0 // indirect + github.com/charmbracelet/colorprofile v0.4.1 // indirect + github.com/charmbracelet/x/ansi v0.11.6 // indirect + github.com/charmbracelet/x/cellbuf v0.0.15 // indirect + github.com/clipperhouse/displaywidth v0.9.0 // indirect + github.com/clipperhouse/stringish v0.1.1 // indirect + github.com/clipperhouse/uax29/v2 v2.5.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect - github.com/joho/godotenv v1.5.1 // indirect - github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/lucasb-eyer/go-colorful v1.3.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.1 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/mattn/go-runewidth v0.0.19 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/termenv v0.16.0 // indirect - github.com/pelletier/go-toml/v2 v2.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/spf13/pflag v1.0.10 // indirect - github.com/stretchr/testify v1.11.1 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/sys v0.36.0 // indirect + golang.org/x/sys v0.38.0 // indirect golang.org/x/text v0.3.8 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) @@ -1,19 +1,37 @@ github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc= +github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E= github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= +github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk= +github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ= github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= +github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8= +github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI= +github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= +github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= +github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA= +github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA= +github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= +github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= +github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U= +github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= @@ -22,12 +40,16 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= +github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= +github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= @@ -47,12 +69,18 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= +golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -139,8 +139,9 @@ func main() { if *flags.List { for _, s := range st.Sources { + _, _ = spool.Print("%v", s.Label()+paths.Ifs) for _, t := range s.Targets { - _, _ = spool.Print("%v\n", t.ShortestId()+paths.Ifs) + _, _ = spool.Print("%v", t.ShortestId()+paths.Ifs) } } os.Exit(0) @@ -169,7 +170,7 @@ func main() { result := search.Search(st, args...) // TODO: Move auto-all logic into Search? - if !*flags.All && result.Target == nil && len(result.Args) > 0 { + if !*flags.All && result.Target == nil && len(result.Args) > 0 && SourcesWithoutResults == nil && !ForceConfirm { ForceConfirm = true if err != nil { _, _ = spool.Warn("%v\n", err) @@ -181,7 +182,7 @@ func main() { } if result.Target == nil { - _, _ = spool.Warn("target not found.") + _, _ = spool.Warn("target not found.\n") os.Exit(1) return } diff --git a/menu/input.go b/menu/input.go index cd07543..e2e35b3 100644 --- a/menu/input.go +++ b/menu/input.go @@ -3,8 +3,32 @@ package menu import tea "github.com/charmbracelet/bubbletea" func (m *Model) HandleInput(msg tea.KeyMsg) (tea.Cmd, error) { + + if m.Search.Focused() { + var cmd tea.Cmd + switch msg.String() { + case "ctrl+c": + m.Search.SetValue("") + m.Search.Blur() + case "ctrl+d": + m.Search.Blur() + case "enter": + m.Search.Blur() + default: + result, c := m.Search.Update(msg) + cmd = c + m.Search = result + } + return cmd, nil + } + var cmd tea.Cmd switch msg.String() { + case "/": + m.Search.SetValue("") + fallthrough + case "?": + return m.Search.Focus(), nil case "i", "I": if m.Alt { m.Alt = false @@ -23,6 +47,10 @@ func (m *Model) HandleInput(msg tea.KeyMsg) (tea.Cmd, error) { m.Index-- case "down", "j": m.Index++ + case "n": + m.LeapFilter(1) + case "N": + m.LeapFilter(-1) case "q", "esc", "ctrl+c": m.Cancel = true return tea.Quit, nil @@ -31,11 +59,28 @@ func (m *Model) HandleInput(msg tea.KeyMsg) (tea.Cmd, error) { return tea.Quit, nil } - m.Validate() + _ = m.Validate() return cmd, nil } +func (m *Model) LeapFilter(direction int) { + startIndex := m.Index + for { + m.Index += direction + clamped := m.Validate() + if clamped { + m.Index = startIndex + return + } + + source, target := m.Result() + if m.Highlights(source, target) { + return + } + } +} + func (m *Model) Leap(direction int) { for { source, target := m.Result() diff --git a/menu/model.go b/menu/model.go index aa7b00e..4480c96 100644 --- a/menu/model.go +++ b/menu/model.go @@ -1,6 +1,7 @@ package menu import ( + "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/x/term" "github.com/ewy1/pik/model" @@ -9,6 +10,7 @@ import ( "github.com/ewy1/pik/viewport" "github.com/spf13/pflag" "os" + "strings" ) type Model struct { @@ -21,9 +23,31 @@ type Model struct { Height int Alt bool AutoAlt bool + Search textinput.Model Motd string } +func (m *Model) Highlights(src *model.HydratedSource, t model.HydratedTarget) bool { + val := m.Search.Value() + if val == "" { + return false + } + + if strings.Contains(t.Target().Label(), val) { + return true + } + + if strings.Contains(t.Description(src), val) { + return true + } + + if strings.Contains(strings.Join(append(t.Target().Sub(), t.Target().Label()), " "), val) { + return true + } + + return false +} + func (m *Model) Init() tea.Cmd { _, h, err := term.GetSize(0) if err != nil { @@ -79,6 +103,9 @@ func (m *Model) View() string { } result := m.State() result = viewport.Process(result, m.Height) + if m.Search.Focused() { + result = m.AddSearch(result) + } return result } @@ -89,13 +116,16 @@ func (m *Model) Result() (*model.HydratedSource, model.HydratedTarget) { return m.SourceIndices[m.Index], m.Indices[m.Index] } -func (m *Model) Validate() { +func (m *Model) Validate() (clamped bool) { if m.Index < 0 { m.Index = 0 + return true } if m.Index > len(m.Indices)-1 { m.Index = len(m.Indices) - 1 + return true } + return false } var ForcedInlineTerminals = map[string]string{ @@ -117,6 +147,7 @@ func NewModel(st *model.State, hydrators []model.Modder) *Model { SourceIndices: make(map[int]*model.HydratedSource), AutoAlt: !pflag.Lookup("inline").Changed && !isBanned, Motd: motd.One(), + Search: textinput.New(), } idx := 0 for _, src := range st.Sources { diff --git a/menu/search.go b/menu/search.go new file mode 100644 index 0000000..79cc03b --- /dev/null +++ b/menu/search.go @@ -0,0 +1,11 @@ +package menu + +import "strings" + +func (m *Model) AddSearch(croppedInput string) string { + lines := strings.Split(croppedInput, "\n") + lastIndex := len(lines) - 1 + view := m.Search.View() + lines[lastIndex] = view + return strings.Join(lines, "\n") +} diff --git a/menu/target.go b/menu/target.go index f0b35fd..ee31889 100644 --- a/menu/target.go +++ b/menu/target.go @@ -14,6 +14,10 @@ var ( st := lipgloss.NewStyle().Border(lipgloss.OuterHalfBlockBorder(), false, false, false, true) return st }) + TargetHighlightedColor = lipgloss.Color("1") + TargetHighlightedStyle = style.New(func() lipgloss.Style { + return TargetStyle.Get().Foreground(TargetHighlightedColor) + }) SelectedTargetStyle = style.New(func() lipgloss.Style { return TargetStyle.Get().BorderBackground(SelectedTargetBackgroundColor).Background(SelectedTargetBackgroundColor) }) @@ -59,6 +63,11 @@ func (m *Model) Target(src *model.HydratedSource, t model.HydratedTarget, header } selectionStyle := TargetStyle selectionDescriptionStyle := TargetDescriptionStyle + + if m.Highlights(src, t) { + selectionStyle = TargetHighlightedStyle + } + if selected { selectionStyle = SelectedTargetStyle selectionDescriptionStyle = SelectedTargetDescriptionStyle diff --git a/runner/shell/shell.go b/runner/shell/shell.go index 7972bf0..53b4df3 100644 --- a/runner/shell/shell.go +++ b/runner/shell/shell.go @@ -64,14 +64,14 @@ func (s *shell) Wants(f fs.FS, file string, entry fs.DirEntry) (bool, error) { } func (s *shell) Find(shell string) (string, error) { + s.Lock() + defer s.Unlock() if s.Locations[shell] != "" { return s.Locations[shell], nil } if p, err := exec.LookPath(shell); err == nil { - s.Lock() s.Locations[shell] = p - s.Unlock() return shell, nil } else { return "", err |
