mirror of https://github.com/liamg/aminal.git
basic colour rendering
This commit is contained in:
parent
726bfe6531
commit
b0c60e7336
92
gui/cell.go
92
gui/cell.go
|
@ -2,29 +2,111 @@ package gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
v41 "github.com/4ydx/gltext/v4.1"
|
v41 "github.com/4ydx/gltext/v4.1"
|
||||||
|
"github.com/go-gl/gl/v4.1-core/gl"
|
||||||
"github.com/go-gl/mathgl/mgl32"
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Cell struct {
|
type Cell struct {
|
||||||
text *v41.Text
|
text *v41.Text
|
||||||
|
vao uint32
|
||||||
|
vbo uint32
|
||||||
|
cv uint32
|
||||||
|
colourAttr uint32
|
||||||
|
points []float32
|
||||||
|
colour [3]float32
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCell(font *v41.Font, x float32, y float32, w float32, h float32) Cell {
|
func (gui *GUI) NewCell(font *v41.Font, x float32, y float32, w float32, h float32, colourAttr uint32) Cell {
|
||||||
cell := Cell{
|
cell := Cell{
|
||||||
text: v41.NewText(font, 1.0, 1.1),
|
text: v41.NewText(font, 1.0, 1.1),
|
||||||
|
colourAttr: colourAttr,
|
||||||
}
|
}
|
||||||
|
|
||||||
cell.text.SetPosition(mgl32.Vec2{x, y})
|
cell.text.SetPosition(mgl32.Vec2{x, y})
|
||||||
|
|
||||||
|
x = (x - (w / 2)) / (float32(gui.width) / 2)
|
||||||
|
y = (y - (h / 2)) / (float32(gui.height) / 2)
|
||||||
|
w = (w / float32(gui.width/2))
|
||||||
|
h = (h / float32(gui.height/2))
|
||||||
|
cell.points = []float32{
|
||||||
|
x, y + h, 0,
|
||||||
|
x, y, 0,
|
||||||
|
x + w, y, 0,
|
||||||
|
x, y + h, 0,
|
||||||
|
x + w, y + h, 0,
|
||||||
|
x + w, y, 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.makeVao()
|
||||||
|
|
||||||
return cell
|
return cell
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cell *Cell) Draw() {
|
func (cell *Cell) SetFgColour(r, g, b float32) {
|
||||||
|
if cell.text != nil {
|
||||||
|
cell.text.SetColor(mgl32.Vec3{r, g, b})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cell *Cell) SetBgColour(r float32, g float32, b float32) {
|
||||||
|
|
||||||
|
if cell.colour[0] == r && cell.colour[1] == g && cell.colour[2] == b {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.colour = [3]float32{r, g, b}
|
||||||
|
cell.Clean()
|
||||||
|
cell.makeVao()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cell *Cell) Clean() {
|
||||||
|
gl.DeleteVertexArrays(1, &cell.vao)
|
||||||
|
gl.DeleteBuffers(1, &cell.vbo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cell *Cell) makeVao() {
|
||||||
|
|
||||||
|
gl.GenBuffers(1, &cell.vbo)
|
||||||
|
gl.BindBuffer(gl.ARRAY_BUFFER, cell.vbo)
|
||||||
|
gl.BufferData(gl.ARRAY_BUFFER, 4*len(cell.points), gl.Ptr(cell.points), gl.STATIC_DRAW)
|
||||||
|
|
||||||
|
gl.GenVertexArrays(1, &cell.vao)
|
||||||
|
gl.BindVertexArray(cell.vao)
|
||||||
|
gl.EnableVertexAttribArray(0)
|
||||||
|
gl.BindBuffer(gl.ARRAY_BUFFER, cell.vbo)
|
||||||
|
gl.VertexAttribPointer(0, 3, gl.FLOAT, false, 0, nil)
|
||||||
|
|
||||||
|
// COLOUR
|
||||||
|
gl.GenBuffers(1, &cell.cv)
|
||||||
|
gl.BindBuffer(gl.ARRAY_BUFFER, cell.cv)
|
||||||
|
triColor := []float32{
|
||||||
|
cell.colour[0], cell.colour[1], cell.colour[2],
|
||||||
|
cell.colour[0], cell.colour[1], cell.colour[2],
|
||||||
|
cell.colour[0], cell.colour[1], cell.colour[2],
|
||||||
|
cell.colour[0], cell.colour[1], cell.colour[2],
|
||||||
|
cell.colour[0], cell.colour[1], cell.colour[2],
|
||||||
|
cell.colour[0], cell.colour[1], cell.colour[2],
|
||||||
|
}
|
||||||
|
gl.BufferData(gl.ARRAY_BUFFER, len(triColor)*4, gl.Ptr(triColor), gl.STATIC_DRAW)
|
||||||
|
gl.EnableVertexAttribArray(cell.colourAttr)
|
||||||
|
gl.VertexAttribPointer(cell.colourAttr, 3, gl.FLOAT, false, 0, gl.PtrOffset(0))
|
||||||
|
|
||||||
|
// END COLOUR
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cell *Cell) DrawBg() {
|
||||||
|
gl.BindVertexArray(cell.vao)
|
||||||
|
gl.DrawArrays(gl.TRIANGLES, 0, 6)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cell *Cell) DrawText() {
|
||||||
|
|
||||||
if cell.text != nil {
|
if cell.text != nil {
|
||||||
cell.text.Draw()
|
cell.text.Draw()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cell *Cell) Show() {
|
func (cell *Cell) Show() {
|
||||||
|
@ -45,12 +127,6 @@ func (cell *Cell) SetRune(r rune) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cell *Cell) SetColour(r float32, g float32, b float32) {
|
|
||||||
if cell.text != nil {
|
|
||||||
cell.text.SetColor(mgl32.Vec3{r, g, b})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cell *Cell) Release() {
|
func (cell *Cell) Release() {
|
||||||
if cell.text != nil {
|
if cell.text != nil {
|
||||||
cell.text.Release()
|
cell.text.Release()
|
||||||
|
|
59
gui/gui.go
59
gui/gui.go
|
@ -31,7 +31,7 @@ type GUI struct {
|
||||||
cells [][]Cell
|
cells [][]Cell
|
||||||
cols int
|
cols int
|
||||||
rows int
|
rows int
|
||||||
capslock bool
|
colourAttr uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(config config.Config, terminal *terminal.Terminal, logger *zap.SugaredLogger) *GUI {
|
func New(config config.Config, terminal *terminal.Terminal, logger *zap.SugaredLogger) *GUI {
|
||||||
|
@ -63,7 +63,6 @@ func (gui *GUI) resize(w *glfw.Window, width int, height int) {
|
||||||
if gui.font != nil {
|
if gui.font != nil {
|
||||||
gui.font.ResizeWindow(float32(width), float32(height))
|
gui.font.ResizeWindow(float32(width), float32(height))
|
||||||
}
|
}
|
||||||
gl.Viewport(0, 0, int32(width), int32(height))
|
|
||||||
|
|
||||||
scaleMin, scaleMax := float32(1.0), float32(1.1)
|
scaleMin, scaleMax := float32(1.0), float32(1.1)
|
||||||
text := v41.NewText(gui.font, scaleMin, scaleMax)
|
text := v41.NewText(gui.font, scaleMin, scaleMax)
|
||||||
|
@ -105,18 +104,12 @@ func (gui *GUI) updateTexts() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsHidden() {
|
if c.IsHidden() {
|
||||||
|
|
||||||
gui.cells[row][col].Hide()
|
gui.cells[row][col].Hide()
|
||||||
|
|
||||||
// debug
|
|
||||||
//gui.texts[row][col].SetColor(c.GetColourVec())
|
|
||||||
//gui.texts[row][col].SetString("?")
|
|
||||||
//gui.texts[row][col].Show()
|
|
||||||
// end debug
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.cells[row][col].SetColour(c.GetColour())
|
gui.cells[row][col].SetFgColour(c.GetFgColour())
|
||||||
|
gui.cells[row][col].SetBgColour(c.GetBgColour())
|
||||||
gui.cells[row][col].SetRune(c.GetRune())
|
gui.cells[row][col].SetRune(c.GetRune())
|
||||||
gui.cells[row][col].Show()
|
gui.cells[row][col].Show()
|
||||||
|
|
||||||
|
@ -141,7 +134,7 @@ func (gui *GUI) createTexts() {
|
||||||
x := ((float32(col) * gui.charWidth) - (float32(gui.width) / 2)) + (gui.charWidth / 2)
|
x := ((float32(col) * gui.charWidth) - (float32(gui.width) / 2)) + (gui.charWidth / 2)
|
||||||
y := -(((float32(row) * gui.charHeight) - (float32(gui.height) / 2)) + (gui.charHeight / 2))
|
y := -(((float32(row) * gui.charHeight) - (float32(gui.height) / 2)) + (gui.charHeight / 2))
|
||||||
|
|
||||||
cells[row] = append(cells[row], NewCell(gui.font, x, y, gui.charWidth, gui.charHeight))
|
cells[row] = append(cells[row], gui.NewCell(gui.font, x, y, gui.charWidth, gui.charHeight, gui.colourAttr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,6 +144,10 @@ func (gui *GUI) createTexts() {
|
||||||
gui.updateTexts()
|
gui.updateTexts()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (gui *GUI) Close() {
|
||||||
|
gui.window.SetShouldClose(true)
|
||||||
|
}
|
||||||
|
|
||||||
func (gui *GUI) Render() error {
|
func (gui *GUI) Render() error {
|
||||||
|
|
||||||
gui.logger.Debugf("Locking OS thread...")
|
gui.logger.Debugf("Locking OS thread...")
|
||||||
|
@ -170,6 +167,9 @@ func (gui *GUI) Render() error {
|
||||||
return fmt.Errorf("Failed to initialise OpenGL: %s", err)
|
return fmt.Errorf("Failed to initialise OpenGL: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gui.colourAttr = uint32(gl.GetAttribLocation(program, gl.Str("inColour\x00")))
|
||||||
|
gl.BindFragDataLocation(program, 0, gl.Str("outColour\x00"))
|
||||||
|
|
||||||
gui.logger.Debugf("Loading font...")
|
gui.logger.Debugf("Loading font...")
|
||||||
//gui.font, err = gui.loadFont("/usr/share/fonts/nerd-fonts-complete/ttf/Roboto Mono Nerd Font Complete.ttf", 12)
|
//gui.font, err = gui.loadFont("/usr/share/fonts/nerd-fonts-complete/ttf/Roboto Mono Nerd Font Complete.ttf", 12)
|
||||||
if err := gui.loadFont("./fonts/CamingoCode-Regular.ttf", 12); err != nil {
|
if err := gui.loadFont("./fonts/CamingoCode-Regular.ttf", 12); err != nil {
|
||||||
|
@ -182,8 +182,6 @@ func (gui *GUI) Render() error {
|
||||||
w, h := gui.window.GetSize()
|
w, h := gui.window.GetSize()
|
||||||
gui.resize(gui.window, w, h)
|
gui.resize(gui.window, w, h)
|
||||||
|
|
||||||
gl.Viewport(0, 0, int32(gui.width), int32(gui.height))
|
|
||||||
|
|
||||||
gui.logger.Debugf("Starting pty read handling...")
|
gui.logger.Debugf("Starting pty read handling...")
|
||||||
|
|
||||||
updateChan := make(chan bool, 1024)
|
updateChan := make(chan bool, 1024)
|
||||||
|
@ -191,7 +189,13 @@ func (gui *GUI) Render() error {
|
||||||
gui.terminal.OnUpdate(func() {
|
gui.terminal.OnUpdate(func() {
|
||||||
updateChan <- true
|
updateChan <- true
|
||||||
})
|
})
|
||||||
go gui.terminal.Read()
|
go func() {
|
||||||
|
err := gui.terminal.Read()
|
||||||
|
if err != nil {
|
||||||
|
gui.logger.Errorf("Read from pty failed: %s", err)
|
||||||
|
}
|
||||||
|
gui.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
text := v41.NewText(gui.font, 1.0, 1.1)
|
text := v41.NewText(gui.font, 1.0, 1.1)
|
||||||
text.SetString("")
|
text.SetString("")
|
||||||
|
@ -209,6 +213,8 @@ func (gui *GUI) Render() error {
|
||||||
|
|
||||||
gui.logger.Debugf("Starting render...")
|
gui.logger.Debugf("Starting render...")
|
||||||
|
|
||||||
|
// todo set bg colour
|
||||||
|
//bgColour := gui.terminal.colourScheme.DefaultBgColor
|
||||||
gl.ClearColor(0.1, 0.1, 0.1, 1.0)
|
gl.ClearColor(0.1, 0.1, 0.1, 1.0)
|
||||||
|
|
||||||
for !gui.window.ShouldClose() {
|
for !gui.window.ShouldClose() {
|
||||||
|
@ -232,6 +238,8 @@ func (gui *GUI) Render() error {
|
||||||
|
|
||||||
if updateRequired {
|
if updateRequired {
|
||||||
|
|
||||||
|
gl.Viewport(0, 0, int32(gui.width), int32(gui.height))
|
||||||
|
|
||||||
gui.updateTexts()
|
gui.updateTexts()
|
||||||
|
|
||||||
// Render the string.
|
// Render the string.
|
||||||
|
@ -243,7 +251,14 @@ func (gui *GUI) Render() error {
|
||||||
|
|
||||||
for row := 0; row < rows; row++ {
|
for row := 0; row < rows; row++ {
|
||||||
for col := 0; col < cols; col++ {
|
for col := 0; col < cols; col++ {
|
||||||
gui.cells[row][col].Draw()
|
gui.cells[row][col].DrawBg()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for row := 0; row < rows; row++ {
|
||||||
|
for col := 0; col < cols; col++ {
|
||||||
|
|
||||||
|
gui.cells[row][col].DrawText()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +335,21 @@ func (gui *GUI) createProgram() (uint32, error) {
|
||||||
}
|
}
|
||||||
gui.logger.Infof("OpenGL version %s", gl.GoStr(gl.GetString(gl.VERSION)))
|
gui.logger.Infof("OpenGL version %s", gl.GoStr(gl.GetString(gl.VERSION)))
|
||||||
|
|
||||||
|
gui.logger.Debugf("Compiling shaders...")
|
||||||
|
|
||||||
|
vertexShader, err := compileShader(vertexShaderSource, gl.VERTEX_SHADER)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fragmentShader, err := compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
prog := gl.CreateProgram()
|
prog := gl.CreateProgram()
|
||||||
|
gl.AttachShader(prog, vertexShader)
|
||||||
|
gl.AttachShader(prog, fragmentShader)
|
||||||
gl.LinkProgram(prog)
|
gl.LinkProgram(prog)
|
||||||
|
|
||||||
return prog, nil
|
return prog, nil
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package gui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-gl/gl/v4.1-core/gl" // OR: github.com/go-gl/gl/v2.1/gl
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
vertexShaderSource = `
|
||||||
|
#version 410
|
||||||
|
in vec3 vp;
|
||||||
|
attribute vec3 inColour;
|
||||||
|
smooth out vec3 theColour;
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(vp, 1.0);
|
||||||
|
theColour = inColour;
|
||||||
|
}
|
||||||
|
` + "\x00"
|
||||||
|
|
||||||
|
fragmentShaderSource = `
|
||||||
|
#version 410
|
||||||
|
smooth in vec3 theColour;
|
||||||
|
out vec4 outColour;
|
||||||
|
void main() {
|
||||||
|
outColour = vec4(theColour, 1.0);
|
||||||
|
}
|
||||||
|
` + "\x00"
|
||||||
|
)
|
||||||
|
|
||||||
|
func compileShader(source string, shaderType uint32) (uint32, error) {
|
||||||
|
shader := gl.CreateShader(shaderType)
|
||||||
|
|
||||||
|
csources, free := gl.Strs(source)
|
||||||
|
gl.ShaderSource(shader, 1, csources, nil)
|
||||||
|
free()
|
||||||
|
gl.CompileShader(shader)
|
||||||
|
|
||||||
|
var status int32
|
||||||
|
gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status)
|
||||||
|
if status == gl.FALSE {
|
||||||
|
var logLength int32
|
||||||
|
gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &logLength)
|
||||||
|
|
||||||
|
log := strings.Repeat("\x00", int(logLength+1))
|
||||||
|
gl.GetShaderInfoLog(shader, logLength, nil, gl.Str(log))
|
||||||
|
|
||||||
|
return 0, fmt.Errorf("failed to compile %v: %v", source, log)
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader, nil
|
||||||
|
}
|
2
main.go
2
main.go
|
@ -37,7 +37,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
sugaredLogger.Infof("Creating terminal...")
|
sugaredLogger.Infof("Creating terminal...")
|
||||||
terminal := terminal.New(pty, sugaredLogger)
|
terminal := terminal.New(pty, sugaredLogger, terminal.DefaultColourScheme)
|
||||||
/*
|
/*
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
package terminal
|
package terminal
|
||||||
|
|
||||||
import "github.com/go-gl/mathgl/mgl32"
|
|
||||||
|
|
||||||
type Cell struct {
|
type Cell struct {
|
||||||
r rune
|
r rune
|
||||||
wrapper bool
|
attr CellAttributes
|
||||||
isWrapped bool
|
}
|
||||||
|
|
||||||
|
type CellAttributes struct {
|
||||||
|
FgColour [3]float32
|
||||||
|
BgColour [3]float32
|
||||||
|
Bold bool
|
||||||
|
Dim bool
|
||||||
|
Underline bool
|
||||||
|
Blink bool
|
||||||
|
Reverse bool
|
||||||
|
Hidden bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cell *Cell) GetRune() rune {
|
func (cell *Cell) GetRune() rune {
|
||||||
|
@ -13,28 +21,19 @@ func (cell *Cell) GetRune() rune {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cell *Cell) IsHidden() bool {
|
func (cell *Cell) IsHidden() bool {
|
||||||
return cell.r == 0
|
return cell.attr.Hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cell *Cell) GetColour() (r float32, g float32, b float32) {
|
func (cell *Cell) GetFgColour() (r float32, g float32, b float32) {
|
||||||
|
if cell.attr.Reverse {
|
||||||
if cell.wrapper {
|
return cell.attr.BgColour[0], cell.attr.BgColour[1], cell.attr.BgColour[2]
|
||||||
return 0, 1, 0
|
}
|
||||||
|
return cell.attr.FgColour[0], cell.attr.FgColour[1], cell.attr.FgColour[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
if cell.isWrapped {
|
func (cell *Cell) GetBgColour() (r float32, g float32, b float32) {
|
||||||
return 1, 1, 0
|
if cell.attr.Reverse {
|
||||||
|
return cell.attr.FgColour[0], cell.attr.FgColour[1], cell.attr.FgColour[2]
|
||||||
}
|
}
|
||||||
|
return cell.attr.BgColour[0], cell.attr.BgColour[1], cell.attr.BgColour[2]
|
||||||
if cell.IsHidden() {
|
|
||||||
return 0, 0, 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1, 1, 1
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cell *Cell) GetColourVec() mgl32.Vec3 {
|
|
||||||
r, g, b := cell.GetColour()
|
|
||||||
return mgl32.Vec3{r, g, b}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package terminal
|
||||||
|
|
||||||
|
type ColourScheme struct {
|
||||||
|
DefaultFg [3]float32
|
||||||
|
BlackFg [3]float32
|
||||||
|
RedFg [3]float32
|
||||||
|
GreenFg [3]float32
|
||||||
|
YellowFg [3]float32
|
||||||
|
BlueFg [3]float32
|
||||||
|
MagentaFg [3]float32
|
||||||
|
CyanFg [3]float32
|
||||||
|
LightGreyFg [3]float32
|
||||||
|
DarkGreyFg [3]float32
|
||||||
|
LightRedFg [3]float32
|
||||||
|
LightGreenFg [3]float32
|
||||||
|
LightYellowFg [3]float32
|
||||||
|
LightBlueFg [3]float32
|
||||||
|
LightMagentaFg [3]float32
|
||||||
|
LightCyanFg [3]float32
|
||||||
|
WhiteFg [3]float32
|
||||||
|
DefaultBg [3]float32
|
||||||
|
BlackBg [3]float32
|
||||||
|
RedBg [3]float32
|
||||||
|
GreenBg [3]float32
|
||||||
|
YellowBg [3]float32
|
||||||
|
BlueBg [3]float32
|
||||||
|
MagentaBg [3]float32
|
||||||
|
CyanBg [3]float32
|
||||||
|
LightGreyBg [3]float32
|
||||||
|
DarkGreyBg [3]float32
|
||||||
|
LightRedBg [3]float32
|
||||||
|
LightGreenBg [3]float32
|
||||||
|
LightYellowBg [3]float32
|
||||||
|
LightBlueBg [3]float32
|
||||||
|
LightMagentaBg [3]float32
|
||||||
|
LightCyanBg [3]float32
|
||||||
|
WhiteBg [3]float32
|
||||||
|
}
|
||||||
|
|
||||||
|
var DefaultColourScheme = ColourScheme{
|
||||||
|
//fg
|
||||||
|
DefaultFg: [3]float32{1, 1, 1},
|
||||||
|
BlackFg: [3]float32{0, 0, 0},
|
||||||
|
RedFg: [3]float32{1, 0, 0},
|
||||||
|
GreenFg: [3]float32{0, 1, 0},
|
||||||
|
YellowFg: [3]float32{1, 1, 0},
|
||||||
|
BlueFg: [3]float32{0, 0, 1},
|
||||||
|
MagentaFg: [3]float32{1, 0, 1},
|
||||||
|
CyanFg: [3]float32{0, 1, 1},
|
||||||
|
LightGreyFg: [3]float32{0.7, 0.7, 0.7},
|
||||||
|
DarkGreyFg: [3]float32{0.3, 0.3, 0.3},
|
||||||
|
LightRedFg: [3]float32{1, 0.5, 0.5},
|
||||||
|
LightGreenFg: [3]float32{0.5, 1, 0.5},
|
||||||
|
LightYellowFg: [3]float32{1, 1, 0.5},
|
||||||
|
LightBlueFg: [3]float32{0.5, 0.5, 1},
|
||||||
|
LightMagentaFg: [3]float32{1, 0.5, 1},
|
||||||
|
LightCyanFg: [3]float32{0.5, 1, 1},
|
||||||
|
WhiteFg: [3]float32{1, 1, 1},
|
||||||
|
// bg
|
||||||
|
DefaultBg: [3]float32{0.1, 0.1, 0.1},
|
||||||
|
BlackBg: [3]float32{0, 0, 0},
|
||||||
|
RedBg: [3]float32{1, 0, 0},
|
||||||
|
GreenBg: [3]float32{0, 1, 0},
|
||||||
|
YellowBg: [3]float32{1, 1, 0},
|
||||||
|
BlueBg: [3]float32{0, 0, 1},
|
||||||
|
MagentaBg: [3]float32{1, 0, 1},
|
||||||
|
CyanBg: [3]float32{0, 1, 1},
|
||||||
|
LightGreyBg: [3]float32{0.7, 0.7, 0.7},
|
||||||
|
DarkGreyBg: [3]float32{0.3, 0.3, 0.3},
|
||||||
|
LightRedBg: [3]float32{1, 0.5, 0.5},
|
||||||
|
LightGreenBg: [3]float32{0.5, 1, 0.5},
|
||||||
|
LightYellowBg: [3]float32{1, 1, 0.5},
|
||||||
|
LightBlueBg: [3]float32{0.5, 0.5, 1},
|
||||||
|
LightMagentaBg: [3]float32{1, 0.5, 1},
|
||||||
|
LightCyanBg: [3]float32{0.5, 1, 1},
|
||||||
|
WhiteBg: [3]float32{1, 1, 1},
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
@ -20,6 +21,9 @@ type Terminal struct {
|
||||||
title string
|
title string
|
||||||
onUpdate []func()
|
onUpdate []func()
|
||||||
size Winsize
|
size Winsize
|
||||||
|
colourScheme ColourScheme
|
||||||
|
cellAttr CellAttributes
|
||||||
|
defaultCellAttr CellAttributes
|
||||||
}
|
}
|
||||||
|
|
||||||
type Line struct {
|
type Line struct {
|
||||||
|
@ -84,7 +88,13 @@ type Position struct {
|
||||||
Col int
|
Col int
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(pty *os.File, logger *zap.SugaredLogger) *Terminal {
|
func New(pty *os.File, logger *zap.SugaredLogger, colourScheme ColourScheme) *Terminal {
|
||||||
|
|
||||||
|
defaultCellAttr := CellAttributes{
|
||||||
|
FgColour: colourScheme.DefaultFg,
|
||||||
|
BgColour: colourScheme.DefaultBg,
|
||||||
|
}
|
||||||
|
|
||||||
return &Terminal{
|
return &Terminal{
|
||||||
lines: []Line{
|
lines: []Line{
|
||||||
NewLine(),
|
NewLine(),
|
||||||
|
@ -92,6 +102,9 @@ func New(pty *os.File, logger *zap.SugaredLogger) *Terminal {
|
||||||
pty: pty,
|
pty: pty,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
onUpdate: []func(){},
|
onUpdate: []func(){},
|
||||||
|
cellAttr: defaultCellAttr,
|
||||||
|
defaultCellAttr: defaultCellAttr,
|
||||||
|
colourScheme: colourScheme,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,6 +238,42 @@ func (terminal *Terminal) Read() error {
|
||||||
}
|
}
|
||||||
case byte('m'):
|
case byte('m'):
|
||||||
// SGR: colour and shit
|
// SGR: colour and shit
|
||||||
|
sgr := string(params)
|
||||||
|
sgrParams := strings.Split(sgr, ";")
|
||||||
|
for i := range sgrParams {
|
||||||
|
param := sgrParams[i]
|
||||||
|
switch param {
|
||||||
|
case "0":
|
||||||
|
terminal.cellAttr = terminal.defaultCellAttr
|
||||||
|
case "1":
|
||||||
|
terminal.cellAttr.Bold = true
|
||||||
|
case "2":
|
||||||
|
terminal.cellAttr.Dim = true
|
||||||
|
case "4":
|
||||||
|
terminal.cellAttr.Underline = true
|
||||||
|
case "5":
|
||||||
|
terminal.cellAttr.Blink = true
|
||||||
|
case "7":
|
||||||
|
terminal.cellAttr.Reverse = true
|
||||||
|
case "8":
|
||||||
|
terminal.cellAttr.Hidden = true
|
||||||
|
case "21":
|
||||||
|
terminal.cellAttr.Bold = false
|
||||||
|
case "22":
|
||||||
|
terminal.cellAttr.Dim = false
|
||||||
|
case "24":
|
||||||
|
terminal.cellAttr.Underline = false
|
||||||
|
case "25":
|
||||||
|
terminal.cellAttr.Blink = false
|
||||||
|
case "27":
|
||||||
|
terminal.cellAttr.Reverse = false
|
||||||
|
case "28":
|
||||||
|
terminal.cellAttr.Hidden = false
|
||||||
|
case "39":
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
terminal.logger.Debugf("SGR params %#v intermediate %#v", params, intermediate)
|
||||||
default:
|
default:
|
||||||
b = <-buffer
|
b = <-buffer
|
||||||
terminal.logger.Debugf("Unknown CSI control sequence: 0x%02X (%s)", final, string([]byte{final}))
|
terminal.logger.Debugf("Unknown CSI control sequence: 0x%02X (%s)", final, string([]byte{final}))
|
||||||
|
@ -251,6 +300,8 @@ func (terminal *Terminal) Read() error {
|
||||||
default:
|
default:
|
||||||
terminal.logger.Debugf("Unknown OSC control sequence: 0x%02X", b)
|
terminal.logger.Debugf("Unknown OSC control sequence: 0x%02X", b)
|
||||||
}
|
}
|
||||||
|
case byte('c'):
|
||||||
|
terminal.logger.Errorf("RIS not yet supported")
|
||||||
default:
|
default:
|
||||||
terminal.logger.Debugf("Unknown control sequence: 0x%02X", b)
|
terminal.logger.Debugf("Unknown control sequence: 0x%02X", b)
|
||||||
}
|
}
|
||||||
|
@ -285,6 +336,7 @@ func (terminal *Terminal) Read() error {
|
||||||
n, err := terminal.pty.Read(readBytes)
|
n, err := terminal.pty.Read(readBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
terminal.logger.Errorf("Failed to read from pty: %s", err)
|
terminal.logger.Errorf("Failed to read from pty: %s", err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
if len(readBytes) > 0 {
|
if len(readBytes) > 0 {
|
||||||
readBytes = readBytes[:n]
|
readBytes = readBytes[:n]
|
||||||
|
@ -355,6 +407,7 @@ func (terminal *Terminal) setRuneAtPos(pos Position, r rune) error {
|
||||||
line.Cells = append(line.Cells, Cell{})
|
line.Cells = append(line.Cells, Cell{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
line.Cells[pos.Col].attr = terminal.cellAttr
|
||||||
line.Cells[pos.Col].r = r
|
line.Cells[pos.Col].r = r
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue