diff --git a/cellbuf/buffer.go b/cellbuf/buffer.go index 804064a0..845687d9 100644 --- a/cellbuf/buffer.go +++ b/cellbuf/buffer.go @@ -35,8 +35,8 @@ func (b *Buffer) Cell(x, y int) (Cell, bool) { return b.cells[idx], true } -// SetCell sets the cell at the given x, y position. -func (b *Buffer) SetCell(x, y int, c Cell) (v bool) { +// Draw sets the cell at the given x, y position. +func (b *Buffer) Draw(x, y int, c Cell) (v bool) { if b.width == 0 { return } @@ -55,7 +55,7 @@ func (b *Buffer) SetCell(x, y int, c Cell) (v bool) { prev := b.cells[idx] if prev.Width > 1 { // Writing to the first wide cell - for j := 0; j < prev.Width; j++ { + for j := 0; j < prev.Width && idx+j < len(b.cells); j++ { newCell := prev newCell.Content = " " newCell.Width = 1 @@ -82,7 +82,7 @@ func (b *Buffer) SetCell(x, y int, c Cell) (v bool) { // Mark wide cells with emptyCell zero width // We set the wide cell down below if c.Width > 1 { - for j := 1; j < c.Width; j++ { + for j := 1; j < c.Width && idx+j < len(b.cells); j++ { b.cells[idx+j] = emptyCell } } @@ -116,3 +116,39 @@ func (b *Buffer) Resize(width, height int) { b.cells = b.cells[:area] } } + +// Bounds returns the bounds of the buffer. +func (b *Buffer) Bounds() Rectangle { + return Rect(0, 0, b.Width(), b.Height()) +} + +// Fill fills the buffer with the given cell. If rect is not nil, it fills the +// rectangle with the cell. Otherwise, it fills the whole buffer. +func (b *Buffer) Fill(c Cell, rect *Rectangle) { + Fill(b, c, rect) +} + +// Clear clears the buffer with space cells. If rect is not nil, it clears the +// rectangle. Otherwise, it clears the whole buffer. +func (b *Buffer) Clear(rect *Rectangle) { + Clear(b, rect) +} + +// Paint writes the given data to the buffer. If rect is not nil, it writes the +// data within the rectangle. Otherwise, it writes the data to the whole +// buffer. +func (b *Buffer) Paint(m Method, data string, rect *Rectangle) []int { + return Paint(b, m, data, rect) +} + +// Render returns a string representation of the buffer with ANSI escape +// sequences. +func (b *Buffer) Render(opts ...RenderOption) string { + return Render(b, opts...) +} + +// RenderLine returns a string representation of the yth line of the buffer along +// with the width of the line. +func (b *Buffer) RenderLine(n int, opts ...RenderOption) (w int, line string) { + return RenderLine(b, n, opts...) +} diff --git a/cellbuf/geom.go b/cellbuf/geom.go new file mode 100644 index 00000000..86bd5b78 --- /dev/null +++ b/cellbuf/geom.go @@ -0,0 +1,44 @@ +package cellbuf + +import ( + "fmt" + "image" +) + +// Position represents an x, y position. +type Position image.Point + +// String returns a string representation of the position. +func (p Position) String() string { + return image.Point(p).String() +} + +// Pos is a shorthand for Position{X: x, Y: y}. +func Pos(x, y int) Position { + return Position{X: x, Y: y} +} + +// Rectange represents a rectangle. +type Rectangle struct { + X, Y, Width, Height int +} + +// String returns a string representation of the rectangle. +func (r Rectangle) String() string { + return fmt.Sprintf("(%d,%d)-(%d,%d)", r.X, r.Y, r.X+r.Width, r.Y+r.Height) +} + +// Bounds returns the rectangle as an image.Rectangle. +func (r Rectangle) Bounds() image.Rectangle { + return image.Rect(r.X, r.Y, r.X+r.Width, r.Y+r.Height) +} + +// Contains reports whether the rectangle contains the given point. +func (r Rectangle) Contains(p Position) bool { + return image.Point(p).In(r.Bounds()) +} + +// Rect is a shorthand for Rectangle. +func Rect(x, y, w, h int) Rectangle { + return Rectangle{X: x, Y: y, Width: w, Height: h} +} diff --git a/cellbuf/go.mod b/cellbuf/go.mod index 6d7b8203..fa1619bc 100644 --- a/cellbuf/go.mod +++ b/cellbuf/go.mod @@ -13,6 +13,7 @@ require ( github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.19.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect ) diff --git a/cellbuf/go.sum b/cellbuf/go.sum index c8e5f764..c7e809a2 100644 --- a/cellbuf/go.sum +++ b/cellbuf/go.sum @@ -12,8 +12,6 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= -golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= diff --git a/cellbuf/screen.go b/cellbuf/screen.go index 9b2ea1a2..257cacde 100644 --- a/cellbuf/screen.go +++ b/cellbuf/screen.go @@ -12,8 +12,7 @@ import ( // attributes and hyperlink. type Segment = Cell -// Screen represents an interface for a grid of cells that can be written to -// and read from. +// Screen represents a screen grid of cells. type Screen interface { // Width returns the width of the grid. Width() int @@ -21,34 +20,49 @@ type Screen interface { // Height returns the height of the grid. Height() int - // SetCell writes a cell to the grid at the given position. It returns true - // if the cell was written successfully. - SetCell(x, y int, c Cell) bool - // Cell returns the cell at the given position. Cell(x, y int) (Cell, bool) - // Resize resizes the grid to the given width and height. - Resize(width, height int) + // Draw writes a cell to the grid at the given position. It returns true if + // the cell was written successfully. + Draw(x, y int, c Cell) bool } -// SetContent writes the given data to the grid starting from the first cell. -func SetContent(d Screen, m Method, content string) []int { - return setContent(d, content, m) +// Paint writes the given data to the canvas. If rect is not nil, it only +// writes to the rectangle. Otherwise, it writes to the whole canvas. +func Paint(d Screen, m Method, content string, rect *Rectangle) []int { + if rect == nil { + rect = &Rectangle{0, 0, d.Width(), d.Height()} + } + return setContent(d, content, m, *rect) } -// Render returns a string representation of the grid with ANSI escape sequences. -func Render(d Screen) string { - return RenderWithProfile(d, colorprofile.TrueColor) +// RenderOptions represents options for rendering a canvas. +type RenderOptions struct { + // Profile is the color profile to use when rendering the canvas. + Profile colorprofile.Profile +} + +// RenderOption is a function that configures a RenderOptions. +type RenderOption func(*RenderOptions) + +// WithRenderProfile sets the color profile to use when rendering the canvas. +func WithRenderProfile(p colorprofile.Profile) RenderOption { + return func(o *RenderOptions) { + o.Profile = p + } } -// RenderWithProfile returns a string representation of the grid with ANSI escape -// sequences converting styles and colors to the given color profile. -func RenderWithProfile(d Screen, p colorprofile.Profile) string { +// Render returns a string representation of the grid with ANSI escape sequences. +func Render(d Screen, opts ...RenderOption) string { + var opt RenderOptions + for _, o := range opts { + o(&opt) + } var buf bytes.Buffer height := d.Height() for y := 0; y < height; y++ { - _, line := RenderLineWithProfile(d, y, p) + _, line := renderLine(d, y, opt) buf.WriteString(line) if y < height-1 { buf.WriteString("\r\n") @@ -59,14 +73,15 @@ func RenderWithProfile(d Screen, p colorprofile.Profile) string { // RenderLine returns a string representation of the yth line of the grid along // with the width of the line. -func RenderLine(d Screen, n int) (w int, line string) { - return RenderLineWithProfile(d, n, colorprofile.TrueColor) +func RenderLine(d Screen, n int, opts ...RenderOption) (w int, line string) { + var opt RenderOptions + for _, o := range opts { + o(&opt) + } + return renderLine(d, n, opt) } -// RenderLineWithProfile returns a string representation of the nth line of the -// grid along with the width of the line converting styles and colors to the -// given color profile. -func RenderLineWithProfile(d Screen, n int, p colorprofile.Profile) (w int, line string) { +func renderLine(d Screen, n int, opt RenderOptions) (w int, line string) { var pen Style var link Link var buf bytes.Buffer @@ -87,8 +102,8 @@ func RenderLineWithProfile(d Screen, n int, p colorprofile.Profile) (w int, line for x := 0; x < d.Width(); x++ { if cell, ok := d.Cell(x, n); ok && cell.Width > 0 { // Convert the cell's style and link to the given color profile. - cellStyle := cell.Style.Convert(p) - cellLink := cell.Link.Convert(p) + cellStyle := cell.Style.Convert(opt.Profile) + cellLink := cell.Link.Convert(opt.Profile) if cellStyle.Empty() && !pen.Empty() { writePending() buf.WriteString(ansi.ResetStyle) //nolint:errcheck @@ -134,15 +149,26 @@ func RenderLineWithProfile(d Screen, n int, p colorprofile.Profile) (w int, line return w, strings.TrimRight(buf.String(), " ") // Trim trailing spaces } -// Fill fills the grid with the given cell. -func Fill(d Screen, c Cell) { - for y := 0; y < d.Height(); y++ { - for x := 0; x < d.Width(); x++ { - d.SetCell(x, y, c) //nolint:errcheck +// Fill fills the canvas with the given cell. If rect is not nil, it only fills +// the rectangle. Otherwise, it fills the whole canvas. +func Fill(d Screen, c Cell, rect *Rectangle) { + if rect == nil { + rect = &Rectangle{0, 0, d.Width(), d.Height()} + } + + for y := rect.Y; y < rect.Y+rect.Height; y++ { + for x := rect.X; x < rect.X+rect.Width; x += c.Width { + d.Draw(x, y, c) //nolint:errcheck } } } +// Clear clears the canvas with space cells. If rect is not nil, it only clears +// the rectangle. Otherwise, it clears the whole canvas. +func Clear(d Screen, rect *Rectangle) { + Fill(d, spaceCell, rect) +} + // Equal returns whether two grids are equal. func Equal(a, b Screen) bool { if a.Width() != b.Width() || a.Height() != b.Height() { diff --git a/cellbuf/screen_write.go b/cellbuf/screen_write.go index a2765b55..371ea5df 100644 --- a/cellbuf/screen_write.go +++ b/cellbuf/screen_write.go @@ -12,14 +12,15 @@ import ( // setContent writes the given data to the buffer starting from the first cell. // It accepts both string and []byte data types. func setContent( - dis Screen, + d Screen, data string, method Method, + rect Rectangle, ) []int { var cell Cell var pen Style var link Link - var x, y int + x, y := rect.X, rect.Y p := ansi.GetParser() defer ansi.PutParser(p) @@ -28,7 +29,7 @@ func setContent( // linew is a slice of line widths. We use this to keep track of the // written widths of each line. We use this information later to optimize // rendering of the buffer. - linew := make([]int, dis.Height()) + linew := make([]int, rect.Height) var pendingWidth int @@ -52,18 +53,22 @@ func setContent( } fallthrough case 1: + if x >= rect.X+rect.Width || y >= rect.Y+rect.Height { + break + } + cell.Content = seq cell.Width = width cell.Style = pen cell.Link = link - dis.SetCell(x, y, cell) //nolint:errcheck + d.Draw(x, y, cell) //nolint:errcheck // Advance the cursor and line width x += cell.Width if cell.Equal(spaceCell) { pendingWidth += cell.Width - } else if y < len(linew) { + } else if y := y - rect.Y; y < len(linew) { linew[y] += cell.Width + pendingWidth pendingWidth = 0 } @@ -84,8 +89,8 @@ func setContent( } case ansi.Equal(seq, "\n"): // Reset the rest of the line - for x < dis.Width() { - dis.SetCell(x, y, spaceCell) //nolint:errcheck + for x < rect.X+rect.Width { + d.Draw(x, y, spaceCell) //nolint:errcheck x++ } @@ -102,8 +107,8 @@ func setContent( data = data[n:] } - for x < dis.Width() { - dis.SetCell(x, y, spaceCell) //nolint:errcheck + for x < rect.X+rect.Width { + d.Draw(x, y, spaceCell) //nolint:errcheck x++ } diff --git a/colors/go.mod b/colors/go.mod index 019dc6aa..df301d7a 100644 --- a/colors/go.mod +++ b/colors/go.mod @@ -9,8 +9,7 @@ require ( github.com/charmbracelet/x/ansi v0.4.2 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/muesli/termenv v0.15.2 // indirect + github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect github.com/rivo/uniseg v0.4.7 // indirect - golang.org/x/sys v0.26.0 // indirect + golang.org/x/sys v0.27.0 // indirect ) diff --git a/colors/go.sum b/colors/go.sum index f1cf47aa..aed14c12 100644 --- a/colors/go.sum +++ b/colors/go.sum @@ -8,13 +8,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= -github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= -github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= diff --git a/examples/cellbuf/main.go b/examples/cellbuf/main.go new file mode 100644 index 00000000..c19e8ec1 --- /dev/null +++ b/examples/cellbuf/main.go @@ -0,0 +1,93 @@ +package main + +import ( + "log" + "os" + "runtime" + + "github.com/charmbracelet/x/ansi" + "github.com/charmbracelet/x/cellbuf" + "github.com/charmbracelet/x/input" + "github.com/charmbracelet/x/term" +) + +func main() { + w, h, err := term.GetSize(os.Stdout.Fd()) + if err != nil { + log.Fatalf("getting terminal size: %v", err) + } + + state, err := term.MakeRaw(os.Stdin.Fd()) + if err != nil { + log.Fatalf("making raw: %v", err) + } + + defer term.Restore(os.Stdin.Fd(), state) + + drv, err := input.NewDriver(os.Stdin, os.Getenv("TERM"), 0) + if err != nil { + log.Fatalf("creating input driver: %v", err) + } + + os.Stdout.WriteString(ansi.EnableAltScreenBuffer + ansi.EnableMouseCellMotion + ansi.EnableMouseSgrExt) + defer os.Stdout.WriteString(ansi.DisableMouseSgrExt + ansi.DisableMouseCellMotion + ansi.DisableAltScreenBuffer) + + var buf cellbuf.Buffer + var style cellbuf.Style + style.Reverse(true) + x, y := (w/2)-8, h/2 + buf.Resize(w, h) + + reset(&buf, x, y) + + if runtime.GOOS != "windows" { + // Listen for resize events + go listenForResize(func() { + updateWinsize(&buf) + reset(&buf, x, y) + }) + } + + for { + evs, err := drv.ReadEvents() + if err != nil { + log.Fatalf("reading events: %v", err) + } + + for _, ev := range evs { + switch ev := ev.(type) { + case input.WindowSizeEvent: + updateWinsize(&buf) + case input.MouseClickEvent: + x, y = ev.X, ev.Y + case input.KeyPressEvent: + switch ev.String() { + case "ctrl+c", "q": + return + case "left": + x-- + case "down": + y++ + case "up": + y-- + case "right": + x++ + } + } + } + + reset(&buf, x, y) + } +} + +func reset(buf *cellbuf.Buffer, x, y int) { + buf.Fill(cellbuf.Cell{Content: "你", Width: 2}, nil) + buf.Paint(0, "\x1b[7m !Hello, world! \x1b[m", &cellbuf.Rectangle{X: x, Y: y, Width: 16, Height: 1}) + os.Stdout.WriteString(ansi.SetCursorPosition(1, 1) + buf.Render()) +} + +func updateWinsize(buf *cellbuf.Buffer) (w, h int) { + w, h, _ = term.GetSize(os.Stdout.Fd()) + buf.Resize(w, h) + return +} diff --git a/examples/cellbuf/winsize_other.go b/examples/cellbuf/winsize_other.go new file mode 100644 index 00000000..c4977cd3 --- /dev/null +++ b/examples/cellbuf/winsize_other.go @@ -0,0 +1,19 @@ +//go:build !windows +// +build !windows + +package main + +import ( + "os" + "os/signal" + "syscall" +) + +func listenForResize(fn func()) { + sig := make(chan os.Signal, 1) + signal.Notify(sig, syscall.SIGWINCH) + + for range sig { + fn() + } +} diff --git a/examples/cellbuf/winsize_windows.go b/examples/cellbuf/winsize_windows.go new file mode 100644 index 00000000..41536f83 --- /dev/null +++ b/examples/cellbuf/winsize_windows.go @@ -0,0 +1,6 @@ +//go:build windows +// +build windows + +package main + +func listenForResize(func()) {} diff --git a/examples/go.mod b/examples/go.mod index c8b3f6cf..f21abdf7 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -2,12 +2,32 @@ module examples go 1.18 -require github.com/charmbracelet/x/ansi v0.1.4 - -require github.com/rivo/uniseg v0.4.7 // indirect +require ( + github.com/charmbracelet/x/ansi v0.4.5 + github.com/charmbracelet/x/cellbuf v0.0.5 + github.com/charmbracelet/x/input v0.2.0 +) + +require ( + github.com/charmbracelet/colorprofile v0.1.7 // indirect + github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect +) + +require ( + github.com/charmbracelet/x/term v0.2.0 + github.com/charmbracelet/x/wcwidth v0.0.0-20241011142426-46044092ad91 // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect +) replace github.com/charmbracelet/x/ansi => ../ansi +replace github.com/charmbracelet/x/cellbuf => ../cellbuf + replace github.com/charmbracelet/x/term => ../term replace github.com/charmbracelet/x/input => ../input diff --git a/examples/go.sum b/examples/go.sum index 9008848b..b348f37a 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -1,2 +1,17 @@ +github.com/charmbracelet/colorprofile v0.1.7 h1:q7PtMQrRBBnLNE2EbtbNUtouu979EivKcDGGaimhyO8= +github.com/charmbracelet/x/wcwidth v0.0.0-20241011142426-46044092ad91 h1:D5OO0lVavz7A+Swdhp62F9gbkibxmz9B2hZ/jVdMPf0= +github.com/charmbracelet/x/wcwidth v0.0.0-20241011142426-46044092ad91/go.mod h1:Ey8PFmYwH+/td9bpiEx07Fdx9ZVkxfIjWXxBluxF4Nw= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= diff --git a/exp/teatest/go.mod b/exp/teatest/go.mod index 0d7cd6cd..33e5cddc 100644 --- a/exp/teatest/go.mod +++ b/exp/teatest/go.mod @@ -10,8 +10,8 @@ require ( require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-udiff v0.2.0 // indirect - github.com/charmbracelet/lipgloss v0.13.0 // indirect - github.com/charmbracelet/x/ansi v0.4.0 // indirect + github.com/charmbracelet/lipgloss v1.0.0 // indirect + github.com/charmbracelet/x/ansi v0.4.2 // indirect github.com/charmbracelet/x/term v0.2.0 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect @@ -20,9 +20,9 @@ require ( github.com/mattn/go-runewidth v0.0.16 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect - github.com/muesli/termenv v0.15.2 // indirect + github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect github.com/rivo/uniseg v0.4.7 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.19.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect ) diff --git a/exp/teatest/go.sum b/exp/teatest/go.sum index b5efe2d1..e83afa31 100644 --- a/exp/teatest/go.sum +++ b/exp/teatest/go.sum @@ -4,10 +4,8 @@ github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWp github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/charmbracelet/bubbletea v1.1.2 h1:naQXF2laRxyLyil/i7fxdpiz1/k06IKquhm4vBfHsIc= github.com/charmbracelet/bubbletea v1.1.2/go.mod h1:9HIU/hBV24qKjlehyj8z1r/tR9TYTQEag+cWZnuXo8E= -github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= -github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= -github.com/charmbracelet/x/ansi v0.4.0 h1:NqwHA4B23VwsDn4H3VcNX1W1tOmgnvY1NDx5tOXdnOU= -github.com/charmbracelet/x/ansi v0.4.0/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg= +github.com/charmbracelet/x/ansi v0.4.2 h1:0JM6Aj/g/KC154/gOP4vfxun0ff6itogDYk41kof+qk= github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30= github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= @@ -26,16 +24,12 @@ github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= -github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= -github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= +github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= diff --git a/exp/teatest/v2/go.mod b/exp/teatest/v2/go.mod index dc2fabee..97adee15 100644 --- a/exp/teatest/v2/go.mod +++ b/exp/teatest/v2/go.mod @@ -10,7 +10,7 @@ require ( require ( github.com/aymanbagabas/go-udiff v0.2.0 // indirect - github.com/charmbracelet/colorprofile v0.1.6 // indirect + github.com/charmbracelet/colorprofile v0.1.7 // indirect github.com/charmbracelet/x/ansi v0.4.5 // indirect github.com/charmbracelet/x/cellbuf v0.0.6-0.20241106170917-eb0997d7d743 // indirect github.com/charmbracelet/x/term v0.2.0 // indirect @@ -20,9 +20,9 @@ require ( github.com/muesli/cancelreader v0.2.2 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.19.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect ) replace github.com/charmbracelet/x/vt => ../../../vt diff --git a/exp/teatest/v2/go.sum b/exp/teatest/v2/go.sum index e8b60702..93819098 100644 --- a/exp/teatest/v2/go.sum +++ b/exp/teatest/v2/go.sum @@ -2,8 +2,7 @@ github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWp github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20241106193122-7b01292d0f80 h1:z/uITKE0kEdMj3CHmH37PqN5XnX/pTrS4m0tXWw0AQ4= github.com/charmbracelet/bubbletea/v2 v2.0.0-alpha.1.0.20241106193122-7b01292d0f80/go.mod h1:24niqT9RbtXhWg8zLRU/v/xTixlo1+DUsHQZ3+kez5Y= -github.com/charmbracelet/colorprofile v0.1.6 h1:nMMqCns0c0DfCwNGdagBh6SxutFqkltSxxKk5S9kt+Y= -github.com/charmbracelet/colorprofile v0.1.6/go.mod h1:3EMXDxwRDJl0c17eJ1jX99MhtlP9OxE/9Qw0C5lvyUg= +github.com/charmbracelet/colorprofile v0.1.7 h1:q7PtMQrRBBnLNE2EbtbNUtouu979EivKcDGGaimhyO8= github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM= github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30= @@ -22,11 +21,7 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= -golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= -golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= diff --git a/sshkey/go.mod b/sshkey/go.mod index 0acca8fb..a75e05cb 100644 --- a/sshkey/go.mod +++ b/sshkey/go.mod @@ -12,9 +12,9 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/catppuccin/go v0.2.0 // indirect github.com/charmbracelet/bubbles v0.20.0 // indirect - github.com/charmbracelet/bubbletea v1.1.0 // indirect - github.com/charmbracelet/lipgloss v0.13.0 // indirect - github.com/charmbracelet/x/ansi v0.2.3 // indirect + github.com/charmbracelet/bubbletea v1.1.2 // indirect + github.com/charmbracelet/lipgloss v1.0.0 // indirect + github.com/charmbracelet/x/ansi v0.4.2 // indirect github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect github.com/charmbracelet/x/term v0.2.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect diff --git a/sshkey/go.sum b/sshkey/go.sum index d1dc5e35..6e398227 100644 --- a/sshkey/go.sum +++ b/sshkey/go.sum @@ -8,14 +8,11 @@ github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA= github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE= github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU= -github.com/charmbracelet/bubbletea v1.1.0 h1:FjAl9eAL3HBCHenhz/ZPjkKdScmaS5SK69JAK2YJK9c= -github.com/charmbracelet/bubbletea v1.1.0/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4= +github.com/charmbracelet/bubbletea v1.1.2 h1:naQXF2laRxyLyil/i7fxdpiz1/k06IKquhm4vBfHsIc= github.com/charmbracelet/huh v0.6.0 h1:mZM8VvZGuE0hoDXq6XLxRtgfWyTI3b2jZNKh0xWmax8= github.com/charmbracelet/huh v0.6.0/go.mod h1:GGNKeWCeNzKpEOh/OJD8WBwTQjV3prFAtQPpLv+AVwU= -github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= -github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= -github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY= -github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg= +github.com/charmbracelet/x/ansi v0.4.2 h1:0JM6Aj/g/KC154/gOP4vfxun0ff6itogDYk41kof+qk= github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 h1:qko3AQ4gK1MTS/de7F5hPGx6/k1u0w4TeYmBFwzYVP4= github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= diff --git a/vt/examples/output.png b/vt/examples/output.png new file mode 100644 index 00000000..72e070d3 Binary files /dev/null and b/vt/examples/output.png differ diff --git a/vt/go.mod b/vt/go.mod index 45188d5a..ef7cca7a 100644 --- a/vt/go.mod +++ b/vt/go.mod @@ -9,12 +9,13 @@ require ( ) require ( - github.com/charmbracelet/colorprofile v0.1.6 // indirect + github.com/charmbracelet/colorprofile v0.1.7 // indirect github.com/charmbracelet/x/term v0.2.0 // indirect github.com/charmbracelet/x/wcwidth v0.0.0-20241011142426-46044092ad91 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/sys v0.24.0 // indirect + golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect + golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.20.0 // indirect ) diff --git a/vt/go.sum b/vt/go.sum index aaedfcbb..723ce2dc 100644 --- a/vt/go.sum +++ b/vt/go.sum @@ -1,5 +1,4 @@ -github.com/charmbracelet/colorprofile v0.1.6 h1:nMMqCns0c0DfCwNGdagBh6SxutFqkltSxxKk5S9kt+Y= -github.com/charmbracelet/colorprofile v0.1.6/go.mod h1:3EMXDxwRDJl0c17eJ1jX99MhtlP9OxE/9Qw0C5lvyUg= +github.com/charmbracelet/colorprofile v0.1.7 h1:q7PtMQrRBBnLNE2EbtbNUtouu979EivKcDGGaimhyO8= github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM= github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/cellbuf v0.0.6-0.20241106170917-eb0997d7d743 h1:iKVWAITVASXoMQGoesfzRP81cAkr/GAR3TkOYN2n3WU= @@ -14,10 +13,9 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= -golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/image v0.22.0 h1:UtK5yLUzilVrkjMAZAZ34DXGpASN8i8pj8g+O+yd10g= golang.org/x/image v0.22.0/go.mod h1:9hPFhljd4zZ1GNSIZJ49sqbp45GKK9t6w+iXvGqZUz4= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=