diff options
| -rw-r--r-- | popups.go | 37 | ||||
| -rw-r--r-- | tui.go | 36 |
2 files changed, 69 insertions, 4 deletions
@@ -70,6 +70,10 @@ func showModelSelectionPopup() { pages.RemovePage("modelSelectionPopup") return nil } + if event.Key() == tcell.KeyRune && event.Rune() == 'x' { + pages.RemovePage("modelSelectionPopup") + return nil + } return event }) modal := func(p tview.Primitive, width, height int) tview.Primitive { @@ -163,6 +167,10 @@ func showAPILinkSelectionPopup() { pages.RemovePage("apiLinkSelectionPopup") return nil } + if event.Key() == tcell.KeyRune && event.Rune() == 'x' { + pages.RemovePage("apiLinkSelectionPopup") + return nil + } return event }) modal := func(p tview.Primitive, width, height int) tview.Primitive { @@ -229,6 +237,10 @@ func showUserRoleSelectionPopup() { pages.RemovePage("userRoleSelectionPopup") return nil } + if event.Key() == tcell.KeyRune && event.Rune() == 'x' { + pages.RemovePage("userRoleSelectionPopup") + return nil + } return event }) modal := func(p tview.Primitive, width, height int) tview.Primitive { @@ -297,6 +309,10 @@ func showBotRoleSelectionPopup() { pages.RemovePage("botRoleSelectionPopup") return nil } + if event.Key() == tcell.KeyRune && event.Rune() == 'x' { + pages.RemovePage("botRoleSelectionPopup") + return nil + } return event }) modal := func(p tview.Primitive, width, height int) tview.Primitive { @@ -322,6 +338,16 @@ func showFileCompletionPopup(filter string) { if len(complMatches) == 0 { return } + // If only one match, auto-complete without showing popup + if len(complMatches) == 1 { + currentText := textArea.GetText() + atIdx := strings.LastIndex(currentText, "@") + if atIdx >= 0 { + before := currentText[:atIdx] + textArea.SetText(before+complMatches[0], true) + } + return + } widget := tview.NewList().ShowSecondaryText(false). SetSelectedBackgroundColor(tcell.ColorGray) widget.SetTitle("file completion").SetBorder(true) @@ -337,6 +363,17 @@ func showFileCompletionPopup(filter string) { } pages.RemovePage("fileCompletionPopup") }) + widget.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + if event.Key() == tcell.KeyEscape { + pages.RemovePage("fileCompletionPopup") + return nil + } + if event.Key() == tcell.KeyRune && event.Rune() == 'x' { + pages.RemovePage("fileCompletionPopup") + return nil + } + return event + }) modal := func(p tview.Primitive, width, height int) tview.Primitive { return tview.NewFlex(). AddItem(nil, 0, 1, false). @@ -74,8 +74,6 @@ var ( [yellow]Ctrl+c[white]: close programm [yellow]Ctrl+n[white]: start a new chat [yellow]Ctrl+o[white]: open image file picker -[yellow]@[white]: file completion (type @ in input to get file suggestions) -[yellow]c[white]: (in file picker) set current dir as CodingDir [yellow]Ctrl+p[white]: props edit form (min-p, dry, etc.) [yellow]Ctrl+v[white]: show API link selection popup to choose current API [yellow]Ctrl+r[white]: start/stop recording from your microphone (needs stt server or whisper binary) @@ -109,6 +107,13 @@ var ( === tables (chat history, agent pick, file pick, properties) === [yellow]x[white]: to exit the table page +=== filepicker === +[yellow]c[white]: (in file picker) set current dir as CodingDir +[yellow]x[white]: to exit + +=== shell mode === +[yellow]@match->Tab[white]: file completion (type @ in input to get file suggestions) + === status line === %s @@ -179,10 +184,33 @@ func init() { textArea.SetBorder(true).SetTitle("input") // Add input capture for @ completion textArea.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { - if shellMode && event.Key() == tcell.KeyRune && event.Rune() == '@' { - showFileCompletionPopup("") + if !shellMode { return event } + // Handle Tab key for file completion + if event.Key() == tcell.KeyTab { + currentText := textArea.GetText() + row, col, _, _ := textArea.GetCursor() + // Calculate absolute position from row/col + lines := strings.Split(currentText, "\n") + cursorPos := 0 + for i := 0; i < row && i < len(lines); i++ { + cursorPos += len(lines[i]) + 1 // +1 for newline + } + cursorPos += col + // Look backwards from cursor to find @ + if cursorPos > 0 { + // Find the last @ before cursor + textBeforeCursor := currentText[:cursorPos] + atIndex := strings.LastIndex(textBeforeCursor, "@") + if atIndex >= 0 { + // Extract the partial match text after @ + filter := textBeforeCursor[atIndex+1:] + showFileCompletionPopup(filter) + return nil // Consume the Tab event + } + } + } return event }) textView = tview.NewTextView(). |
