// Copyright 2017-2025 WIT.COM Inc. All rights reserved. // Use of this source code is governed by the GPL 3.0 package main import ( "errors" "fmt" "slices" "strings" "github.com/awesome-gocui/gocui" "go.wit.com/log" "go.wit.com/widget" ) func showMsg(g *gocui.Gui, v *gocui.View) error { var l string var err error log.Log(NOW, "showMsg() v.name =", v.Name()) if _, err := g.SetCurrentView(v.Name()); err != nil { return err } _, cy := v.Cursor() if l, err = v.Line(cy); err != nil { l = "" } outv := makeOutputWidget(g, l) outv.Write([]byte("test out2")) log.Info("test out2") return nil } func makeOutputWidget(g *gocui.Gui, stringFromMouseClick string) *gocui.View { if me.treeRoot == nil { // keep skipping this until the binary tree is initialized return nil } if me.stdout.tk == nil { a := new(widget.Action) a.ProgName = "2stdout2" a.WidgetType = widget.Stdout a.WidgetId = -3 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 } v, err := g.View("msg") if v == nil { log.Log(NOW, "makeoutputwindow() this is supposed to happen. v == nil", err) } else { log.Log(NOW, "makeoutputwindow() msg != nil. WTF now? err =", err) } rect := me.stdout.tk.gocuiSize v, err = g.SetView("msg", rect.w0, rect.h0, rect.w1, rect.h1, 0) if errors.Is(err, gocui.ErrUnknownView) { log.Log(NOW, "makeoutputwindow() this is supposed to happen?", err) } if err != nil { log.Log(NOW, "makeoutputwindow() create output window failed", err) return nil } if v == nil { log.Log(NOW, "makeoutputwindow() msg == nil. WTF now? err =", err) return nil } else { me.stdout.tk.v = v } v.Clear() v.SelBgColor = gocui.ColorCyan v.SelFgColor = gocui.ColorBlack fmt.Fprintln(v, "figure out how to capture STDOUT to here\n"+stringFromMouseClick) // g.SetViewOnBottom("msg") // setBottomBG() me.stdout.tk.v = v me.stdout.tk.DrawAt(me.stdout.lastW, me.stdout.lastH) relocateStdoutOffscreen() return v } func relocateStdoutOffscreen() { if me.stdout.tk == nil { return } log.CaptureMode(me.stdout.tk) log.Log(ERROR, "setting log.CaptureMode(tk.v) in relocateStdoutOffscreen()") newW := 10 newH := 0 - me.stdout.h - 4 me.stdout.tk.relocateStdout(newW, newH) } func (tk *guiWidget) relocateStdout(w int, h int) { w0 := w h0 := h w1 := w + me.stdout.w h1 := h + me.stdout.h tk.gocuiSize.w0 = w0 tk.gocuiSize.w1 = w1 tk.gocuiSize.h0 = h0 tk.gocuiSize.h1 = h1 tk.full.w0 = w0 tk.full.w1 = w1 tk.full.h0 = h0 tk.full.h1 = h1 me.baseGui.SetView("msg", w0, h0, w1, h1, 0) // me.baseGui.SetViewOnBottom("msg") } // from the gocui devs: // Write appends a byte slice into the view's internal buffer. Because // View implements the io.Writer interface, it can be passed as parameter // of functions like fmt.Fprintf, fmt.Fprintln, io.Copy, etc. Clear must // be called to clear the view's buffer. func (w *guiWidget) Write(p []byte) (n int, err error) { w.tainted = true me.writeMutex.Lock() defer me.writeMutex.Unlock() tk := me.stdout.tk if tk.v == nil { // optionally write the output to /tmp s := fmt.Sprint(string(p)) s = strings.TrimSuffix(s, "\n") fmt.Fprintln(outf, s) v, _ := me.baseGui.View("msg") if v != nil { // fmt.Fprintln(outf, "found msg") tk.v = v } } else { // display the output in the gocui window lines := strings.Split(strings.TrimSpace(string(p)), "\n") me.stdout.outputS = append(me.stdout.outputS, lines...) var cur []string // chop off the last lines in the buffer chop := len(me.stdout.outputS) - (me.stdout.h - 1) if chop < 0 { chop = 0 } if len(me.stdout.outputS) > chop { cur = append(cur, me.stdout.outputS[chop:]...) } else { cur = append(cur, me.stdout.outputS...) } slices.Reverse(cur) tk.v.Clear() fmt.Fprintln(tk.v, strings.Join(cur, "\n")) } return len(p), nil } // lets the user page up and down through the stdout buffer func (tk *guiWidget) refreshStdout() { if len(me.stdout.outputS) < me.stdout.h+me.stdout.pager { log.Info(fmt.Sprintf("buffer too small=%d len(%d)", me.stdout.pager, len(me.stdout.outputS))) return } var cur []string // chop off the last lines in the buffer chop := len(me.stdout.outputS) - (me.stdout.pager + me.stdout.h) cur = append(cur, me.stdout.outputS[chop:chop+me.stdout.h]...) slices.Reverse(cur) tk.v.Clear() fmt.Fprintln(tk.v, strings.Join(cur, "\n")) }