fconvert 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fconvert-picker +0 -0
- package/package.json +1 -1
- package/tools/format-picker/go.mod +21 -10
- package/tools/format-picker/go.sum +38 -19
- package/tools/format-picker/main.go +189 -36
package/dist/fconvert-picker
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,24 +1,35 @@
|
|
|
1
1
|
module github.com/timmy6942025/convert/tools/format-picker
|
|
2
2
|
|
|
3
|
-
go 1.
|
|
3
|
+
go 1.24.2
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
toolchain go1.24.4
|
|
6
6
|
|
|
7
7
|
require (
|
|
8
|
+
github.com/charmbracelet/bubbles v1.0.0
|
|
9
|
+
github.com/charmbracelet/bubbletea v1.3.10
|
|
10
|
+
github.com/charmbracelet/lipgloss v1.1.0
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
require (
|
|
14
|
+
github.com/atotto/clipboard v0.1.4 // indirect
|
|
8
15
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
|
9
|
-
github.com/charmbracelet/
|
|
10
|
-
github.com/charmbracelet/x/ansi v0.
|
|
11
|
-
github.com/charmbracelet/x/
|
|
16
|
+
github.com/charmbracelet/colorprofile v0.4.1 // indirect
|
|
17
|
+
github.com/charmbracelet/x/ansi v0.11.6 // indirect
|
|
18
|
+
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
|
|
19
|
+
github.com/charmbracelet/x/term v0.2.2 // indirect
|
|
20
|
+
github.com/clipperhouse/displaywidth v0.9.0 // indirect
|
|
21
|
+
github.com/clipperhouse/stringish v0.1.1 // indirect
|
|
22
|
+
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
|
|
12
23
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
|
13
|
-
github.com/lucasb-eyer/go-colorful v1.
|
|
24
|
+
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
|
|
14
25
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
|
15
26
|
github.com/mattn/go-localereader v0.0.1 // indirect
|
|
16
|
-
github.com/mattn/go-runewidth v0.0.
|
|
27
|
+
github.com/mattn/go-runewidth v0.0.19 // indirect
|
|
17
28
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
|
18
29
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
|
19
|
-
github.com/muesli/termenv v0.
|
|
30
|
+
github.com/muesli/termenv v0.16.0 // indirect
|
|
20
31
|
github.com/rivo/uniseg v0.4.7 // indirect
|
|
21
|
-
|
|
22
|
-
golang.org/x/sys v0.
|
|
32
|
+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
|
33
|
+
golang.org/x/sys v0.38.0 // indirect
|
|
23
34
|
golang.org/x/text v0.3.8 // indirect
|
|
24
35
|
)
|
|
@@ -1,37 +1,56 @@
|
|
|
1
|
+
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
|
2
|
+
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
|
1
3
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
|
2
4
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
|
3
|
-
github.com/
|
|
4
|
-
github.com/
|
|
5
|
-
github.com/charmbracelet/
|
|
6
|
-
github.com/charmbracelet/
|
|
7
|
-
github.com/charmbracelet/
|
|
8
|
-
github.com/charmbracelet/
|
|
9
|
-
github.com/charmbracelet/
|
|
10
|
-
github.com/charmbracelet/
|
|
5
|
+
github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
|
|
6
|
+
github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E=
|
|
7
|
+
github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc=
|
|
8
|
+
github.com/charmbracelet/bubbles v1.0.0/go.mod h1:9d/Zd5GdnauMI5ivUIVisuEm3ave1XwXtD1ckyV6r3E=
|
|
9
|
+
github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw=
|
|
10
|
+
github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4=
|
|
11
|
+
github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
|
|
12
|
+
github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
|
|
13
|
+
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
|
14
|
+
github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30=
|
|
15
|
+
github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
|
|
16
|
+
github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
|
|
17
|
+
github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI=
|
|
18
|
+
github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q=
|
|
19
|
+
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ=
|
|
20
|
+
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
|
|
21
|
+
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
|
22
|
+
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
|
23
|
+
github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
|
|
24
|
+
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
|
|
25
|
+
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
|
|
26
|
+
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
|
27
|
+
github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
|
|
28
|
+
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
|
|
11
29
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
|
12
30
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
|
13
|
-
github.com/lucasb-eyer/go-colorful v1.
|
|
14
|
-
github.com/lucasb-eyer/go-colorful v1.
|
|
31
|
+
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
|
|
32
|
+
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
|
15
33
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
|
16
34
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
|
17
35
|
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
|
18
36
|
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
|
19
|
-
github.com/mattn/go-runewidth v0.0.
|
|
20
|
-
github.com/mattn/go-runewidth v0.0.
|
|
37
|
+
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
|
|
38
|
+
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
|
21
39
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
|
22
40
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
|
23
41
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
|
24
42
|
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
|
25
|
-
github.com/muesli/termenv v0.
|
|
26
|
-
github.com/muesli/termenv v0.
|
|
27
|
-
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
|
43
|
+
github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc=
|
|
44
|
+
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
|
28
45
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
|
29
46
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
|
30
|
-
|
|
31
|
-
|
|
47
|
+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
|
48
|
+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
|
49
|
+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
|
50
|
+
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
|
32
51
|
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
33
52
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
34
|
-
golang.org/x/sys v0.
|
|
35
|
-
golang.org/x/sys v0.
|
|
53
|
+
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
|
54
|
+
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
|
36
55
|
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
|
37
56
|
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
|
@@ -8,7 +8,11 @@ import (
|
|
|
8
8
|
"sort"
|
|
9
9
|
"strings"
|
|
10
10
|
|
|
11
|
+
"github.com/charmbracelet/bubbles/help"
|
|
12
|
+
"github.com/charmbracelet/bubbles/key"
|
|
13
|
+
"github.com/charmbracelet/bubbles/textinput"
|
|
11
14
|
tea "github.com/charmbracelet/bubbletea"
|
|
15
|
+
"github.com/charmbracelet/lipgloss"
|
|
12
16
|
)
|
|
13
17
|
|
|
14
18
|
type option struct {
|
|
@@ -29,9 +33,54 @@ type scoredOption struct {
|
|
|
29
33
|
score int
|
|
30
34
|
}
|
|
31
35
|
|
|
36
|
+
type keyMap struct {
|
|
37
|
+
Up key.Binding
|
|
38
|
+
Down key.Binding
|
|
39
|
+
PageUp key.Binding
|
|
40
|
+
PageDown key.Binding
|
|
41
|
+
Accept key.Binding
|
|
42
|
+
Quit key.Binding
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
func (k keyMap) ShortHelp() []key.Binding {
|
|
46
|
+
return []key.Binding{k.Up, k.Down, k.Accept, k.Quit}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
func (k keyMap) FullHelp() [][]key.Binding {
|
|
50
|
+
return [][]key.Binding{{k.Up, k.Down, k.PageUp, k.PageDown}, {k.Accept, k.Quit}}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func defaultKeys() keyMap {
|
|
54
|
+
return keyMap{
|
|
55
|
+
Up: key.NewBinding(
|
|
56
|
+
key.WithKeys("up", "k", "ctrl+p"),
|
|
57
|
+
key.WithHelp("up", "move up"),
|
|
58
|
+
),
|
|
59
|
+
Down: key.NewBinding(
|
|
60
|
+
key.WithKeys("down", "j", "ctrl+n"),
|
|
61
|
+
key.WithHelp("down", "move down"),
|
|
62
|
+
),
|
|
63
|
+
PageUp: key.NewBinding(
|
|
64
|
+
key.WithKeys("pgup", "u"),
|
|
65
|
+
key.WithHelp("pgup", "page up"),
|
|
66
|
+
),
|
|
67
|
+
PageDown: key.NewBinding(
|
|
68
|
+
key.WithKeys("pgdown", "d"),
|
|
69
|
+
key.WithHelp("pgdown", "page down"),
|
|
70
|
+
),
|
|
71
|
+
Accept: key.NewBinding(
|
|
72
|
+
key.WithKeys("enter"),
|
|
73
|
+
key.WithHelp("enter", "select"),
|
|
74
|
+
),
|
|
75
|
+
Quit: key.NewBinding(
|
|
76
|
+
key.WithKeys("esc", "ctrl+c"),
|
|
77
|
+
key.WithHelp("esc", "cancel"),
|
|
78
|
+
),
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
32
82
|
type model struct {
|
|
33
83
|
prompt string
|
|
34
|
-
query string
|
|
35
84
|
preferred string
|
|
36
85
|
all []option
|
|
37
86
|
filtered []option
|
|
@@ -40,10 +89,45 @@ type model struct {
|
|
|
40
89
|
cancelled bool
|
|
41
90
|
width int
|
|
42
91
|
height int
|
|
92
|
+
input textinput.Model
|
|
93
|
+
help help.Model
|
|
94
|
+
keys keyMap
|
|
43
95
|
}
|
|
44
96
|
|
|
97
|
+
var (
|
|
98
|
+
appStyle = lipgloss.NewStyle().
|
|
99
|
+
BorderStyle(lipgloss.RoundedBorder()).
|
|
100
|
+
BorderForeground(lipgloss.AdaptiveColor{Light: "251", Dark: "238"}).
|
|
101
|
+
Padding(0, 1)
|
|
102
|
+
|
|
103
|
+
titleStyle = lipgloss.NewStyle().
|
|
104
|
+
Bold(true)
|
|
105
|
+
|
|
106
|
+
mutedStyle = lipgloss.NewStyle().
|
|
107
|
+
Foreground(lipgloss.AdaptiveColor{Light: "245", Dark: "240"})
|
|
108
|
+
|
|
109
|
+
promptStyle = lipgloss.NewStyle().
|
|
110
|
+
Foreground(lipgloss.AdaptiveColor{Light: "63", Dark: "111"})
|
|
111
|
+
|
|
112
|
+
hintStyle = lipgloss.NewStyle().
|
|
113
|
+
Foreground(lipgloss.AdaptiveColor{Light: "245", Dark: "240"})
|
|
114
|
+
|
|
115
|
+
selectedStyle = lipgloss.NewStyle().
|
|
116
|
+
Bold(true).
|
|
117
|
+
Foreground(lipgloss.AdaptiveColor{Light: "39", Dark: "117"})
|
|
118
|
+
|
|
119
|
+
rowStyle = lipgloss.NewStyle().
|
|
120
|
+
Foreground(lipgloss.AdaptiveColor{Light: "250", Dark: "252"})
|
|
121
|
+
|
|
122
|
+
footerStyle = lipgloss.NewStyle().
|
|
123
|
+
Foreground(lipgloss.AdaptiveColor{Light: "245", Dark: "240"})
|
|
124
|
+
|
|
125
|
+
emptyStyle = lipgloss.NewStyle().
|
|
126
|
+
Foreground(lipgloss.AdaptiveColor{Light: "203", Dark: "210"})
|
|
127
|
+
)
|
|
128
|
+
|
|
45
129
|
func (m model) Init() tea.Cmd {
|
|
46
|
-
return
|
|
130
|
+
return textinput.Blink
|
|
47
131
|
}
|
|
48
132
|
|
|
49
133
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
@@ -51,67 +135,76 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
|
51
135
|
case tea.WindowSizeMsg:
|
|
52
136
|
m.width = msg.Width
|
|
53
137
|
m.height = msg.Height
|
|
138
|
+
if m.width > 0 {
|
|
139
|
+
m.input.Width = maxInt(12, m.width-24)
|
|
140
|
+
}
|
|
54
141
|
return m, nil
|
|
55
142
|
case tea.KeyMsg:
|
|
56
|
-
switch
|
|
57
|
-
case
|
|
143
|
+
switch {
|
|
144
|
+
case key.Matches(msg, m.keys.Quit):
|
|
58
145
|
m.cancelled = true
|
|
59
146
|
return m, tea.Quit
|
|
60
|
-
case
|
|
147
|
+
case key.Matches(msg, m.keys.Accept):
|
|
61
148
|
if len(m.filtered) == 0 {
|
|
62
149
|
return m, nil
|
|
63
150
|
}
|
|
64
151
|
selected := m.filtered[m.cursor]
|
|
65
152
|
m.selected = &selected
|
|
66
153
|
return m, tea.Quit
|
|
67
|
-
case
|
|
154
|
+
case key.Matches(msg, m.keys.Up):
|
|
68
155
|
if m.cursor > 0 {
|
|
69
156
|
m.cursor--
|
|
70
157
|
}
|
|
71
158
|
return m, nil
|
|
72
|
-
case
|
|
159
|
+
case key.Matches(msg, m.keys.Down):
|
|
73
160
|
if m.cursor < len(m.filtered)-1 {
|
|
74
161
|
m.cursor++
|
|
75
162
|
}
|
|
76
163
|
return m, nil
|
|
77
|
-
case
|
|
78
|
-
|
|
79
|
-
|
|
164
|
+
case key.Matches(msg, m.keys.PageUp):
|
|
165
|
+
step := m.visibleRows()
|
|
166
|
+
m.cursor = maxInt(0, m.cursor-step)
|
|
167
|
+
return m, nil
|
|
168
|
+
case key.Matches(msg, m.keys.PageDown):
|
|
169
|
+
step := m.visibleRows()
|
|
170
|
+
if len(m.filtered) > 0 {
|
|
171
|
+
m.cursor = minInt(len(m.filtered)-1, m.cursor+step)
|
|
80
172
|
}
|
|
81
|
-
m.query = m.query[:len(m.query)-1]
|
|
82
|
-
m.refilter()
|
|
83
173
|
return m, nil
|
|
84
174
|
}
|
|
175
|
+
}
|
|
85
176
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
177
|
+
previousQuery := m.input.Value()
|
|
178
|
+
var cmd tea.Cmd
|
|
179
|
+
m.input, cmd = m.input.Update(msg)
|
|
180
|
+
if previousQuery != m.input.Value() {
|
|
181
|
+
m.refilter()
|
|
90
182
|
}
|
|
91
183
|
|
|
92
|
-
return m,
|
|
184
|
+
return m, cmd
|
|
93
185
|
}
|
|
94
186
|
|
|
95
187
|
func (m model) View() string {
|
|
96
188
|
var builder strings.Builder
|
|
97
|
-
builder.WriteString(
|
|
98
|
-
|
|
99
|
-
|
|
189
|
+
builder.WriteString(titleStyle.Render("fconvert format picker"))
|
|
190
|
+
builder.WriteString("\n")
|
|
191
|
+
builder.WriteString(promptStyle.Render(m.prompt))
|
|
192
|
+
builder.WriteString("\n")
|
|
193
|
+
builder.WriteString(m.input.View())
|
|
194
|
+
builder.WriteString("\n")
|
|
195
|
+
if strings.TrimSpace(m.input.Value()) == "" && m.preferred != "" {
|
|
196
|
+
builder.WriteString(hintStyle.Render(fmt.Sprintf("hint: original extension '.%s' is ranked first", m.preferred)))
|
|
197
|
+
builder.WriteString("\n")
|
|
100
198
|
}
|
|
101
199
|
|
|
102
200
|
if len(m.filtered) == 0 {
|
|
103
|
-
builder.WriteString("
|
|
104
|
-
builder.WriteString("
|
|
105
|
-
|
|
201
|
+
builder.WriteString(emptyStyle.Render("no matches"))
|
|
202
|
+
builder.WriteString("\n")
|
|
203
|
+
builder.WriteString(footerStyle.Render(m.help.View(m.keys)))
|
|
204
|
+
return appStyle.Render(builder.String())
|
|
106
205
|
}
|
|
107
206
|
|
|
108
|
-
maxRows :=
|
|
109
|
-
if m.height > 6 {
|
|
110
|
-
maxRows = m.height - 4
|
|
111
|
-
}
|
|
112
|
-
if maxRows < 4 {
|
|
113
|
-
maxRows = 4
|
|
114
|
-
}
|
|
207
|
+
maxRows := m.visibleRows()
|
|
115
208
|
if maxRows > len(m.filtered) {
|
|
116
209
|
maxRows = len(m.filtered)
|
|
117
210
|
}
|
|
@@ -128,19 +221,45 @@ func (m model) View() string {
|
|
|
128
221
|
|
|
129
222
|
for index := start; index < end; index++ {
|
|
130
223
|
prefix := " "
|
|
224
|
+
style := rowStyle
|
|
131
225
|
if index == m.cursor {
|
|
132
|
-
prefix = "
|
|
226
|
+
prefix = "->"
|
|
227
|
+
style = selectedStyle
|
|
133
228
|
}
|
|
134
229
|
item := m.filtered[index]
|
|
135
|
-
|
|
230
|
+
extra := ""
|
|
231
|
+
if strings.EqualFold(item.Extension, m.preferred) {
|
|
232
|
+
extra = mutedStyle.Render(" same-ext")
|
|
233
|
+
}
|
|
234
|
+
line := fmt.Sprintf("%s %-10s .%-6s %s%s", prefix, item.ID, item.Extension, item.Name, extra)
|
|
235
|
+
builder.WriteString(style.Render(line))
|
|
236
|
+
builder.WriteString("\n")
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
status := fmt.Sprintf("%d shown / %d total", len(m.filtered), len(m.all))
|
|
240
|
+
if len(m.filtered) != len(m.all) {
|
|
241
|
+
status = fmt.Sprintf("%d matches / %d total", len(m.filtered), len(m.all))
|
|
136
242
|
}
|
|
243
|
+
builder.WriteString(footerStyle.Render(status))
|
|
244
|
+
builder.WriteString("\n")
|
|
245
|
+
builder.WriteString(footerStyle.Render(m.help.View(m.keys)))
|
|
246
|
+
|
|
247
|
+
return appStyle.Render(builder.String())
|
|
248
|
+
}
|
|
137
249
|
|
|
138
|
-
|
|
139
|
-
|
|
250
|
+
func (m model) visibleRows() int {
|
|
251
|
+
rows := 10
|
|
252
|
+
if m.height > 0 {
|
|
253
|
+
rows = m.height - 11
|
|
254
|
+
}
|
|
255
|
+
if rows < 4 {
|
|
256
|
+
rows = 4
|
|
257
|
+
}
|
|
258
|
+
return rows
|
|
140
259
|
}
|
|
141
260
|
|
|
142
261
|
func (m *model) refilter() {
|
|
143
|
-
query := strings.ToLower(strings.TrimSpace(m.
|
|
262
|
+
query := strings.ToLower(strings.TrimSpace(m.input.Value()))
|
|
144
263
|
scored := make([]scoredOption, 0, len(m.all))
|
|
145
264
|
|
|
146
265
|
for _, item := range m.all {
|
|
@@ -235,6 +354,20 @@ func fuzzyScore(query string, item option, preferred string) int {
|
|
|
235
354
|
return score
|
|
236
355
|
}
|
|
237
356
|
|
|
357
|
+
func minInt(a int, b int) int {
|
|
358
|
+
if a < b {
|
|
359
|
+
return a
|
|
360
|
+
}
|
|
361
|
+
return b
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
func maxInt(a int, b int) int {
|
|
365
|
+
if a > b {
|
|
366
|
+
return a
|
|
367
|
+
}
|
|
368
|
+
return b
|
|
369
|
+
}
|
|
370
|
+
|
|
238
371
|
func readPayload(path string) (payload, error) {
|
|
239
372
|
raw, err := os.ReadFile(path)
|
|
240
373
|
if err != nil {
|
|
@@ -249,6 +382,10 @@ func readPayload(path string) (payload, error) {
|
|
|
249
382
|
if data.Prompt == "" {
|
|
250
383
|
data.Prompt = "output format"
|
|
251
384
|
}
|
|
385
|
+
if data.Query != "" {
|
|
386
|
+
data.Query = strings.TrimSpace(data.Query)
|
|
387
|
+
}
|
|
388
|
+
data.Prompt = strings.TrimSpace(data.Prompt)
|
|
252
389
|
return data, nil
|
|
253
390
|
}
|
|
254
391
|
|
|
@@ -270,9 +407,25 @@ func main() {
|
|
|
270
407
|
|
|
271
408
|
picker := model{
|
|
272
409
|
prompt: data.Prompt,
|
|
273
|
-
query: data.Query,
|
|
274
410
|
preferred: strings.TrimSpace(data.Preferred),
|
|
275
411
|
all: data.Options,
|
|
412
|
+
keys: defaultKeys(),
|
|
413
|
+
help: help.New(),
|
|
414
|
+
}
|
|
415
|
+
picker.input = textinput.New()
|
|
416
|
+
picker.input.Prompt = ""
|
|
417
|
+
picker.input.Placeholder = "type to fuzzy filter"
|
|
418
|
+
picker.input.CharLimit = 128
|
|
419
|
+
picker.input.SetValue(data.Query)
|
|
420
|
+
picker.input.Focus()
|
|
421
|
+
picker.help.ShowAll = false
|
|
422
|
+
picker.help.Styles.ShortKey = mutedStyle
|
|
423
|
+
picker.help.Styles.ShortDesc = mutedStyle
|
|
424
|
+
picker.help.Styles.FullKey = mutedStyle
|
|
425
|
+
picker.help.Styles.FullDesc = mutedStyle
|
|
426
|
+
|
|
427
|
+
if picker.prompt == "" {
|
|
428
|
+
picker.prompt = "output format"
|
|
276
429
|
}
|
|
277
430
|
picker.refilter()
|
|
278
431
|
|