diff --git a/internal/cops/display/terminal.go b/internal/cops/display/terminal.go index 3937b91..cfef86b 100644 --- a/internal/cops/display/terminal.go +++ b/internal/cops/display/terminal.go @@ -2,6 +2,7 @@ package display import ( "io" + "log" "os" "github.com/borkshop/bork/internal/cops/terminal" @@ -11,22 +12,22 @@ import ( type Terminal struct { *Display - out *os.File - term terminal.Terminal - model ColorModel - buf []byte - cur Cursor + ColorModel ColorModel + out *os.File + term terminal.Terminal + buf []byte + cur Cursor } // NewTerminal takes control of a terminal, readying it for rendering by // putting it in raw mode, clearing it, and hiding the cursor. func NewTerminal(out *os.File) (*Terminal, error) { term := &Terminal{ - out: out, - term: terminal.New(out.Fd()), - model: Model24, // TODO #choices - buf: make([]byte, 0, 65536), - cur: Start, + out: out, + term: terminal.New(out.Fd()), + ColorModel: Model24, // TODO #choices + buf: make([]byte, 0, 65536), + cur: Start, } return term, term.open() } @@ -74,10 +75,12 @@ func (term *Terminal) flush() error { } attempts := 5 // TODO sanity check: is this even worthwhile? n, err := term.out.Write(term.buf) + log.Printf("display.Terminal flushed %q", term.buf[:n]) for attempts > 1 && err == io.ErrShortWrite { attempts-- term.buf = term.buf[:copy(term.buf, term.buf[n:])] n, err = term.out.Write(term.buf) + log.Printf("display.Terminal flushed %q", term.buf[:n]) } term.buf = term.buf[:0] return err @@ -96,7 +99,7 @@ func (term *Terminal) UpdateSize() error { } func (term Terminal) fullRender(cur Cursor, buf []byte) ([]byte, Cursor) { - return Render(buf, cur, term.Display, term.model) + return Render(buf, cur, term.Display, term.ColorModel) } // Render the display buffer to the terminal. diff --git a/proofs/testpattern/main.go b/proofs/testpattern/main.go new file mode 100644 index 0000000..d7609c6 --- /dev/null +++ b/proofs/testpattern/main.go @@ -0,0 +1,148 @@ +package main + +import ( + "fmt" + "image/color" + "log" + "os" + "os/signal" + "strconv" + "syscall" + + "github.com/borkshop/bork/internal/cops/display" + "github.com/borkshop/bork/internal/input" +) + +func colorGB(x, y int) (f, b color.RGBA) { + f.A = 0xff + b.A = 0xff + f.G += uint8(y) + b.B += uint8(x) + return f, b +} + +func colorEights(x, y int) (f, b color.RGBA) { + return display.Colors[y%8], display.Colors[x%8] +} + +type xyColorFunc func(x, y int) (f, b color.RGBA) + +func fgOnly(cf xyColorFunc) xyColorFunc { + return func(x, y int) (f, b color.RGBA) { + f, _ = cf(x, y) + b = display.Colors[0] + return f, b + } +} + +func bgOnly(cf xyColorFunc) xyColorFunc { + return func(x, y int) (f, b color.RGBA) { + _, b = cf(x, y) + f = display.Colors[7] + return f, b + } +} + +func run() (rerr error) { + f, err := os.Create("debug.log") + if err != nil { + return err + } + log.SetOutput(f) + + term, err := display.NewTerminal(os.Stdout) + if err != nil { + return err + } + defer func() { + if cerr := term.Close(); rerr == nil { + rerr = cerr + } + }() + + commands, mute := input.Channel(os.Stdin) + defer mute() + + sigwinch := make(chan os.Signal) + signal.Notify(sigwinch, syscall.SIGWINCH) + + var colorFunc xyColorFunc = colorGB + + for { + sz := term.Display.Rect.Size() + for y := 0; y < sz.Y; y++ { + for x := 0; x < sz.X; x++ { + t := strconv.Itoa(y % 10) + f, b := colorFunc(x, y) + term.Display.SetRGBA(x, y, t, f, b) + // term.Display.Set(x, y, t, nil, nil) + } + } + + if err := term.Render(); err != nil { + return err + } + + select { + case <-sigwinch: + if err := term.UpdateSize(); err != nil { + return err + } + log.Printf("display resized to %v", term.Bounds()) + + case command := <-commands: + switch c := command.(type) { + case rune: + switch c { + case 'q': + colorFunc = colorEights + log.Printf("using colorFunc = colorEights") + case 'w': + colorFunc = colorGB + log.Printf("using colorFunc = colorGB") + case 'a': + colorFunc = fgOnly(colorEights) + log.Printf("using colorFunc = fgOnly(colorEights)") + case 's': + colorFunc = fgOnly(colorGB) + log.Printf("using colorFunc = fgOnly(colorGB)") + case 'z': + colorFunc = bgOnly(colorEights) + log.Printf("using colorFunc = bgOnly(colorEights)") + case 'x': + colorFunc = bgOnly(colorGB) + log.Printf("using colorFunc = bgOnly(colorGB)") + + case '1': + term.ColorModel = display.Model0 + log.Printf("using ColorModel = Model0") + case '2': + term.ColorModel = display.Model3 + log.Printf("using ColorModel = Model3") + case '3': + term.ColorModel = display.Model4 + log.Printf("using ColorModel = Model4") + case '4': + term.ColorModel = display.Model8 + log.Printf("using ColorModel = Model8") + case '5': + term.ColorModel = display.Model24 + log.Printf("using ColorModel = Model24") + case '6': + term.ColorModel = display.ModelCompat24 + log.Printf("using ColorModel = ModelCompat24") + + case '', '': + return nil + } + } + } + + } +} + +func main() { + if err := run(); err != nil { + fmt.Printf("%v\n", err) + } +}