Fix: avoid raw terminal after ctrl+c exit
This commit is contained in:
15
main.go
15
main.go
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/gdamore/tcell/v2"
|
||||||
"github.com/rivo/tview"
|
"github.com/rivo/tview"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,9 +20,23 @@ var (
|
|||||||
toolCollapsed = true
|
toolCollapsed = true
|
||||||
statusLineTempl = "help (F12) | chat: [orange:-:b]%s[-:-:-] (F1) | [%s:-:b]tool use[-:-:-] (ctrl+k) | model: [%s:-:b]%s[-:-:-] (ctrl+l) | [%s:-:b]skip LLM resp[-:-:-] (F10) | API: [orange:-:b]%s[-:-:-] (ctrl+v)\nwriting as: [orange:-:b]%s[-:-:-] (ctrl+q) | bot will write as [orange:-:b]%s[-:-:-] (ctrl+x)"
|
statusLineTempl = "help (F12) | chat: [orange:-:b]%s[-:-:-] (F1) | [%s:-:b]tool use[-:-:-] (ctrl+k) | model: [%s:-:b]%s[-:-:-] (ctrl+l) | [%s:-:b]skip LLM resp[-:-:-] (F10) | API: [orange:-:b]%s[-:-:-] (ctrl+v)\nwriting as: [orange:-:b]%s[-:-:-] (ctrl+q) | bot will write as [orange:-:b]%s[-:-:-] (ctrl+x)"
|
||||||
focusSwitcher = map[tview.Primitive]tview.Primitive{}
|
focusSwitcher = map[tview.Primitive]tview.Primitive{}
|
||||||
|
app *tview.Application
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||||
|
if event.Key() == tcell.KeyCtrlC {
|
||||||
|
logger.Info("caught Ctrl+C via tcell event")
|
||||||
|
go func() {
|
||||||
|
if err := pwShutDown(); err != nil {
|
||||||
|
logger.Error("shutdown failed", "err", err)
|
||||||
|
}
|
||||||
|
app.Stop()
|
||||||
|
}()
|
||||||
|
return nil // swallow the event
|
||||||
|
}
|
||||||
|
return event
|
||||||
|
})
|
||||||
pages.AddPage("main", flex, true, true)
|
pages.AddPage("main", flex, true, true)
|
||||||
if err := app.SetRoot(pages,
|
if err := app.SetRoot(pages,
|
||||||
true).EnableMouse(cfg.EnableMouse).EnablePaste(true).Run(); err != nil {
|
true).EnableMouse(cfg.EnableMouse).EnablePaste(true).Run(); err != nil {
|
||||||
|
|||||||
@@ -101,6 +101,14 @@ var (
|
|||||||
page playwright.Page
|
page playwright.Page
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func pwShutDown() error {
|
||||||
|
if pw == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
pwStop(nil)
|
||||||
|
return pw.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
func installPW() error {
|
func installPW() error {
|
||||||
err := playwright.Install(&playwright.RunOptions{Verbose: false})
|
err := playwright.Install(&playwright.RunOptions{Verbose: false})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
39
tui.go
39
tui.go
@@ -10,6 +10,7 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gdamore/tcell/v2"
|
"github.com/gdamore/tcell/v2"
|
||||||
"github.com/rivo/tview"
|
"github.com/rivo/tview"
|
||||||
@@ -21,7 +22,6 @@ func isFullScreenPageActive() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
app *tview.Application
|
|
||||||
pages *tview.Pages
|
pages *tview.Pages
|
||||||
textArea *tview.TextArea
|
textArea *tview.TextArea
|
||||||
editArea *tview.TextArea
|
editArea *tview.TextArea
|
||||||
@@ -137,6 +137,42 @@ func setShellMode(enabled bool) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// showToast displays a temporary message in the top‑right corner.
|
||||||
|
// It auto‑hides after 3 seconds and disappears when clicked.
|
||||||
|
func showToast(title, message string) {
|
||||||
|
// Create a small, bordered text view for the notification.
|
||||||
|
notification := tview.NewTextView().
|
||||||
|
SetTextAlign(tview.AlignCenter).
|
||||||
|
SetDynamicColors(true).
|
||||||
|
SetRegions(true).
|
||||||
|
SetText(fmt.Sprintf("[yellow]%s[-]\n", message)).
|
||||||
|
SetChangedFunc(func() {
|
||||||
|
app.Draw()
|
||||||
|
})
|
||||||
|
notification.SetTitleAlign(tview.AlignLeft).
|
||||||
|
SetBorder(true).
|
||||||
|
SetTitle(title)
|
||||||
|
// Wrap it in a full‑screen Flex to position it in the top‑right corner.
|
||||||
|
// Outer Flex (row) pushes content to the top; inner Flex (column) pushes to the right.
|
||||||
|
background := tview.NewFlex().SetDirection(tview.FlexRow).
|
||||||
|
AddItem(nil, 0, 1, false). // top spacer
|
||||||
|
AddItem(tview.NewFlex().SetDirection(tview.FlexColumn).
|
||||||
|
AddItem(nil, 0, 1, false). // left spacer
|
||||||
|
AddItem(notification, 40, 1, true), // notification width 40
|
||||||
|
5, 1, false) // notification height 5
|
||||||
|
// Generate a unique page name (e.g., using timestamp) to allow multiple toasts.
|
||||||
|
pageName := fmt.Sprintf("toast-%d", time.Now().UnixNano())
|
||||||
|
pages.AddPage(pageName, background, true, true)
|
||||||
|
// Auto‑dismiss after 3 seconds.
|
||||||
|
time.AfterFunc(3*time.Second, func() {
|
||||||
|
app.QueueUpdateDraw(func() {
|
||||||
|
if pages.HasPage(pageName) {
|
||||||
|
pages.RemovePage(pageName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Start background goroutine to update model color cache
|
// Start background goroutine to update model color cache
|
||||||
startModelColorUpdater()
|
startModelColorUpdater()
|
||||||
@@ -575,6 +611,7 @@ func init() {
|
|||||||
if scrollToEndEnabled {
|
if scrollToEndEnabled {
|
||||||
status = "enabled"
|
status = "enabled"
|
||||||
}
|
}
|
||||||
|
showToast("autoscroll", "Auto-scrolling "+status)
|
||||||
if err := notifyUser("autoscroll", "Auto-scrolling "+status); err != nil {
|
if err := notifyUser("autoscroll", "Auto-scrolling "+status); err != nil {
|
||||||
logger.Error("failed to send notification", "error", err)
|
logger.Error("failed to send notification", "error", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user