finally starting to clean up the init() process

This commit is contained in:
Jeff Carr 2025-02-13 14:11:52 -06:00
parent fa9ec36dbb
commit c5472a42a2
6 changed files with 127 additions and 117 deletions

View File

@ -4,6 +4,7 @@
package main
import (
"fmt"
"syscall"
"time"
@ -16,6 +17,12 @@ import (
// tells 'gocui' where to send events
func registerHandlers(g *gocui.Gui) {
defer func() {
if r := recover(); r != nil {
fmt.Fprintln(outf, "EVENT BINDINGS recovered in r", r)
return
}
}()
// mouse handlers
g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, mouseDown) // normal left mouse down
@ -56,8 +63,15 @@ func registerHandlers(g *gocui.Gui) {
g.SetKeybinding("", 'q', gocui.ModNone, quit) // 'q' only exits gocui. plugin stays alive (?)
time.Sleep(100 * time.Millisecond)
fmt.Fprintln(outf, "hello world", time.Since(me.starttime))
// coreStdout()
// createStdout(g)
// tell 'tree' that we are okay to start talking to
me.myTree.InitOK()
me.ok = true // this tells init() it's okay to work with gocui
}
// flips on 'super mouse' mode // this was awesome for debugging gocui. never remove this code.

View File

@ -23,8 +23,6 @@ import (
// this function uses the mouse position to highlight & unhighlight things
// this is run every time the user moves the mouse over the terminal window
func mouseMove(g *gocui.Gui) {
me.ok = true // this tells init() it's okay to work with gocui
// this runs while the user moves the mouse. this highlights text
// toggle off all highlight views except for whatever is under the mouse
// START HIGHLIGHTING

View File

@ -131,6 +131,15 @@ func setThingsOnTop() {
me.baseGui.SetViewOnTop(me.clock.tk.v.Name())
}
if me.stdout.tk == nil {
makeOutputWidget(me.baseGui, "from setThingsOnTop()")
}
if me.stdout.tk == nil {
return
}
if me.stdout.tk.v == nil {
return
}
if me.dark {
me.stdout.tk.v.FgColor = gocui.ColorWhite
me.stdout.tk.v.BgColor = gocui.ColorBlack

174
init.go
View File

@ -9,6 +9,7 @@ package main
import (
"errors"
"fmt"
"os"
"runtime"
"runtime/debug"
@ -31,6 +32,21 @@ func toolkitClose() {
// sets defaults and establishes communication
// to this toolkit from the wit/gui golang package
func initPlugin() {
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(outf, "PANIC: initPlugin() recovered %v\n", r)
return
}
}()
var err error
// todo: make this a tmp file that goes away
outf, err = os.OpenFile("/tmp/captureMode.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Info("error opening file:", err)
os.Exit(0)
}
me.starttime = time.Now()
log.Log(INFO, "Init() of awesome-gocui")
// init the config struct default values
@ -86,16 +102,59 @@ func initPlugin() {
}
log.Log(NOW, "Init() start pluginChan")
// log.Sleep(.1) // probably not needed, but in here for now under development
go mainGogui()
// log.Sleep(.1) // probably not needed, but in here for now under development
os.Stdout = outf
log.CaptureMode(outf)
// init gocui
g, err := gocui.NewGui(gocui.OutputNormal, true)
if err != nil {
return
}
me.baseGui = g
g.Cursor = true
g.Mouse = true
// this sets the function that is run on every event. For example:
// When you click the mouse, move the mouse, or press a key on the keyboard
// This is equivalent to xev or similar to cat /dev/input on linux
g.SetManagerFunc(gocuiEvent)
// register how the 'gocui' will work as a GO toolkit plugin
// all applications will use these keys. they are universal.
// registered event handlers still have the events sent to gocuiEvent() above
registerHandlers(g)
go gocuiMain()
}
// This goroutine sits in gocui's MainLoop()
func gocuiMain() {
defer func() {
if r := recover(); r != nil {
log.Warn("PANIC ecovered in gocuiMain()", r)
fmt.Fprintf(outf, "PANIC recovered in r = %v", r)
os.Stderr = outf
os.Stdout = outf
debug.PrintStack()
panic(outf)
}
}()
// me.stdout.Write([]byte("begin gogui.MainLoop()\n"))
if err := me.baseGui.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
log.Log(NOW, "g.MainLoop() panic err =", err)
// normally panic here
panic("gocuiTKmainloop OOPS")
}
}
func standardExit() {
log.Log(NOW, "standardExit() doing baseGui.Close()")
me.baseGui.Close()
log.Log(NOW, "standardExit() doing outf.Close()")
me.outf.Close()
outf.Close()
// log(true, "standardExit() setOutput(os.Stdout)")
// setOutput(os.Stdout)
log.Log(NOW, "standardExit() send back Quit()")
@ -110,7 +169,7 @@ func standardClose() {
log.Log(NOW, "standardExit() doing baseGui.Close()")
me.baseGui.Close()
log.Log(NOW, "standardExit() doing outf.Close()")
me.outf.Close()
outf.Close()
// os.Stdin = os.Stdin
// os.Stdout = os.Stdout
// os.Stderr = os.Stderr
@ -120,101 +179,15 @@ func standardClose() {
func main() {
}
var origStdout *os.File
var origStderr *os.File
func mainGogui() {
defer func() {
if r := recover(); r != nil {
log.Warn("YAHOOOO Recovered in guiMain application:", r)
log.Warn("Recovered from panic:", r)
me.baseGui.Close()
log.CaptureMode(nil)
log.Warn("YAHOOOO Recovered in guiMain application:", r)
log.Warn("Recovered from panic:", r)
me.myTree.SendToolkitPanic()
return
}
}()
var err error
// todo: make this a tmp file that goes away
me.outf, err = os.OpenFile("/tmp/captureMode.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Info("error opening file:", err)
os.Exit(0)
}
origStdout = os.Stdout
os.Stdout = me.outf
defer me.outf.Close()
log.CaptureMode(me.outf)
gocuiMain()
}
// This initializes the gocui package
// it runs SetManagerFunc which passes every input
// event (keyboard, mouse, etc) to the function "gocuiEvent()"
func gocuiMain() {
defer func() {
if r := recover(); r != nil {
log.Warn("YAHOOOO Recovered in gocuiMain()", r)
log.Warn("Recovered from panic:", r)
me.baseGui.Close()
// allow gocui to close if possible, then print stack
log.Sleep(1)
os.Stdout = origStdout
os.Stderr = origStderr
me.myTree.SendToolkitPanic()
log.Warn("Stack trace:")
debug.PrintStack()
// panic("BUMMER 2")
// attempt to switch to the nocui toolkit
log.Sleep(1)
me.myTree.SendToolkitLoad("nocui")
log.Sleep(3)
me.myTree.SendToolkitLoad("nocui")
// panic("BUMMER")
return
}
}()
g, err := gocui.NewGui(gocui.OutputNormal, true)
if err != nil {
return
}
defer g.Close()
me.baseGui = g
g.Cursor = true
g.Mouse = true
// this sets the function that is run on every event. For example:
// When you click the mouse, move the mouse, or press a key on the keyboard
// This is equivalent to xev or similar to cat /dev/input on linux
g.SetManagerFunc(gocuiEvent)
// register how the 'gocui' will work as a GO toolkit plugin
// all applications will use these keys. they are universal.
// registered event handlers still have the events sent to gocuiEvent() above
registerHandlers(g)
// me.stdout.Write([]byte("begin gogui.MainLoop()\n"))
if err := g.MainLoop(); err != nil && !errors.Is(err, gocui.ErrQuit) {
log.Log(NOW, "g.MainLoop() panic err =", err)
// normally panic here
panic("gocuiTKmainloop OOPS")
}
}
// this hack is to wait for the application to send something
// before trying to do anything. todo: rethink this someday
func waitOK() {
defer func() {
if r := recover(); r != nil {
fmt.Fprintln(outf, "INIT PLUGIN recovered in r", r)
return
}
}()
for {
if me.ok {
return
@ -231,6 +204,12 @@ func testRefresh(*gocui.Gui) error {
// refresh the screen 10 times a second
func refreshGocui() {
defer func() {
if r := recover(); r != nil {
fmt.Fprintln(outf, "INIT PLUGIN recovered in r", r)
return
}
}()
var lastRefresh time.Time
lastRefresh = time.Now()
for {
@ -286,6 +265,7 @@ func newWindowTrigger() {
// log.Log(NOW, "newWindowTrigger() got new window", tk.cuiName)
time.Sleep(200 * time.Millisecond)
waitOK()
time.Sleep(200 * time.Millisecond)
redoWindows(3, 3)
if !me.stdout.init {
me.stdout.init = true

View File

@ -32,28 +32,36 @@ func createStdout(g *gocui.Gui) bool {
return true
}
func coreStdout() {
if me.stdout.tk != nil {
return
}
a := new(widget.Action)
a.ProgName = "2stdout2"
a.WidgetType = widget.Stdout
a.WidgetId = me.stdout.wId
a.ParentId = 0
// n := addNode(a)
n := me.myTree.AddNode(a)
me.stdout.tk = initWidget(n)
tk := me.stdout.tk
tk.gocuiSize.w0 = me.stdout.lastW
tk.gocuiSize.h0 = me.stdout.lastH
tk.gocuiSize.w1 = tk.gocuiSize.w0 + me.stdout.w
tk.gocuiSize.h1 = tk.gocuiSize.h0 + me.stdout.h
}
func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View {
if me.treeRoot == nil {
// keep skipping this until the binary tree is initialized
return nil
}
coreStdout()
if me.stdout.tk == nil {
a := new(widget.Action)
a.ProgName = "2stdout2"
a.WidgetType = widget.Stdout
a.WidgetId = me.stdout.wId
a.ParentId = 0
// n := addNode(a)
n := me.myTree.AddNode(a)
me.stdout.tk = initWidget(n)
tk := me.stdout.tk
tk.gocuiSize.w0 = me.stdout.lastW
tk.gocuiSize.h0 = me.stdout.lastH
tk.gocuiSize.w1 = tk.gocuiSize.w0 + me.stdout.w
tk.gocuiSize.h1 = tk.gocuiSize.h0 + me.stdout.h
return nil
}
v, err := g.View("msg")
@ -61,6 +69,7 @@ func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View {
log.Log(NOW, "makeoutputwindow() this is supposed to happen. v == nil", err)
} else {
log.Log(NOW, "makeoutputwindow() msg != nil. WTF now? err =", err)
return v
}
rect := me.stdout.tk.gocuiSize

View File

@ -22,7 +22,8 @@ import (
"go.wit.com/toolkits/tree"
)
var initOnce sync.Once
var initOnce sync.Once // run initPlugin() only once
var outf *os.File // hacks for capturing stdout
// It's probably a terrible idea to call this 'me'
// 2025 note: doesn't seem terrible to call this 'me' anymore. notsure.
@ -77,8 +78,7 @@ type config struct {
mouse mouse // mouse settings
showDebug bool // todo: move this into config struct
debug bool // todo: move this into config struct
outf *os.File // hacks for capturing stdout
starttime time.Time // checks how long it takes on startup
}
// stuff controlling how the mouse works