on main help sign in
perf: drop reflection usage and use string builder
1dccc97Raphael Amorim
internal/llm/tools/diagnostics.go+16−16
@@ -245,28 +245,28 @@ func getDiagnostics(filePath string, lsps map[string]*lsp.Client) string {
245 return projectDiagnostics[i] < projectDiagnostics[j]
245 return projectDiagnostics[i] < projectDiagnostics[j]
246 })
246 })
247
247
248− output := ""
248+ var output strings.Builder
249
249
250 if len(fileDiagnostics) > 0 {
250 if len(fileDiagnostics) > 0 {
251− output += "\n<file_diagnostics>\n"
251+ output.WriteString("\n<file_diagnostics>\n")
252 if len(fileDiagnostics) > 10 {
252 if len(fileDiagnostics) > 10 {
253− output += strings.Join(fileDiagnostics[:10], "\n")
253+ output.WriteString(strings.Join(fileDiagnostics[:10], "\n"))
254− output += fmt.Sprintf("\n... and %d more diagnostics", len(fileDiagnostics)-10)
254+ fmt.Fprintf(&output, "\n... and %d more diagnostics", len(fileDiagnostics)-10)
255 } else {
255 } else {
256− output += strings.Join(fileDiagnostics, "\n")
256+ output.WriteString(strings.Join(fileDiagnostics, "\n"))
257 }
257 }
258− output += "\n</file_diagnostics>\n"
258+ output.WriteString("\n</file_diagnostics>\n")
259 }
259 }
260
260
261 if len(projectDiagnostics) > 0 {
261 if len(projectDiagnostics) > 0 {
262− output += "\n<project_diagnostics>\n"
262+ output.WriteString("\n<project_diagnostics>\n")
263 if len(projectDiagnostics) > 10 {
263 if len(projectDiagnostics) > 10 {
264− output += strings.Join(projectDiagnostics[:10], "\n")
264+ output.WriteString(strings.Join(projectDiagnostics[:10], "\n"))
265− output += fmt.Sprintf("\n... and %d more diagnostics", len(projectDiagnostics)-10)
265+ fmt.Fprintf(&output, "\n... and %d more diagnostics", len(projectDiagnostics)-10)
266 } else {
266 } else {
267− output += strings.Join(projectDiagnostics, "\n")
267+ output.WriteString(strings.Join(projectDiagnostics, "\n"))
268 }
268 }
269− output += "\n</project_diagnostics>\n"
269+ output.WriteString("\n</project_diagnostics>\n")
270 }
270 }
271
271
272 if len(fileDiagnostics) > 0 || len(projectDiagnostics) > 0 {
272 if len(fileDiagnostics) > 0 || len(projectDiagnostics) > 0 {
@@ -275,13 +275,13 @@ func getDiagnostics(filePath string, lsps map[string]*lsp.Client) string {
275 projectErrors := countSeverity(projectDiagnostics, "Error")
275 projectErrors := countSeverity(projectDiagnostics, "Error")
276 projectWarnings := countSeverity(projectDiagnostics, "Warn")
276 projectWarnings := countSeverity(projectDiagnostics, "Warn")
277
277
278− output += "\n<diagnostic_summary>\n"
278+ output.WriteString("\n<diagnostic_summary>\n")
279− output += fmt.Sprintf("Current file: %d errors, %d warnings\n", fileErrors, fileWarnings)
279+ fmt.Fprintf(&output, "Current file: %d errors, %d warnings\n", fileErrors, fileWarnings)
280− output += fmt.Sprintf("Project: %d errors, %d warnings\n", projectErrors, projectWarnings)
280+ fmt.Fprintf(&output, "Project: %d errors, %d warnings\n", projectErrors, projectWarnings)
281− output += "</diagnostic_summary>\n"
281+ output.WriteString("</diagnostic_summary>\n")
282 }
282 }
283
283
284− return output
284+ return output.String()
285}
285}
286
286
287func countSeverity(diagnostics []string, severity string) int {
287func countSeverity(diagnostics []string, severity string) int {
internal/llm/tools/grep.go+9−9
@@ -198,35 +198,35 @@ func (g *grepTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error)
198 return ToolResponse{}, fmt.Errorf("error searching files: %w", err)
198 return ToolResponse{}, fmt.Errorf("error searching files: %w", err)
199 }
199 }
200
200
201− var output string
201+ var output strings.Builder
202 if len(matches) == 0 {
202 if len(matches) == 0 {
203− output = "No files found"
203+ output.WriteString("No files found")
204 } else {
204 } else {
205− output = fmt.Sprintf("Found %d matches\n", len(matches))
205+ fmt.Fprintf(&output, "Found %d matches\n", len(matches))
206
206
207 currentFile := ""
207 currentFile := ""
208 for _, match := range matches {
208 for _, match := range matches {
209 if currentFile != match.path {
209 if currentFile != match.path {
210 if currentFile != "" {
210 if currentFile != "" {
211− output += "\n"
211+ output.WriteString("\n")
212 }
212 }
213 currentFile = match.path
213 currentFile = match.path
214− output += fmt.Sprintf("%s:\n", match.path)
214+ fmt.Fprintf(&output, "%s:\n", match.path)
215 }
215 }
216 if match.lineNum > 0 {
216 if match.lineNum > 0 {
217− output += fmt.Sprintf(" Line %d: %s\n", match.lineNum, match.lineText)
217+ fmt.Fprintf(&output, " Line %d: %s\n", match.lineNum, match.lineText)
218 } else {
218 } else {
219− output += fmt.Sprintf(" %s\n", match.path)
219+ fmt.Fprintf(&output, " %s\n", match.path)
220 }
220 }
221 }
221 }
222
222
223 if truncated {
223 if truncated {
224− output += "\n(Results are truncated. Consider using a more specific path or pattern.)"
224+ output.WriteString("\n(Results are truncated. Consider using a more specific path or pattern.)")
225 }
225 }
226 }
226 }
227
227
228 return WithResponseMetadata(
228 return WithResponseMetadata(
229− NewTextResponse(output),
229+ NewTextResponse(output.String()),
230 GrepResponseMetadata{
230 GrepResponseMetadata{
231 NumberOfMatches: len(matches),
231 NumberOfMatches: len(matches),
232 Truncated: truncated,
232 Truncated: truncated,
internal/llm/tools/ls.go+1−1
@@ -209,7 +209,7 @@ func printNode(builder *strings.Builder, node *TreeNode, level int) {
209
209
210 nodeName := node.Name
210 nodeName := node.Name
211 if node.Type == "directory" {
211 if node.Type == "directory" {
212− nodeName += string(filepath.Separator)
212+ nodeName = nodeName + string(filepath.Separator)
213 }
213 }
214
214
215 fmt.Fprintf(builder, "%s- %s\n", indent, nodeName)
215 fmt.Fprintf(builder, "%s- %s\n", indent, nodeName)
internal/tui/components/chat/editor/keys.go+9−2
@@ -2,7 +2,6 @@ package editor
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type EditorKeyMap struct {
7type EditorKeyMap struct {
@@ -23,10 +22,18 @@ func DefaultEditorKeyMap() EditorKeyMap {
23 }
22 }
24}
23}
25
24
25+// KeyBindings implements layout.KeyMapProvider
26+func (k EditorKeyMap) KeyBindings() []key.Binding {
27+ return []key.Binding{
28+ k.Send,
29+ k.OpenEditor,
30+ }
31+}
32+
26// FullHelp implements help.KeyMap.
33// FullHelp implements help.KeyMap.
27func (k EditorKeyMap) FullHelp() [][]key.Binding {
34func (k EditorKeyMap) FullHelp() [][]key.Binding {
28 m := [][]key.Binding{}
35 m := [][]key.Binding{}
29− slice := layout.KeyMapToSlice(k)
36+ slice := k.KeyBindings()
30 for i := 0; i < len(slice); i += 4 {
37 for i := 0; i < len(slice); i += 4 {
31 end := min(i+4, len(slice))
38 end := min(i+4, len(slice))
32 m = append(m, slice[i:end])
39 m = append(m, slice[i:end])
internal/tui/components/completions/keys.go+11−2
@@ -2,7 +2,6 @@ package completions
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type KeyMap struct {
7type KeyMap struct {
@@ -33,10 +32,20 @@ func DefaultKeyMap() KeyMap {
33 }
32 }
34}
33}
35
34
35+// KeyBindings implements layout.KeyMapProvider
36+func (k KeyMap) KeyBindings() []key.Binding {
37+ return []key.Binding{
38+ k.Down,
39+ k.Up,
40+ k.Select,
41+ k.Cancel,
42+ }
43+}
44+
36// FullHelp implements help.KeyMap.
45// FullHelp implements help.KeyMap.
37func (k KeyMap) FullHelp() [][]key.Binding {
46func (k KeyMap) FullHelp() [][]key.Binding {
38 m := [][]key.Binding{}
47 m := [][]key.Binding{}
39− slice := layout.KeyMapToSlice(k)
48+ slice := k.KeyBindings()
40 for i := 0; i < len(slice); i += 4 {
49 for i := 0; i < len(slice); i += 4 {
41 end := min(i+4, len(slice))
50 end := min(i+4, len(slice))
42 m = append(m, slice[i:end])
51 m = append(m, slice[i:end])
internal/tui/components/core/layout/layout.go+3−12
@@ -1,8 +1,6 @@
1package layout
1package layout
2
2
3import (
3import (
4− "reflect"
5−
6 "github.com/charmbracelet/bubbles/v2/help"
4 "github.com/charmbracelet/bubbles/v2/help"
7 "github.com/charmbracelet/bubbles/v2/key"
5 "github.com/charmbracelet/bubbles/v2/key"
8 tea "github.com/charmbracelet/bubbletea/v2"
6 tea "github.com/charmbracelet/bubbletea/v2"
@@ -27,14 +25,7 @@ type Positionable interface {
27 SetPosition(x, y int) tea.Cmd
25 SetPosition(x, y int) tea.Cmd
28}
26}
29
27
30−func KeyMapToSlice(t any) (bindings []key.Binding) {
28+// KeyMapProvider defines an interface for types that can provide their key bindings as a slice
31− typ := reflect.TypeOf(t)
29+type KeyMapProvider interface {
32− if typ.Kind() != reflect.Struct {
30+ KeyBindings() []key.Binding
33− return nil
34− }
35− for i := range typ.NumField() {
36− v := reflect.ValueOf(t).Field(i)
37− bindings = append(bindings, v.Interface().(key.Binding))
38− }
39− return
40}
31}
internal/tui/components/core/list/keys.go+17−2
@@ -2,7 +2,6 @@ package list
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type KeyMap struct {
7type KeyMap struct {
@@ -53,10 +52,26 @@ func DefaultKeyMap() KeyMap {
53 }
52 }
54}
53}
55
54
55+// KeyBindings implements layout.KeyMapProvider
56+func (k KeyMap) KeyBindings() []key.Binding {
57+ return []key.Binding{
58+ k.Down,
59+ k.Up,
60+ k.NDown,
61+ k.NUp,
62+ k.DownOneItem,
63+ k.UpOneItem,
64+ k.HalfPageDown,
65+ k.HalfPageUp,
66+ k.Home,
67+ k.End,
68+ }
69+}
70+
56// FullHelp implements help.KeyMap.
71// FullHelp implements help.KeyMap.
57func (k KeyMap) FullHelp() [][]key.Binding {
72func (k KeyMap) FullHelp() [][]key.Binding {
58 m := [][]key.Binding{}
73 m := [][]key.Binding{}
59− slice := layout.KeyMapToSlice(k)
74+ slice := k.KeyBindings()
60 for i := 0; i < len(slice); i += 4 {
75 for i := 0; i < len(slice); i += 4 {
61 end := min(i+4, len(slice))
76 end := min(i+4, len(slice))
62 m = append(m, slice[i:end])
77 m = append(m, slice[i:end])
internal/tui/components/core/status/keys.go+11−2
@@ -2,7 +2,6 @@ package status
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type KeyMap struct {
7type KeyMap struct {
@@ -33,10 +32,20 @@ func DefaultKeyMap(tabHelp string) KeyMap {
33 }
32 }
34}
33}
35
34
35+// KeyBindings implements layout.KeyMapProvider
36+func (k KeyMap) KeyBindings() []key.Binding {
37+ return []key.Binding{
38+ k.Tab,
39+ k.Commands,
40+ k.Sessions,
41+ k.Help,
42+ }
43+}
44+
36// FullHelp implements help.KeyMap.
45// FullHelp implements help.KeyMap.
37func (k KeyMap) FullHelp() [][]key.Binding {
46func (k KeyMap) FullHelp() [][]key.Binding {
38 m := [][]key.Binding{}
47 m := [][]key.Binding{}
39− slice := layout.KeyMapToSlice(k)
48+ slice := k.KeyBindings()
40 for i := 0; i < len(slice); i += 4 {
49 for i := 0; i < len(slice); i += 4 {
41 end := min(i+4, len(slice))
50 end := min(i+4, len(slice))
42 m = append(m, slice[i:end])
51 m = append(m, slice[i:end])
internal/tui/components/dialogs/commands/keys.go+22−3
@@ -2,7 +2,6 @@ package commands
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type CommandsDialogKeyMap struct {
7type CommandsDialogKeyMap struct {
@@ -38,10 +37,21 @@ func DefaultCommandsDialogKeyMap() CommandsDialogKeyMap {
38 }
37 }
39}
38}
40
39
40+// KeyBindings implements layout.KeyMapProvider
41+func (k CommandsDialogKeyMap) KeyBindings() []key.Binding {
42+ return []key.Binding{
43+ k.Select,
44+ k.Next,
45+ k.Previous,
46+ k.Tab,
47+ k.Close,
48+ }
49+}
50+
41// FullHelp implements help.KeyMap.
51// FullHelp implements help.KeyMap.
42func (k CommandsDialogKeyMap) FullHelp() [][]key.Binding {
52func (k CommandsDialogKeyMap) FullHelp() [][]key.Binding {
43 m := [][]key.Binding{}
53 m := [][]key.Binding{}
44− slice := layout.KeyMapToSlice(k)
54+ slice := k.KeyBindings()
45 for i := 0; i < len(slice); i += 4 {
55 for i := 0; i < len(slice); i += 4 {
46 end := min(i+4, len(slice))
56 end := min(i+4, len(slice))
47 m = append(m, slice[i:end])
57 m = append(m, slice[i:end])
@@ -86,10 +96,19 @@ func DefaultArgumentsDialogKeyMap() ArgumentsDialogKeyMap {
86 }
96 }
87}
97}
88
98
99+// KeyBindings implements layout.KeyMapProvider
100+func (k ArgumentsDialogKeyMap) KeyBindings() []key.Binding {
101+ return []key.Binding{
102+ k.Confirm,
103+ k.Next,
104+ k.Previous,
105+ }
106+}
107+
89// FullHelp implements help.KeyMap.
108// FullHelp implements help.KeyMap.
90func (k ArgumentsDialogKeyMap) FullHelp() [][]key.Binding {
109func (k ArgumentsDialogKeyMap) FullHelp() [][]key.Binding {
91 m := [][]key.Binding{}
110 m := [][]key.Binding{}
92− slice := layout.KeyMapToSlice(k)
111+ slice := k.KeyBindings()
93 for i := 0; i < len(slice); i += 4 {
112 for i := 0; i < len(slice); i += 4 {
94 end := min(i+4, len(slice))
113 end := min(i+4, len(slice))
95 m = append(m, slice[i:end])
114 m = append(m, slice[i:end])
internal/tui/components/dialogs/compact/keys.go+12−2
@@ -2,7 +2,6 @@ package compact
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8// KeyMap defines the key bindings for the compact dialog.
7// KeyMap defines the key bindings for the compact dialog.
@@ -40,10 +39,21 @@ func DefaultKeyMap() KeyMap {
40 }
39 }
41}
40}
42
41
42+// KeyBindings implements layout.KeyMapProvider
43+func (k KeyMap) KeyBindings() []key.Binding {
44+ return []key.Binding{
45+ k.ChangeSelection,
46+ k.Select,
47+ k.Y,
48+ k.N,
49+ k.Close,
50+ }
51+}
52+
43// FullHelp implements help.KeyMap.
53// FullHelp implements help.KeyMap.
44func (k KeyMap) FullHelp() [][]key.Binding {
54func (k KeyMap) FullHelp() [][]key.Binding {
45 m := [][]key.Binding{}
55 m := [][]key.Binding{}
46− slice := layout.KeyMapToSlice(k)
56+ slice := k.KeyBindings()
47 for i := 0; i < len(slice); i += 4 {
57 for i := 0; i < len(slice); i += 4 {
48 end := min(i+4, len(slice))
58 end := min(i+4, len(slice))
49 m = append(m, slice[i:end])
59 m = append(m, slice[i:end])
internal/tui/components/dialogs/filepicker/keys.go+13−2
@@ -2,7 +2,6 @@ package filepicker
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8// KeyMap defines keyboard bindings for dialog management.
7// KeyMap defines keyboard bindings for dialog management.
@@ -45,10 +44,22 @@ func DefaultKeyMap() KeyMap {
45 }
44 }
46}
45}
47
46
47+// KeyBindings implements layout.KeyMapProvider
48+func (k KeyMap) KeyBindings() []key.Binding {
49+ return []key.Binding{
50+ k.Select,
51+ k.Down,
52+ k.Up,
53+ k.Forward,
54+ k.Backward,
55+ k.Close,
56+ }
57+}
58+
48// FullHelp implements help.KeyMap.
59// FullHelp implements help.KeyMap.
49func (k KeyMap) FullHelp() [][]key.Binding {
60func (k KeyMap) FullHelp() [][]key.Binding {
50 m := [][]key.Binding{}
61 m := [][]key.Binding{}
51− slice := layout.KeyMapToSlice(k)
62+ slice := k.KeyBindings()
52 for i := 0; i < len(slice); i += 4 {
63 for i := 0; i < len(slice); i += 4 {
53 end := min(i+4, len(slice))
64 end := min(i+4, len(slice))
54 m = append(m, slice[i:end])
65 m = append(m, slice[i:end])
internal/tui/components/dialogs/init/keys.go+12−2
@@ -2,7 +2,6 @@ package init
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type KeyMap struct {
7type KeyMap struct {
@@ -38,10 +37,21 @@ func DefaultKeyMap() KeyMap {
38 }
37 }
39}
38}
40
39
40+// KeyBindings implements layout.KeyMapProvider
41+func (k KeyMap) KeyBindings() []key.Binding {
42+ return []key.Binding{
43+ k.ChangeSelection,
44+ k.Select,
45+ k.Y,
46+ k.N,
47+ k.Close,
48+ }
49+}
50+
41// FullHelp implements help.KeyMap.
51// FullHelp implements help.KeyMap.
42func (k KeyMap) FullHelp() [][]key.Binding {
52func (k KeyMap) FullHelp() [][]key.Binding {
43 m := [][]key.Binding{}
53 m := [][]key.Binding{}
44− slice := layout.KeyMapToSlice(k)
54+ slice := k.KeyBindings()
45 for i := 0; i < len(slice); i += 4 {
55 for i := 0; i < len(slice); i += 4 {
46 end := min(i+4, len(slice))
56 end := min(i+4, len(slice))
47 m = append(m, slice[i:end])
57 m = append(m, slice[i:end])
internal/tui/components/dialogs/keys.go+8−2
@@ -2,7 +2,6 @@ package dialogs
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8// KeyMap defines keyboard bindings for dialog management.
7// KeyMap defines keyboard bindings for dialog management.
@@ -18,10 +17,17 @@ func DefaultKeyMap() KeyMap {
18 }
17 }
19}
18}
20
19
20+// KeyBindings implements layout.KeyMapProvider
21+func (k KeyMap) KeyBindings() []key.Binding {
22+ return []key.Binding{
23+ k.Close,
24+ }
25+}
26+
21// FullHelp implements help.KeyMap.
27// FullHelp implements help.KeyMap.
22func (k KeyMap) FullHelp() [][]key.Binding {
28func (k KeyMap) FullHelp() [][]key.Binding {
23 m := [][]key.Binding{}
29 m := [][]key.Binding{}
24− slice := layout.KeyMapToSlice(k)
30+ slice := k.KeyBindings()
25 for i := 0; i < len(slice); i += 4 {
31 for i := 0; i < len(slice); i += 4 {
26 end := min(i+4, len(slice))
32 end := min(i+4, len(slice))
27 m = append(m, slice[i:end])
33 m = append(m, slice[i:end])
internal/tui/components/dialogs/models/keys.go+11−2
@@ -2,7 +2,6 @@ package models
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type KeyMap struct {
7type KeyMap struct {
@@ -33,10 +32,20 @@ func DefaultKeyMap() KeyMap {
33 }
32 }
34}
33}
35
34
35+// KeyBindings implements layout.KeyMapProvider
36+func (k KeyMap) KeyBindings() []key.Binding {
37+ return []key.Binding{
38+ k.Select,
39+ k.Next,
40+ k.Previous,
41+ k.Close,
42+ }
43+}
44+
36// FullHelp implements help.KeyMap.
45// FullHelp implements help.KeyMap.
37func (k KeyMap) FullHelp() [][]key.Binding {
46func (k KeyMap) FullHelp() [][]key.Binding {
38 m := [][]key.Binding{}
47 m := [][]key.Binding{}
39− slice := layout.KeyMapToSlice(k)
48+ slice := k.KeyBindings()
40 for i := 0; i < len(slice); i += 4 {
49 for i := 0; i < len(slice); i += 4 {
41 end := min(i+4, len(slice))
50 end := min(i+4, len(slice))
42 m = append(m, slice[i:end])
51 m = append(m, slice[i:end])
internal/tui/components/dialogs/permissions/keys.go+14−2
@@ -2,7 +2,6 @@ package permissions
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type KeyMap struct {
7type KeyMap struct {
@@ -48,10 +47,23 @@ func DefaultKeyMap() KeyMap {
48 }
47 }
49}
48}
50
49
50+// KeyBindings implements layout.KeyMapProvider
51+func (k KeyMap) KeyBindings() []key.Binding {
52+ return []key.Binding{
53+ k.Left,
54+ k.Right,
55+ k.Tab,
56+ k.Select,
57+ k.Allow,
58+ k.AllowSession,
59+ k.Deny,
60+ }
61+}
62+
51// FullHelp implements help.KeyMap.
63// FullHelp implements help.KeyMap.
52func (k KeyMap) FullHelp() [][]key.Binding {
64func (k KeyMap) FullHelp() [][]key.Binding {
53 m := [][]key.Binding{}
65 m := [][]key.Binding{}
54− slice := layout.KeyMapToSlice(k)
66+ slice := k.KeyBindings()
55 for i := 0; i < len(slice); i += 4 {
67 for i := 0; i < len(slice); i += 4 {
56 end := min(i+4, len(slice))
68 end := min(i+4, len(slice))
57 m = append(m, slice[i:end])
69 m = append(m, slice[i:end])
internal/tui/components/dialogs/quit/keys.go+13−2
@@ -2,7 +2,6 @@ package quit
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8// KeyMap defines the keyboard bindings for the quit dialog.
7// KeyMap defines the keyboard bindings for the quit dialog.
@@ -44,10 +43,22 @@ func DefaultKeymap() KeyMap {
44 }
43 }
45}
44}
46
45
46+// KeyBindings implements layout.KeyMapProvider
47+func (k KeyMap) KeyBindings() []key.Binding {
48+ return []key.Binding{
49+ k.LeftRight,
50+ k.EnterSpace,
51+ k.Yes,
52+ k.No,
53+ k.Tab,
54+ k.Close,
55+ }
56+}
57+
47// FullHelp implements help.KeyMap.
58// FullHelp implements help.KeyMap.
48func (k KeyMap) FullHelp() [][]key.Binding {
59func (k KeyMap) FullHelp() [][]key.Binding {
49 m := [][]key.Binding{}
60 m := [][]key.Binding{}
50− slice := layout.KeyMapToSlice(k)
61+ slice := k.KeyBindings()
51 for i := 0; i < len(slice); i += 4 {
62 for i := 0; i < len(slice); i += 4 {
52 end := min(i+4, len(slice))
63 end := min(i+4, len(slice))
53 m = append(m, slice[i:end])
64 m = append(m, slice[i:end])
internal/tui/components/dialogs/sessions/keys.go+11−2
@@ -2,7 +2,6 @@ package sessions
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type KeyMap struct {
7type KeyMap struct {
@@ -33,10 +32,20 @@ func DefaultKeyMap() KeyMap {
33 }
32 }
34}
33}
35
34
35+// KeyBindings implements layout.KeyMapProvider
36+func (k KeyMap) KeyBindings() []key.Binding {
37+ return []key.Binding{
38+ k.Select,
39+ k.Next,
40+ k.Previous,
41+ k.Close,
42+ }
43+}
44+
36// FullHelp implements help.KeyMap.
45// FullHelp implements help.KeyMap.
37func (k KeyMap) FullHelp() [][]key.Binding {
46func (k KeyMap) FullHelp() [][]key.Binding {
38 m := [][]key.Binding{}
47 m := [][]key.Binding{}
39− slice := layout.KeyMapToSlice(k)
48+ slice := k.KeyBindings()
40 for i := 0; i < len(slice); i += 4 {
49 for i := 0; i < len(slice); i += 4 {
41 end := min(i+4, len(slice))
50 end := min(i+4, len(slice))
42 m = append(m, slice[i:end])
51 m = append(m, slice[i:end])
internal/tui/keys.go+12−2
@@ -2,7 +2,6 @@ package tui
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type KeyMap struct {
7type KeyMap struct {
@@ -42,7 +41,7 @@ func DefaultKeyMap() KeyMap {
42// FullHelp implements help.KeyMap.
41// FullHelp implements help.KeyMap.
43func (k KeyMap) FullHelp() [][]key.Binding {
42func (k KeyMap) FullHelp() [][]key.Binding {
44 m := [][]key.Binding{}
43 m := [][]key.Binding{}
45− slice := layout.KeyMapToSlice(k)
44+ slice := k.KeyBindings()
46 for i := 0; i < len(slice); i += 4 {
45 for i := 0; i < len(slice); i += 4 {
47 end := min(i+4, len(slice))
46 end := min(i+4, len(slice))
48 m = append(m, slice[i:end])
47 m = append(m, slice[i:end])
@@ -50,6 +49,17 @@ func (k KeyMap) FullHelp() [][]key.Binding {
50 return m
49 return m
51}
50}
52
51
52+// KeyBindings implements layout.KeyMapProvider
53+func (k KeyMap) KeyBindings() []key.Binding {
54+ return []key.Binding{
55+ k.Logs,
56+ k.Quit,
57+ k.Help,
58+ k.Commands,
59+ k.Sessions,
60+ }
61+}
62+
53// ShortHelp implements help.KeyMap.
63// ShortHelp implements help.KeyMap.
54func (k KeyMap) ShortHelp() []key.Binding {
64func (k KeyMap) ShortHelp() []key.Binding {
55 return []key.Binding{}
65 return []key.Binding{}
internal/tui/page/chat/keys.go+11−2
@@ -2,7 +2,6 @@ package chat
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type KeyMap struct {
7type KeyMap struct {
@@ -33,10 +32,20 @@ func DefaultKeyMap() KeyMap {
33 }
32 }
34}
33}
35
34
35+// KeyBindings implements layout.KeyMapProvider
36+func (k KeyMap) KeyBindings() []key.Binding {
37+ return []key.Binding{
38+ k.NewSession,
39+ k.FilePicker,
40+ k.Cancel,
41+ k.Tab,
42+ }
43+}
44+
36// FullHelp implements help.KeyMap.
45// FullHelp implements help.KeyMap.
37func (k KeyMap) FullHelp() [][]key.Binding {
46func (k KeyMap) FullHelp() [][]key.Binding {
38 m := [][]key.Binding{}
47 m := [][]key.Binding{}
39− slice := layout.KeyMapToSlice(k)
48+ slice := k.KeyBindings()
40 for i := 0; i < len(slice); i += 4 {
49 for i := 0; i < len(slice); i += 4 {
41 end := min(i+4, len(slice))
50 end := min(i+4, len(slice))
42 m = append(m, slice[i:end])
51 m = append(m, slice[i:end])
internal/tui/page/logs/keys.go+8−2
@@ -2,7 +2,6 @@ package logs
2
2
3import (
3import (
4 "github.com/charmbracelet/bubbles/v2/key"
4 "github.com/charmbracelet/bubbles/v2/key"
5− "github.com/charmbracelet/crush/internal/tui/components/core/layout"
6)
5)
7
6
8type KeyMap struct {
7type KeyMap struct {
@@ -18,10 +17,17 @@ func DefaultKeyMap() KeyMap {
18 }
17 }
19}
18}
20
19
20+// KeyBindings implements layout.KeyMapProvider
21+func (k KeyMap) KeyBindings() []key.Binding {
22+ return []key.Binding{
23+ k.Back,
24+ }
25+}
26+
21// FullHelp implements help.KeyMap.
27// FullHelp implements help.KeyMap.
22func (k KeyMap) FullHelp() [][]key.Binding {
28func (k KeyMap) FullHelp() [][]key.Binding {
23 m := [][]key.Binding{}
29 m := [][]key.Binding{}
24− slice := layout.KeyMapToSlice(k)
30+ slice := k.KeyBindings()
25 for i := 0; i < len(slice); i += 4 {
31 for i := 0; i < len(slice); i += 4 {
26 end := min(i+4, len(slice))
32 end := min(i+4, len(slice))
27 m = append(m, slice[i:end])
33 m = append(m, slice[i:end])