diff --git a/internal/llm/tools/diagnostics.go b/internal/llm/tools/diagnostics.go
index 89ad484c134a30fa4b18526e64a25e37cc0912eb..e48132414ad338635ada6294134e3d7f2d938c7d 100644
--- a/internal/llm/tools/diagnostics.go
+++ b/internal/llm/tools/diagnostics.go
@@ -245,28 +245,28 @@ func getDiagnostics(filePath string, lsps map[string]*lsp.Client) string {
return projectDiagnostics[i] < projectDiagnostics[j]
})
- output := ""
+ var output strings.Builder
if len(fileDiagnostics) > 0 {
- output += "\n\n"
+ output.WriteString("\n\n")
if len(fileDiagnostics) > 10 {
- output += strings.Join(fileDiagnostics[:10], "\n")
- output += fmt.Sprintf("\n... and %d more diagnostics", len(fileDiagnostics)-10)
+ output.WriteString(strings.Join(fileDiagnostics[:10], "\n"))
+ fmt.Fprintf(&output, "\n... and %d more diagnostics", len(fileDiagnostics)-10)
} else {
- output += strings.Join(fileDiagnostics, "\n")
+ output.WriteString(strings.Join(fileDiagnostics, "\n"))
}
- output += "\n\n"
+ output.WriteString("\n\n")
}
if len(projectDiagnostics) > 0 {
- output += "\n\n"
+ output.WriteString("\n\n")
if len(projectDiagnostics) > 10 {
- output += strings.Join(projectDiagnostics[:10], "\n")
- output += fmt.Sprintf("\n... and %d more diagnostics", len(projectDiagnostics)-10)
+ output.WriteString(strings.Join(projectDiagnostics[:10], "\n"))
+ fmt.Fprintf(&output, "\n... and %d more diagnostics", len(projectDiagnostics)-10)
} else {
- output += strings.Join(projectDiagnostics, "\n")
+ output.WriteString(strings.Join(projectDiagnostics, "\n"))
}
- output += "\n\n"
+ output.WriteString("\n\n")
}
if len(fileDiagnostics) > 0 || len(projectDiagnostics) > 0 {
@@ -275,13 +275,13 @@ func getDiagnostics(filePath string, lsps map[string]*lsp.Client) string {
projectErrors := countSeverity(projectDiagnostics, "Error")
projectWarnings := countSeverity(projectDiagnostics, "Warn")
- output += "\n\n"
- output += fmt.Sprintf("Current file: %d errors, %d warnings\n", fileErrors, fileWarnings)
- output += fmt.Sprintf("Project: %d errors, %d warnings\n", projectErrors, projectWarnings)
- output += "\n"
+ output.WriteString("\n\n")
+ fmt.Fprintf(&output, "Current file: %d errors, %d warnings\n", fileErrors, fileWarnings)
+ fmt.Fprintf(&output, "Project: %d errors, %d warnings\n", projectErrors, projectWarnings)
+ output.WriteString("\n")
}
- return output
+ return output.String()
}
func countSeverity(diagnostics []string, severity string) int {
diff --git a/internal/llm/tools/grep.go b/internal/llm/tools/grep.go
index e043a71e0bafc77050bf444a02f50c2462018e8d..e6992a4f8c23dc440898298d8f0e5d880b2fdc53 100644
--- a/internal/llm/tools/grep.go
+++ b/internal/llm/tools/grep.go
@@ -198,35 +198,35 @@ func (g *grepTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error)
return ToolResponse{}, fmt.Errorf("error searching files: %w", err)
}
- var output string
+ var output strings.Builder
if len(matches) == 0 {
- output = "No files found"
+ output.WriteString("No files found")
} else {
- output = fmt.Sprintf("Found %d matches\n", len(matches))
+ fmt.Fprintf(&output, "Found %d matches\n", len(matches))
currentFile := ""
for _, match := range matches {
if currentFile != match.path {
if currentFile != "" {
- output += "\n"
+ output.WriteString("\n")
}
currentFile = match.path
- output += fmt.Sprintf("%s:\n", match.path)
+ fmt.Fprintf(&output, "%s:\n", match.path)
}
if match.lineNum > 0 {
- output += fmt.Sprintf(" Line %d: %s\n", match.lineNum, match.lineText)
+ fmt.Fprintf(&output, " Line %d: %s\n", match.lineNum, match.lineText)
} else {
- output += fmt.Sprintf(" %s\n", match.path)
+ fmt.Fprintf(&output, " %s\n", match.path)
}
}
if truncated {
- output += "\n(Results are truncated. Consider using a more specific path or pattern.)"
+ output.WriteString("\n(Results are truncated. Consider using a more specific path or pattern.)")
}
}
return WithResponseMetadata(
- NewTextResponse(output),
+ NewTextResponse(output.String()),
GrepResponseMetadata{
NumberOfMatches: len(matches),
Truncated: truncated,
diff --git a/internal/llm/tools/grep_test.go b/internal/llm/tools/grep_test.go
index de4e6afb225075df34e14d54fb1e5db76955625b..22680fd0980213ea9943959367d3d987620695df 100644
--- a/internal/llm/tools/grep_test.go
+++ b/internal/llm/tools/grep_test.go
@@ -7,24 +7,24 @@ import (
func TestRegexCache(t *testing.T) {
cache := newRegexCache()
-
+
// Test basic caching
pattern := "test.*pattern"
regex1, err := cache.get(pattern)
if err != nil {
t.Fatalf("Failed to compile regex: %v", err)
}
-
+
regex2, err := cache.get(pattern)
if err != nil {
t.Fatalf("Failed to get cached regex: %v", err)
}
-
+
// Should be the same instance (cached)
if regex1 != regex2 {
t.Error("Expected cached regex to be the same instance")
}
-
+
// Test that it actually works
if !regex1.MatchString("test123pattern") {
t.Error("Regex should match test string")
@@ -34,13 +34,13 @@ func TestRegexCache(t *testing.T) {
func TestGlobToRegexCaching(t *testing.T) {
// Test that globToRegex uses pre-compiled regex
pattern1 := globToRegex("*.{js,ts}")
-
+
// Should not panic and should work correctly
regex1, err := regexp.Compile(pattern1)
if err != nil {
t.Fatalf("Failed to compile glob regex: %v", err)
}
-
+
if !regex1.MatchString("test.js") {
t.Error("Glob regex should match .js files")
}
@@ -56,7 +56,7 @@ func TestGlobToRegexCaching(t *testing.T) {
func BenchmarkRegexCacheVsCompile(b *testing.B) {
cache := newRegexCache()
pattern := "test.*pattern.*[0-9]+"
-
+
b.Run("WithCache", func(b *testing.B) {
for b.Loop() {
_, err := cache.get(pattern)
@@ -65,7 +65,7 @@ func BenchmarkRegexCacheVsCompile(b *testing.B) {
}
}
})
-
+
b.Run("WithoutCache", func(b *testing.B) {
for b.Loop() {
_, err := regexp.Compile(pattern)
@@ -74,4 +74,4 @@ func BenchmarkRegexCacheVsCompile(b *testing.B) {
}
}
})
-}
\ No newline at end of file
+}
diff --git a/internal/llm/tools/ls.go b/internal/llm/tools/ls.go
index 81539abe8db1ce2ccde5b8261d34474ab77ea076..a0426b1393f42bc4729db558641e0c178a680d27 100644
--- a/internal/llm/tools/ls.go
+++ b/internal/llm/tools/ls.go
@@ -209,7 +209,7 @@ func printNode(builder *strings.Builder, node *TreeNode, level int) {
nodeName := node.Name
if node.Type == "directory" {
- nodeName += string(filepath.Separator)
+ nodeName = nodeName + string(filepath.Separator)
}
fmt.Fprintf(builder, "%s- %s\n", indent, nodeName)
diff --git a/internal/tui/components/chat/chat.go b/internal/tui/components/chat/chat.go
index d0c83857e5ea95ee582371d14c9ea1724669c60d..332d0ff5070290377342e75b0af6c2f4a59d70e5 100644
--- a/internal/tui/components/chat/chat.go
+++ b/internal/tui/components/chat/chat.go
@@ -500,6 +500,6 @@ func (m *messageListCmp) IsFocused() bool {
}
func (m *messageListCmp) Bindings() []key.Binding {
- bindings := layout.KeyMapToSlice(m.defaultListKeyMap)
+ bindings := m.defaultListKeyMap.KeyBindings()
return bindings
}
diff --git a/internal/tui/components/chat/editor/editor.go b/internal/tui/components/chat/editor/editor.go
index 2f7e02b676512a226f8da5f25329a937c13c64dc..97493a00508e765baedb35c7df2239fb24b3075a 100644
--- a/internal/tui/components/chat/editor/editor.go
+++ b/internal/tui/components/chat/editor/editor.go
@@ -18,7 +18,6 @@ import (
"github.com/charmbracelet/crush/internal/session"
"github.com/charmbracelet/crush/internal/tui/components/chat"
"github.com/charmbracelet/crush/internal/tui/components/completions"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
"github.com/charmbracelet/crush/internal/tui/components/dialogs"
"github.com/charmbracelet/crush/internal/tui/components/dialogs/filepicker"
"github.com/charmbracelet/crush/internal/tui/components/dialogs/quit"
@@ -49,12 +48,6 @@ type editorCmp struct {
isCompletionsOpen bool
}
-type DeleteAttachmentKeyMaps struct {
- AttachmentDeleteMode key.Binding
- Escape key.Binding
- DeleteAllAttachments key.Binding
-}
-
var DeleteKeyMaps = DeleteAttachmentKeyMaps{
AttachmentDeleteMode: key.NewBinding(
key.WithKeys("ctrl+r"),
@@ -372,7 +365,7 @@ func (c *editorCmp) IsFocused() bool {
}
func (c *editorCmp) Bindings() []key.Binding {
- return layout.KeyMapToSlice(c.keyMap)
+ return c.keyMap.KeyBindings()
}
func NewEditorCmp(app *app.App) util.Model {
diff --git a/internal/tui/components/chat/editor/keys.go b/internal/tui/components/chat/editor/keys.go
index d384f1fdcad6977b984e51b11da01e8c46140ef5..c64a92d526a1a81e558909fe5500b2bf1d4e3990 100644
--- a/internal/tui/components/chat/editor/keys.go
+++ b/internal/tui/components/chat/editor/keys.go
@@ -27,6 +27,21 @@ func DefaultEditorKeyMap() EditorKeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k EditorKeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.AddFile,
+ k.SendMessage,
+ k.OpenEditor,
+ }
+}
+
+type DeleteAttachmentKeyMaps struct {
+ AttachmentDeleteMode key.Binding
+ Escape key.Binding
+ DeleteAllAttachments key.Binding
+}
+
// TODO: update this to use the new keymap concepts
var AttachmentsKeyMaps = DeleteAttachmentKeyMaps{
AttachmentDeleteMode: key.NewBinding(
diff --git a/internal/tui/components/chat/sidebar/sidebar.go b/internal/tui/components/chat/sidebar/sidebar.go
index ad0531e2e16c673dad7003cba5a2416d4506e7b3..2e86f6a9750f858a10cbdba02cfcbaf439a1cdfa 100644
--- a/internal/tui/components/chat/sidebar/sidebar.go
+++ b/internal/tui/components/chat/sidebar/sidebar.go
@@ -10,8 +10,8 @@ import (
"github.com/charmbracelet/crush/internal/session"
"github.com/charmbracelet/crush/internal/tui/components/chat"
"github.com/charmbracelet/crush/internal/tui/components/core"
- "github.com/charmbracelet/crush/internal/tui/components/logo"
"github.com/charmbracelet/crush/internal/tui/components/core/layout"
+ "github.com/charmbracelet/crush/internal/tui/components/logo"
"github.com/charmbracelet/crush/internal/tui/styles"
"github.com/charmbracelet/crush/internal/tui/util"
"github.com/charmbracelet/crush/internal/version"
diff --git a/internal/tui/components/completions/item.go b/internal/tui/components/completions/item.go
index e26ef7f92dce616a25236379b17d9a8f18fc4c12..12e14b48edffddb2043c03da61c956bdac2ab242 100644
--- a/internal/tui/components/completions/item.go
+++ b/internal/tui/components/completions/item.go
@@ -4,8 +4,8 @@ import (
"image/color"
tea "github.com/charmbracelet/bubbletea/v2"
- "github.com/charmbracelet/crush/internal/tui/components/core/list"
"github.com/charmbracelet/crush/internal/tui/components/core/layout"
+ "github.com/charmbracelet/crush/internal/tui/components/core/list"
"github.com/charmbracelet/crush/internal/tui/styles"
"github.com/charmbracelet/crush/internal/tui/util"
"github.com/charmbracelet/lipgloss/v2"
diff --git a/internal/tui/components/completions/keys.go b/internal/tui/components/completions/keys.go
index c2f7a10d77b12439f18d6bf110c11debaa8b4ba7..fee3a0e574ab926cb4e80d02c0d9d19c0e614edd 100644
--- a/internal/tui/components/completions/keys.go
+++ b/internal/tui/components/completions/keys.go
@@ -2,7 +2,6 @@ package completions
import (
"github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
)
type KeyMap struct {
@@ -33,10 +32,20 @@ func DefaultKeyMap() KeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k KeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.Down,
+ k.Up,
+ k.Select,
+ k.Cancel,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k KeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])
diff --git a/internal/tui/components/core/layout/layout.go b/internal/tui/components/core/layout/layout.go
index 6c7ce4e11112423c0f3ab330e81cae8fb24e9908..6af2d5fa87776716a2d96446cd060adccbe83654 100644
--- a/internal/tui/components/core/layout/layout.go
+++ b/internal/tui/components/core/layout/layout.go
@@ -1,8 +1,6 @@
package layout
import (
- "reflect"
-
"github.com/charmbracelet/bubbles/v2/key"
tea "github.com/charmbracelet/bubbletea/v2"
)
@@ -26,14 +24,7 @@ type Positionable interface {
SetPosition(x, y int) tea.Cmd
}
-func KeyMapToSlice(t any) (bindings []key.Binding) {
- typ := reflect.TypeOf(t)
- if typ.Kind() != reflect.Struct {
- return nil
- }
- for i := range typ.NumField() {
- v := reflect.ValueOf(t).Field(i)
- bindings = append(bindings, v.Interface().(key.Binding))
- }
- return
+// KeyMapProvider defines an interface for types that can provide their key bindings as a slice
+type KeyMapProvider interface {
+ KeyBindings() []key.Binding
}
diff --git a/internal/tui/components/core/list/keys.go b/internal/tui/components/core/list/keys.go
index 2bc5cc737b8191c36062b1c676cfd6e368aa576d..4ad2a9e27807063609215f1f6c834872ceff2aac 100644
--- a/internal/tui/components/core/list/keys.go
+++ b/internal/tui/components/core/list/keys.go
@@ -51,3 +51,19 @@ func DefaultKeyMap() KeyMap {
),
}
}
+
+// KeyBindings implements layout.KeyMapProvider
+func (k KeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.Down,
+ k.Up,
+ k.NDown,
+ k.NUp,
+ k.DownOneItem,
+ k.UpOneItem,
+ k.HalfPageDown,
+ k.HalfPageUp,
+ k.Home,
+ k.End,
+ }
+}
diff --git a/internal/tui/components/dialogs/commands/item.go b/internal/tui/components/dialogs/commands/item.go
index 09c97e16ed930c21e81246573b453b061d12d78e..a89a884472cff75a0051d89b637ae4f55feba527 100644
--- a/internal/tui/components/dialogs/commands/item.go
+++ b/internal/tui/components/dialogs/commands/item.go
@@ -3,8 +3,8 @@ package commands
import (
tea "github.com/charmbracelet/bubbletea/v2"
"github.com/charmbracelet/crush/internal/tui/components/core"
- "github.com/charmbracelet/crush/internal/tui/components/core/list"
"github.com/charmbracelet/crush/internal/tui/components/core/layout"
+ "github.com/charmbracelet/crush/internal/tui/components/core/list"
"github.com/charmbracelet/crush/internal/tui/styles"
"github.com/charmbracelet/crush/internal/tui/util"
"github.com/charmbracelet/x/ansi"
diff --git a/internal/tui/components/dialogs/commands/keys.go b/internal/tui/components/dialogs/commands/keys.go
index 08420f56fd2b57aeaa407a4908bba2e83fc0e569..9685216817c02cdfaab682f94e0f89aa64af365f 100644
--- a/internal/tui/components/dialogs/commands/keys.go
+++ b/internal/tui/components/dialogs/commands/keys.go
@@ -2,7 +2,6 @@ package commands
import (
"github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
)
type CommandsDialogKeyMap struct {
@@ -38,10 +37,21 @@ func DefaultCommandsDialogKeyMap() CommandsDialogKeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k CommandsDialogKeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.Select,
+ k.Next,
+ k.Previous,
+ k.Tab,
+ k.Close,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k CommandsDialogKeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])
@@ -86,10 +96,19 @@ func DefaultArgumentsDialogKeyMap() ArgumentsDialogKeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k ArgumentsDialogKeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.Confirm,
+ k.Next,
+ k.Previous,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k ArgumentsDialogKeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])
diff --git a/internal/tui/components/dialogs/compact/keys.go b/internal/tui/components/dialogs/compact/keys.go
index 491b582388593ec33ef2584e503aa3677679c59d..c3dd98e13035085b7d46e7a2e94450b25a7f0d59 100644
--- a/internal/tui/components/dialogs/compact/keys.go
+++ b/internal/tui/components/dialogs/compact/keys.go
@@ -2,7 +2,6 @@ package compact
import (
"github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
)
// KeyMap defines the key bindings for the compact dialog.
@@ -40,10 +39,21 @@ func DefaultKeyMap() KeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k KeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.ChangeSelection,
+ k.Select,
+ k.Y,
+ k.N,
+ k.Close,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k KeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])
diff --git a/internal/tui/components/dialogs/filepicker/keys.go b/internal/tui/components/dialogs/filepicker/keys.go
index cc95915c675058e3728d2bd5d1228b638204b093..9f3b706e3cf677b66cbc3136a7b98a466470d949 100644
--- a/internal/tui/components/dialogs/filepicker/keys.go
+++ b/internal/tui/components/dialogs/filepicker/keys.go
@@ -2,7 +2,6 @@ package filepicker
import (
"github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
)
// KeyMap defines keyboard bindings for dialog management.
@@ -45,10 +44,22 @@ func DefaultKeyMap() KeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k KeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.Select,
+ k.Down,
+ k.Up,
+ k.Forward,
+ k.Backward,
+ k.Close,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k KeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])
diff --git a/internal/tui/components/dialogs/init/keys.go b/internal/tui/components/dialogs/init/keys.go
index 163b4869fb477ae34545ef169725b551cd05c6fd..afd82d45ea8b47630c2d5ed1450419ae8d4b4c19 100644
--- a/internal/tui/components/dialogs/init/keys.go
+++ b/internal/tui/components/dialogs/init/keys.go
@@ -2,7 +2,6 @@ package init
import (
"github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
)
type KeyMap struct {
@@ -38,10 +37,21 @@ func DefaultKeyMap() KeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k KeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.ChangeSelection,
+ k.Select,
+ k.Y,
+ k.N,
+ k.Close,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k KeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])
diff --git a/internal/tui/components/dialogs/keys.go b/internal/tui/components/dialogs/keys.go
index 027ed6e3a8ad86d2587061085623117a44016d01..c382b7e09e15de04efb5b2520bc490ef9d57b985 100644
--- a/internal/tui/components/dialogs/keys.go
+++ b/internal/tui/components/dialogs/keys.go
@@ -2,7 +2,6 @@ package dialogs
import (
"github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
)
// KeyMap defines keyboard bindings for dialog management.
@@ -18,10 +17,17 @@ func DefaultKeyMap() KeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k KeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.Close,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k KeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])
diff --git a/internal/tui/components/dialogs/models/keys.go b/internal/tui/components/dialogs/models/keys.go
index f17fdb95e366275660287a17a0df2ffc8e375355..f9c3c549c30c6d95282e88818c247ec80a2f0e4c 100644
--- a/internal/tui/components/dialogs/models/keys.go
+++ b/internal/tui/components/dialogs/models/keys.go
@@ -2,7 +2,6 @@ package models
import (
"github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
)
type KeyMap struct {
@@ -33,10 +32,20 @@ func DefaultKeyMap() KeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k KeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.Select,
+ k.Next,
+ k.Previous,
+ k.Close,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k KeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])
diff --git a/internal/tui/components/dialogs/permissions/keys.go b/internal/tui/components/dialogs/permissions/keys.go
index de4e595ac273e31be661cccec9d8053bf3c7a379..d626eecf9a819cfb209823f922f96dfb58ea3ca4 100644
--- a/internal/tui/components/dialogs/permissions/keys.go
+++ b/internal/tui/components/dialogs/permissions/keys.go
@@ -2,7 +2,6 @@ package permissions
import (
"github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
)
type KeyMap struct {
@@ -48,10 +47,23 @@ func DefaultKeyMap() KeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k KeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.Left,
+ k.Right,
+ k.Tab,
+ k.Select,
+ k.Allow,
+ k.AllowSession,
+ k.Deny,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k KeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])
diff --git a/internal/tui/components/dialogs/quit/keys.go b/internal/tui/components/dialogs/quit/keys.go
index 20421fb1c2709f515b31b57b2e984e76f02eb071..3268749b20c703ae1faf7640e253ce557f051c65 100644
--- a/internal/tui/components/dialogs/quit/keys.go
+++ b/internal/tui/components/dialogs/quit/keys.go
@@ -2,7 +2,6 @@ package quit
import (
"github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
)
// KeyMap defines the keyboard bindings for the quit dialog.
@@ -44,10 +43,22 @@ func DefaultKeymap() KeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k KeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.LeftRight,
+ k.EnterSpace,
+ k.Yes,
+ k.No,
+ k.Tab,
+ k.Close,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k KeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])
diff --git a/internal/tui/components/dialogs/sessions/keys.go b/internal/tui/components/dialogs/sessions/keys.go
index 1dfdf43f9e841f45cc4ec6d854117bad63a738ba..a3ca4b31f0c04c491fa7990f7e69ac546f608a7d 100644
--- a/internal/tui/components/dialogs/sessions/keys.go
+++ b/internal/tui/components/dialogs/sessions/keys.go
@@ -2,7 +2,6 @@ package sessions
import (
"github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
)
type KeyMap struct {
@@ -33,10 +32,20 @@ func DefaultKeyMap() KeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k KeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.Select,
+ k.Next,
+ k.Previous,
+ k.Close,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k KeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])
diff --git a/internal/tui/page/logs/keys.go b/internal/tui/page/logs/keys.go
index 7fc25bf4d399bd30946406bb9a7c7bc5b2747fd1..3c612b949183b4180494bdbb8224dd8eedbbb156 100644
--- a/internal/tui/page/logs/keys.go
+++ b/internal/tui/page/logs/keys.go
@@ -2,7 +2,6 @@ package logs
import (
"github.com/charmbracelet/bubbles/v2/key"
- "github.com/charmbracelet/crush/internal/tui/components/core/layout"
)
type KeyMap struct {
@@ -18,10 +17,17 @@ func DefaultKeyMap() KeyMap {
}
}
+// KeyBindings implements layout.KeyMapProvider
+func (k KeyMap) KeyBindings() []key.Binding {
+ return []key.Binding{
+ k.Back,
+ }
+}
+
// FullHelp implements help.KeyMap.
func (k KeyMap) FullHelp() [][]key.Binding {
m := [][]key.Binding{}
- slice := layout.KeyMapToSlice(k)
+ slice := k.KeyBindings()
for i := 0; i < len(slice); i += 4 {
end := min(i+4, len(slice))
m = append(m, slice[i:end])