Enha: tool role index for shellmode

This commit is contained in:
Grail Finder
2026-02-27 08:07:55 +03:00
parent a0ff384b81
commit 0d94734090
3 changed files with 6 additions and 97 deletions

View File

@@ -452,11 +452,12 @@ func updateFlexLayout() {
} }
// Keep focus on currently focused widget // Keep focus on currently focused widget
focused := app.GetFocus() focused := app.GetFocus()
if focused == textView { switch {
case focused == textView:
app.SetFocus(textView) app.SetFocus(textView)
} else if shellMode { case shellMode:
app.SetFocus(shellInput) app.SetFocus(shellInput)
} else { default:
app.SetFocus(textArea) app.SetFocus(textArea)
} }
} }
@@ -483,7 +484,8 @@ func executeCommandAndDisplay(cmdText string) {
// Execute the command and get output // Execute the command and get output
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
// Add the command being executed to the chat // Add the command being executed to the chat
fmt.Fprintf(textView, "\n[yellow]$ %s[-:-:-]\n", cmdText) fmt.Fprintf(textView, "\n[-:-:b](%d) <%s>: [-:-:-]\n$ %s\n",
len(chatBody.Messages), cfg.ToolRole, cmdText)
var outputContent string var outputContent string
if err != nil { if err != nil {
// Include both output and error // Include both output and error

View File

@@ -343,68 +343,6 @@ func showBotRoleSelectionPopup() {
app.SetFocus(roleListWidget) app.SetFocus(roleListWidget)
} }
func showFileCompletionPopup(filter string) {
baseDir := cfg.FilePickerDir
if baseDir == "" {
baseDir = "."
}
complMatches := scanFiles(baseDir, filter)
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)
for _, m := range complMatches {
widget.AddItem(m, "", 0, nil)
}
widget.SetSelectedFunc(func(index int, mainText string, secondaryText string, shortcut rune) {
currentText := textArea.GetText()
atIdx := strings.LastIndex(currentText, "@")
if atIdx >= 0 {
before := currentText[:atIdx]
textArea.SetText(before+mainText, true)
}
pages.RemovePage("fileCompletionPopup")
app.SetFocus(textArea)
})
widget.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyEscape {
pages.RemovePage("fileCompletionPopup")
app.SetFocus(textArea)
return nil
}
if event.Key() == tcell.KeyRune && event.Rune() == 'x' {
pages.RemovePage("fileCompletionPopup")
app.SetFocus(textArea)
return nil
}
return event
})
modal := func(p tview.Primitive, width, height int) tview.Primitive {
return tview.NewFlex().
AddItem(nil, 0, 1, false).
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
AddItem(nil, 0, 1, false).
AddItem(p, height, 1, true).
AddItem(nil, 0, 1, false), width, 1, true).
AddItem(nil, 0, 1, false)
}
// Add modal page and make it visible
pages.AddPage("fileCompletionPopup", modal(widget, 80, 20), true, true)
app.SetFocus(widget)
}
func showShellFileCompletionPopup(filter string) { func showShellFileCompletionPopup(filter string) {
baseDir := cfg.FilePickerDir baseDir := cfg.FilePickerDir
if baseDir == "" { if baseDir == "" {

31
tui.go
View File

@@ -197,37 +197,6 @@ func init() {
textArea = tview.NewTextArea(). textArea = tview.NewTextArea().
SetPlaceholder("input is multiline; press <Enter> to start the next line;\npress <Esc> to send the message.") SetPlaceholder("input is multiline; press <Enter> to start the next line;\npress <Esc> to send the message.")
textArea.SetBorder(true).SetTitle("input") textArea.SetBorder(true).SetTitle("input")
// Add input capture for @ completion
textArea.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
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(). textView = tview.NewTextView().
SetDynamicColors(true). SetDynamicColors(true).
SetRegions(true). SetRegions(true).