make stdout upside down

This commit is contained in:
Jeff Carr 2025-02-06 16:19:36 -06:00
parent 5bae8b7e41
commit e134ecb6a4
4 changed files with 78 additions and 50 deletions

View File

@ -20,9 +20,11 @@ import (
func registerHandlers(g *gocui.Gui) {
// mouse handlers
g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, mouseDown) // normal left mouse down
g.SetKeybinding("", gocui.MouseLeft, gocui.ModMouseCtrl, ctrlDown) // mouse with the ctrl key held down
g.SetKeybinding("", gocui.MouseRelease, gocui.ModNone, mouseUp) // mouse button release
g.SetKeybinding("", gocui.MouseLeft, gocui.ModNone, mouseDown) // normal left mouse down
g.SetKeybinding("", gocui.MouseLeft, gocui.ModMouseCtrl, ctrlDown) // mouse with the ctrl key held down
g.SetKeybinding("", gocui.MouseRelease, gocui.ModNone, mouseUp) // mouse button release
g.SetKeybinding("", gocui.MouseWheelUp, gocui.ModNone, wheelsUp) // mouse button release
g.SetKeybinding("", gocui.MouseWheelDown, gocui.ModNone, wheelsDown) // mouse button release
// Ctrl key handlers
g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, doExit) // CTRL-C : exits the application
@ -36,6 +38,8 @@ func registerHandlers(g *gocui.Gui) {
g.SetKeybinding("", 'O', gocui.ModNone, theStdout) // 'o' toggle the STDOUT window
g.SetKeybinding("", 'q', gocui.ModNone, doExit) // 'q' exit
g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, tabCycleWindows) // '2' use this to test new ideas
g.SetKeybinding("", gocui.KeyPgup, gocui.ModNone, stdoutPgup) // Pgup scroll up the Stdout buffer
g.SetKeybinding("", gocui.KeyPgdn, gocui.ModNone, stdoutPgdn) // Pgdn scroll down the Stdout buffer
// debugging
g.SetKeybinding("", '2', gocui.ModNone, theNotsure) // '2' use this to test new ideas
@ -95,7 +99,26 @@ func addDropdown() *tree.Node {
// use this to test code ideas // put whatever you want here and hit '2' to activate it
func theNotsure(g *gocui.Gui, v *gocui.View) error {
log.Info("got keypress 2. now what?")
log.Info("try to switch windows here")
return nil
}
func stdoutPgup(g *gocui.Gui, v *gocui.View) error {
log.Info("try to page up in the stdout buffer here")
return nil
}
func stdoutPgdn(g *gocui.Gui, v *gocui.View) error {
log.Info("try to page down in the stdout buffer here")
return nil
}
func wheelsUp(g *gocui.Gui, v *gocui.View) error {
log.Info("private wheels up")
return nil
}
func wheelsDown(g *gocui.Gui, v *gocui.View) error {
log.Info("you've landed")
return nil
}

2
log.go
View File

@ -11,8 +11,6 @@ import (
"go.wit.com/log"
)
var outputS []string
var NOW *log.LogFlag
var INFO *log.LogFlag
var GOCUI *log.LogFlag

View File

@ -6,6 +6,8 @@ package main
import (
"errors"
"fmt"
"slices"
"strings"
"github.com/awesome-gocui/gocui"
@ -126,3 +128,50 @@ func (tk *guiWidget) relocateStdout(w int, h int) {
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
}

View File

@ -12,7 +12,6 @@ import (
"fmt"
"reflect"
"strconv"
"strings"
"sync"
"github.com/awesome-gocui/gocui"
@ -88,6 +87,8 @@ type stdout struct {
mouseOffsetH int // the current 'h' offset
init bool // moves the window offscreen on startup
resize bool // user is resizing the window
outputS []string // the buffer of all the output
}
// settings for the dropdown window
@ -166,49 +167,6 @@ type guiWidget struct {
isBG bool // means this is the background widget. There is only one of these
}
// 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()
// _, outputH := w.Size()
outputH := 33 // special output length for "msg" window until I figure things out
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
tk.v.Clear()
s := fmt.Sprint(string(p))
s = strings.TrimSuffix(s, "\n")
tmp := strings.Split(s, "\n")
outputS = append(outputS, tmp...)
if len(outputS) > outputH {
l := len(outputS) - outputH
outputS = outputS[l:]
}
fmt.Fprintln(tk.v, strings.Join(outputS, "\n"))
}
return len(p), nil
}
// THIS IS GO COMPILER MAGIC
// this sets the `default` in the structs above on init()
// this is cool code. thank the GO devs for this code and Alex Flint for explaining it to me