This commit is contained in:
40
vendor/github.com/charmbracelet/bubbletea/.golangci-soft.yml
generated
vendored
40
vendor/github.com/charmbracelet/bubbletea/.golangci-soft.yml
generated
vendored
@ -1,40 +0,0 @@
|
||||
run:
|
||||
tests: false
|
||||
issues-exit-code: 0
|
||||
|
||||
issues:
|
||||
include:
|
||||
- EXC0001
|
||||
- EXC0005
|
||||
- EXC0011
|
||||
- EXC0012
|
||||
- EXC0013
|
||||
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- exhaustive
|
||||
- goconst
|
||||
- godot
|
||||
- godox
|
||||
- mnd
|
||||
- gomoddirectives
|
||||
- goprintffuncname
|
||||
- misspell
|
||||
- nakedret
|
||||
- nestif
|
||||
- noctx
|
||||
- nolintlint
|
||||
- prealloc
|
||||
- wrapcheck
|
||||
|
||||
# disable default linters, they are already enabled in .golangci.yml
|
||||
disable:
|
||||
- errcheck
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- staticcheck
|
||||
- unused
|
40
vendor/github.com/charmbracelet/bubbletea/.golangci.yml
generated
vendored
40
vendor/github.com/charmbracelet/bubbletea/.golangci.yml
generated
vendored
@ -1,24 +1,22 @@
|
||||
version: "2"
|
||||
run:
|
||||
tests: false
|
||||
|
||||
issues:
|
||||
include:
|
||||
- EXC0001
|
||||
- EXC0005
|
||||
- EXC0011
|
||||
- EXC0012
|
||||
- EXC0013
|
||||
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- bodyclose
|
||||
- gofumpt
|
||||
- goimports
|
||||
- exhaustive
|
||||
- goconst
|
||||
- godot
|
||||
- gomoddirectives
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- misspell
|
||||
- nakedret
|
||||
- nestif
|
||||
- nilerr
|
||||
- noctx
|
||||
- nolintlint
|
||||
- prealloc
|
||||
- revive
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
@ -26,3 +24,17 @@ linters:
|
||||
- unconvert
|
||||
- unparam
|
||||
- whitespace
|
||||
- wrapcheck
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- common-false-positives
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
formatters:
|
||||
enable:
|
||||
- gofumpt
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
|
8
vendor/github.com/charmbracelet/bubbletea/README.md
generated
vendored
8
vendor/github.com/charmbracelet/bubbletea/README.md
generated
vendored
@ -1,11 +1,15 @@
|
||||
# Bubble Tea
|
||||
|
||||
<p>
|
||||
<a href="https://stuff.charm.sh/bubbletea/bubbletea-4k.png"><img src="https://github.com/charmbracelet/bubbletea/assets/25087/108d4fdb-d554-4910-abed-2a5f5586a60e" width="313" alt="Bubble Tea Title Treatment"></a><br>
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://stuff.charm.sh/bubbletea/bubble-tea-v2-light.png" width="308">
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://stuff.charm.sh/bubbletea/bubble-tea-v2-dark.png" width="312">
|
||||
<img src="https://stuff.charm.sh/bubbletea/bubble-tea-v2-light.png" width="308" />
|
||||
</picture>
|
||||
<br>
|
||||
<a href="https://github.com/charmbracelet/bubbletea/releases"><img src="https://img.shields.io/github/release/charmbracelet/bubbletea.svg" alt="Latest Release"></a>
|
||||
<a href="https://pkg.go.dev/github.com/charmbracelet/bubbletea?tab=doc"><img src="https://godoc.org/github.com/charmbracelet/bubbletea?status.svg" alt="GoDoc"></a>
|
||||
<a href="https://github.com/charmbracelet/bubbletea/actions"><img src="https://github.com/charmbracelet/bubbletea/actions/workflows/build.yml/badge.svg" alt="Build Status"></a>
|
||||
<a href="https://www.phorm.ai/query?projectId=a0e324b6-b706-4546-b951-6671ea60c13f"><img src="https://stuff.charm.sh/misc/phorm-badge.svg" alt="phorm.ai"></a>
|
||||
</p>
|
||||
|
||||
The fun, functional and stateful way to build terminal apps. A Go framework
|
||||
|
14
vendor/github.com/charmbracelet/bubbletea/Taskfile.yaml
generated
vendored
Normal file
14
vendor/github.com/charmbracelet/bubbletea/Taskfile.yaml
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
# https://taskfile.dev
|
||||
|
||||
version: '3'
|
||||
|
||||
tasks:
|
||||
lint:
|
||||
desc: Run lint
|
||||
cmds:
|
||||
- golangci-lint run
|
||||
|
||||
test:
|
||||
desc: Run tests
|
||||
cmds:
|
||||
- go test ./... {{.CLI_ARGS}}
|
4
vendor/github.com/charmbracelet/bubbletea/exec.go
generated
vendored
4
vendor/github.com/charmbracelet/bubbletea/exec.go
generated
vendored
@ -114,6 +114,7 @@ func (p *Program) exec(c ExecCommand, fn ExecCallback) {
|
||||
|
||||
// Execute system command.
|
||||
if err := c.Run(); err != nil {
|
||||
p.renderer.resetLinesRendered()
|
||||
_ = p.RestoreTerminal() // also try to restore the terminal.
|
||||
if fn != nil {
|
||||
go p.Send(fn(err))
|
||||
@ -121,6 +122,9 @@ func (p *Program) exec(c ExecCommand, fn ExecCallback) {
|
||||
return
|
||||
}
|
||||
|
||||
// Maintain the existing output from the command
|
||||
p.renderer.resetLinesRendered()
|
||||
|
||||
// Have the program re-capture input.
|
||||
err := p.RestoreTerminal()
|
||||
if fn != nil {
|
||||
|
7
vendor/github.com/charmbracelet/bubbletea/inputreader_other.go
generated
vendored
7
vendor/github.com/charmbracelet/bubbletea/inputreader_other.go
generated
vendored
@ -4,11 +4,16 @@
|
||||
package tea
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/muesli/cancelreader"
|
||||
)
|
||||
|
||||
func newInputReader(r io.Reader, _ bool) (cancelreader.CancelReader, error) {
|
||||
return cancelreader.NewReader(r)
|
||||
cr, err := cancelreader.NewReader(r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bubbletea: error creating cancel reader: %w", err)
|
||||
}
|
||||
return cr, nil
|
||||
}
|
||||
|
2
vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go
generated
vendored
2
vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go
generated
vendored
@ -67,6 +67,8 @@ func newInputReader(r io.Reader, enableMouse bool) (cancelreader.CancelReader, e
|
||||
func (r *conInputReader) Cancel() bool {
|
||||
r.setCanceled()
|
||||
|
||||
// Warning: These cancel methods do not reliably work on console input
|
||||
// and should not be counted on.
|
||||
return windows.CancelIoEx(r.conin, nil) == nil || windows.CancelIo(r.conin) == nil
|
||||
}
|
||||
|
||||
|
2
vendor/github.com/charmbracelet/bubbletea/key.go
generated
vendored
2
vendor/github.com/charmbracelet/bubbletea/key.go
generated
vendored
@ -622,7 +622,7 @@ func detectOneMsg(b []byte, canHaveMoreData bool) (w int, msg Msg) {
|
||||
case '<':
|
||||
if matchIndices := mouseSGRRegex.FindSubmatchIndex(b[3:]); matchIndices != nil {
|
||||
// SGR mouse events length is the length of the match plus the length of the escape sequence
|
||||
mouseEventSGRLen := matchIndices[1] + 3 //nolint:gomnd
|
||||
mouseEventSGRLen := matchIndices[1] + 3 //nolint:mnd
|
||||
return mouseEventSGRLen, MouseMsg(parseSGRMouseEvent(b))
|
||||
}
|
||||
}
|
||||
|
5
vendor/github.com/charmbracelet/bubbletea/key_sequences.go
generated
vendored
5
vendor/github.com/charmbracelet/bubbletea/key_sequences.go
generated
vendored
@ -119,13 +119,12 @@ func detectBracketedPaste(input []byte) (hasBp bool, width int, msg Msg) {
|
||||
}
|
||||
|
||||
// detectReportFocus detects a focus report sequence.
|
||||
// nolint: gomnd
|
||||
func detectReportFocus(input []byte) (hasRF bool, width int, msg Msg) {
|
||||
switch {
|
||||
case bytes.Equal(input, []byte("\x1b[I")):
|
||||
return true, 3, FocusMsg{}
|
||||
return true, 3, FocusMsg{} //nolint:mnd
|
||||
case bytes.Equal(input, []byte("\x1b[O")):
|
||||
return true, 3, BlurMsg{}
|
||||
return true, 3, BlurMsg{} //nolint:mnd
|
||||
}
|
||||
return false, 0, nil
|
||||
}
|
||||
|
103
vendor/github.com/charmbracelet/bubbletea/key_windows.go
generated
vendored
103
vendor/github.com/charmbracelet/bubbletea/key_windows.go
generated
vendored
@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/erikgeiser/coninput"
|
||||
localereader "github.com/mattn/go-localereader"
|
||||
@ -25,14 +26,10 @@ func readConInputs(ctx context.Context, msgsch chan<- Msg, con *conInputReader)
|
||||
var ps coninput.ButtonState // keep track of previous mouse state
|
||||
var ws coninput.WindowBufferSizeEventRecord // keep track of the last window size event
|
||||
for {
|
||||
events, err := coninput.ReadNConsoleInputs(con.conin, 16)
|
||||
events, err := peekAndReadConsInput(con)
|
||||
if err != nil {
|
||||
if con.isCanceled() {
|
||||
return cancelreader.ErrCanceled
|
||||
}
|
||||
return fmt.Errorf("read coninput events: %w", err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, event := range events {
|
||||
var msgs []Msg
|
||||
switch e := event.Unwrap().(type) {
|
||||
@ -87,13 +84,57 @@ func readConInputs(ctx context.Context, msgsch chan<- Msg, con *conInputReader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("coninput context error: %w", err)
|
||||
}
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Peek for new input in a tight loop and then read the input.
|
||||
// windows.CancelIo* does not work reliably so peek first and only use the data if
|
||||
// the console input is not cancelled.
|
||||
func peekAndReadConsInput(con *conInputReader) ([]coninput.InputRecord, error) {
|
||||
events, err := peekConsInput(con)
|
||||
if err != nil {
|
||||
return events, err
|
||||
}
|
||||
events, err = coninput.ReadNConsoleInputs(con.conin, intToUint32OrDie(len(events)))
|
||||
if con.isCanceled() {
|
||||
return events, cancelreader.ErrCanceled
|
||||
}
|
||||
if err != nil {
|
||||
return events, fmt.Errorf("read coninput events: %w", err)
|
||||
}
|
||||
return events, nil
|
||||
}
|
||||
|
||||
// Convert i to unit32 or panic if it cannot be converted. Check satisifes lint G115.
|
||||
func intToUint32OrDie(i int) uint32 {
|
||||
if i < 0 {
|
||||
panic("cannot convert numEvents " + fmt.Sprint(i) + " to uint32")
|
||||
}
|
||||
return uint32(i)
|
||||
}
|
||||
|
||||
// Keeps peeking until there is data or the input is cancelled.
|
||||
func peekConsInput(con *conInputReader) ([]coninput.InputRecord, error) {
|
||||
for {
|
||||
events, err := coninput.PeekNConsoleInputs(con.conin, 16)
|
||||
if con.isCanceled() {
|
||||
return events, cancelreader.ErrCanceled
|
||||
}
|
||||
if err != nil {
|
||||
return events, fmt.Errorf("peek coninput events: %w", err)
|
||||
}
|
||||
if len(events) > 0 {
|
||||
return events, nil
|
||||
}
|
||||
// Sleep for a bit to avoid busy waiting.
|
||||
time.Sleep(16 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func mouseEventButton(p, s coninput.ButtonState) (button MouseButton, action MouseAction) {
|
||||
btn := p ^ s
|
||||
action = MouseActionPress
|
||||
@ -114,7 +155,7 @@ func mouseEventButton(p, s coninput.ButtonState) (button MouseButton, action Mou
|
||||
case s&coninput.FROM_LEFT_4TH_BUTTON_PRESSED > 0:
|
||||
button = MouseButtonForward
|
||||
}
|
||||
return
|
||||
return button, action
|
||||
}
|
||||
|
||||
switch {
|
||||
@ -147,7 +188,7 @@ func mouseEvent(p coninput.ButtonState, e coninput.MouseEventRecord) MouseMsg {
|
||||
if ev.Action == MouseActionRelease {
|
||||
ev.Type = MouseRelease
|
||||
}
|
||||
switch ev.Button {
|
||||
switch ev.Button { //nolint:exhaustive
|
||||
case MouseButtonLeft:
|
||||
ev.Type = MouseLeft
|
||||
case MouseButtonMiddle:
|
||||
@ -190,7 +231,7 @@ func keyType(e coninput.KeyEventRecord) KeyType {
|
||||
shiftPressed := e.ControlKeyState.Contains(coninput.SHIFT_PRESSED)
|
||||
ctrlPressed := e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED | coninput.RIGHT_CTRL_PRESSED)
|
||||
|
||||
switch code {
|
||||
switch code { //nolint:exhaustive
|
||||
case coninput.VK_RETURN:
|
||||
return KeyEnter
|
||||
case coninput.VK_BACK:
|
||||
@ -276,6 +317,46 @@ func keyType(e coninput.KeyEventRecord) KeyType {
|
||||
return KeyPgDown
|
||||
case coninput.VK_DELETE:
|
||||
return KeyDelete
|
||||
case coninput.VK_F1:
|
||||
return KeyF1
|
||||
case coninput.VK_F2:
|
||||
return KeyF2
|
||||
case coninput.VK_F3:
|
||||
return KeyF3
|
||||
case coninput.VK_F4:
|
||||
return KeyF4
|
||||
case coninput.VK_F5:
|
||||
return KeyF5
|
||||
case coninput.VK_F6:
|
||||
return KeyF6
|
||||
case coninput.VK_F7:
|
||||
return KeyF7
|
||||
case coninput.VK_F8:
|
||||
return KeyF8
|
||||
case coninput.VK_F9:
|
||||
return KeyF9
|
||||
case coninput.VK_F10:
|
||||
return KeyF10
|
||||
case coninput.VK_F11:
|
||||
return KeyF11
|
||||
case coninput.VK_F12:
|
||||
return KeyF12
|
||||
case coninput.VK_F13:
|
||||
return KeyF13
|
||||
case coninput.VK_F14:
|
||||
return KeyF14
|
||||
case coninput.VK_F15:
|
||||
return KeyF15
|
||||
case coninput.VK_F16:
|
||||
return KeyF16
|
||||
case coninput.VK_F17:
|
||||
return KeyF17
|
||||
case coninput.VK_F18:
|
||||
return KeyF18
|
||||
case coninput.VK_F19:
|
||||
return KeyF19
|
||||
case coninput.VK_F20:
|
||||
return KeyF20
|
||||
default:
|
||||
switch {
|
||||
case e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED) && e.ControlKeyState.Contains(coninput.RIGHT_ALT_PRESSED):
|
||||
@ -348,7 +429,7 @@ func keyType(e coninput.KeyEventRecord) KeyType {
|
||||
return KeyCtrlUnderscore
|
||||
}
|
||||
|
||||
switch code {
|
||||
switch code { //nolint:exhaustive
|
||||
case coninput.VK_OEM_4:
|
||||
return KeyCtrlOpenBracket
|
||||
case coninput.VK_OEM_6:
|
||||
|
2
vendor/github.com/charmbracelet/bubbletea/logging.go
generated
vendored
2
vendor/github.com/charmbracelet/bubbletea/logging.go
generated
vendored
@ -33,7 +33,7 @@ type LogOptionsSetter interface {
|
||||
|
||||
// LogToFileWith does allows to call LogToFile with a custom LogOptionsSetter.
|
||||
func LogToFileWith(path string, prefix string, log LogOptionsSetter) (*os.File, error) {
|
||||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600) //nolint:gomnd
|
||||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600) //nolint:mnd
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening file for logging: %w", err)
|
||||
}
|
||||
|
2
vendor/github.com/charmbracelet/bubbletea/mouse.go
generated
vendored
2
vendor/github.com/charmbracelet/bubbletea/mouse.go
generated
vendored
@ -172,7 +172,7 @@ const (
|
||||
func parseSGRMouseEvent(buf []byte) MouseEvent {
|
||||
str := string(buf[3:])
|
||||
matches := mouseSGRRegex.FindStringSubmatch(str)
|
||||
if len(matches) != 5 { //nolint:gomnd
|
||||
if len(matches) != 5 { //nolint:mnd
|
||||
// Unreachable, we already checked the regex in `detectOneMsg`.
|
||||
panic("invalid mouse event")
|
||||
}
|
||||
|
1
vendor/github.com/charmbracelet/bubbletea/nil_renderer.go
generated
vendored
1
vendor/github.com/charmbracelet/bubbletea/nil_renderer.go
generated
vendored
@ -26,3 +26,4 @@ func (n nilRenderer) setWindowTitle(_ string) {}
|
||||
func (n nilRenderer) reportFocus() bool { return false }
|
||||
func (n nilRenderer) enableReportFocus() {}
|
||||
func (n nilRenderer) disableReportFocus() {}
|
||||
func (n nilRenderer) resetLinesRendered() {}
|
||||
|
2
vendor/github.com/charmbracelet/bubbletea/options.go
generated
vendored
2
vendor/github.com/charmbracelet/bubbletea/options.go
generated
vendored
@ -19,7 +19,7 @@ type ProgramOption func(*Program)
|
||||
// cancelled it will exit with an error ErrProgramKilled.
|
||||
func WithContext(ctx context.Context) ProgramOption {
|
||||
return func(p *Program) {
|
||||
p.ctx = ctx
|
||||
p.externalCtx = ctx
|
||||
}
|
||||
}
|
||||
|
||||
|
3
vendor/github.com/charmbracelet/bubbletea/renderer.go
generated
vendored
3
vendor/github.com/charmbracelet/bubbletea/renderer.go
generated
vendored
@ -79,6 +79,9 @@ type renderer interface {
|
||||
|
||||
// disableReportFocus stops reporting focus events to the program.
|
||||
disableReportFocus()
|
||||
|
||||
// resetLinesRendered ensures exec output remains on screen on exit
|
||||
resetLinesRendered()
|
||||
}
|
||||
|
||||
// repaintMsg forces a full repaint.
|
||||
|
4
vendor/github.com/charmbracelet/bubbletea/standard_renderer.go
generated
vendored
4
vendor/github.com/charmbracelet/bubbletea/standard_renderer.go
generated
vendored
@ -545,6 +545,10 @@ func (r *standardRenderer) clearIgnoredLines() {
|
||||
r.ignoreLines = nil
|
||||
}
|
||||
|
||||
func (r *standardRenderer) resetLinesRendered() {
|
||||
r.linesRendered = 0
|
||||
}
|
||||
|
||||
// insertTop effectively scrolls up. It inserts lines at the top of a given
|
||||
// area designated to be a scrollable region, pushing everything else down.
|
||||
// This is roughly how ncurses does it.
|
||||
|
119
vendor/github.com/charmbracelet/bubbletea/tea.go
generated
vendored
119
vendor/github.com/charmbracelet/bubbletea/tea.go
generated
vendored
@ -27,6 +27,9 @@ import (
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// ErrProgramPanic is returned by [Program.Run] when the program recovers from a panic.
|
||||
var ErrProgramPanic = errors.New("program experienced a panic")
|
||||
|
||||
// ErrProgramKilled is returned by [Program.Run] when the program gets killed.
|
||||
var ErrProgramKilled = errors.New("program was killed")
|
||||
|
||||
@ -147,6 +150,12 @@ type Program struct {
|
||||
|
||||
inputType inputType
|
||||
|
||||
// externalCtx is a context that was passed in via WithContext, otherwise defaulting
|
||||
// to ctx.Background() (in case it was not), the internal context is derived from it.
|
||||
externalCtx context.Context
|
||||
|
||||
// ctx is the programs's internal context for signalling internal teardown.
|
||||
// It is built and derived from the externalCtx in NewProgram().
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
|
||||
@ -243,11 +252,11 @@ func NewProgram(model Model, opts ...ProgramOption) *Program {
|
||||
|
||||
// A context can be provided with a ProgramOption, but if none was provided
|
||||
// we'll use the default background context.
|
||||
if p.ctx == nil {
|
||||
p.ctx = context.Background()
|
||||
if p.externalCtx == nil {
|
||||
p.externalCtx = context.Background()
|
||||
}
|
||||
// Initialize context and teardown channel.
|
||||
p.ctx, p.cancel = context.WithCancel(p.ctx)
|
||||
p.ctx, p.cancel = context.WithCancel(p.externalCtx)
|
||||
|
||||
// if no output was set, set it to stdout
|
||||
if p.output == nil {
|
||||
@ -346,7 +355,11 @@ func (p *Program) handleCommands(cmds chan Cmd) chan struct{} {
|
||||
go func() {
|
||||
// Recover from panics.
|
||||
if !p.startupOptions.has(withoutCatchPanics) {
|
||||
defer p.recoverFromPanic()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
p.recoverFromGoPanic(r)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
msg := cmd() // this can be long.
|
||||
@ -422,7 +435,7 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
||||
// work.
|
||||
if runtime.GOOS == "windows" && !p.mouseMode {
|
||||
p.mouseMode = true
|
||||
p.initCancelReader(true) //nolint:errcheck
|
||||
p.initCancelReader(true) //nolint:errcheck,gosec
|
||||
}
|
||||
|
||||
case disableMouseMsg:
|
||||
@ -433,7 +446,7 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
||||
// mouse events.
|
||||
if runtime.GOOS == "windows" && p.mouseMode {
|
||||
p.mouseMode = false
|
||||
p.initCancelReader(true) //nolint:errcheck
|
||||
p.initCancelReader(true) //nolint:errcheck,gosec
|
||||
}
|
||||
|
||||
case showCursorMsg:
|
||||
@ -460,7 +473,11 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
||||
|
||||
case BatchMsg:
|
||||
for _, cmd := range msg {
|
||||
cmds <- cmd
|
||||
select {
|
||||
case <-p.ctx.Done():
|
||||
return model, nil
|
||||
case cmds <- cmd:
|
||||
}
|
||||
}
|
||||
continue
|
||||
|
||||
@ -483,7 +500,7 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
||||
})
|
||||
}
|
||||
|
||||
//nolint:errcheck
|
||||
//nolint:errcheck,gosec
|
||||
g.Wait() // wait for all commands from batch msg to finish
|
||||
continue
|
||||
}
|
||||
@ -506,7 +523,13 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
||||
|
||||
var cmd Cmd
|
||||
model, cmd = model.Update(msg) // run update
|
||||
cmds <- cmd // process command (if any)
|
||||
|
||||
select {
|
||||
case <-p.ctx.Done():
|
||||
return model, nil
|
||||
case cmds <- cmd: // process command (if any)
|
||||
}
|
||||
|
||||
p.renderer.write(model.View()) // send view to renderer
|
||||
}
|
||||
}
|
||||
@ -515,11 +538,15 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
|
||||
// Run initializes the program and runs its event loops, blocking until it gets
|
||||
// terminated by either [Program.Quit], [Program.Kill], or its signal handler.
|
||||
// Returns the final model.
|
||||
func (p *Program) Run() (Model, error) {
|
||||
func (p *Program) Run() (returnModel Model, returnErr error) {
|
||||
p.handlers = channelHandlers{}
|
||||
cmds := make(chan Cmd)
|
||||
p.errs = make(chan error)
|
||||
p.finished = make(chan struct{}, 1)
|
||||
p.errs = make(chan error, 1)
|
||||
|
||||
p.finished = make(chan struct{})
|
||||
defer func() {
|
||||
close(p.finished)
|
||||
}()
|
||||
|
||||
defer p.cancel()
|
||||
|
||||
@ -568,7 +595,12 @@ func (p *Program) Run() (Model, error) {
|
||||
|
||||
// Recover from panics.
|
||||
if !p.startupOptions.has(withoutCatchPanics) {
|
||||
defer p.recoverFromPanic()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
returnErr = fmt.Errorf("%w: %w", ErrProgramKilled, ErrProgramPanic)
|
||||
p.recoverFromPanic(r)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// If no renderer is set use the standard one.
|
||||
@ -645,11 +677,27 @@ func (p *Program) Run() (Model, error) {
|
||||
|
||||
// Run event loop, handle updates and draw.
|
||||
model, err := p.eventLoop(model, cmds)
|
||||
killed := p.ctx.Err() != nil || err != nil
|
||||
if killed && err == nil {
|
||||
err = fmt.Errorf("%w: %s", ErrProgramKilled, p.ctx.Err())
|
||||
|
||||
if err == nil && len(p.errs) > 0 {
|
||||
err = <-p.errs // Drain a leftover error in case eventLoop crashed
|
||||
}
|
||||
if err == nil {
|
||||
|
||||
killed := p.externalCtx.Err() != nil || p.ctx.Err() != nil || err != nil
|
||||
if killed {
|
||||
if err == nil && p.externalCtx.Err() != nil {
|
||||
// Return also as context error the cancellation of an external context.
|
||||
// This is the context the user knows about and should be able to act on.
|
||||
err = fmt.Errorf("%w: %w", ErrProgramKilled, p.externalCtx.Err())
|
||||
} else if err == nil && p.ctx.Err() != nil {
|
||||
// Return only that the program was killed (not the internal mechanism).
|
||||
// The user does not know or need to care about the internal program context.
|
||||
err = ErrProgramKilled
|
||||
} else {
|
||||
// Return that the program was killed and also the error that caused it.
|
||||
err = fmt.Errorf("%w: %w", ErrProgramKilled, err)
|
||||
}
|
||||
} else {
|
||||
// Graceful shutdown of the program (not killed):
|
||||
// Ensure we rendered the final state of the model.
|
||||
p.renderer.write(model.View())
|
||||
}
|
||||
@ -704,11 +752,11 @@ func (p *Program) Quit() {
|
||||
p.Send(Quit())
|
||||
}
|
||||
|
||||
// Kill stops the program immediately and restores the former terminal state.
|
||||
// Kill signals the program to stop immediately and restore the former terminal state.
|
||||
// The final render that you would normally see when quitting will be skipped.
|
||||
// [program.Run] returns a [ErrProgramKilled] error.
|
||||
func (p *Program) Kill() {
|
||||
p.shutdown(true)
|
||||
p.cancel()
|
||||
}
|
||||
|
||||
// Wait waits/blocks until the underlying Program finished shutting down.
|
||||
@ -717,7 +765,11 @@ func (p *Program) Wait() {
|
||||
}
|
||||
|
||||
// shutdown performs operations to free up resources and restore the terminal
|
||||
// to its original state.
|
||||
// to its original state. It is called once at the end of the program's lifetime.
|
||||
//
|
||||
// This method should not be called to signal the program to be killed/shutdown.
|
||||
// Doing so can lead to race conditions with the eventual call at the program's end.
|
||||
// As alternatives, the [Quit] or [Kill] convenience methods should be used instead.
|
||||
func (p *Program) shutdown(kill bool) {
|
||||
p.cancel()
|
||||
|
||||
@ -744,19 +796,30 @@ func (p *Program) shutdown(kill bool) {
|
||||
}
|
||||
|
||||
_ = p.restoreTerminalState()
|
||||
if !kill {
|
||||
p.finished <- struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// recoverFromPanic recovers from a panic, prints the stack trace, and restores
|
||||
// the terminal to a usable state.
|
||||
func (p *Program) recoverFromPanic() {
|
||||
if r := recover(); r != nil {
|
||||
p.shutdown(true)
|
||||
fmt.Printf("Caught panic:\n\n%s\n\nRestoring terminal...\n\n", r)
|
||||
debug.PrintStack()
|
||||
func (p *Program) recoverFromPanic(r interface{}) {
|
||||
select {
|
||||
case p.errs <- ErrProgramPanic:
|
||||
default:
|
||||
}
|
||||
p.shutdown(true) // Ok to call here, p.Run() cannot do it anymore.
|
||||
fmt.Printf("Caught panic:\n\n%s\n\nRestoring terminal...\n\n", r)
|
||||
debug.PrintStack()
|
||||
}
|
||||
|
||||
// recoverFromGoPanic recovers from a goroutine panic, prints a stack trace and
|
||||
// signals for the program to be killed and terminal restored to a usable state.
|
||||
func (p *Program) recoverFromGoPanic(r interface{}) {
|
||||
select {
|
||||
case p.errs <- ErrProgramPanic:
|
||||
default:
|
||||
}
|
||||
p.cancel()
|
||||
fmt.Printf("Caught goroutine panic:\n\n%s\n\nRestoring terminal...\n\n", r)
|
||||
debug.PrintStack()
|
||||
}
|
||||
|
||||
// ReleaseTerminal restores the original terminal state and cancels the input
|
||||
|
4
vendor/github.com/charmbracelet/bubbletea/tty.go
generated
vendored
4
vendor/github.com/charmbracelet/bubbletea/tty.go
generated
vendored
@ -52,7 +52,7 @@ func (p *Program) restoreTerminalState() error {
|
||||
p.renderer.exitAltScreen()
|
||||
|
||||
// give the terminal a moment to catch up
|
||||
time.Sleep(time.Millisecond * 10) //nolint:gomnd
|
||||
time.Sleep(time.Millisecond * 10) //nolint:mnd
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ func (p *Program) readLoop() {
|
||||
func (p *Program) waitForReadLoop() {
|
||||
select {
|
||||
case <-p.readLoopDone:
|
||||
case <-time.After(500 * time.Millisecond): //nolint:gomnd
|
||||
case <-time.After(500 * time.Millisecond): //nolint:mnd
|
||||
// The read loop hangs, which means the input
|
||||
// cancelReader's cancel function has returned true even
|
||||
// though it was not able to cancel the read.
|
||||
|
8
vendor/github.com/charmbracelet/bubbletea/tty_windows.go
generated
vendored
8
vendor/github.com/charmbracelet/bubbletea/tty_windows.go
generated
vendored
@ -19,7 +19,7 @@ func (p *Program) initInput() (err error) {
|
||||
p.ttyInput = f
|
||||
p.previousTtyInputState, err = term.MakeRaw(p.ttyInput.Fd())
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("error making raw: %w", err)
|
||||
}
|
||||
|
||||
// Enable VT input
|
||||
@ -38,7 +38,7 @@ func (p *Program) initInput() (err error) {
|
||||
p.ttyOutput = f
|
||||
p.previousOutputState, err = term.GetState(f.Fd())
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("error getting state: %w", err)
|
||||
}
|
||||
|
||||
var mode uint32
|
||||
@ -51,14 +51,14 @@ func (p *Program) initInput() (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// Open the Windows equivalent of a TTY.
|
||||
func openInputTTY() (*os.File, error) {
|
||||
f, err := os.OpenFile("CONIN$", os.O_RDWR, 0o644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("error opening file: %w", err)
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
40
vendor/github.com/charmbracelet/colorprofile/.golangci-soft.yml
generated
vendored
40
vendor/github.com/charmbracelet/colorprofile/.golangci-soft.yml
generated
vendored
@ -1,40 +0,0 @@
|
||||
run:
|
||||
tests: false
|
||||
issues-exit-code: 0
|
||||
|
||||
issues:
|
||||
include:
|
||||
- EXC0001
|
||||
- EXC0005
|
||||
- EXC0011
|
||||
- EXC0012
|
||||
- EXC0013
|
||||
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- exhaustive
|
||||
- goconst
|
||||
- godot
|
||||
- godox
|
||||
- mnd
|
||||
- gomoddirectives
|
||||
- goprintffuncname
|
||||
- misspell
|
||||
- nakedret
|
||||
- nestif
|
||||
- noctx
|
||||
- nolintlint
|
||||
- prealloc
|
||||
- wrapcheck
|
||||
|
||||
# disable default linters, they are already enabled in .golangci.yml
|
||||
disable:
|
||||
- errcheck
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- staticcheck
|
||||
- unused
|
41
vendor/github.com/charmbracelet/colorprofile/.golangci.yml
generated
vendored
41
vendor/github.com/charmbracelet/colorprofile/.golangci.yml
generated
vendored
@ -1,24 +1,23 @@
|
||||
version: "2"
|
||||
run:
|
||||
tests: false
|
||||
|
||||
issues:
|
||||
include:
|
||||
- EXC0001
|
||||
- EXC0005
|
||||
- EXC0011
|
||||
- EXC0012
|
||||
- EXC0013
|
||||
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- bodyclose
|
||||
- gofumpt
|
||||
- goimports
|
||||
- exhaustive
|
||||
- goconst
|
||||
- godot
|
||||
- godox
|
||||
- gomoddirectives
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- misspell
|
||||
- nakedret
|
||||
- nestif
|
||||
- nilerr
|
||||
- noctx
|
||||
- nolintlint
|
||||
- prealloc
|
||||
- revive
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
@ -26,3 +25,17 @@ linters:
|
||||
- unconvert
|
||||
- unparam
|
||||
- whitespace
|
||||
- wrapcheck
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- common-false-positives
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
formatters:
|
||||
enable:
|
||||
- gofumpt
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
|
4
vendor/github.com/charmbracelet/colorprofile/doc.go
generated
vendored
Normal file
4
vendor/github.com/charmbracelet/colorprofile/doc.go
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
// Package colorprofile provides a way to downsample ANSI escape sequence
|
||||
// colors and styles automatically based on output, environment variables, and
|
||||
// Terminfo databases.
|
||||
package colorprofile
|
36
vendor/github.com/charmbracelet/colorprofile/env.go
generated
vendored
36
vendor/github.com/charmbracelet/colorprofile/env.go
generated
vendored
@ -12,6 +12,8 @@ import (
|
||||
"github.com/xo/terminfo"
|
||||
)
|
||||
|
||||
const dumbTerm = "dumb"
|
||||
|
||||
// Detect returns the color profile based on the terminal output, and
|
||||
// environment variables. This respects NO_COLOR, CLICOLOR, and CLICOLOR_FORCE
|
||||
// environment variables.
|
||||
@ -29,10 +31,10 @@ import (
|
||||
// See https://no-color.org/ and https://bixense.com/clicolors/ for more information.
|
||||
func Detect(output io.Writer, env []string) Profile {
|
||||
out, ok := output.(term.File)
|
||||
isatty := ok && term.IsTerminal(out.Fd())
|
||||
environ := newEnviron(env)
|
||||
term := environ.get("TERM")
|
||||
isDumb := term == "dumb"
|
||||
isatty := isTTYForced(environ) || (ok && term.IsTerminal(out.Fd()))
|
||||
term, ok := environ.lookup("TERM")
|
||||
isDumb := !ok || term == dumbTerm
|
||||
envp := colorProfile(isatty, environ)
|
||||
if envp == TrueColor || envNoColor(environ) {
|
||||
// We already know we have TrueColor, or NO_COLOR is set.
|
||||
@ -69,7 +71,8 @@ func Env(env []string) (p Profile) {
|
||||
}
|
||||
|
||||
func colorProfile(isatty bool, env environ) (p Profile) {
|
||||
isDumb := env.get("TERM") == "dumb"
|
||||
term, ok := env.lookup("TERM")
|
||||
isDumb := (!ok && runtime.GOOS != "windows") || term == dumbTerm
|
||||
envp := envColorProfile(env)
|
||||
if !isatty || isDumb {
|
||||
// Check if the output is a terminal.
|
||||
@ -83,7 +86,7 @@ func colorProfile(isatty bool, env environ) (p Profile) {
|
||||
if p > Ascii {
|
||||
p = Ascii
|
||||
}
|
||||
return
|
||||
return //nolint:nakedret
|
||||
}
|
||||
|
||||
if cliColorForced(env) {
|
||||
@ -94,7 +97,7 @@ func colorProfile(isatty bool, env environ) (p Profile) {
|
||||
p = envp
|
||||
}
|
||||
|
||||
return
|
||||
return //nolint:nakedret
|
||||
}
|
||||
|
||||
if cliColor(env) {
|
||||
@ -123,6 +126,11 @@ func cliColorForced(env environ) bool {
|
||||
return cliColorForce
|
||||
}
|
||||
|
||||
func isTTYForced(env environ) bool {
|
||||
skip, _ := strconv.ParseBool(env.get("TTY_FORCE"))
|
||||
return skip
|
||||
}
|
||||
|
||||
func colorTerm(env environ) bool {
|
||||
colorTerm := strings.ToLower(env.get("COLORTERM"))
|
||||
return colorTerm == "truecolor" || colorTerm == "24bit" ||
|
||||
@ -132,7 +140,7 @@ func colorTerm(env environ) bool {
|
||||
// envColorProfile returns infers the color profile from the environment.
|
||||
func envColorProfile(env environ) (p Profile) {
|
||||
term, ok := env.lookup("TERM")
|
||||
if !ok || len(term) == 0 || term == "dumb" {
|
||||
if !ok || len(term) == 0 || term == dumbTerm {
|
||||
p = NoTTY
|
||||
if runtime.GOOS == "windows" {
|
||||
// Use Windows API to detect color profile. Windows Terminal and
|
||||
@ -184,7 +192,12 @@ func envColorProfile(env environ) (p Profile) {
|
||||
p = ANSI256
|
||||
}
|
||||
|
||||
return
|
||||
// Direct color terminals support true colors.
|
||||
if strings.HasSuffix(term, "direct") {
|
||||
return TrueColor
|
||||
}
|
||||
|
||||
return //nolint:nakedret
|
||||
}
|
||||
|
||||
// Terminfo returns the color profile based on the terminal's terminfo
|
||||
@ -278,10 +291,3 @@ func (e environ) get(key string) string {
|
||||
v, _ := e.lookup(key)
|
||||
return v
|
||||
}
|
||||
|
||||
func max[T ~byte | ~int](a, b T) T {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
10
vendor/github.com/charmbracelet/colorprofile/profile.go
generated
vendored
10
vendor/github.com/charmbracelet/colorprofile/profile.go
generated
vendored
@ -12,15 +12,15 @@ import (
|
||||
type Profile byte
|
||||
|
||||
const (
|
||||
// NoTTY, not a terminal profile.
|
||||
// NoTTY is a profile with no terminal support.
|
||||
NoTTY Profile = iota
|
||||
// Ascii, uncolored profile.
|
||||
// Ascii is a profile with no color support.
|
||||
Ascii //nolint:revive
|
||||
// ANSI, 4-bit color profile.
|
||||
// ANSI is a profile with 16 colors (4-bit).
|
||||
ANSI
|
||||
// ANSI256, 8-bit color profile.
|
||||
// ANSI256 is a profile with 256 colors (8-bit).
|
||||
ANSI256
|
||||
// TrueColor, 24-bit color profile.
|
||||
// TrueColor is a profile with 16 million colors (24-bit).
|
||||
TrueColor
|
||||
)
|
||||
|
||||
|
13
vendor/github.com/charmbracelet/colorprofile/writer.go
generated
vendored
13
vendor/github.com/charmbracelet/colorprofile/writer.go
generated
vendored
@ -2,6 +2,7 @@ package colorprofile
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"io"
|
||||
"strconv"
|
||||
@ -37,11 +38,13 @@ type Writer struct {
|
||||
func (w *Writer) Write(p []byte) (int, error) {
|
||||
switch w.Profile {
|
||||
case TrueColor:
|
||||
return w.Forward.Write(p)
|
||||
return w.Forward.Write(p) //nolint:wrapcheck
|
||||
case NoTTY:
|
||||
return io.WriteString(w.Forward, ansi.Strip(string(p)))
|
||||
default:
|
||||
return io.WriteString(w.Forward, ansi.Strip(string(p))) //nolint:wrapcheck
|
||||
case Ascii, ANSI, ANSI256:
|
||||
return w.downsample(p)
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid profile: %v", w.Profile)
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +66,7 @@ func (w *Writer) downsample(p []byte) (int, error) {
|
||||
default:
|
||||
// If we're not a style SGR sequence, just write the bytes.
|
||||
if n, err := buf.Write(seq); err != nil {
|
||||
return n, err
|
||||
return n, err //nolint:wrapcheck
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +74,7 @@ func (w *Writer) downsample(p []byte) (int, error) {
|
||||
state = newState
|
||||
}
|
||||
|
||||
return w.Forward.Write(buf.Bytes())
|
||||
return w.Forward.Write(buf.Bytes()) //nolint:wrapcheck
|
||||
}
|
||||
|
||||
// WriteString writes the given text to the underlying writer.
|
||||
|
28
vendor/github.com/charmbracelet/log/.golangci.yml
generated
vendored
28
vendor/github.com/charmbracelet/log/.golangci.yml
generated
vendored
@ -1,17 +1,6 @@
|
||||
version: "2"
|
||||
run:
|
||||
tests: false
|
||||
|
||||
issues:
|
||||
include:
|
||||
- EXC0001
|
||||
- EXC0005
|
||||
- EXC0011
|
||||
- EXC0012
|
||||
- EXC0013
|
||||
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- bodyclose
|
||||
@ -19,8 +8,6 @@ linters:
|
||||
- goconst
|
||||
- godot
|
||||
- godox
|
||||
- gofumpt
|
||||
- goimports
|
||||
- gomoddirectives
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
@ -39,3 +26,16 @@ linters:
|
||||
- unparam
|
||||
- whitespace
|
||||
- wrapcheck
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- common-false-positives
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
formatters:
|
||||
enable:
|
||||
- gofumpt
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
|
8
vendor/github.com/charmbracelet/log/json.go
generated
vendored
8
vendor/github.com/charmbracelet/log/json.go
generated
vendored
@ -88,7 +88,13 @@ func (l *Logger) writeSlogValue(jw *jsonWriter, v slogValue) {
|
||||
}
|
||||
jw.end()
|
||||
default:
|
||||
jw.objectValue(v.Any())
|
||||
a := v.Any()
|
||||
_, jm := a.(json.Marshaler)
|
||||
if err, ok := a.(error); ok && !jm {
|
||||
jw.objectValue(err.Error())
|
||||
} else {
|
||||
jw.objectValue(a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
2
vendor/github.com/charmbracelet/log/logger_121.go
generated
vendored
2
vendor/github.com/charmbracelet/log/logger_121.go
generated
vendored
@ -17,6 +17,8 @@ type (
|
||||
slogLogValuer = slog.LogValuer
|
||||
)
|
||||
|
||||
var slogAnyValue = slog.AnyValue
|
||||
|
||||
const slogKindGroup = slog.KindGroup
|
||||
|
||||
// Enabled reports whether the logger is enabled for the given level.
|
||||
|
2
vendor/github.com/charmbracelet/log/logger_no121.go
generated
vendored
2
vendor/github.com/charmbracelet/log/logger_no121.go
generated
vendored
@ -18,6 +18,8 @@ type (
|
||||
slogLogValuer = slog.LogValuer
|
||||
)
|
||||
|
||||
var slogAnyValue = slog.AnyValue
|
||||
|
||||
const slogKindGroup = slog.KindGroup
|
||||
|
||||
// Enabled reports whether the logger is enabled for the given level.
|
||||
|
2
vendor/github.com/charmbracelet/x/ansi/ansi.go
generated
vendored
2
vendor/github.com/charmbracelet/x/ansi/ansi.go
generated
vendored
@ -7,5 +7,5 @@ import "io"
|
||||
//
|
||||
// This is a syntactic sugar over [io.WriteString].
|
||||
func Execute(w io.Writer, s string) (int, error) {
|
||||
return io.WriteString(w, s)
|
||||
return io.WriteString(w, s) //nolint:wrapcheck
|
||||
}
|
||||
|
129
vendor/github.com/charmbracelet/x/ansi/background.go
generated
vendored
129
vendor/github.com/charmbracelet/x/ansi/background.go
generated
vendored
@ -3,63 +3,93 @@ package ansi
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"github.com/lucasb-eyer/go-colorful"
|
||||
)
|
||||
|
||||
// Colorizer is a [color.Color] interface that can be formatted as a string.
|
||||
type Colorizer interface {
|
||||
color.Color
|
||||
fmt.Stringer
|
||||
// HexColor is a [color.Color] that can be formatted as a hex string.
|
||||
type HexColor string
|
||||
|
||||
// RGBA returns the RGBA values of the color.
|
||||
func (h HexColor) RGBA() (r, g, b, a uint32) {
|
||||
hex := h.color()
|
||||
if hex == nil {
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
return hex.RGBA()
|
||||
}
|
||||
|
||||
// HexColorizer is a [color.Color] that can be formatted as a hex string.
|
||||
type HexColorizer struct{ color.Color }
|
||||
|
||||
var _ Colorizer = HexColorizer{}
|
||||
// Hex returns the hex representation of the color. If the color is invalid, it
|
||||
// returns an empty string.
|
||||
func (h HexColor) Hex() string {
|
||||
hex := h.color()
|
||||
if hex == nil {
|
||||
return ""
|
||||
}
|
||||
return hex.Hex()
|
||||
}
|
||||
|
||||
// String returns the color as a hex string. If the color is nil, an empty
|
||||
// string is returned.
|
||||
func (h HexColorizer) String() string {
|
||||
if h.Color == nil {
|
||||
return ""
|
||||
}
|
||||
r, g, b, _ := h.RGBA()
|
||||
// Get the lower 8 bits
|
||||
r &= 0xff
|
||||
g &= 0xff
|
||||
b &= 0xff
|
||||
return fmt.Sprintf("#%02x%02x%02x", uint8(r), uint8(g), uint8(b)) //nolint:gosec
|
||||
func (h HexColor) String() string {
|
||||
return h.Hex()
|
||||
}
|
||||
|
||||
// XRGBColorizer is a [color.Color] that can be formatted as an XParseColor
|
||||
// color returns the underlying color of the HexColor.
|
||||
func (h HexColor) color() *colorful.Color {
|
||||
hex, err := colorful.Hex(string(h))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return &hex
|
||||
}
|
||||
|
||||
// XRGBColor is a [color.Color] that can be formatted as an XParseColor
|
||||
// rgb: string.
|
||||
//
|
||||
// See: https://linux.die.net/man/3/xparsecolor
|
||||
type XRGBColorizer struct{ color.Color }
|
||||
type XRGBColor struct {
|
||||
color.Color
|
||||
}
|
||||
|
||||
var _ Colorizer = XRGBColorizer{}
|
||||
// RGBA returns the RGBA values of the color.
|
||||
func (x XRGBColor) RGBA() (r, g, b, a uint32) {
|
||||
if x.Color == nil {
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
return x.Color.RGBA()
|
||||
}
|
||||
|
||||
// String returns the color as an XParseColor rgb: string. If the color is nil,
|
||||
// an empty string is returned.
|
||||
func (x XRGBColorizer) String() string {
|
||||
func (x XRGBColor) String() string {
|
||||
if x.Color == nil {
|
||||
return ""
|
||||
}
|
||||
r, g, b, _ := x.RGBA()
|
||||
r, g, b, _ := x.Color.RGBA()
|
||||
// Get the lower 8 bits
|
||||
return fmt.Sprintf("rgb:%04x/%04x/%04x", r, g, b)
|
||||
}
|
||||
|
||||
// XRGBAColorizer is a [color.Color] that can be formatted as an XParseColor
|
||||
// XRGBAColor is a [color.Color] that can be formatted as an XParseColor
|
||||
// rgba: string.
|
||||
//
|
||||
// See: https://linux.die.net/man/3/xparsecolor
|
||||
type XRGBAColorizer struct{ color.Color }
|
||||
type XRGBAColor struct {
|
||||
color.Color
|
||||
}
|
||||
|
||||
var _ Colorizer = XRGBAColorizer{}
|
||||
// RGBA returns the RGBA values of the color.
|
||||
func (x XRGBAColor) RGBA() (r, g, b, a uint32) {
|
||||
if x.Color == nil {
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
return x.Color.RGBA()
|
||||
}
|
||||
|
||||
// String returns the color as an XParseColor rgba: string. If the color is nil,
|
||||
// an empty string is returned.
|
||||
func (x XRGBAColorizer) String() string {
|
||||
func (x XRGBAColor) String() string {
|
||||
if x.Color == nil {
|
||||
return ""
|
||||
}
|
||||
@ -74,19 +104,12 @@ func (x XRGBAColorizer) String() string {
|
||||
// OSC 10 ; color ST
|
||||
// OSC 10 ; color BEL
|
||||
//
|
||||
// Where color is the encoded color number.
|
||||
// Where color is the encoded color number. Most terminals support hex,
|
||||
// XParseColor rgb: and rgba: strings. You could use [HexColor], [XRGBColor],
|
||||
// or [XRGBAColor] to format the color.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
|
||||
func SetForegroundColor(c color.Color) string {
|
||||
var s string
|
||||
switch c := c.(type) {
|
||||
case Colorizer:
|
||||
s = c.String()
|
||||
case fmt.Stringer:
|
||||
s = c.String()
|
||||
default:
|
||||
s = HexColorizer{c}.String()
|
||||
}
|
||||
func SetForegroundColor(s string) string {
|
||||
return "\x1b]10;" + s + "\x07"
|
||||
}
|
||||
|
||||
@ -108,19 +131,12 @@ const ResetForegroundColor = "\x1b]110\x07"
|
||||
// OSC 11 ; color ST
|
||||
// OSC 11 ; color BEL
|
||||
//
|
||||
// Where color is the encoded color number.
|
||||
// Where color is the encoded color number. Most terminals support hex,
|
||||
// XParseColor rgb: and rgba: strings. You could use [HexColor], [XRGBColor],
|
||||
// or [XRGBAColor] to format the color.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
|
||||
func SetBackgroundColor(c color.Color) string {
|
||||
var s string
|
||||
switch c := c.(type) {
|
||||
case Colorizer:
|
||||
s = c.String()
|
||||
case fmt.Stringer:
|
||||
s = c.String()
|
||||
default:
|
||||
s = HexColorizer{c}.String()
|
||||
}
|
||||
func SetBackgroundColor(s string) string {
|
||||
return "\x1b]11;" + s + "\x07"
|
||||
}
|
||||
|
||||
@ -141,19 +157,12 @@ const ResetBackgroundColor = "\x1b]111\x07"
|
||||
// OSC 12 ; color ST
|
||||
// OSC 12 ; color BEL
|
||||
//
|
||||
// Where color is the encoded color number.
|
||||
// Where color is the encoded color number. Most terminals support hex,
|
||||
// XParseColor rgb: and rgba: strings. You could use [HexColor], [XRGBColor],
|
||||
// or [XRGBAColor] to format the color.
|
||||
//
|
||||
// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
|
||||
func SetCursorColor(c color.Color) string {
|
||||
var s string
|
||||
switch c := c.(type) {
|
||||
case Colorizer:
|
||||
s = c.String()
|
||||
case fmt.Stringer:
|
||||
s = c.String()
|
||||
default:
|
||||
s = HexColorizer{c}.String()
|
||||
}
|
||||
func SetCursorColor(s string) string {
|
||||
return "\x1b]12;" + s + "\x07"
|
||||
}
|
||||
|
||||
|
10
vendor/github.com/charmbracelet/x/ansi/charset.go
generated
vendored
10
vendor/github.com/charmbracelet/x/ansi/charset.go
generated
vendored
@ -39,17 +39,17 @@ func SCS(gset byte, charset byte) string {
|
||||
return SelectCharacterSet(gset, charset)
|
||||
}
|
||||
|
||||
// Locking Shift 1 Right (LS1R) shifts G1 into GR character set.
|
||||
// LS1R (Locking Shift 1 Right) shifts G1 into GR character set.
|
||||
const LS1R = "\x1b~"
|
||||
|
||||
// Locking Shift 2 (LS2) shifts G2 into GL character set.
|
||||
// LS2 (Locking Shift 2) shifts G2 into GL character set.
|
||||
const LS2 = "\x1bn"
|
||||
|
||||
// Locking Shift 2 Right (LS2R) shifts G2 into GR character set.
|
||||
// LS2R (Locking Shift 2 Right) shifts G2 into GR character set.
|
||||
const LS2R = "\x1b}"
|
||||
|
||||
// Locking Shift 3 (LS3) shifts G3 into GL character set.
|
||||
// LS3 (Locking Shift 3) shifts G3 into GL character set.
|
||||
const LS3 = "\x1bo"
|
||||
|
||||
// Locking Shift 3 Right (LS3R) shifts G3 into GR character set.
|
||||
// LS3R (Locking Shift 3 Right) shifts G3 into GR character set.
|
||||
const LS3R = "\x1b|"
|
||||
|
728
vendor/github.com/charmbracelet/x/ansi/color.go
generated
vendored
728
vendor/github.com/charmbracelet/x/ansi/color.go
generated
vendored
@ -2,34 +2,9 @@ package ansi
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
)
|
||||
|
||||
// Technically speaking, the 16 basic ANSI colors are arbitrary and can be
|
||||
// customized at the terminal level. Given that, we're returning what we feel
|
||||
// are good defaults.
|
||||
//
|
||||
// This could also be a slice, but we use a map to make the mappings very
|
||||
// explicit.
|
||||
//
|
||||
// See: https://www.ditig.com/publications/256-colors-cheat-sheet
|
||||
var lowANSI = map[uint32]uint32{
|
||||
0: 0x000000, // black
|
||||
1: 0x800000, // red
|
||||
2: 0x008000, // green
|
||||
3: 0x808000, // yellow
|
||||
4: 0x000080, // blue
|
||||
5: 0x800080, // magenta
|
||||
6: 0x008080, // cyan
|
||||
7: 0xc0c0c0, // white
|
||||
8: 0x808080, // bright black
|
||||
9: 0xff0000, // bright red
|
||||
10: 0x00ff00, // bright green
|
||||
11: 0xffff00, // bright yellow
|
||||
12: 0x0000ff, // bright blue
|
||||
13: 0xff00ff, // bright magenta
|
||||
14: 0x00ffff, // bright cyan
|
||||
15: 0xffffff, // bright white
|
||||
}
|
||||
"github.com/lucasb-eyer/go-colorful"
|
||||
)
|
||||
|
||||
// Color is a color that can be used in a terminal. ANSI (including
|
||||
// ANSI256) and 24-bit "true colors" fall under this category.
|
||||
@ -100,28 +75,33 @@ func (c BasicColor) RGBA() (uint32, uint32, uint32, uint32) {
|
||||
return 0, 0, 0, 0xffff
|
||||
}
|
||||
|
||||
r, g, b := ansiToRGB(ansi)
|
||||
return toRGBA(r, g, b)
|
||||
return ansiToRGB(byte(ansi)).RGBA()
|
||||
}
|
||||
|
||||
// ExtendedColor is an ANSI 256 (8-bit) color with a value from 0 to 255.
|
||||
type ExtendedColor uint8
|
||||
// IndexedColor is an ANSI 256 (8-bit) color with a value from 0 to 255.
|
||||
type IndexedColor uint8
|
||||
|
||||
var _ Color = ExtendedColor(0)
|
||||
var _ Color = IndexedColor(0)
|
||||
|
||||
// RGBA returns the red, green, blue and alpha components of the color. It
|
||||
// satisfies the color.Color interface.
|
||||
func (c ExtendedColor) RGBA() (uint32, uint32, uint32, uint32) {
|
||||
r, g, b := ansiToRGB(uint32(c))
|
||||
return toRGBA(r, g, b)
|
||||
func (c IndexedColor) RGBA() (uint32, uint32, uint32, uint32) {
|
||||
return ansiToRGB(byte(c)).RGBA()
|
||||
}
|
||||
|
||||
// ExtendedColor is an ANSI 256 (8-bit) color with a value from 0 to 255.
|
||||
//
|
||||
// Deprecated: use [IndexedColor] instead.
|
||||
type ExtendedColor = IndexedColor
|
||||
|
||||
// TrueColor is a 24-bit color that can be used in the terminal.
|
||||
// This can be used to represent RGB colors.
|
||||
//
|
||||
// For example, the color red can be represented as:
|
||||
//
|
||||
// TrueColor(0xff0000)
|
||||
//
|
||||
// Deprecated: use [RGBColor] instead.
|
||||
type TrueColor uint32
|
||||
|
||||
var _ Color = TrueColor(0)
|
||||
@ -133,44 +113,25 @@ func (c TrueColor) RGBA() (uint32, uint32, uint32, uint32) {
|
||||
return toRGBA(r, g, b)
|
||||
}
|
||||
|
||||
// RGBColor is a 24-bit color that can be used in the terminal.
|
||||
// This can be used to represent RGB colors.
|
||||
type RGBColor struct {
|
||||
R uint8
|
||||
G uint8
|
||||
B uint8
|
||||
}
|
||||
|
||||
// RGBA returns the red, green, blue and alpha components of the color. It
|
||||
// satisfies the color.Color interface.
|
||||
func (c RGBColor) RGBA() (uint32, uint32, uint32, uint32) {
|
||||
return toRGBA(uint32(c.R), uint32(c.G), uint32(c.B))
|
||||
}
|
||||
|
||||
// ansiToRGB converts an ANSI color to a 24-bit RGB color.
|
||||
//
|
||||
// r, g, b := ansiToRGB(57)
|
||||
func ansiToRGB(ansi uint32) (uint32, uint32, uint32) {
|
||||
// For out-of-range values return black.
|
||||
if ansi > 255 {
|
||||
return 0, 0, 0
|
||||
}
|
||||
|
||||
// Low ANSI.
|
||||
if ansi < 16 {
|
||||
h, ok := lowANSI[ansi]
|
||||
if !ok {
|
||||
return 0, 0, 0
|
||||
}
|
||||
r, g, b := hexToRGB(h)
|
||||
return r, g, b
|
||||
}
|
||||
|
||||
// Grays.
|
||||
if ansi > 231 {
|
||||
s := (ansi-232)*10 + 8
|
||||
return s, s, s
|
||||
}
|
||||
|
||||
// ANSI256.
|
||||
n := ansi - 16
|
||||
b := n % 6
|
||||
g := (n - b) / 6 % 6
|
||||
r := (n - b - g*6) / 36 % 6
|
||||
for _, v := range []*uint32{&r, &g, &b} {
|
||||
if *v > 0 {
|
||||
c := *v*40 + 55
|
||||
*v = c
|
||||
}
|
||||
}
|
||||
|
||||
return r, g, b
|
||||
func ansiToRGB(ansi byte) color.Color {
|
||||
return ansiHex[ansi]
|
||||
}
|
||||
|
||||
// hexToRGB converts a number in hexadecimal format to red, green, and blue
|
||||
@ -194,3 +155,630 @@ func toRGBA(r, g, b uint32) (uint32, uint32, uint32, uint32) {
|
||||
b |= b << 8
|
||||
return r, g, b, 0xffff
|
||||
}
|
||||
|
||||
//nolint:unused
|
||||
func distSq(r1, g1, b1, r2, g2, b2 int) int {
|
||||
return ((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2))
|
||||
}
|
||||
|
||||
func to6Cube[T int | float64](v T) int {
|
||||
if v < 48 {
|
||||
return 0
|
||||
}
|
||||
if v < 115 {
|
||||
return 1
|
||||
}
|
||||
return int((v - 35) / 40)
|
||||
}
|
||||
|
||||
// Convert256 converts a [color.Color], usually a 24-bit color, to xterm(1) 256
|
||||
// color palette.
|
||||
//
|
||||
// xterm provides a 6x6x6 color cube (16 - 231) and 24 greys (232 - 255). We
|
||||
// map our RGB color to the closest in the cube, also work out the closest
|
||||
// grey, and use the nearest of the two based on the lightness of the color.
|
||||
//
|
||||
// Note that the xterm has much lower resolution for darker colors (they are
|
||||
// not evenly spread out), so our 6 levels are not evenly spread: 0x0, 0x5f
|
||||
// (95), 0x87 (135), 0xaf (175), 0xd7 (215) and 0xff (255). Greys are more
|
||||
// evenly spread (8, 18, 28 ... 238).
|
||||
func Convert256(c color.Color) IndexedColor {
|
||||
// If the color is already an IndexedColor, return it.
|
||||
if i, ok := c.(IndexedColor); ok {
|
||||
return i
|
||||
}
|
||||
|
||||
// Note: this is mostly ported from tmux/colour.c.
|
||||
col, ok := colorful.MakeColor(c)
|
||||
if !ok {
|
||||
return IndexedColor(0)
|
||||
}
|
||||
|
||||
r := col.R * 255
|
||||
g := col.G * 255
|
||||
b := col.B * 255
|
||||
|
||||
q2c := [6]int{0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff}
|
||||
|
||||
// Map RGB to 6x6x6 cube.
|
||||
qr := to6Cube(r)
|
||||
cr := q2c[qr]
|
||||
qg := to6Cube(g)
|
||||
cg := q2c[qg]
|
||||
qb := to6Cube(b)
|
||||
cb := q2c[qb]
|
||||
|
||||
// If we have hit the color exactly, return early.
|
||||
ci := (36 * qr) + (6 * qg) + qb
|
||||
if cr == int(r) && cg == int(g) && cb == int(b) {
|
||||
return IndexedColor(16 + ci) //nolint:gosec
|
||||
}
|
||||
|
||||
// Work out the closest grey (average of RGB).
|
||||
greyAvg := int(r+g+b) / 3
|
||||
var greyIdx int
|
||||
if greyAvg > 238 {
|
||||
greyIdx = 23
|
||||
} else {
|
||||
greyIdx = (greyAvg - 3) / 10
|
||||
}
|
||||
grey := 8 + (10 * greyIdx)
|
||||
|
||||
// Return the one which is nearer to the original input rgb value
|
||||
// XXX: This is where it differs from tmux's implementation, we prefer the
|
||||
// closer color to the original in terms of light distances rather than the
|
||||
// cube distance.
|
||||
c2 := colorful.Color{R: float64(cr) / 255.0, G: float64(cg) / 255.0, B: float64(cb) / 255.0}
|
||||
g2 := colorful.Color{R: float64(grey) / 255.0, G: float64(grey) / 255.0, B: float64(grey) / 255.0}
|
||||
colorDist := col.DistanceHSLuv(c2)
|
||||
grayDist := col.DistanceHSLuv(g2)
|
||||
|
||||
if colorDist <= grayDist {
|
||||
return IndexedColor(16 + ci) //nolint:gosec
|
||||
}
|
||||
return IndexedColor(232 + greyIdx) //nolint:gosec
|
||||
|
||||
// // Is grey or 6x6x6 color closest?
|
||||
// d := distSq(cr, cg, cb, int(r), int(g), int(b))
|
||||
// if distSq(grey, grey, grey, int(r), int(g), int(b)) < d {
|
||||
// return IndexedColor(232 + greyIdx) //nolint:gosec
|
||||
// }
|
||||
// return IndexedColor(16 + ci) //nolint:gosec
|
||||
}
|
||||
|
||||
// Convert16 converts a [color.Color] to a 16-color ANSI color. It will first
|
||||
// try to find a match in the 256 xterm(1) color palette, and then map that to
|
||||
// the 16-color ANSI palette.
|
||||
func Convert16(c color.Color) BasicColor {
|
||||
switch c := c.(type) {
|
||||
case BasicColor:
|
||||
// If the color is already a BasicColor, return it.
|
||||
return c
|
||||
case IndexedColor:
|
||||
// If the color is already an IndexedColor, return the corresponding
|
||||
// BasicColor.
|
||||
return ansi256To16[c]
|
||||
default:
|
||||
c256 := Convert256(c)
|
||||
return ansi256To16[c256]
|
||||
}
|
||||
}
|
||||
|
||||
// RGB values of ANSI colors (0-255).
|
||||
var ansiHex = [...]color.RGBA{
|
||||
0: {R: 0x00, G: 0x00, B: 0x00, A: 0xff}, // "#000000"
|
||||
1: {R: 0x80, G: 0x00, B: 0x00, A: 0xff}, // "#800000"
|
||||
2: {R: 0x00, G: 0x80, B: 0x00, A: 0xff}, // "#008000"
|
||||
3: {R: 0x80, G: 0x80, B: 0x00, A: 0xff}, // "#808000"
|
||||
4: {R: 0x00, G: 0x00, B: 0x80, A: 0xff}, // "#000080"
|
||||
5: {R: 0x80, G: 0x00, B: 0x80, A: 0xff}, // "#800080"
|
||||
6: {R: 0x00, G: 0x80, B: 0x80, A: 0xff}, // "#008080"
|
||||
7: {R: 0xc0, G: 0xc0, B: 0xc0, A: 0xff}, // "#c0c0c0"
|
||||
8: {R: 0x80, G: 0x80, B: 0x80, A: 0xff}, // "#808080"
|
||||
9: {R: 0xff, G: 0x00, B: 0x00, A: 0xff}, // "#ff0000"
|
||||
10: {R: 0x00, G: 0xff, B: 0x00, A: 0xff}, // "#00ff00"
|
||||
11: {R: 0xff, G: 0xff, B: 0x00, A: 0xff}, // "#ffff00"
|
||||
12: {R: 0x00, G: 0x00, B: 0xff, A: 0xff}, // "#0000ff"
|
||||
13: {R: 0xff, G: 0x00, B: 0xff, A: 0xff}, // "#ff00ff"
|
||||
14: {R: 0x00, G: 0xff, B: 0xff, A: 0xff}, // "#00ffff"
|
||||
15: {R: 0xff, G: 0xff, B: 0xff, A: 0xff}, // "#ffffff"
|
||||
16: {R: 0x00, G: 0x00, B: 0x00, A: 0xff}, // "#000000"
|
||||
17: {R: 0x00, G: 0x00, B: 0x5f, A: 0xff}, // "#00005f"
|
||||
18: {R: 0x00, G: 0x00, B: 0x87, A: 0xff}, // "#000087"
|
||||
19: {R: 0x00, G: 0x00, B: 0xaf, A: 0xff}, // "#0000af"
|
||||
20: {R: 0x00, G: 0x00, B: 0xd7, A: 0xff}, // "#0000d7"
|
||||
21: {R: 0x00, G: 0x00, B: 0xff, A: 0xff}, // "#0000ff"
|
||||
22: {R: 0x00, G: 0x5f, B: 0x00, A: 0xff}, // "#005f00"
|
||||
23: {R: 0x00, G: 0x5f, B: 0x5f, A: 0xff}, // "#005f5f"
|
||||
24: {R: 0x00, G: 0x5f, B: 0x87, A: 0xff}, // "#005f87"
|
||||
25: {R: 0x00, G: 0x5f, B: 0xaf, A: 0xff}, // "#005faf"
|
||||
26: {R: 0x00, G: 0x5f, B: 0xd7, A: 0xff}, // "#005fd7"
|
||||
27: {R: 0x00, G: 0x5f, B: 0xff, A: 0xff}, // "#005fff"
|
||||
28: {R: 0x00, G: 0x87, B: 0x00, A: 0xff}, // "#008700"
|
||||
29: {R: 0x00, G: 0x87, B: 0x5f, A: 0xff}, // "#00875f"
|
||||
30: {R: 0x00, G: 0x87, B: 0x87, A: 0xff}, // "#008787"
|
||||
31: {R: 0x00, G: 0x87, B: 0xaf, A: 0xff}, // "#0087af"
|
||||
32: {R: 0x00, G: 0x87, B: 0xd7, A: 0xff}, // "#0087d7"
|
||||
33: {R: 0x00, G: 0x87, B: 0xff, A: 0xff}, // "#0087ff"
|
||||
34: {R: 0x00, G: 0xaf, B: 0x00, A: 0xff}, // "#00af00"
|
||||
35: {R: 0x00, G: 0xaf, B: 0x5f, A: 0xff}, // "#00af5f"
|
||||
36: {R: 0x00, G: 0xaf, B: 0x87, A: 0xff}, // "#00af87"
|
||||
37: {R: 0x00, G: 0xaf, B: 0xaf, A: 0xff}, // "#00afaf"
|
||||
38: {R: 0x00, G: 0xaf, B: 0xd7, A: 0xff}, // "#00afd7"
|
||||
39: {R: 0x00, G: 0xaf, B: 0xff, A: 0xff}, // "#00afff"
|
||||
40: {R: 0x00, G: 0xd7, B: 0x00, A: 0xff}, // "#00d700"
|
||||
41: {R: 0x00, G: 0xd7, B: 0x5f, A: 0xff}, // "#00d75f"
|
||||
42: {R: 0x00, G: 0xd7, B: 0x87, A: 0xff}, // "#00d787"
|
||||
43: {R: 0x00, G: 0xd7, B: 0xaf, A: 0xff}, // "#00d7af"
|
||||
44: {R: 0x00, G: 0xd7, B: 0xd7, A: 0xff}, // "#00d7d7"
|
||||
45: {R: 0x00, G: 0xd7, B: 0xff, A: 0xff}, // "#00d7ff"
|
||||
46: {R: 0x00, G: 0xff, B: 0x00, A: 0xff}, // "#00ff00"
|
||||
47: {R: 0x00, G: 0xff, B: 0x5f, A: 0xff}, // "#00ff5f"
|
||||
48: {R: 0x00, G: 0xff, B: 0x87, A: 0xff}, // "#00ff87"
|
||||
49: {R: 0x00, G: 0xff, B: 0xaf, A: 0xff}, // "#00ffaf"
|
||||
50: {R: 0x00, G: 0xff, B: 0xd7, A: 0xff}, // "#00ffd7"
|
||||
51: {R: 0x00, G: 0xff, B: 0xff, A: 0xff}, // "#00ffff"
|
||||
52: {R: 0x5f, G: 0x00, B: 0x00, A: 0xff}, // "#5f0000"
|
||||
53: {R: 0x5f, G: 0x00, B: 0x5f, A: 0xff}, // "#5f005f"
|
||||
54: {R: 0x5f, G: 0x00, B: 0x87, A: 0xff}, // "#5f0087"
|
||||
55: {R: 0x5f, G: 0x00, B: 0xaf, A: 0xff}, // "#5f00af"
|
||||
56: {R: 0x5f, G: 0x00, B: 0xd7, A: 0xff}, // "#5f00d7"
|
||||
57: {R: 0x5f, G: 0x00, B: 0xff, A: 0xff}, // "#5f00ff"
|
||||
58: {R: 0x5f, G: 0x5f, B: 0x00, A: 0xff}, // "#5f5f00"
|
||||
59: {R: 0x5f, G: 0x5f, B: 0x5f, A: 0xff}, // "#5f5f5f"
|
||||
60: {R: 0x5f, G: 0x5f, B: 0x87, A: 0xff}, // "#5f5f87"
|
||||
61: {R: 0x5f, G: 0x5f, B: 0xaf, A: 0xff}, // "#5f5faf"
|
||||
62: {R: 0x5f, G: 0x5f, B: 0xd7, A: 0xff}, // "#5f5fd7"
|
||||
63: {R: 0x5f, G: 0x5f, B: 0xff, A: 0xff}, // "#5f5fff"
|
||||
64: {R: 0x5f, G: 0x87, B: 0x00, A: 0xff}, // "#5f8700"
|
||||
65: {R: 0x5f, G: 0x87, B: 0x5f, A: 0xff}, // "#5f875f"
|
||||
66: {R: 0x5f, G: 0x87, B: 0x87, A: 0xff}, // "#5f8787"
|
||||
67: {R: 0x5f, G: 0x87, B: 0xaf, A: 0xff}, // "#5f87af"
|
||||
68: {R: 0x5f, G: 0x87, B: 0xd7, A: 0xff}, // "#5f87d7"
|
||||
69: {R: 0x5f, G: 0x87, B: 0xff, A: 0xff}, // "#5f87ff"
|
||||
70: {R: 0x5f, G: 0xaf, B: 0x00, A: 0xff}, // "#5faf00"
|
||||
71: {R: 0x5f, G: 0xaf, B: 0x5f, A: 0xff}, // "#5faf5f"
|
||||
72: {R: 0x5f, G: 0xaf, B: 0x87, A: 0xff}, // "#5faf87"
|
||||
73: {R: 0x5f, G: 0xaf, B: 0xaf, A: 0xff}, // "#5fafaf"
|
||||
74: {R: 0x5f, G: 0xaf, B: 0xd7, A: 0xff}, // "#5fafd7"
|
||||
75: {R: 0x5f, G: 0xaf, B: 0xff, A: 0xff}, // "#5fafff"
|
||||
76: {R: 0x5f, G: 0xd7, B: 0x00, A: 0xff}, // "#5fd700"
|
||||
77: {R: 0x5f, G: 0xd7, B: 0x5f, A: 0xff}, // "#5fd75f"
|
||||
78: {R: 0x5f, G: 0xd7, B: 0x87, A: 0xff}, // "#5fd787"
|
||||
79: {R: 0x5f, G: 0xd7, B: 0xaf, A: 0xff}, // "#5fd7af"
|
||||
80: {R: 0x5f, G: 0xd7, B: 0xd7, A: 0xff}, // "#5fd7d7"
|
||||
81: {R: 0x5f, G: 0xd7, B: 0xff, A: 0xff}, // "#5fd7ff"
|
||||
82: {R: 0x5f, G: 0xff, B: 0x00, A: 0xff}, // "#5fff00"
|
||||
83: {R: 0x5f, G: 0xff, B: 0x5f, A: 0xff}, // "#5fff5f"
|
||||
84: {R: 0x5f, G: 0xff, B: 0x87, A: 0xff}, // "#5fff87"
|
||||
85: {R: 0x5f, G: 0xff, B: 0xaf, A: 0xff}, // "#5fffaf"
|
||||
86: {R: 0x5f, G: 0xff, B: 0xd7, A: 0xff}, // "#5fffd7"
|
||||
87: {R: 0x5f, G: 0xff, B: 0xff, A: 0xff}, // "#5fffff"
|
||||
88: {R: 0x87, G: 0x00, B: 0x00, A: 0xff}, // "#870000"
|
||||
89: {R: 0x87, G: 0x00, B: 0x5f, A: 0xff}, // "#87005f"
|
||||
90: {R: 0x87, G: 0x00, B: 0x87, A: 0xff}, // "#870087"
|
||||
91: {R: 0x87, G: 0x00, B: 0xaf, A: 0xff}, // "#8700af"
|
||||
92: {R: 0x87, G: 0x00, B: 0xd7, A: 0xff}, // "#8700d7"
|
||||
93: {R: 0x87, G: 0x00, B: 0xff, A: 0xff}, // "#8700ff"
|
||||
94: {R: 0x87, G: 0x5f, B: 0x00, A: 0xff}, // "#875f00"
|
||||
95: {R: 0x87, G: 0x5f, B: 0x5f, A: 0xff}, // "#875f5f"
|
||||
96: {R: 0x87, G: 0x5f, B: 0x87, A: 0xff}, // "#875f87"
|
||||
97: {R: 0x87, G: 0x5f, B: 0xaf, A: 0xff}, // "#875faf"
|
||||
98: {R: 0x87, G: 0x5f, B: 0xd7, A: 0xff}, // "#875fd7"
|
||||
99: {R: 0x87, G: 0x5f, B: 0xff, A: 0xff}, // "#875fff"
|
||||
100: {R: 0x87, G: 0x87, B: 0x00, A: 0xff}, // "#878700"
|
||||
101: {R: 0x87, G: 0x87, B: 0x5f, A: 0xff}, // "#87875f"
|
||||
102: {R: 0x87, G: 0x87, B: 0x87, A: 0xff}, // "#878787"
|
||||
103: {R: 0x87, G: 0x87, B: 0xaf, A: 0xff}, // "#8787af"
|
||||
104: {R: 0x87, G: 0x87, B: 0xd7, A: 0xff}, // "#8787d7"
|
||||
105: {R: 0x87, G: 0x87, B: 0xff, A: 0xff}, // "#8787ff"
|
||||
106: {R: 0x87, G: 0xaf, B: 0x00, A: 0xff}, // "#87af00"
|
||||
107: {R: 0x87, G: 0xaf, B: 0x5f, A: 0xff}, // "#87af5f"
|
||||
108: {R: 0x87, G: 0xaf, B: 0x87, A: 0xff}, // "#87af87"
|
||||
109: {R: 0x87, G: 0xaf, B: 0xaf, A: 0xff}, // "#87afaf"
|
||||
110: {R: 0x87, G: 0xaf, B: 0xd7, A: 0xff}, // "#87afd7"
|
||||
111: {R: 0x87, G: 0xaf, B: 0xff, A: 0xff}, // "#87afff"
|
||||
112: {R: 0x87, G: 0xd7, B: 0x00, A: 0xff}, // "#87d700"
|
||||
113: {R: 0x87, G: 0xd7, B: 0x5f, A: 0xff}, // "#87d75f"
|
||||
114: {R: 0x87, G: 0xd7, B: 0x87, A: 0xff}, // "#87d787"
|
||||
115: {R: 0x87, G: 0xd7, B: 0xaf, A: 0xff}, // "#87d7af"
|
||||
116: {R: 0x87, G: 0xd7, B: 0xd7, A: 0xff}, // "#87d7d7"
|
||||
117: {R: 0x87, G: 0xd7, B: 0xff, A: 0xff}, // "#87d7ff"
|
||||
118: {R: 0x87, G: 0xff, B: 0x00, A: 0xff}, // "#87ff00"
|
||||
119: {R: 0x87, G: 0xff, B: 0x5f, A: 0xff}, // "#87ff5f"
|
||||
120: {R: 0x87, G: 0xff, B: 0x87, A: 0xff}, // "#87ff87"
|
||||
121: {R: 0x87, G: 0xff, B: 0xaf, A: 0xff}, // "#87ffaf"
|
||||
122: {R: 0x87, G: 0xff, B: 0xd7, A: 0xff}, // "#87ffd7"
|
||||
123: {R: 0x87, G: 0xff, B: 0xff, A: 0xff}, // "#87ffff"
|
||||
124: {R: 0xaf, G: 0x00, B: 0x00, A: 0xff}, // "#af0000"
|
||||
125: {R: 0xaf, G: 0x00, B: 0x5f, A: 0xff}, // "#af005f"
|
||||
126: {R: 0xaf, G: 0x00, B: 0x87, A: 0xff}, // "#af0087"
|
||||
127: {R: 0xaf, G: 0x00, B: 0xaf, A: 0xff}, // "#af00af"
|
||||
128: {R: 0xaf, G: 0x00, B: 0xd7, A: 0xff}, // "#af00d7"
|
||||
129: {R: 0xaf, G: 0x00, B: 0xff, A: 0xff}, // "#af00ff"
|
||||
130: {R: 0xaf, G: 0x5f, B: 0x00, A: 0xff}, // "#af5f00"
|
||||
131: {R: 0xaf, G: 0x5f, B: 0x5f, A: 0xff}, // "#af5f5f"
|
||||
132: {R: 0xaf, G: 0x5f, B: 0x87, A: 0xff}, // "#af5f87"
|
||||
133: {R: 0xaf, G: 0x5f, B: 0xaf, A: 0xff}, // "#af5faf"
|
||||
134: {R: 0xaf, G: 0x5f, B: 0xd7, A: 0xff}, // "#af5fd7"
|
||||
135: {R: 0xaf, G: 0x5f, B: 0xff, A: 0xff}, // "#af5fff"
|
||||
136: {R: 0xaf, G: 0x87, B: 0x00, A: 0xff}, // "#af8700"
|
||||
137: {R: 0xaf, G: 0x87, B: 0x5f, A: 0xff}, // "#af875f"
|
||||
138: {R: 0xaf, G: 0x87, B: 0x87, A: 0xff}, // "#af8787"
|
||||
139: {R: 0xaf, G: 0x87, B: 0xaf, A: 0xff}, // "#af87af"
|
||||
140: {R: 0xaf, G: 0x87, B: 0xd7, A: 0xff}, // "#af87d7"
|
||||
141: {R: 0xaf, G: 0x87, B: 0xff, A: 0xff}, // "#af87ff"
|
||||
142: {R: 0xaf, G: 0xaf, B: 0x00, A: 0xff}, // "#afaf00"
|
||||
143: {R: 0xaf, G: 0xaf, B: 0x5f, A: 0xff}, // "#afaf5f"
|
||||
144: {R: 0xaf, G: 0xaf, B: 0x87, A: 0xff}, // "#afaf87"
|
||||
145: {R: 0xaf, G: 0xaf, B: 0xaf, A: 0xff}, // "#afafaf"
|
||||
146: {R: 0xaf, G: 0xaf, B: 0xd7, A: 0xff}, // "#afafd7"
|
||||
147: {R: 0xaf, G: 0xaf, B: 0xff, A: 0xff}, // "#afafff"
|
||||
148: {R: 0xaf, G: 0xd7, B: 0x00, A: 0xff}, // "#afd700"
|
||||
149: {R: 0xaf, G: 0xd7, B: 0x5f, A: 0xff}, // "#afd75f"
|
||||
150: {R: 0xaf, G: 0xd7, B: 0x87, A: 0xff}, // "#afd787"
|
||||
151: {R: 0xaf, G: 0xd7, B: 0xaf, A: 0xff}, // "#afd7af"
|
||||
152: {R: 0xaf, G: 0xd7, B: 0xd7, A: 0xff}, // "#afd7d7"
|
||||
153: {R: 0xaf, G: 0xd7, B: 0xff, A: 0xff}, // "#afd7ff"
|
||||
154: {R: 0xaf, G: 0xff, B: 0x00, A: 0xff}, // "#afff00"
|
||||
155: {R: 0xaf, G: 0xff, B: 0x5f, A: 0xff}, // "#afff5f"
|
||||
156: {R: 0xaf, G: 0xff, B: 0x87, A: 0xff}, // "#afff87"
|
||||
157: {R: 0xaf, G: 0xff, B: 0xaf, A: 0xff}, // "#afffaf"
|
||||
158: {R: 0xaf, G: 0xff, B: 0xd7, A: 0xff}, // "#afffd7"
|
||||
159: {R: 0xaf, G: 0xff, B: 0xff, A: 0xff}, // "#afffff"
|
||||
160: {R: 0xd7, G: 0x00, B: 0x00, A: 0xff}, // "#d70000"
|
||||
161: {R: 0xd7, G: 0x00, B: 0x5f, A: 0xff}, // "#d7005f"
|
||||
162: {R: 0xd7, G: 0x00, B: 0x87, A: 0xff}, // "#d70087"
|
||||
163: {R: 0xd7, G: 0x00, B: 0xaf, A: 0xff}, // "#d700af"
|
||||
164: {R: 0xd7, G: 0x00, B: 0xd7, A: 0xff}, // "#d700d7"
|
||||
165: {R: 0xd7, G: 0x00, B: 0xff, A: 0xff}, // "#d700ff"
|
||||
166: {R: 0xd7, G: 0x5f, B: 0x00, A: 0xff}, // "#d75f00"
|
||||
167: {R: 0xd7, G: 0x5f, B: 0x5f, A: 0xff}, // "#d75f5f"
|
||||
168: {R: 0xd7, G: 0x5f, B: 0x87, A: 0xff}, // "#d75f87"
|
||||
169: {R: 0xd7, G: 0x5f, B: 0xaf, A: 0xff}, // "#d75faf"
|
||||
170: {R: 0xd7, G: 0x5f, B: 0xd7, A: 0xff}, // "#d75fd7"
|
||||
171: {R: 0xd7, G: 0x5f, B: 0xff, A: 0xff}, // "#d75fff"
|
||||
172: {R: 0xd7, G: 0x87, B: 0x00, A: 0xff}, // "#d78700"
|
||||
173: {R: 0xd7, G: 0x87, B: 0x5f, A: 0xff}, // "#d7875f"
|
||||
174: {R: 0xd7, G: 0x87, B: 0x87, A: 0xff}, // "#d78787"
|
||||
175: {R: 0xd7, G: 0x87, B: 0xaf, A: 0xff}, // "#d787af"
|
||||
176: {R: 0xd7, G: 0x87, B: 0xd7, A: 0xff}, // "#d787d7"
|
||||
177: {R: 0xd7, G: 0x87, B: 0xff, A: 0xff}, // "#d787ff"
|
||||
178: {R: 0xd7, G: 0xaf, B: 0x00, A: 0xff}, // "#d7af00"
|
||||
179: {R: 0xd7, G: 0xaf, B: 0x5f, A: 0xff}, // "#d7af5f"
|
||||
180: {R: 0xd7, G: 0xaf, B: 0x87, A: 0xff}, // "#d7af87"
|
||||
181: {R: 0xd7, G: 0xaf, B: 0xaf, A: 0xff}, // "#d7afaf"
|
||||
182: {R: 0xd7, G: 0xaf, B: 0xd7, A: 0xff}, // "#d7afd7"
|
||||
183: {R: 0xd7, G: 0xaf, B: 0xff, A: 0xff}, // "#d7afff"
|
||||
184: {R: 0xd7, G: 0xd7, B: 0x00, A: 0xff}, // "#d7d700"
|
||||
185: {R: 0xd7, G: 0xd7, B: 0x5f, A: 0xff}, // "#d7d75f"
|
||||
186: {R: 0xd7, G: 0xd7, B: 0x87, A: 0xff}, // "#d7d787"
|
||||
187: {R: 0xd7, G: 0xd7, B: 0xaf, A: 0xff}, // "#d7d7af"
|
||||
188: {R: 0xd7, G: 0xd7, B: 0xd7, A: 0xff}, // "#d7d7d7"
|
||||
189: {R: 0xd7, G: 0xd7, B: 0xff, A: 0xff}, // "#d7d7ff"
|
||||
190: {R: 0xd7, G: 0xff, B: 0x00, A: 0xff}, // "#d7ff00"
|
||||
191: {R: 0xd7, G: 0xff, B: 0x5f, A: 0xff}, // "#d7ff5f"
|
||||
192: {R: 0xd7, G: 0xff, B: 0x87, A: 0xff}, // "#d7ff87"
|
||||
193: {R: 0xd7, G: 0xff, B: 0xaf, A: 0xff}, // "#d7ffaf"
|
||||
194: {R: 0xd7, G: 0xff, B: 0xd7, A: 0xff}, // "#d7ffd7"
|
||||
195: {R: 0xd7, G: 0xff, B: 0xff, A: 0xff}, // "#d7ffff"
|
||||
196: {R: 0xff, G: 0x00, B: 0x00, A: 0xff}, // "#ff0000"
|
||||
197: {R: 0xff, G: 0x00, B: 0x5f, A: 0xff}, // "#ff005f"
|
||||
198: {R: 0xff, G: 0x00, B: 0x87, A: 0xff}, // "#ff0087"
|
||||
199: {R: 0xff, G: 0x00, B: 0xaf, A: 0xff}, // "#ff00af"
|
||||
200: {R: 0xff, G: 0x00, B: 0xd7, A: 0xff}, // "#ff00d7"
|
||||
201: {R: 0xff, G: 0x00, B: 0xff, A: 0xff}, // "#ff00ff"
|
||||
202: {R: 0xff, G: 0x5f, B: 0x00, A: 0xff}, // "#ff5f00"
|
||||
203: {R: 0xff, G: 0x5f, B: 0x5f, A: 0xff}, // "#ff5f5f"
|
||||
204: {R: 0xff, G: 0x5f, B: 0x87, A: 0xff}, // "#ff5f87"
|
||||
205: {R: 0xff, G: 0x5f, B: 0xaf, A: 0xff}, // "#ff5faf"
|
||||
206: {R: 0xff, G: 0x5f, B: 0xd7, A: 0xff}, // "#ff5fd7"
|
||||
207: {R: 0xff, G: 0x5f, B: 0xff, A: 0xff}, // "#ff5fff"
|
||||
208: {R: 0xff, G: 0x87, B: 0x00, A: 0xff}, // "#ff8700"
|
||||
209: {R: 0xff, G: 0x87, B: 0x5f, A: 0xff}, // "#ff875f"
|
||||
210: {R: 0xff, G: 0x87, B: 0x87, A: 0xff}, // "#ff8787"
|
||||
211: {R: 0xff, G: 0x87, B: 0xaf, A: 0xff}, // "#ff87af"
|
||||
212: {R: 0xff, G: 0x87, B: 0xd7, A: 0xff}, // "#ff87d7"
|
||||
213: {R: 0xff, G: 0x87, B: 0xff, A: 0xff}, // "#ff87ff"
|
||||
214: {R: 0xff, G: 0xaf, B: 0x00, A: 0xff}, // "#ffaf00"
|
||||
215: {R: 0xff, G: 0xaf, B: 0x5f, A: 0xff}, // "#ffaf5f"
|
||||
216: {R: 0xff, G: 0xaf, B: 0x87, A: 0xff}, // "#ffaf87"
|
||||
217: {R: 0xff, G: 0xaf, B: 0xaf, A: 0xff}, // "#ffafaf"
|
||||
218: {R: 0xff, G: 0xaf, B: 0xd7, A: 0xff}, // "#ffafd7"
|
||||
219: {R: 0xff, G: 0xaf, B: 0xff, A: 0xff}, // "#ffafff"
|
||||
220: {R: 0xff, G: 0xd7, B: 0x00, A: 0xff}, // "#ffd700"
|
||||
221: {R: 0xff, G: 0xd7, B: 0x5f, A: 0xff}, // "#ffd75f"
|
||||
222: {R: 0xff, G: 0xd7, B: 0x87, A: 0xff}, // "#ffd787"
|
||||
223: {R: 0xff, G: 0xd7, B: 0xaf, A: 0xff}, // "#ffd7af"
|
||||
224: {R: 0xff, G: 0xd7, B: 0xd7, A: 0xff}, // "#ffd7d7"
|
||||
225: {R: 0xff, G: 0xd7, B: 0xff, A: 0xff}, // "#ffd7ff"
|
||||
226: {R: 0xff, G: 0xff, B: 0x00, A: 0xff}, // "#ffff00"
|
||||
227: {R: 0xff, G: 0xff, B: 0x5f, A: 0xff}, // "#ffff5f"
|
||||
228: {R: 0xff, G: 0xff, B: 0x87, A: 0xff}, // "#ffff87"
|
||||
229: {R: 0xff, G: 0xff, B: 0xaf, A: 0xff}, // "#ffffaf"
|
||||
230: {R: 0xff, G: 0xff, B: 0xd7, A: 0xff}, // "#ffffd7"
|
||||
231: {R: 0xff, G: 0xff, B: 0xff, A: 0xff}, // "#ffffff"
|
||||
232: {R: 0x08, G: 0x08, B: 0x08, A: 0xff}, // "#080808"
|
||||
233: {R: 0x12, G: 0x12, B: 0x12, A: 0xff}, // "#121212"
|
||||
234: {R: 0x1c, G: 0x1c, B: 0x1c, A: 0xff}, // "#1c1c1c"
|
||||
235: {R: 0x26, G: 0x26, B: 0x26, A: 0xff}, // "#262626"
|
||||
236: {R: 0x30, G: 0x30, B: 0x30, A: 0xff}, // "#303030"
|
||||
237: {R: 0x3a, G: 0x3a, B: 0x3a, A: 0xff}, // "#3a3a3a"
|
||||
238: {R: 0x44, G: 0x44, B: 0x44, A: 0xff}, // "#444444"
|
||||
239: {R: 0x4e, G: 0x4e, B: 0x4e, A: 0xff}, // "#4e4e4e"
|
||||
240: {R: 0x58, G: 0x58, B: 0x58, A: 0xff}, // "#585858"
|
||||
241: {R: 0x62, G: 0x62, B: 0x62, A: 0xff}, // "#626262"
|
||||
242: {R: 0x6c, G: 0x6c, B: 0x6c, A: 0xff}, // "#6c6c6c"
|
||||
243: {R: 0x76, G: 0x76, B: 0x76, A: 0xff}, // "#767676"
|
||||
244: {R: 0x80, G: 0x80, B: 0x80, A: 0xff}, // "#808080"
|
||||
245: {R: 0x8a, G: 0x8a, B: 0x8a, A: 0xff}, // "#8a8a8a"
|
||||
246: {R: 0x94, G: 0x94, B: 0x94, A: 0xff}, // "#949494"
|
||||
247: {R: 0x9e, G: 0x9e, B: 0x9e, A: 0xff}, // "#9e9e9e"
|
||||
248: {R: 0xa8, G: 0xa8, B: 0xa8, A: 0xff}, // "#a8a8a8"
|
||||
249: {R: 0xb2, G: 0xb2, B: 0xb2, A: 0xff}, // "#b2b2b2"
|
||||
250: {R: 0xbc, G: 0xbc, B: 0xbc, A: 0xff}, // "#bcbcbc"
|
||||
251: {R: 0xc6, G: 0xc6, B: 0xc6, A: 0xff}, // "#c6c6c6"
|
||||
252: {R: 0xd0, G: 0xd0, B: 0xd0, A: 0xff}, // "#d0d0d0"
|
||||
253: {R: 0xda, G: 0xda, B: 0xda, A: 0xff}, // "#dadada"
|
||||
254: {R: 0xe4, G: 0xe4, B: 0xe4, A: 0xff}, // "#e4e4e4"
|
||||
255: {R: 0xee, G: 0xee, B: 0xee, A: 0xff}, // "#eeeeee"
|
||||
}
|
||||
|
||||
var ansi256To16 = [...]BasicColor{
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 3,
|
||||
4: 4,
|
||||
5: 5,
|
||||
6: 6,
|
||||
7: 7,
|
||||
8: 8,
|
||||
9: 9,
|
||||
10: 10,
|
||||
11: 11,
|
||||
12: 12,
|
||||
13: 13,
|
||||
14: 14,
|
||||
15: 15,
|
||||
16: 0,
|
||||
17: 4,
|
||||
18: 4,
|
||||
19: 4,
|
||||
20: 12,
|
||||
21: 12,
|
||||
22: 2,
|
||||
23: 6,
|
||||
24: 4,
|
||||
25: 4,
|
||||
26: 12,
|
||||
27: 12,
|
||||
28: 2,
|
||||
29: 2,
|
||||
30: 6,
|
||||
31: 4,
|
||||
32: 12,
|
||||
33: 12,
|
||||
34: 2,
|
||||
35: 2,
|
||||
36: 2,
|
||||
37: 6,
|
||||
38: 12,
|
||||
39: 12,
|
||||
40: 10,
|
||||
41: 10,
|
||||
42: 10,
|
||||
43: 10,
|
||||
44: 14,
|
||||
45: 12,
|
||||
46: 10,
|
||||
47: 10,
|
||||
48: 10,
|
||||
49: 10,
|
||||
50: 10,
|
||||
51: 14,
|
||||
52: 1,
|
||||
53: 5,
|
||||
54: 4,
|
||||
55: 4,
|
||||
56: 12,
|
||||
57: 12,
|
||||
58: 3,
|
||||
59: 8,
|
||||
60: 4,
|
||||
61: 4,
|
||||
62: 12,
|
||||
63: 12,
|
||||
64: 2,
|
||||
65: 2,
|
||||
66: 6,
|
||||
67: 4,
|
||||
68: 12,
|
||||
69: 12,
|
||||
70: 2,
|
||||
71: 2,
|
||||
72: 2,
|
||||
73: 6,
|
||||
74: 12,
|
||||
75: 12,
|
||||
76: 10,
|
||||
77: 10,
|
||||
78: 10,
|
||||
79: 10,
|
||||
80: 14,
|
||||
81: 12,
|
||||
82: 10,
|
||||
83: 10,
|
||||
84: 10,
|
||||
85: 10,
|
||||
86: 10,
|
||||
87: 14,
|
||||
88: 1,
|
||||
89: 1,
|
||||
90: 5,
|
||||
91: 4,
|
||||
92: 12,
|
||||
93: 12,
|
||||
94: 1,
|
||||
95: 1,
|
||||
96: 5,
|
||||
97: 4,
|
||||
98: 12,
|
||||
99: 12,
|
||||
100: 3,
|
||||
101: 3,
|
||||
102: 8,
|
||||
103: 4,
|
||||
104: 12,
|
||||
105: 12,
|
||||
106: 2,
|
||||
107: 2,
|
||||
108: 2,
|
||||
109: 6,
|
||||
110: 12,
|
||||
111: 12,
|
||||
112: 10,
|
||||
113: 10,
|
||||
114: 10,
|
||||
115: 10,
|
||||
116: 14,
|
||||
117: 12,
|
||||
118: 10,
|
||||
119: 10,
|
||||
120: 10,
|
||||
121: 10,
|
||||
122: 10,
|
||||
123: 14,
|
||||
124: 1,
|
||||
125: 1,
|
||||
126: 1,
|
||||
127: 5,
|
||||
128: 12,
|
||||
129: 12,
|
||||
130: 1,
|
||||
131: 1,
|
||||
132: 1,
|
||||
133: 5,
|
||||
134: 12,
|
||||
135: 12,
|
||||
136: 1,
|
||||
137: 1,
|
||||
138: 1,
|
||||
139: 5,
|
||||
140: 12,
|
||||
141: 12,
|
||||
142: 3,
|
||||
143: 3,
|
||||
144: 3,
|
||||
145: 7,
|
||||
146: 12,
|
||||
147: 12,
|
||||
148: 10,
|
||||
149: 10,
|
||||
150: 10,
|
||||
151: 10,
|
||||
152: 14,
|
||||
153: 12,
|
||||
154: 10,
|
||||
155: 10,
|
||||
156: 10,
|
||||
157: 10,
|
||||
158: 10,
|
||||
159: 14,
|
||||
160: 9,
|
||||
161: 9,
|
||||
162: 9,
|
||||
163: 9,
|
||||
164: 13,
|
||||
165: 12,
|
||||
166: 9,
|
||||
167: 9,
|
||||
168: 9,
|
||||
169: 9,
|
||||
170: 13,
|
||||
171: 12,
|
||||
172: 9,
|
||||
173: 9,
|
||||
174: 9,
|
||||
175: 9,
|
||||
176: 13,
|
||||
177: 12,
|
||||
178: 9,
|
||||
179: 9,
|
||||
180: 9,
|
||||
181: 9,
|
||||
182: 13,
|
||||
183: 12,
|
||||
184: 11,
|
||||
185: 11,
|
||||
186: 11,
|
||||
187: 11,
|
||||
188: 7,
|
||||
189: 12,
|
||||
190: 10,
|
||||
191: 10,
|
||||
192: 10,
|
||||
193: 10,
|
||||
194: 10,
|
||||
195: 14,
|
||||
196: 9,
|
||||
197: 9,
|
||||
198: 9,
|
||||
199: 9,
|
||||
200: 9,
|
||||
201: 13,
|
||||
202: 9,
|
||||
203: 9,
|
||||
204: 9,
|
||||
205: 9,
|
||||
206: 9,
|
||||
207: 13,
|
||||
208: 9,
|
||||
209: 9,
|
||||
210: 9,
|
||||
211: 9,
|
||||
212: 9,
|
||||
213: 13,
|
||||
214: 9,
|
||||
215: 9,
|
||||
216: 9,
|
||||
217: 9,
|
||||
218: 9,
|
||||
219: 13,
|
||||
220: 9,
|
||||
221: 9,
|
||||
222: 9,
|
||||
223: 9,
|
||||
224: 9,
|
||||
225: 13,
|
||||
226: 11,
|
||||
227: 11,
|
||||
228: 11,
|
||||
229: 11,
|
||||
230: 11,
|
||||
231: 15,
|
||||
232: 0,
|
||||
233: 0,
|
||||
234: 0,
|
||||
235: 0,
|
||||
236: 0,
|
||||
237: 0,
|
||||
238: 8,
|
||||
239: 8,
|
||||
240: 8,
|
||||
241: 8,
|
||||
242: 8,
|
||||
243: 8,
|
||||
244: 7,
|
||||
245: 7,
|
||||
246: 7,
|
||||
247: 7,
|
||||
248: 7,
|
||||
249: 7,
|
||||
250: 15,
|
||||
251: 15,
|
||||
252: 15,
|
||||
253: 15,
|
||||
254: 15,
|
||||
255: 15,
|
||||
}
|
||||
|
19
vendor/github.com/charmbracelet/x/ansi/ctrl.go
generated
vendored
19
vendor/github.com/charmbracelet/x/ansi/ctrl.go
generated
vendored
@ -38,6 +38,25 @@ const RequestXTVersion = RequestNameVersion
|
||||
// If no attributes are given, or if the attribute is 0, this function returns
|
||||
// the request sequence. Otherwise, it returns the response sequence.
|
||||
//
|
||||
// Common attributes include:
|
||||
// - 1 132 columns
|
||||
// - 2 Printer port
|
||||
// - 4 Sixel
|
||||
// - 6 Selective erase
|
||||
// - 7 Soft character set (DRCS)
|
||||
// - 8 User-defined keys (UDKs)
|
||||
// - 9 National replacement character sets (NRCS) (International terminal only)
|
||||
// - 12 Yugoslavian (SCS)
|
||||
// - 15 Technical character set
|
||||
// - 18 Windowing capability
|
||||
// - 21 Horizontal scrolling
|
||||
// - 23 Greek
|
||||
// - 24 Turkish
|
||||
// - 42 ISO Latin-2 character set
|
||||
// - 44 PCTerm
|
||||
// - 45 Soft key map
|
||||
// - 46 ASCII emulation
|
||||
//
|
||||
// See https://vt100.net/docs/vt510-rm/DA1.html
|
||||
func PrimaryDeviceAttributes(attrs ...int) string {
|
||||
if len(attrs) == 0 {
|
||||
|
12
vendor/github.com/charmbracelet/x/ansi/cursor.go
generated
vendored
12
vendor/github.com/charmbracelet/x/ansi/cursor.go
generated
vendored
@ -1,6 +1,8 @@
|
||||
package ansi
|
||||
|
||||
import "strconv"
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// SaveCursor (DECSC) is an escape sequence that saves the current cursor
|
||||
// position.
|
||||
@ -260,7 +262,7 @@ func CHA(col int) string {
|
||||
// See: https://vt100.net/docs/vt510-rm/CUP.html
|
||||
func CursorPosition(col, row int) string {
|
||||
if row <= 0 && col <= 0 {
|
||||
return HomeCursorPosition
|
||||
return CursorHomePosition
|
||||
}
|
||||
|
||||
var r, c string
|
||||
@ -356,8 +358,8 @@ func CHT(n int) string {
|
||||
return CursorHorizontalForwardTab(n)
|
||||
}
|
||||
|
||||
// EraseCharacter (ECH) returns a sequence for erasing n characters and moving
|
||||
// the cursor to the right. This doesn't affect other cell attributes.
|
||||
// EraseCharacter (ECH) returns a sequence for erasing n characters from the
|
||||
// screen. This doesn't affect other cell attributes.
|
||||
//
|
||||
// Default is 1.
|
||||
//
|
||||
@ -589,7 +591,7 @@ const ReverseIndex = "\x1bM"
|
||||
//
|
||||
// Default is 1.
|
||||
//
|
||||
// CSI n `
|
||||
// CSI n \`
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/HPA.html
|
||||
func HorizontalPositionAbsolute(col int) string {
|
||||
|
67
vendor/github.com/charmbracelet/x/ansi/finalterm.go
generated
vendored
Normal file
67
vendor/github.com/charmbracelet/x/ansi/finalterm.go
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
package ansi
|
||||
|
||||
import "strings"
|
||||
|
||||
// FinalTerm returns an escape sequence that is used for shell integrations.
|
||||
// Originally, FinalTerm designed the protocol hence the name.
|
||||
//
|
||||
// OSC 133 ; Ps ; Pm ST
|
||||
// OSC 133 ; Ps ; Pm BEL
|
||||
//
|
||||
// See: https://iterm2.com/documentation-shell-integration.html
|
||||
func FinalTerm(pm ...string) string {
|
||||
return "\x1b]133;" + strings.Join(pm, ";") + "\x07"
|
||||
}
|
||||
|
||||
// FinalTermPrompt returns an escape sequence that is used for shell
|
||||
// integrations prompt marks. This is sent just before the start of the shell
|
||||
// prompt.
|
||||
//
|
||||
// This is an alias for FinalTerm("A").
|
||||
func FinalTermPrompt(pm ...string) string {
|
||||
if len(pm) == 0 {
|
||||
return FinalTerm("A")
|
||||
}
|
||||
return FinalTerm(append([]string{"A"}, pm...)...)
|
||||
}
|
||||
|
||||
// FinalTermCmdStart returns an escape sequence that is used for shell
|
||||
// integrations command start marks. This is sent just after the end of the
|
||||
// shell prompt, before the user enters a command.
|
||||
//
|
||||
// This is an alias for FinalTerm("B").
|
||||
func FinalTermCmdStart(pm ...string) string {
|
||||
if len(pm) == 0 {
|
||||
return FinalTerm("B")
|
||||
}
|
||||
return FinalTerm(append([]string{"B"}, pm...)...)
|
||||
}
|
||||
|
||||
// FinalTermCmdExecuted returns an escape sequence that is used for shell
|
||||
// integrations command executed marks. This is sent just before the start of
|
||||
// the command output.
|
||||
//
|
||||
// This is an alias for FinalTerm("C").
|
||||
func FinalTermCmdExecuted(pm ...string) string {
|
||||
if len(pm) == 0 {
|
||||
return FinalTerm("C")
|
||||
}
|
||||
return FinalTerm(append([]string{"C"}, pm...)...)
|
||||
}
|
||||
|
||||
// FinalTermCmdFinished returns an escape sequence that is used for shell
|
||||
// integrations command finished marks.
|
||||
//
|
||||
// If the command was sent after
|
||||
// [FinalTermCmdStart], it indicates that the command was aborted. If the
|
||||
// command was sent after [FinalTermCmdExecuted], it indicates the end of the
|
||||
// command output. If neither was sent, [FinalTermCmdFinished] should be
|
||||
// ignored.
|
||||
//
|
||||
// This is an alias for FinalTerm("D").
|
||||
func FinalTermCmdFinished(pm ...string) string {
|
||||
if len(pm) == 0 {
|
||||
return FinalTerm("D")
|
||||
}
|
||||
return FinalTerm(append([]string{"D"}, pm...)...)
|
||||
}
|
213
vendor/github.com/charmbracelet/x/ansi/graphics.go
generated
vendored
213
vendor/github.com/charmbracelet/x/ansi/graphics.go
generated
vendored
@ -2,17 +2,47 @@ package ansi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/x/ansi/kitty"
|
||||
)
|
||||
|
||||
// SixelGraphics returns a sequence that encodes the given sixel image payload to
|
||||
// a DCS sixel sequence.
|
||||
//
|
||||
// DCS p1; p2; p3; q [sixel payload] ST
|
||||
//
|
||||
// p1 = pixel aspect ratio, deprecated and replaced by pixel metrics in the payload
|
||||
//
|
||||
// p2 = This is supposed to be 0 for transparency, but terminals don't seem to
|
||||
// to use it properly. Value 0 leaves an unsightly black bar on all terminals
|
||||
// I've tried and looks correct with value 1.
|
||||
//
|
||||
// p3 = Horizontal grid size parameter. Everyone ignores this and uses a fixed grid
|
||||
// size, as far as I can tell.
|
||||
//
|
||||
// See https://shuford.invisible-island.net/all_about_sixels.txt
|
||||
func SixelGraphics(p1, p2, p3 int, payload []byte) string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
buf.WriteString("\x1bP")
|
||||
if p1 >= 0 {
|
||||
buf.WriteString(strconv.Itoa(p1))
|
||||
}
|
||||
buf.WriteByte(';')
|
||||
if p2 >= 0 {
|
||||
buf.WriteString(strconv.Itoa(p2))
|
||||
}
|
||||
if p3 > 0 {
|
||||
buf.WriteByte(';')
|
||||
buf.WriteString(strconv.Itoa(p3))
|
||||
}
|
||||
buf.WriteByte('q')
|
||||
buf.Write(payload)
|
||||
buf.WriteString("\x1b\\")
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// KittyGraphics returns a sequence that encodes the given image in the Kitty
|
||||
// graphics protocol.
|
||||
//
|
||||
@ -30,170 +60,3 @@ func KittyGraphics(payload []byte, opts ...string) string {
|
||||
buf.WriteString("\x1b\\")
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
var (
|
||||
// KittyGraphicsTempDir is the directory where temporary files are stored.
|
||||
// This is used in [WriteKittyGraphics] along with [os.CreateTemp].
|
||||
KittyGraphicsTempDir = ""
|
||||
|
||||
// KittyGraphicsTempPattern is the pattern used to create temporary files.
|
||||
// This is used in [WriteKittyGraphics] along with [os.CreateTemp].
|
||||
// The Kitty Graphics protocol requires the file path to contain the
|
||||
// substring "tty-graphics-protocol".
|
||||
KittyGraphicsTempPattern = "tty-graphics-protocol-*"
|
||||
)
|
||||
|
||||
// WriteKittyGraphics writes an image using the Kitty Graphics protocol with
|
||||
// the given options to w. It chunks the written data if o.Chunk is true.
|
||||
//
|
||||
// You can omit m and use nil when rendering an image from a file. In this
|
||||
// case, you must provide a file path in o.File and use o.Transmission =
|
||||
// [kitty.File]. You can also use o.Transmission = [kitty.TempFile] to write
|
||||
// the image to a temporary file. In that case, the file path is ignored, and
|
||||
// the image is written to a temporary file that is automatically deleted by
|
||||
// the terminal.
|
||||
//
|
||||
// See https://sw.kovidgoyal.net/kitty/graphics-protocol/
|
||||
func WriteKittyGraphics(w io.Writer, m image.Image, o *kitty.Options) error {
|
||||
if o == nil {
|
||||
o = &kitty.Options{}
|
||||
}
|
||||
|
||||
if o.Transmission == 0 && len(o.File) != 0 {
|
||||
o.Transmission = kitty.File
|
||||
}
|
||||
|
||||
var data bytes.Buffer // the data to be encoded into base64
|
||||
e := &kitty.Encoder{
|
||||
Compress: o.Compression == kitty.Zlib,
|
||||
Format: o.Format,
|
||||
}
|
||||
|
||||
switch o.Transmission {
|
||||
case kitty.Direct:
|
||||
if err := e.Encode(&data, m); err != nil {
|
||||
return fmt.Errorf("failed to encode direct image: %w", err)
|
||||
}
|
||||
|
||||
case kitty.SharedMemory:
|
||||
// TODO: Implement shared memory
|
||||
return fmt.Errorf("shared memory transmission is not yet implemented")
|
||||
|
||||
case kitty.File:
|
||||
if len(o.File) == 0 {
|
||||
return kitty.ErrMissingFile
|
||||
}
|
||||
|
||||
f, err := os.Open(o.File)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open file: %w", err)
|
||||
}
|
||||
|
||||
defer f.Close() //nolint:errcheck
|
||||
|
||||
stat, err := f.Stat()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get file info: %w", err)
|
||||
}
|
||||
|
||||
mode := stat.Mode()
|
||||
if !mode.IsRegular() {
|
||||
return fmt.Errorf("file is not a regular file")
|
||||
}
|
||||
|
||||
// Write the file path to the buffer
|
||||
if _, err := data.WriteString(f.Name()); err != nil {
|
||||
return fmt.Errorf("failed to write file path to buffer: %w", err)
|
||||
}
|
||||
|
||||
case kitty.TempFile:
|
||||
f, err := os.CreateTemp(KittyGraphicsTempDir, KittyGraphicsTempPattern)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create file: %w", err)
|
||||
}
|
||||
|
||||
defer f.Close() //nolint:errcheck
|
||||
|
||||
if err := e.Encode(f, m); err != nil {
|
||||
return fmt.Errorf("failed to encode image to file: %w", err)
|
||||
}
|
||||
|
||||
// Write the file path to the buffer
|
||||
if _, err := data.WriteString(f.Name()); err != nil {
|
||||
return fmt.Errorf("failed to write file path to buffer: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Encode image to base64
|
||||
var payload bytes.Buffer // the base64 encoded image to be written to w
|
||||
b64 := base64.NewEncoder(base64.StdEncoding, &payload)
|
||||
if _, err := data.WriteTo(b64); err != nil {
|
||||
return fmt.Errorf("failed to write base64 encoded image to payload: %w", err)
|
||||
}
|
||||
if err := b64.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If not chunking, write all at once
|
||||
if !o.Chunk {
|
||||
_, err := io.WriteString(w, KittyGraphics(payload.Bytes(), o.Options()...))
|
||||
return err
|
||||
}
|
||||
|
||||
// Write in chunks
|
||||
var (
|
||||
err error
|
||||
n int
|
||||
)
|
||||
chunk := make([]byte, kitty.MaxChunkSize)
|
||||
isFirstChunk := true
|
||||
|
||||
for {
|
||||
// Stop if we read less than the chunk size [kitty.MaxChunkSize].
|
||||
n, err = io.ReadFull(&payload, chunk)
|
||||
if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read chunk: %w", err)
|
||||
}
|
||||
|
||||
opts := buildChunkOptions(o, isFirstChunk, false)
|
||||
if _, err := io.WriteString(w, KittyGraphics(chunk[:n], opts...)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isFirstChunk = false
|
||||
}
|
||||
|
||||
// Write the last chunk
|
||||
opts := buildChunkOptions(o, isFirstChunk, true)
|
||||
_, err = io.WriteString(w, KittyGraphics(chunk[:n], opts...))
|
||||
return err
|
||||
}
|
||||
|
||||
// buildChunkOptions creates the options slice for a chunk
|
||||
func buildChunkOptions(o *kitty.Options, isFirstChunk, isLastChunk bool) []string {
|
||||
var opts []string
|
||||
if isFirstChunk {
|
||||
opts = o.Options()
|
||||
} else {
|
||||
// These options are allowed in subsequent chunks
|
||||
if o.Quite > 0 {
|
||||
opts = append(opts, fmt.Sprintf("q=%d", o.Quite))
|
||||
}
|
||||
if o.Action == kitty.Frame {
|
||||
opts = append(opts, "a=f")
|
||||
}
|
||||
}
|
||||
|
||||
if !isFirstChunk || !isLastChunk {
|
||||
// We don't need to encode the (m=) option when we only have one chunk.
|
||||
if isLastChunk {
|
||||
opts = append(opts, "m=0")
|
||||
} else {
|
||||
opts = append(opts, "m=1")
|
||||
}
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
85
vendor/github.com/charmbracelet/x/ansi/kitty/decoder.go
generated
vendored
85
vendor/github.com/charmbracelet/x/ansi/kitty/decoder.go
generated
vendored
@ -1,85 +0,0 @@
|
||||
package kitty
|
||||
|
||||
import (
|
||||
"compress/zlib"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/png"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Decoder is a decoder for the Kitty graphics protocol. It supports decoding
|
||||
// images in the 24-bit [RGB], 32-bit [RGBA], and [PNG] formats. It can also
|
||||
// decompress data using zlib.
|
||||
// The default format is 32-bit [RGBA].
|
||||
type Decoder struct {
|
||||
// Uses zlib decompression.
|
||||
Decompress bool
|
||||
|
||||
// Can be one of [RGB], [RGBA], or [PNG].
|
||||
Format int
|
||||
|
||||
// Width of the image in pixels. This can be omitted if the image is [PNG]
|
||||
// formatted.
|
||||
Width int
|
||||
|
||||
// Height of the image in pixels. This can be omitted if the image is [PNG]
|
||||
// formatted.
|
||||
Height int
|
||||
}
|
||||
|
||||
// Decode decodes the image data from r in the specified format.
|
||||
func (d *Decoder) Decode(r io.Reader) (image.Image, error) {
|
||||
if d.Decompress {
|
||||
zr, err := zlib.NewReader(r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create zlib reader: %w", err)
|
||||
}
|
||||
|
||||
defer zr.Close() //nolint:errcheck
|
||||
r = zr
|
||||
}
|
||||
|
||||
if d.Format == 0 {
|
||||
d.Format = RGBA
|
||||
}
|
||||
|
||||
switch d.Format {
|
||||
case RGBA, RGB:
|
||||
return d.decodeRGBA(r, d.Format == RGBA)
|
||||
|
||||
case PNG:
|
||||
return png.Decode(r)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported format: %d", d.Format)
|
||||
}
|
||||
}
|
||||
|
||||
// decodeRGBA decodes the image data in 32-bit RGBA or 24-bit RGB formats.
|
||||
func (d *Decoder) decodeRGBA(r io.Reader, alpha bool) (image.Image, error) {
|
||||
m := image.NewRGBA(image.Rect(0, 0, d.Width, d.Height))
|
||||
|
||||
var buf []byte
|
||||
if alpha {
|
||||
buf = make([]byte, 4)
|
||||
} else {
|
||||
buf = make([]byte, 3)
|
||||
}
|
||||
|
||||
for y := 0; y < d.Height; y++ {
|
||||
for x := 0; x < d.Width; x++ {
|
||||
if _, err := io.ReadFull(r, buf[:]); err != nil {
|
||||
return nil, fmt.Errorf("failed to read pixel data: %w", err)
|
||||
}
|
||||
if alpha {
|
||||
m.SetRGBA(x, y, color.RGBA{buf[0], buf[1], buf[2], buf[3]})
|
||||
} else {
|
||||
m.SetRGBA(x, y, color.RGBA{buf[0], buf[1], buf[2], 0xff})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
64
vendor/github.com/charmbracelet/x/ansi/kitty/encoder.go
generated
vendored
64
vendor/github.com/charmbracelet/x/ansi/kitty/encoder.go
generated
vendored
@ -1,64 +0,0 @@
|
||||
package kitty
|
||||
|
||||
import (
|
||||
"compress/zlib"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/png"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Encoder is an encoder for the Kitty graphics protocol. It supports encoding
|
||||
// images in the 24-bit [RGB], 32-bit [RGBA], and [PNG] formats, and
|
||||
// compressing the data using zlib.
|
||||
// The default format is 32-bit [RGBA].
|
||||
type Encoder struct {
|
||||
// Uses zlib compression.
|
||||
Compress bool
|
||||
|
||||
// Can be one of [RGBA], [RGB], or [PNG].
|
||||
Format int
|
||||
}
|
||||
|
||||
// Encode encodes the image data in the specified format and writes it to w.
|
||||
func (e *Encoder) Encode(w io.Writer, m image.Image) error {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if e.Compress {
|
||||
zw := zlib.NewWriter(w)
|
||||
defer zw.Close() //nolint:errcheck
|
||||
w = zw
|
||||
}
|
||||
|
||||
if e.Format == 0 {
|
||||
e.Format = RGBA
|
||||
}
|
||||
|
||||
switch e.Format {
|
||||
case RGBA, RGB:
|
||||
bounds := m.Bounds()
|
||||
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
||||
for x := bounds.Min.X; x < bounds.Max.X; x++ {
|
||||
r, g, b, a := m.At(x, y).RGBA()
|
||||
switch e.Format {
|
||||
case RGBA:
|
||||
w.Write([]byte{byte(r >> 8), byte(g >> 8), byte(b >> 8), byte(a >> 8)}) //nolint:errcheck
|
||||
case RGB:
|
||||
w.Write([]byte{byte(r >> 8), byte(g >> 8), byte(b >> 8)}) //nolint:errcheck
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case PNG:
|
||||
if err := png.Encode(w, m); err != nil {
|
||||
return fmt.Errorf("failed to encode PNG: %w", err)
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unsupported format: %d", e.Format)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
414
vendor/github.com/charmbracelet/x/ansi/kitty/graphics.go
generated
vendored
414
vendor/github.com/charmbracelet/x/ansi/kitty/graphics.go
generated
vendored
@ -1,414 +0,0 @@
|
||||
package kitty
|
||||
|
||||
import "errors"
|
||||
|
||||
// ErrMissingFile is returned when the file path is missing.
|
||||
var ErrMissingFile = errors.New("missing file path")
|
||||
|
||||
// MaxChunkSize is the maximum chunk size for the image data.
|
||||
const MaxChunkSize = 1024 * 4
|
||||
|
||||
// Placeholder is a special Unicode character that can be used as a placeholder
|
||||
// for an image.
|
||||
const Placeholder = '\U0010EEEE'
|
||||
|
||||
// Graphics image format.
|
||||
const (
|
||||
// 32-bit RGBA format.
|
||||
RGBA = 32
|
||||
|
||||
// 24-bit RGB format.
|
||||
RGB = 24
|
||||
|
||||
// PNG format.
|
||||
PNG = 100
|
||||
)
|
||||
|
||||
// Compression types.
|
||||
const (
|
||||
Zlib = 'z'
|
||||
)
|
||||
|
||||
// Transmission types.
|
||||
const (
|
||||
// The data transmitted directly in the escape sequence.
|
||||
Direct = 'd'
|
||||
|
||||
// The data transmitted in a regular file.
|
||||
File = 'f'
|
||||
|
||||
// A temporary file is used and deleted after transmission.
|
||||
TempFile = 't'
|
||||
|
||||
// A shared memory object.
|
||||
// For POSIX see https://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html
|
||||
// For Windows see https://docs.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory
|
||||
SharedMemory = 's'
|
||||
)
|
||||
|
||||
// Action types.
|
||||
const (
|
||||
// Transmit image data.
|
||||
Transmit = 't'
|
||||
// TransmitAndPut transmit image data and display (put) it.
|
||||
TransmitAndPut = 'T'
|
||||
// Query terminal for image info.
|
||||
Query = 'q'
|
||||
// Put (display) previously transmitted image.
|
||||
Put = 'p'
|
||||
// Delete image.
|
||||
Delete = 'd'
|
||||
// Frame transmits data for animation frames.
|
||||
Frame = 'f'
|
||||
// Animate controls animation.
|
||||
Animate = 'a'
|
||||
// Compose composes animation frames.
|
||||
Compose = 'c'
|
||||
)
|
||||
|
||||
// Delete types.
|
||||
const (
|
||||
// Delete all placements visible on screen
|
||||
DeleteAll = 'a'
|
||||
// Delete all images with the specified id, specified using the i key. If
|
||||
// you specify a p key for the placement id as well, then only the
|
||||
// placement with the specified image id and placement id will be deleted.
|
||||
DeleteID = 'i'
|
||||
// Delete newest image with the specified number, specified using the I
|
||||
// key. If you specify a p key for the placement id as well, then only the
|
||||
// placement with the specified number and placement id will be deleted.
|
||||
DeleteNumber = 'n'
|
||||
// Delete all placements that intersect with the current cursor position.
|
||||
DeleteCursor = 'c'
|
||||
// Delete animation frames.
|
||||
DeleteFrames = 'f'
|
||||
// Delete all placements that intersect a specific cell, the cell is
|
||||
// specified using the x and y keys
|
||||
DeleteCell = 'p'
|
||||
// Delete all placements that intersect a specific cell having a specific
|
||||
// z-index. The cell and z-index is specified using the x, y and z keys.
|
||||
DeleteCellZ = 'q'
|
||||
// Delete all images whose id is greater than or equal to the value of the x
|
||||
// key and less than or equal to the value of the y.
|
||||
DeleteRange = 'r'
|
||||
// Delete all placements that intersect the specified column, specified using
|
||||
// the x key.
|
||||
DeleteColumn = 'x'
|
||||
// Delete all placements that intersect the specified row, specified using
|
||||
// the y key.
|
||||
DeleteRow = 'y'
|
||||
// Delete all placements that have the specified z-index, specified using the
|
||||
// z key.
|
||||
DeleteZ = 'z'
|
||||
)
|
||||
|
||||
// Diacritic returns the diacritic rune at the specified index. If the index is
|
||||
// out of bounds, the first diacritic rune is returned.
|
||||
func Diacritic(i int) rune {
|
||||
if i < 0 || i >= len(diacritics) {
|
||||
return diacritics[0]
|
||||
}
|
||||
return diacritics[i]
|
||||
}
|
||||
|
||||
// From https://sw.kovidgoyal.net/kitty/_downloads/f0a0de9ec8d9ff4456206db8e0814937/rowcolumn-diacritics.txt
|
||||
// See https://sw.kovidgoyal.net/kitty/graphics-protocol/#unicode-placeholders for further explanation.
|
||||
var diacritics = []rune{
|
||||
'\u0305',
|
||||
'\u030D',
|
||||
'\u030E',
|
||||
'\u0310',
|
||||
'\u0312',
|
||||
'\u033D',
|
||||
'\u033E',
|
||||
'\u033F',
|
||||
'\u0346',
|
||||
'\u034A',
|
||||
'\u034B',
|
||||
'\u034C',
|
||||
'\u0350',
|
||||
'\u0351',
|
||||
'\u0352',
|
||||
'\u0357',
|
||||
'\u035B',
|
||||
'\u0363',
|
||||
'\u0364',
|
||||
'\u0365',
|
||||
'\u0366',
|
||||
'\u0367',
|
||||
'\u0368',
|
||||
'\u0369',
|
||||
'\u036A',
|
||||
'\u036B',
|
||||
'\u036C',
|
||||
'\u036D',
|
||||
'\u036E',
|
||||
'\u036F',
|
||||
'\u0483',
|
||||
'\u0484',
|
||||
'\u0485',
|
||||
'\u0486',
|
||||
'\u0487',
|
||||
'\u0592',
|
||||
'\u0593',
|
||||
'\u0594',
|
||||
'\u0595',
|
||||
'\u0597',
|
||||
'\u0598',
|
||||
'\u0599',
|
||||
'\u059C',
|
||||
'\u059D',
|
||||
'\u059E',
|
||||
'\u059F',
|
||||
'\u05A0',
|
||||
'\u05A1',
|
||||
'\u05A8',
|
||||
'\u05A9',
|
||||
'\u05AB',
|
||||
'\u05AC',
|
||||
'\u05AF',
|
||||
'\u05C4',
|
||||
'\u0610',
|
||||
'\u0611',
|
||||
'\u0612',
|
||||
'\u0613',
|
||||
'\u0614',
|
||||
'\u0615',
|
||||
'\u0616',
|
||||
'\u0617',
|
||||
'\u0657',
|
||||
'\u0658',
|
||||
'\u0659',
|
||||
'\u065A',
|
||||
'\u065B',
|
||||
'\u065D',
|
||||
'\u065E',
|
||||
'\u06D6',
|
||||
'\u06D7',
|
||||
'\u06D8',
|
||||
'\u06D9',
|
||||
'\u06DA',
|
||||
'\u06DB',
|
||||
'\u06DC',
|
||||
'\u06DF',
|
||||
'\u06E0',
|
||||
'\u06E1',
|
||||
'\u06E2',
|
||||
'\u06E4',
|
||||
'\u06E7',
|
||||
'\u06E8',
|
||||
'\u06EB',
|
||||
'\u06EC',
|
||||
'\u0730',
|
||||
'\u0732',
|
||||
'\u0733',
|
||||
'\u0735',
|
||||
'\u0736',
|
||||
'\u073A',
|
||||
'\u073D',
|
||||
'\u073F',
|
||||
'\u0740',
|
||||
'\u0741',
|
||||
'\u0743',
|
||||
'\u0745',
|
||||
'\u0747',
|
||||
'\u0749',
|
||||
'\u074A',
|
||||
'\u07EB',
|
||||
'\u07EC',
|
||||
'\u07ED',
|
||||
'\u07EE',
|
||||
'\u07EF',
|
||||
'\u07F0',
|
||||
'\u07F1',
|
||||
'\u07F3',
|
||||
'\u0816',
|
||||
'\u0817',
|
||||
'\u0818',
|
||||
'\u0819',
|
||||
'\u081B',
|
||||
'\u081C',
|
||||
'\u081D',
|
||||
'\u081E',
|
||||
'\u081F',
|
||||
'\u0820',
|
||||
'\u0821',
|
||||
'\u0822',
|
||||
'\u0823',
|
||||
'\u0825',
|
||||
'\u0826',
|
||||
'\u0827',
|
||||
'\u0829',
|
||||
'\u082A',
|
||||
'\u082B',
|
||||
'\u082C',
|
||||
'\u082D',
|
||||
'\u0951',
|
||||
'\u0953',
|
||||
'\u0954',
|
||||
'\u0F82',
|
||||
'\u0F83',
|
||||
'\u0F86',
|
||||
'\u0F87',
|
||||
'\u135D',
|
||||
'\u135E',
|
||||
'\u135F',
|
||||
'\u17DD',
|
||||
'\u193A',
|
||||
'\u1A17',
|
||||
'\u1A75',
|
||||
'\u1A76',
|
||||
'\u1A77',
|
||||
'\u1A78',
|
||||
'\u1A79',
|
||||
'\u1A7A',
|
||||
'\u1A7B',
|
||||
'\u1A7C',
|
||||
'\u1B6B',
|
||||
'\u1B6D',
|
||||
'\u1B6E',
|
||||
'\u1B6F',
|
||||
'\u1B70',
|
||||
'\u1B71',
|
||||
'\u1B72',
|
||||
'\u1B73',
|
||||
'\u1CD0',
|
||||
'\u1CD1',
|
||||
'\u1CD2',
|
||||
'\u1CDA',
|
||||
'\u1CDB',
|
||||
'\u1CE0',
|
||||
'\u1DC0',
|
||||
'\u1DC1',
|
||||
'\u1DC3',
|
||||
'\u1DC4',
|
||||
'\u1DC5',
|
||||
'\u1DC6',
|
||||
'\u1DC7',
|
||||
'\u1DC8',
|
||||
'\u1DC9',
|
||||
'\u1DCB',
|
||||
'\u1DCC',
|
||||
'\u1DD1',
|
||||
'\u1DD2',
|
||||
'\u1DD3',
|
||||
'\u1DD4',
|
||||
'\u1DD5',
|
||||
'\u1DD6',
|
||||
'\u1DD7',
|
||||
'\u1DD8',
|
||||
'\u1DD9',
|
||||
'\u1DDA',
|
||||
'\u1DDB',
|
||||
'\u1DDC',
|
||||
'\u1DDD',
|
||||
'\u1DDE',
|
||||
'\u1DDF',
|
||||
'\u1DE0',
|
||||
'\u1DE1',
|
||||
'\u1DE2',
|
||||
'\u1DE3',
|
||||
'\u1DE4',
|
||||
'\u1DE5',
|
||||
'\u1DE6',
|
||||
'\u1DFE',
|
||||
'\u20D0',
|
||||
'\u20D1',
|
||||
'\u20D4',
|
||||
'\u20D5',
|
||||
'\u20D6',
|
||||
'\u20D7',
|
||||
'\u20DB',
|
||||
'\u20DC',
|
||||
'\u20E1',
|
||||
'\u20E7',
|
||||
'\u20E9',
|
||||
'\u20F0',
|
||||
'\u2CEF',
|
||||
'\u2CF0',
|
||||
'\u2CF1',
|
||||
'\u2DE0',
|
||||
'\u2DE1',
|
||||
'\u2DE2',
|
||||
'\u2DE3',
|
||||
'\u2DE4',
|
||||
'\u2DE5',
|
||||
'\u2DE6',
|
||||
'\u2DE7',
|
||||
'\u2DE8',
|
||||
'\u2DE9',
|
||||
'\u2DEA',
|
||||
'\u2DEB',
|
||||
'\u2DEC',
|
||||
'\u2DED',
|
||||
'\u2DEE',
|
||||
'\u2DEF',
|
||||
'\u2DF0',
|
||||
'\u2DF1',
|
||||
'\u2DF2',
|
||||
'\u2DF3',
|
||||
'\u2DF4',
|
||||
'\u2DF5',
|
||||
'\u2DF6',
|
||||
'\u2DF7',
|
||||
'\u2DF8',
|
||||
'\u2DF9',
|
||||
'\u2DFA',
|
||||
'\u2DFB',
|
||||
'\u2DFC',
|
||||
'\u2DFD',
|
||||
'\u2DFE',
|
||||
'\u2DFF',
|
||||
'\uA66F',
|
||||
'\uA67C',
|
||||
'\uA67D',
|
||||
'\uA6F0',
|
||||
'\uA6F1',
|
||||
'\uA8E0',
|
||||
'\uA8E1',
|
||||
'\uA8E2',
|
||||
'\uA8E3',
|
||||
'\uA8E4',
|
||||
'\uA8E5',
|
||||
'\uA8E6',
|
||||
'\uA8E7',
|
||||
'\uA8E8',
|
||||
'\uA8E9',
|
||||
'\uA8EA',
|
||||
'\uA8EB',
|
||||
'\uA8EC',
|
||||
'\uA8ED',
|
||||
'\uA8EE',
|
||||
'\uA8EF',
|
||||
'\uA8F0',
|
||||
'\uA8F1',
|
||||
'\uAAB0',
|
||||
'\uAAB2',
|
||||
'\uAAB3',
|
||||
'\uAAB7',
|
||||
'\uAAB8',
|
||||
'\uAABE',
|
||||
'\uAABF',
|
||||
'\uAAC1',
|
||||
'\uFE20',
|
||||
'\uFE21',
|
||||
'\uFE22',
|
||||
'\uFE23',
|
||||
'\uFE24',
|
||||
'\uFE25',
|
||||
'\uFE26',
|
||||
'\U00010A0F',
|
||||
'\U00010A38',
|
||||
'\U0001D185',
|
||||
'\U0001D186',
|
||||
'\U0001D187',
|
||||
'\U0001D188',
|
||||
'\U0001D189',
|
||||
'\U0001D1AA',
|
||||
'\U0001D1AB',
|
||||
'\U0001D1AC',
|
||||
'\U0001D1AD',
|
||||
'\U0001D242',
|
||||
'\U0001D243',
|
||||
'\U0001D244',
|
||||
}
|
367
vendor/github.com/charmbracelet/x/ansi/kitty/options.go
generated
vendored
367
vendor/github.com/charmbracelet/x/ansi/kitty/options.go
generated
vendored
@ -1,367 +0,0 @@
|
||||
package kitty
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
_ encoding.TextMarshaler = Options{}
|
||||
_ encoding.TextUnmarshaler = &Options{}
|
||||
)
|
||||
|
||||
// Options represents a Kitty Graphics Protocol options.
|
||||
type Options struct {
|
||||
// Common options.
|
||||
|
||||
// Action (a=t) is the action to be performed on the image. Can be one of
|
||||
// [Transmit], [TransmitDisplay], [Query], [Put], [Delete], [Frame],
|
||||
// [Animate], [Compose].
|
||||
Action byte
|
||||
|
||||
// Quite mode (q=0) is the quiet mode. Can be either zero, one, or two
|
||||
// where zero is the default, 1 suppresses OK responses, and 2 suppresses
|
||||
// both OK and error responses.
|
||||
Quite byte
|
||||
|
||||
// Transmission options.
|
||||
|
||||
// ID (i=) is the image ID. The ID is a unique identifier for the image.
|
||||
// Must be a positive integer up to [math.MaxUint32].
|
||||
ID int
|
||||
|
||||
// PlacementID (p=) is the placement ID. The placement ID is a unique
|
||||
// identifier for the placement of the image. Must be a positive integer up
|
||||
// to [math.MaxUint32].
|
||||
PlacementID int
|
||||
|
||||
// Number (I=0) is the number of images to be transmitted.
|
||||
Number int
|
||||
|
||||
// Format (f=32) is the image format. One of [RGBA], [RGB], [PNG].
|
||||
Format int
|
||||
|
||||
// ImageWidth (s=0) is the transmitted image width.
|
||||
ImageWidth int
|
||||
|
||||
// ImageHeight (v=0) is the transmitted image height.
|
||||
ImageHeight int
|
||||
|
||||
// Compression (o=) is the image compression type. Can be [Zlib] or zero.
|
||||
Compression byte
|
||||
|
||||
// Transmission (t=d) is the image transmission type. Can be [Direct], [File],
|
||||
// [TempFile], or[SharedMemory].
|
||||
Transmission byte
|
||||
|
||||
// File is the file path to be used when the transmission type is [File].
|
||||
// If [Options.Transmission] is omitted i.e. zero and this is non-empty,
|
||||
// the transmission type is set to [File].
|
||||
File string
|
||||
|
||||
// Size (S=0) is the size to be read from the transmission medium.
|
||||
Size int
|
||||
|
||||
// Offset (O=0) is the offset byte to start reading from the transmission
|
||||
// medium.
|
||||
Offset int
|
||||
|
||||
// Chunk (m=) whether the image is transmitted in chunks. Can be either
|
||||
// zero or one. When true, the image is transmitted in chunks. Each chunk
|
||||
// must be a multiple of 4, and up to [MaxChunkSize] bytes. Each chunk must
|
||||
// have the m=1 option except for the last chunk which must have m=0.
|
||||
Chunk bool
|
||||
|
||||
// Display options.
|
||||
|
||||
// X (x=0) is the pixel X coordinate of the image to start displaying.
|
||||
X int
|
||||
|
||||
// Y (y=0) is the pixel Y coordinate of the image to start displaying.
|
||||
Y int
|
||||
|
||||
// Z (z=0) is the Z coordinate of the image to display.
|
||||
Z int
|
||||
|
||||
// Width (w=0) is the width of the image to display.
|
||||
Width int
|
||||
|
||||
// Height (h=0) is the height of the image to display.
|
||||
Height int
|
||||
|
||||
// OffsetX (X=0) is the OffsetX coordinate of the cursor cell to start
|
||||
// displaying the image. OffsetX=0 is the leftmost cell. This must be
|
||||
// smaller than the terminal cell width.
|
||||
OffsetX int
|
||||
|
||||
// OffsetY (Y=0) is the OffsetY coordinate of the cursor cell to start
|
||||
// displaying the image. OffsetY=0 is the topmost cell. This must be
|
||||
// smaller than the terminal cell height.
|
||||
OffsetY int
|
||||
|
||||
// Columns (c=0) is the number of columns to display the image. The image
|
||||
// will be scaled to fit the number of columns.
|
||||
Columns int
|
||||
|
||||
// Rows (r=0) is the number of rows to display the image. The image will be
|
||||
// scaled to fit the number of rows.
|
||||
Rows int
|
||||
|
||||
// VirtualPlacement (U=0) whether to use virtual placement. This is used
|
||||
// with Unicode [Placeholder] to display images.
|
||||
VirtualPlacement bool
|
||||
|
||||
// DoNotMoveCursor (C=0) whether to move the cursor after displaying the
|
||||
// image.
|
||||
DoNotMoveCursor bool
|
||||
|
||||
// ParentID (P=0) is the parent image ID. The parent ID is the ID of the
|
||||
// image that is the parent of the current image. This is used with Unicode
|
||||
// [Placeholder] to display images relative to the parent image.
|
||||
ParentID int
|
||||
|
||||
// ParentPlacementID (Q=0) is the parent placement ID. The parent placement
|
||||
// ID is the ID of the placement of the parent image. This is used with
|
||||
// Unicode [Placeholder] to display images relative to the parent image.
|
||||
ParentPlacementID int
|
||||
|
||||
// Delete options.
|
||||
|
||||
// Delete (d=a) is the delete action. Can be one of [DeleteAll],
|
||||
// [DeleteID], [DeleteNumber], [DeleteCursor], [DeleteFrames],
|
||||
// [DeleteCell], [DeleteCellZ], [DeleteRange], [DeleteColumn], [DeleteRow],
|
||||
// [DeleteZ].
|
||||
Delete byte
|
||||
|
||||
// DeleteResources indicates whether to delete the resources associated
|
||||
// with the image.
|
||||
DeleteResources bool
|
||||
}
|
||||
|
||||
// Options returns the options as a slice of a key-value pairs.
|
||||
func (o *Options) Options() (opts []string) {
|
||||
opts = []string{}
|
||||
if o.Format == 0 {
|
||||
o.Format = RGBA
|
||||
}
|
||||
|
||||
if o.Action == 0 {
|
||||
o.Action = Transmit
|
||||
}
|
||||
|
||||
if o.Delete == 0 {
|
||||
o.Delete = DeleteAll
|
||||
}
|
||||
|
||||
if o.Transmission == 0 {
|
||||
if len(o.File) > 0 {
|
||||
o.Transmission = File
|
||||
} else {
|
||||
o.Transmission = Direct
|
||||
}
|
||||
}
|
||||
|
||||
if o.Format != RGBA {
|
||||
opts = append(opts, fmt.Sprintf("f=%d", o.Format))
|
||||
}
|
||||
|
||||
if o.Quite > 0 {
|
||||
opts = append(opts, fmt.Sprintf("q=%d", o.Quite))
|
||||
}
|
||||
|
||||
if o.ID > 0 {
|
||||
opts = append(opts, fmt.Sprintf("i=%d", o.ID))
|
||||
}
|
||||
|
||||
if o.PlacementID > 0 {
|
||||
opts = append(opts, fmt.Sprintf("p=%d", o.PlacementID))
|
||||
}
|
||||
|
||||
if o.Number > 0 {
|
||||
opts = append(opts, fmt.Sprintf("I=%d", o.Number))
|
||||
}
|
||||
|
||||
if o.ImageWidth > 0 {
|
||||
opts = append(opts, fmt.Sprintf("s=%d", o.ImageWidth))
|
||||
}
|
||||
|
||||
if o.ImageHeight > 0 {
|
||||
opts = append(opts, fmt.Sprintf("v=%d", o.ImageHeight))
|
||||
}
|
||||
|
||||
if o.Transmission != Direct {
|
||||
opts = append(opts, fmt.Sprintf("t=%c", o.Transmission))
|
||||
}
|
||||
|
||||
if o.Size > 0 {
|
||||
opts = append(opts, fmt.Sprintf("S=%d", o.Size))
|
||||
}
|
||||
|
||||
if o.Offset > 0 {
|
||||
opts = append(opts, fmt.Sprintf("O=%d", o.Offset))
|
||||
}
|
||||
|
||||
if o.Compression == Zlib {
|
||||
opts = append(opts, fmt.Sprintf("o=%c", o.Compression))
|
||||
}
|
||||
|
||||
if o.VirtualPlacement {
|
||||
opts = append(opts, "U=1")
|
||||
}
|
||||
|
||||
if o.DoNotMoveCursor {
|
||||
opts = append(opts, "C=1")
|
||||
}
|
||||
|
||||
if o.ParentID > 0 {
|
||||
opts = append(opts, fmt.Sprintf("P=%d", o.ParentID))
|
||||
}
|
||||
|
||||
if o.ParentPlacementID > 0 {
|
||||
opts = append(opts, fmt.Sprintf("Q=%d", o.ParentPlacementID))
|
||||
}
|
||||
|
||||
if o.X > 0 {
|
||||
opts = append(opts, fmt.Sprintf("x=%d", o.X))
|
||||
}
|
||||
|
||||
if o.Y > 0 {
|
||||
opts = append(opts, fmt.Sprintf("y=%d", o.Y))
|
||||
}
|
||||
|
||||
if o.Z > 0 {
|
||||
opts = append(opts, fmt.Sprintf("z=%d", o.Z))
|
||||
}
|
||||
|
||||
if o.Width > 0 {
|
||||
opts = append(opts, fmt.Sprintf("w=%d", o.Width))
|
||||
}
|
||||
|
||||
if o.Height > 0 {
|
||||
opts = append(opts, fmt.Sprintf("h=%d", o.Height))
|
||||
}
|
||||
|
||||
if o.OffsetX > 0 {
|
||||
opts = append(opts, fmt.Sprintf("X=%d", o.OffsetX))
|
||||
}
|
||||
|
||||
if o.OffsetY > 0 {
|
||||
opts = append(opts, fmt.Sprintf("Y=%d", o.OffsetY))
|
||||
}
|
||||
|
||||
if o.Columns > 0 {
|
||||
opts = append(opts, fmt.Sprintf("c=%d", o.Columns))
|
||||
}
|
||||
|
||||
if o.Rows > 0 {
|
||||
opts = append(opts, fmt.Sprintf("r=%d", o.Rows))
|
||||
}
|
||||
|
||||
if o.Delete != DeleteAll || o.DeleteResources {
|
||||
da := o.Delete
|
||||
if o.DeleteResources {
|
||||
da = da - ' ' // to uppercase
|
||||
}
|
||||
|
||||
opts = append(opts, fmt.Sprintf("d=%c", da))
|
||||
}
|
||||
|
||||
if o.Action != Transmit {
|
||||
opts = append(opts, fmt.Sprintf("a=%c", o.Action))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// String returns the string representation of the options.
|
||||
func (o Options) String() string {
|
||||
return strings.Join(o.Options(), ",")
|
||||
}
|
||||
|
||||
// MarshalText returns the string representation of the options.
|
||||
func (o Options) MarshalText() ([]byte, error) {
|
||||
return []byte(o.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText parses the options from the given string.
|
||||
func (o *Options) UnmarshalText(text []byte) error {
|
||||
opts := strings.Split(string(text), ",")
|
||||
for _, opt := range opts {
|
||||
ps := strings.SplitN(opt, "=", 2)
|
||||
if len(ps) != 2 || len(ps[1]) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
switch ps[0] {
|
||||
case "a":
|
||||
o.Action = ps[1][0]
|
||||
case "o":
|
||||
o.Compression = ps[1][0]
|
||||
case "t":
|
||||
o.Transmission = ps[1][0]
|
||||
case "d":
|
||||
d := ps[1][0]
|
||||
if d >= 'A' && d <= 'Z' {
|
||||
o.DeleteResources = true
|
||||
d = d + ' ' // to lowercase
|
||||
}
|
||||
o.Delete = d
|
||||
case "i", "q", "p", "I", "f", "s", "v", "S", "O", "m", "x", "y", "z", "w", "h", "X", "Y", "c", "r", "U", "P", "Q":
|
||||
v, err := strconv.Atoi(ps[1])
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
switch ps[0] {
|
||||
case "i":
|
||||
o.ID = v
|
||||
case "q":
|
||||
o.Quite = byte(v)
|
||||
case "p":
|
||||
o.PlacementID = v
|
||||
case "I":
|
||||
o.Number = v
|
||||
case "f":
|
||||
o.Format = v
|
||||
case "s":
|
||||
o.ImageWidth = v
|
||||
case "v":
|
||||
o.ImageHeight = v
|
||||
case "S":
|
||||
o.Size = v
|
||||
case "O":
|
||||
o.Offset = v
|
||||
case "m":
|
||||
o.Chunk = v == 0 || v == 1
|
||||
case "x":
|
||||
o.X = v
|
||||
case "y":
|
||||
o.Y = v
|
||||
case "z":
|
||||
o.Z = v
|
||||
case "w":
|
||||
o.Width = v
|
||||
case "h":
|
||||
o.Height = v
|
||||
case "X":
|
||||
o.OffsetX = v
|
||||
case "Y":
|
||||
o.OffsetY = v
|
||||
case "c":
|
||||
o.Columns = v
|
||||
case "r":
|
||||
o.Rows = v
|
||||
case "U":
|
||||
o.VirtualPlacement = v == 1
|
||||
case "P":
|
||||
o.ParentID = v
|
||||
case "Q":
|
||||
o.ParentPlacementID = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
106
vendor/github.com/charmbracelet/x/ansi/mode.go
generated
vendored
106
vendor/github.com/charmbracelet/x/ansi/mode.go
generated
vendored
@ -48,7 +48,7 @@ type Mode interface {
|
||||
Mode() int
|
||||
}
|
||||
|
||||
// SetMode (SM) returns a sequence to set a mode.
|
||||
// SetMode (SM) or (DECSET) returns a sequence to set a mode.
|
||||
// The mode arguments are a list of modes to set.
|
||||
//
|
||||
// If one of the modes is a [DECMode], the function will returns two escape
|
||||
@ -72,7 +72,12 @@ func SM(modes ...Mode) string {
|
||||
return SetMode(modes...)
|
||||
}
|
||||
|
||||
// ResetMode (RM) returns a sequence to reset a mode.
|
||||
// DECSET is an alias for [SetMode].
|
||||
func DECSET(modes ...Mode) string {
|
||||
return SetMode(modes...)
|
||||
}
|
||||
|
||||
// ResetMode (RM) or (DECRST) returns a sequence to reset a mode.
|
||||
// The mode arguments are a list of modes to reset.
|
||||
//
|
||||
// If one of the modes is a [DECMode], the function will returns two escape
|
||||
@ -96,9 +101,14 @@ func RM(modes ...Mode) string {
|
||||
return ResetMode(modes...)
|
||||
}
|
||||
|
||||
// DECRST is an alias for [ResetMode].
|
||||
func DECRST(modes ...Mode) string {
|
||||
return ResetMode(modes...)
|
||||
}
|
||||
|
||||
func setMode(reset bool, modes ...Mode) (s string) {
|
||||
if len(modes) == 0 {
|
||||
return
|
||||
return //nolint:nakedret
|
||||
}
|
||||
|
||||
cmd := "h"
|
||||
@ -132,7 +142,7 @@ func setMode(reset bool, modes ...Mode) (s string) {
|
||||
if len(dec) > 0 {
|
||||
s += seq + "?" + strings.Join(dec, ";") + cmd
|
||||
}
|
||||
return
|
||||
return //nolint:nakedret
|
||||
}
|
||||
|
||||
// RequestMode (DECRQM) returns a sequence to request a mode from the terminal.
|
||||
@ -243,6 +253,21 @@ const (
|
||||
RequestInsertReplaceMode = "\x1b[4$p"
|
||||
)
|
||||
|
||||
// BiDirectional Support Mode (BDSM) is a mode that determines whether the
|
||||
// terminal supports bidirectional text. When enabled, the terminal supports
|
||||
// bidirectional text and is set to implicit bidirectional mode. When disabled,
|
||||
// the terminal does not support bidirectional text.
|
||||
//
|
||||
// See ECMA-48 7.2.1.
|
||||
const (
|
||||
BiDirectionalSupportMode = ANSIMode(8)
|
||||
BDSM = BiDirectionalSupportMode
|
||||
|
||||
SetBiDirectionalSupportMode = "\x1b[8h"
|
||||
ResetBiDirectionalSupportMode = "\x1b[8l"
|
||||
RequestBiDirectionalSupportMode = "\x1b[8$p"
|
||||
)
|
||||
|
||||
// Send Receive Mode (SRM) or Local Echo Mode is a mode that determines whether
|
||||
// the terminal echoes characters back to the host. When enabled, the terminal
|
||||
// sends characters to the host as they are typed.
|
||||
@ -297,7 +322,7 @@ const (
|
||||
|
||||
// Deprecated: use [SetCursorKeysMode] and [ResetCursorKeysMode] instead.
|
||||
const (
|
||||
EnableCursorKeys = "\x1b[?1h"
|
||||
EnableCursorKeys = "\x1b[?1h" //nolint:revive // grouped constants
|
||||
DisableCursorKeys = "\x1b[?1l"
|
||||
)
|
||||
|
||||
@ -548,8 +573,9 @@ const (
|
||||
|
||||
// Deprecated: use [SetFocusEventMode], [ResetFocusEventMode], and
|
||||
// [RequestFocusEventMode] instead.
|
||||
// Focus reporting mode constants.
|
||||
const (
|
||||
ReportFocusMode = DECMode(1004)
|
||||
ReportFocusMode = DECMode(1004) //nolint:revive // grouped constants
|
||||
|
||||
EnableReportFocus = "\x1b[?1004h"
|
||||
DisableReportFocus = "\x1b[?1004l"
|
||||
@ -577,7 +603,7 @@ const (
|
||||
// Deprecated: use [SgrExtMouseMode] [SetSgrExtMouseMode],
|
||||
// [ResetSgrExtMouseMode], and [RequestSgrExtMouseMode] instead.
|
||||
const (
|
||||
MouseSgrExtMode = DECMode(1006)
|
||||
MouseSgrExtMode = DECMode(1006) //nolint:revive // grouped constants
|
||||
EnableMouseSgrExt = "\x1b[?1006h"
|
||||
DisableMouseSgrExt = "\x1b[?1006l"
|
||||
RequestMouseSgrExt = "\x1b[?1006$p"
|
||||
@ -693,7 +719,7 @@ const (
|
||||
// Deprecated: use [SetBracketedPasteMode], [ResetBracketedPasteMode], and
|
||||
// [RequestBracketedPasteMode] instead.
|
||||
const (
|
||||
EnableBracketedPaste = "\x1b[?2004h"
|
||||
EnableBracketedPaste = "\x1b[?2004h" //nolint:revive // grouped constants
|
||||
DisableBracketedPaste = "\x1b[?2004l"
|
||||
RequestBracketedPaste = "\x1b[?2004$p"
|
||||
)
|
||||
@ -710,6 +736,8 @@ const (
|
||||
RequestSynchronizedOutputMode = "\x1b[?2026$p"
|
||||
)
|
||||
|
||||
// Synchronized Output Mode. See [SynchronizedOutputMode].
|
||||
//
|
||||
// Deprecated: use [SynchronizedOutputMode], [SetSynchronizedOutputMode], and
|
||||
// [ResetSynchronizedOutputMode], and [RequestSynchronizedOutputMode] instead.
|
||||
const (
|
||||
@ -720,12 +748,28 @@ const (
|
||||
RequestSyncdOutput = "\x1b[?2026$p"
|
||||
)
|
||||
|
||||
// Unicode Core Mode is a mode that determines whether the terminal should use
|
||||
// Unicode grapheme clustering to calculate the width of glyphs for each
|
||||
// terminal cell.
|
||||
//
|
||||
// See: https://github.com/contour-terminal/terminal-unicode-core
|
||||
const (
|
||||
UnicodeCoreMode = DECMode(2027)
|
||||
|
||||
SetUnicodeCoreMode = "\x1b[?2027h"
|
||||
ResetUnicodeCoreMode = "\x1b[?2027l"
|
||||
RequestUnicodeCoreMode = "\x1b[?2027$p"
|
||||
)
|
||||
|
||||
// Grapheme Clustering Mode is a mode that determines whether the terminal
|
||||
// should look for grapheme clusters instead of single runes in the rendered
|
||||
// text. This makes the terminal properly render combining characters such as
|
||||
// emojis.
|
||||
//
|
||||
// See: https://github.com/contour-terminal/terminal-unicode-core
|
||||
//
|
||||
// Deprecated: use [GraphemeClusteringMode], [SetUnicodeCoreMode],
|
||||
// [ResetUnicodeCoreMode], and [RequestUnicodeCoreMode] instead.
|
||||
const (
|
||||
GraphemeClusteringMode = DECMode(2027)
|
||||
|
||||
@ -734,14 +778,54 @@ const (
|
||||
RequestGraphemeClusteringMode = "\x1b[?2027$p"
|
||||
)
|
||||
|
||||
// Deprecated: use [SetGraphemeClusteringMode], [ResetGraphemeClusteringMode], and
|
||||
// [RequestGraphemeClusteringMode] instead.
|
||||
// Grapheme Clustering Mode. See [GraphemeClusteringMode].
|
||||
//
|
||||
// Deprecated: use [SetUnicodeCoreMode], [ResetUnicodeCoreMode], and
|
||||
// [RequestUnicodeCoreMode] instead.
|
||||
const (
|
||||
EnableGraphemeClustering = "\x1b[?2027h"
|
||||
DisableGraphemeClustering = "\x1b[?2027l"
|
||||
RequestGraphemeClustering = "\x1b[?2027$p"
|
||||
)
|
||||
|
||||
// LightDarkMode is a mode that enables reporting the operating system's color
|
||||
// scheme (light or dark) preference. It reports the color scheme as a [DSR]
|
||||
// and [LightDarkReport] escape sequences encoded as follows:
|
||||
//
|
||||
// CSI ? 997 ; 1 n for dark mode
|
||||
// CSI ? 997 ; 2 n for light mode
|
||||
//
|
||||
// The color preference can also be requested via the following [DSR] and
|
||||
// [RequestLightDarkReport] escape sequences:
|
||||
//
|
||||
// CSI ? 996 n
|
||||
//
|
||||
// See: https://contour-terminal.org/vt-extensions/color-palette-update-notifications/
|
||||
const (
|
||||
LightDarkMode = DECMode(2031)
|
||||
|
||||
SetLightDarkMode = "\x1b[?2031h"
|
||||
ResetLightDarkMode = "\x1b[?2031l"
|
||||
RequestLightDarkMode = "\x1b[?2031$p"
|
||||
)
|
||||
|
||||
// InBandResizeMode is a mode that reports terminal resize events as escape
|
||||
// sequences. This is useful for systems that do not support [SIGWINCH] like
|
||||
// Windows.
|
||||
//
|
||||
// The terminal then sends the following encoding:
|
||||
//
|
||||
// CSI 48 ; cellsHeight ; cellsWidth ; pixelHeight ; pixelWidth t
|
||||
//
|
||||
// See: https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83
|
||||
const (
|
||||
InBandResizeMode = DECMode(2048)
|
||||
|
||||
SetInBandResizeMode = "\x1b[?2048h"
|
||||
ResetInBandResizeMode = "\x1b[?2048l"
|
||||
RequestInBandResizeMode = "\x1b[?2048$p"
|
||||
)
|
||||
|
||||
// Win32Input is a mode that determines whether input is processed by the
|
||||
// Win32 console and Conpty.
|
||||
//
|
||||
@ -757,7 +841,7 @@ const (
|
||||
// Deprecated: use [SetWin32InputMode], [ResetWin32InputMode], and
|
||||
// [RequestWin32InputMode] instead.
|
||||
const (
|
||||
EnableWin32Input = "\x1b[?9001h"
|
||||
EnableWin32Input = "\x1b[?9001h" //nolint:revive // grouped constants
|
||||
DisableWin32Input = "\x1b[?9001l"
|
||||
RequestWin32Input = "\x1b[?9001$p"
|
||||
)
|
||||
|
6
vendor/github.com/charmbracelet/x/ansi/modes.go
generated
vendored
6
vendor/github.com/charmbracelet/x/ansi/modes.go
generated
vendored
@ -4,12 +4,6 @@ package ansi
|
||||
// all modes are [ModeNotRecognized].
|
||||
type Modes map[Mode]ModeSetting
|
||||
|
||||
// NewModes creates a new Modes map. By default, all modes are
|
||||
// [ModeNotRecognized].
|
||||
func NewModes() Modes {
|
||||
return make(Modes)
|
||||
}
|
||||
|
||||
// Get returns the setting of a terminal mode. If the mode is not set, it
|
||||
// returns [ModeNotRecognized].
|
||||
func (m Modes) Get(mode Mode) ModeSetting {
|
||||
|
2
vendor/github.com/charmbracelet/x/ansi/mouse.go
generated
vendored
2
vendor/github.com/charmbracelet/x/ansi/mouse.go
generated
vendored
@ -134,7 +134,7 @@ func EncodeMouseButton(b MouseButton, motion, shift, alt, ctrl bool) (m byte) {
|
||||
m |= bitMotion
|
||||
}
|
||||
|
||||
return
|
||||
return //nolint:nakedret
|
||||
}
|
||||
|
||||
// x10Offset is the offset for X10 mouse events.
|
||||
|
4
vendor/github.com/charmbracelet/x/ansi/parser.go
generated
vendored
4
vendor/github.com/charmbracelet/x/ansi/parser.go
generated
vendored
@ -150,7 +150,7 @@ func (p *Parser) StateName() string {
|
||||
// Parse parses the given dispatcher and byte buffer.
|
||||
// Deprecated: Loop over the buffer and call [Parser.Advance] instead.
|
||||
func (p *Parser) Parse(b []byte) {
|
||||
for i := 0; i < len(b); i++ {
|
||||
for i := range b {
|
||||
p.Advance(b[i])
|
||||
}
|
||||
}
|
||||
@ -245,7 +245,7 @@ func (p *Parser) parseStringCmd() {
|
||||
if p.dataLen >= 0 {
|
||||
datalen = p.dataLen
|
||||
}
|
||||
for i := 0; i < datalen; i++ {
|
||||
for i := range datalen {
|
||||
d := p.data[i]
|
||||
if d < '0' || d > '9' {
|
||||
break
|
||||
|
5
vendor/github.com/charmbracelet/x/ansi/parser/const.go
generated
vendored
5
vendor/github.com/charmbracelet/x/ansi/parser/const.go
generated
vendored
@ -1,3 +1,4 @@
|
||||
// Package parser provides ANSI escape sequence parsing functionality.
|
||||
package parser
|
||||
|
||||
// Action is a DEC ANSI parser action.
|
||||
@ -19,7 +20,7 @@ const (
|
||||
IgnoreAction = NoneAction
|
||||
)
|
||||
|
||||
// nolint: unused
|
||||
// ActionNames provides string names for parser actions.
|
||||
var ActionNames = []string{
|
||||
"NoneAction",
|
||||
"ClearAction",
|
||||
@ -58,7 +59,7 @@ const (
|
||||
Utf8State
|
||||
)
|
||||
|
||||
// nolint: unused
|
||||
// StateNames provides string names for parser states.
|
||||
var StateNames = []string{
|
||||
"GroundState",
|
||||
"CsiEntryState",
|
||||
|
6
vendor/github.com/charmbracelet/x/ansi/parser/seq.go
generated
vendored
6
vendor/github.com/charmbracelet/x/ansi/parser/seq.go
generated
vendored
@ -78,7 +78,7 @@ func Subparams(params []int, i int) []int {
|
||||
// Count the number of parameters before the given parameter index.
|
||||
var count int
|
||||
var j int
|
||||
for j = 0; j < len(params); j++ {
|
||||
for j = range params {
|
||||
if count == i {
|
||||
break
|
||||
}
|
||||
@ -116,7 +116,7 @@ func Subparams(params []int, i int) []int {
|
||||
// sub-parameters.
|
||||
func Len(params []int) int {
|
||||
var n int
|
||||
for i := 0; i < len(params); i++ {
|
||||
for i := range params {
|
||||
if !HasMore(params, i) {
|
||||
n++
|
||||
}
|
||||
@ -128,7 +128,7 @@ func Len(params []int) int {
|
||||
// function for each parameter.
|
||||
// The function should return false to stop the iteration.
|
||||
func Range(params []int, fn func(i int, param int, hasMore bool) bool) {
|
||||
for i := 0; i < len(params); i++ {
|
||||
for i := range params {
|
||||
if !fn(i, Param(params, i), HasMore(params, i)) {
|
||||
break
|
||||
}
|
||||
|
4
vendor/github.com/charmbracelet/x/ansi/parser/transition_table.go
generated
vendored
4
vendor/github.com/charmbracelet/x/ansi/parser/transition_table.go
generated
vendored
@ -30,7 +30,7 @@ func NewTransitionTable(size int) TransitionTable {
|
||||
|
||||
// SetDefault sets default transition.
|
||||
func (t TransitionTable) SetDefault(action Action, state State) {
|
||||
for i := 0; i < len(t); i++ {
|
||||
for i := range t {
|
||||
t[i] = action<<TransitionActionShift | state
|
||||
}
|
||||
}
|
||||
@ -63,7 +63,7 @@ func (t TransitionTable) Transition(state State, code byte) (State, Action) {
|
||||
return value & TransitionStateMask, value >> TransitionActionShift
|
||||
}
|
||||
|
||||
// byte range macro
|
||||
// byte range macro.
|
||||
func r(start, end byte) []byte {
|
||||
var a []byte
|
||||
for i := int(start); i <= int(end); i++ {
|
||||
|
2
vendor/github.com/charmbracelet/x/ansi/parser_decode.go
generated
vendored
2
vendor/github.com/charmbracelet/x/ansi/parser_decode.go
generated
vendored
@ -359,7 +359,7 @@ func parseOscCmd(p *Parser) {
|
||||
if p == nil || p.cmd != parser.MissingCommand {
|
||||
return
|
||||
}
|
||||
for j := 0; j < p.dataLen; j++ {
|
||||
for j := range p.dataLen {
|
||||
d := p.data[j]
|
||||
if d < '0' || d > '9' {
|
||||
break
|
||||
|
7
vendor/github.com/charmbracelet/x/ansi/passthrough.go
generated
vendored
7
vendor/github.com/charmbracelet/x/ansi/passthrough.go
generated
vendored
@ -21,10 +21,7 @@ func ScreenPassthrough(seq string, limit int) string {
|
||||
b.WriteString("\x1bP")
|
||||
if limit > 0 {
|
||||
for i := 0; i < len(seq); i += limit {
|
||||
end := i + limit
|
||||
if end > len(seq) {
|
||||
end = len(seq)
|
||||
}
|
||||
end := min(i+limit, len(seq))
|
||||
b.WriteString(seq[i:end])
|
||||
if end < len(seq) {
|
||||
b.WriteString("\x1b\\\x1bP")
|
||||
@ -52,7 +49,7 @@ func ScreenPassthrough(seq string, limit int) string {
|
||||
func TmuxPassthrough(seq string) string {
|
||||
var b bytes.Buffer
|
||||
b.WriteString("\x1bPtmux;")
|
||||
for i := 0; i < len(seq); i++ {
|
||||
for i := range len(seq) {
|
||||
if seq[i] == ESC {
|
||||
b.WriteByte(ESC)
|
||||
}
|
||||
|
6
vendor/github.com/charmbracelet/x/ansi/screen.go
generated
vendored
6
vendor/github.com/charmbracelet/x/ansi/screen.go
generated
vendored
@ -351,7 +351,7 @@ func DECRQPSR(n int) string {
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/DECTABSR.html
|
||||
func TabStopReport(stops ...int) string {
|
||||
var s []string
|
||||
var s []string //nolint:prealloc
|
||||
for _, v := range stops {
|
||||
s = append(s, strconv.Itoa(v))
|
||||
}
|
||||
@ -376,7 +376,7 @@ func DECTABSR(stops ...int) string {
|
||||
//
|
||||
// See: https://vt100.net/docs/vt510-rm/DECCIR.html
|
||||
func CursorInformationReport(values ...int) string {
|
||||
var s []string
|
||||
var s []string //nolint:prealloc
|
||||
for _, v := range values {
|
||||
s = append(s, strconv.Itoa(v))
|
||||
}
|
||||
@ -395,7 +395,7 @@ func DECCIR(values ...int) string {
|
||||
//
|
||||
// CSI Pn b
|
||||
//
|
||||
// See: ECMA-48 § 8.3.103
|
||||
// See: ECMA-48 § 8.3.103.
|
||||
func RepeatPreviousCharacter(n int) string {
|
||||
var s string
|
||||
if n > 1 {
|
||||
|
130
vendor/github.com/charmbracelet/x/ansi/sgr.go
generated
vendored
130
vendor/github.com/charmbracelet/x/ansi/sgr.go
generated
vendored
@ -1,8 +1,6 @@
|
||||
package ansi
|
||||
|
||||
import "strconv"
|
||||
|
||||
// Select Graphic Rendition (SGR) is a command that sets display attributes.
|
||||
// SelectGraphicRendition (SGR) is a command that sets display attributes.
|
||||
//
|
||||
// Default is 0.
|
||||
//
|
||||
@ -14,20 +12,7 @@ func SelectGraphicRendition(ps ...Attr) string {
|
||||
return ResetStyle
|
||||
}
|
||||
|
||||
var s Style
|
||||
for _, p := range ps {
|
||||
attr, ok := attrStrings[p]
|
||||
if ok {
|
||||
s = append(s, attr)
|
||||
} else {
|
||||
if p < 0 {
|
||||
p = 0
|
||||
}
|
||||
s = append(s, strconv.Itoa(p))
|
||||
}
|
||||
}
|
||||
|
||||
return s.String()
|
||||
return NewStyle(ps...).String()
|
||||
}
|
||||
|
||||
// SGR is an alias for [SelectGraphicRendition].
|
||||
@ -36,60 +21,59 @@ func SGR(ps ...Attr) string {
|
||||
}
|
||||
|
||||
var attrStrings = map[int]string{
|
||||
ResetAttr: "0",
|
||||
BoldAttr: "1",
|
||||
FaintAttr: "2",
|
||||
ItalicAttr: "3",
|
||||
UnderlineAttr: "4",
|
||||
SlowBlinkAttr: "5",
|
||||
RapidBlinkAttr: "6",
|
||||
ReverseAttr: "7",
|
||||
ConcealAttr: "8",
|
||||
StrikethroughAttr: "9",
|
||||
NoBoldAttr: "21",
|
||||
NormalIntensityAttr: "22",
|
||||
NoItalicAttr: "23",
|
||||
NoUnderlineAttr: "24",
|
||||
NoBlinkAttr: "25",
|
||||
NoReverseAttr: "27",
|
||||
NoConcealAttr: "28",
|
||||
NoStrikethroughAttr: "29",
|
||||
BlackForegroundColorAttr: "30",
|
||||
RedForegroundColorAttr: "31",
|
||||
GreenForegroundColorAttr: "32",
|
||||
YellowForegroundColorAttr: "33",
|
||||
BlueForegroundColorAttr: "34",
|
||||
MagentaForegroundColorAttr: "35",
|
||||
CyanForegroundColorAttr: "36",
|
||||
WhiteForegroundColorAttr: "37",
|
||||
ExtendedForegroundColorAttr: "38",
|
||||
DefaultForegroundColorAttr: "39",
|
||||
BlackBackgroundColorAttr: "40",
|
||||
RedBackgroundColorAttr: "41",
|
||||
GreenBackgroundColorAttr: "42",
|
||||
YellowBackgroundColorAttr: "43",
|
||||
BlueBackgroundColorAttr: "44",
|
||||
MagentaBackgroundColorAttr: "45",
|
||||
CyanBackgroundColorAttr: "46",
|
||||
WhiteBackgroundColorAttr: "47",
|
||||
ExtendedBackgroundColorAttr: "48",
|
||||
DefaultBackgroundColorAttr: "49",
|
||||
ExtendedUnderlineColorAttr: "58",
|
||||
DefaultUnderlineColorAttr: "59",
|
||||
BrightBlackForegroundColorAttr: "90",
|
||||
BrightRedForegroundColorAttr: "91",
|
||||
BrightGreenForegroundColorAttr: "92",
|
||||
BrightYellowForegroundColorAttr: "93",
|
||||
BrightBlueForegroundColorAttr: "94",
|
||||
BrightMagentaForegroundColorAttr: "95",
|
||||
BrightCyanForegroundColorAttr: "96",
|
||||
BrightWhiteForegroundColorAttr: "97",
|
||||
BrightBlackBackgroundColorAttr: "100",
|
||||
BrightRedBackgroundColorAttr: "101",
|
||||
BrightGreenBackgroundColorAttr: "102",
|
||||
BrightYellowBackgroundColorAttr: "103",
|
||||
BrightBlueBackgroundColorAttr: "104",
|
||||
BrightMagentaBackgroundColorAttr: "105",
|
||||
BrightCyanBackgroundColorAttr: "106",
|
||||
BrightWhiteBackgroundColorAttr: "107",
|
||||
ResetAttr: resetAttr,
|
||||
BoldAttr: boldAttr,
|
||||
FaintAttr: faintAttr,
|
||||
ItalicAttr: italicAttr,
|
||||
UnderlineAttr: underlineAttr,
|
||||
SlowBlinkAttr: slowBlinkAttr,
|
||||
RapidBlinkAttr: rapidBlinkAttr,
|
||||
ReverseAttr: reverseAttr,
|
||||
ConcealAttr: concealAttr,
|
||||
StrikethroughAttr: strikethroughAttr,
|
||||
NormalIntensityAttr: normalIntensityAttr,
|
||||
NoItalicAttr: noItalicAttr,
|
||||
NoUnderlineAttr: noUnderlineAttr,
|
||||
NoBlinkAttr: noBlinkAttr,
|
||||
NoReverseAttr: noReverseAttr,
|
||||
NoConcealAttr: noConcealAttr,
|
||||
NoStrikethroughAttr: noStrikethroughAttr,
|
||||
BlackForegroundColorAttr: blackForegroundColorAttr,
|
||||
RedForegroundColorAttr: redForegroundColorAttr,
|
||||
GreenForegroundColorAttr: greenForegroundColorAttr,
|
||||
YellowForegroundColorAttr: yellowForegroundColorAttr,
|
||||
BlueForegroundColorAttr: blueForegroundColorAttr,
|
||||
MagentaForegroundColorAttr: magentaForegroundColorAttr,
|
||||
CyanForegroundColorAttr: cyanForegroundColorAttr,
|
||||
WhiteForegroundColorAttr: whiteForegroundColorAttr,
|
||||
ExtendedForegroundColorAttr: extendedForegroundColorAttr,
|
||||
DefaultForegroundColorAttr: defaultForegroundColorAttr,
|
||||
BlackBackgroundColorAttr: blackBackgroundColorAttr,
|
||||
RedBackgroundColorAttr: redBackgroundColorAttr,
|
||||
GreenBackgroundColorAttr: greenBackgroundColorAttr,
|
||||
YellowBackgroundColorAttr: yellowBackgroundColorAttr,
|
||||
BlueBackgroundColorAttr: blueBackgroundColorAttr,
|
||||
MagentaBackgroundColorAttr: magentaBackgroundColorAttr,
|
||||
CyanBackgroundColorAttr: cyanBackgroundColorAttr,
|
||||
WhiteBackgroundColorAttr: whiteBackgroundColorAttr,
|
||||
ExtendedBackgroundColorAttr: extendedBackgroundColorAttr,
|
||||
DefaultBackgroundColorAttr: defaultBackgroundColorAttr,
|
||||
ExtendedUnderlineColorAttr: extendedUnderlineColorAttr,
|
||||
DefaultUnderlineColorAttr: defaultUnderlineColorAttr,
|
||||
BrightBlackForegroundColorAttr: brightBlackForegroundColorAttr,
|
||||
BrightRedForegroundColorAttr: brightRedForegroundColorAttr,
|
||||
BrightGreenForegroundColorAttr: brightGreenForegroundColorAttr,
|
||||
BrightYellowForegroundColorAttr: brightYellowForegroundColorAttr,
|
||||
BrightBlueForegroundColorAttr: brightBlueForegroundColorAttr,
|
||||
BrightMagentaForegroundColorAttr: brightMagentaForegroundColorAttr,
|
||||
BrightCyanForegroundColorAttr: brightCyanForegroundColorAttr,
|
||||
BrightWhiteForegroundColorAttr: brightWhiteForegroundColorAttr,
|
||||
BrightBlackBackgroundColorAttr: brightBlackBackgroundColorAttr,
|
||||
BrightRedBackgroundColorAttr: brightRedBackgroundColorAttr,
|
||||
BrightGreenBackgroundColorAttr: brightGreenBackgroundColorAttr,
|
||||
BrightYellowBackgroundColorAttr: brightYellowBackgroundColorAttr,
|
||||
BrightBlueBackgroundColorAttr: brightBlueBackgroundColorAttr,
|
||||
BrightMagentaBackgroundColorAttr: brightMagentaBackgroundColorAttr,
|
||||
BrightCyanBackgroundColorAttr: brightCyanBackgroundColorAttr,
|
||||
BrightWhiteBackgroundColorAttr: brightWhiteBackgroundColorAttr,
|
||||
}
|
||||
|
30
vendor/github.com/charmbracelet/x/ansi/status.go
generated
vendored
30
vendor/github.com/charmbracelet/x/ansi/status.go
generated
vendored
@ -11,10 +11,10 @@ type StatusReport interface {
|
||||
StatusReport() int
|
||||
}
|
||||
|
||||
// ANSIReport represents an ANSI terminal status report.
|
||||
// ANSIStatusReport represents an ANSI terminal status report.
|
||||
type ANSIStatusReport int //nolint:revive
|
||||
|
||||
// Report returns the status report identifier.
|
||||
// StatusReport returns the status report identifier.
|
||||
func (s ANSIStatusReport) StatusReport() int {
|
||||
return int(s)
|
||||
}
|
||||
@ -22,7 +22,7 @@ func (s ANSIStatusReport) StatusReport() int {
|
||||
// DECStatusReport represents a DEC terminal status report.
|
||||
type DECStatusReport int
|
||||
|
||||
// Status returns the status report identifier.
|
||||
// StatusReport returns the status report identifier.
|
||||
func (s DECStatusReport) StatusReport() int {
|
||||
return int(s)
|
||||
}
|
||||
@ -89,6 +89,16 @@ const RequestCursorPositionReport = "\x1b[6n"
|
||||
// See: https://vt100.net/docs/vt510-rm/DECXCPR.html
|
||||
const RequestExtendedCursorPositionReport = "\x1b[?6n"
|
||||
|
||||
// RequestLightDarkReport is a control sequence that requests the terminal to
|
||||
// report its operating system light/dark color preference. Supported terminals
|
||||
// should respond with a [LightDarkReport] sequence as follows:
|
||||
//
|
||||
// CSI ? 997 ; 1 n for dark mode
|
||||
// CSI ? 997 ; 2 n for light mode
|
||||
//
|
||||
// See: https://contour-terminal.org/vt-extensions/color-palette-update-notifications/
|
||||
const RequestLightDarkReport = "\x1b[?996n"
|
||||
|
||||
// CursorPositionReport (CPR) is a control sequence that reports the cursor's
|
||||
// position.
|
||||
//
|
||||
@ -142,3 +152,17 @@ func ExtendedCursorPositionReport(line, column, page int) string {
|
||||
func DECXCPR(line, column, page int) string {
|
||||
return ExtendedCursorPositionReport(line, column, page)
|
||||
}
|
||||
|
||||
// LightDarkReport is a control sequence that reports the terminal's operating
|
||||
// system light/dark color preference.
|
||||
//
|
||||
// CSI ? 997 ; 1 n for dark mode
|
||||
// CSI ? 997 ; 2 n for light mode
|
||||
//
|
||||
// See: https://contour-terminal.org/vt-extensions/color-palette-update-notifications/
|
||||
func LightDarkReport(dark bool) string {
|
||||
if dark {
|
||||
return "\x1b[?997;1n"
|
||||
}
|
||||
return "\x1b[?997;2n"
|
||||
}
|
||||
|
35
vendor/github.com/charmbracelet/x/ansi/style.go
generated
vendored
35
vendor/github.com/charmbracelet/x/ansi/style.go
generated
vendored
@ -17,6 +17,26 @@ type Attr = int
|
||||
// Style represents an ANSI SGR (Select Graphic Rendition) style.
|
||||
type Style []string
|
||||
|
||||
// NewStyle returns a new style with the given attributes.
|
||||
func NewStyle(attrs ...Attr) Style {
|
||||
if len(attrs) == 0 {
|
||||
return Style{}
|
||||
}
|
||||
s := make(Style, 0, len(attrs))
|
||||
for _, a := range attrs {
|
||||
attr, ok := attrStrings[a]
|
||||
if ok {
|
||||
s = append(s, attr)
|
||||
} else {
|
||||
if a < 0 {
|
||||
a = 0
|
||||
}
|
||||
s = append(s, strconv.Itoa(a))
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// String returns the ANSI SGR (Select Graphic Rendition) style sequence for
|
||||
// the given style.
|
||||
func (s Style) String() string {
|
||||
@ -127,11 +147,6 @@ func (s Style) Strikethrough() Style {
|
||||
return append(s, strikethroughAttr)
|
||||
}
|
||||
|
||||
// NoBold appends the no bold style attribute to the style.
|
||||
func (s Style) NoBold() Style {
|
||||
return append(s, noBoldAttr)
|
||||
}
|
||||
|
||||
// NormalIntensity appends the normal intensity style attribute to the style.
|
||||
func (s Style) NormalIntensity() Style {
|
||||
return append(s, normalIntensityAttr)
|
||||
@ -236,7 +251,6 @@ const (
|
||||
ReverseAttr Attr = 7
|
||||
ConcealAttr Attr = 8
|
||||
StrikethroughAttr Attr = 9
|
||||
NoBoldAttr Attr = 21 // Some terminals treat this as double underline.
|
||||
NormalIntensityAttr Attr = 22
|
||||
NoItalicAttr Attr = 23
|
||||
NoUnderlineAttr Attr = 24
|
||||
@ -298,7 +312,6 @@ const (
|
||||
reverseAttr = "7"
|
||||
concealAttr = "8"
|
||||
strikethroughAttr = "9"
|
||||
noBoldAttr = "21"
|
||||
normalIntensityAttr = "22"
|
||||
noItalicAttr = "23"
|
||||
noUnderlineAttr = "24"
|
||||
@ -581,7 +594,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
||||
B: uint8(b), //nolint:gosec
|
||||
A: 0xff,
|
||||
}
|
||||
return
|
||||
return //nolint:nakedret
|
||||
|
||||
case 3: // CMY direct color
|
||||
if len(params) < 5 {
|
||||
@ -599,7 +612,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
||||
Y: uint8(y), //nolint:gosec
|
||||
K: 0,
|
||||
}
|
||||
return
|
||||
return //nolint:nakedret
|
||||
|
||||
case 4: // CMYK direct color
|
||||
if len(params) < 6 {
|
||||
@ -617,7 +630,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
||||
Y: uint8(y), //nolint:gosec
|
||||
K: uint8(k), //nolint:gosec
|
||||
}
|
||||
return
|
||||
return //nolint:nakedret
|
||||
|
||||
case 5: // indexed color
|
||||
if len(params) < 3 {
|
||||
@ -652,7 +665,7 @@ func ReadStyleColor(params Params, co *color.Color) (n int) {
|
||||
B: uint8(b), //nolint:gosec
|
||||
A: uint8(a), //nolint:gosec
|
||||
}
|
||||
return
|
||||
return //nolint:nakedret
|
||||
|
||||
default:
|
||||
return 0
|
||||
|
2
vendor/github.com/charmbracelet/x/ansi/termcap.go
generated
vendored
2
vendor/github.com/charmbracelet/x/ansi/termcap.go
generated
vendored
@ -5,7 +5,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// RequestTermcap (XTGETTCAP) requests Termcap/Terminfo strings.
|
||||
// XTGETTCAP (RequestTermcap) requests Termcap/Terminfo strings.
|
||||
//
|
||||
// DCS + q <Pt> ST
|
||||
//
|
||||
|
16
vendor/github.com/charmbracelet/x/ansi/title.go
generated
vendored
16
vendor/github.com/charmbracelet/x/ansi/title.go
generated
vendored
@ -30,3 +30,19 @@ func SetIconName(s string) string {
|
||||
func SetWindowTitle(s string) string {
|
||||
return "\x1b]2;" + s + "\x07"
|
||||
}
|
||||
|
||||
// DECSWT is a sequence for setting the window title.
|
||||
//
|
||||
// This is an alias for [SetWindowTitle]("1;<name>").
|
||||
// See: EK-VT520-RM 5–156 https://vt100.net/dec/ek-vt520-rm.pdf
|
||||
func DECSWT(name string) string {
|
||||
return SetWindowTitle("1;" + name)
|
||||
}
|
||||
|
||||
// DECSIN is a sequence for setting the icon name.
|
||||
//
|
||||
// This is an alias for [SetWindowTitle]("L;<name>").
|
||||
// See: EK-VT520-RM 5–134 https://vt100.net/dec/ek-vt520-rm.pdf
|
||||
func DECSIN(name string) string {
|
||||
return SetWindowTitle("L;" + name)
|
||||
}
|
||||
|
41
vendor/github.com/charmbracelet/x/ansi/truncate.go
generated
vendored
41
vendor/github.com/charmbracelet/x/ansi/truncate.go
generated
vendored
@ -10,8 +10,7 @@ import (
|
||||
|
||||
// Cut the string, without adding any prefix or tail strings. This function is
|
||||
// aware of ANSI escape codes and will not break them, and accounts for
|
||||
// wide-characters (such as East-Asian characters and emojis). Note that the
|
||||
// [left] parameter is inclusive, while [right] isn't.
|
||||
// wide-characters (such as East-Asian characters and emojis).
|
||||
// This treats the text as a sequence of graphemes.
|
||||
func Cut(s string, left, right int) string {
|
||||
return cut(GraphemeWidth, s, left, right)
|
||||
@ -19,8 +18,10 @@ func Cut(s string, left, right int) string {
|
||||
|
||||
// CutWc the string, without adding any prefix or tail strings. This function is
|
||||
// aware of ANSI escape codes and will not break them, and accounts for
|
||||
// wide-characters (such as East-Asian characters and emojis). Note that the
|
||||
// [left] parameter is inclusive, while [right] isn't.
|
||||
// wide-characters (such as East-Asian characters and emojis).
|
||||
// Note that the [left] parameter is inclusive, while [right] isn't,
|
||||
// which is to say it'll return `[left, right)`.
|
||||
//
|
||||
// This treats the text as a sequence of wide characters and runes.
|
||||
func CutWc(s string, left, right int) string {
|
||||
return cut(WcWidth, s, left, right)
|
||||
@ -41,7 +42,7 @@ func cut(m Method, s string, left, right int) string {
|
||||
if left == 0 {
|
||||
return truncate(s, right, "")
|
||||
}
|
||||
return truncateLeft(Truncate(s, right, ""), left, "")
|
||||
return truncateLeft(truncate(s, right, ""), left, "")
|
||||
}
|
||||
|
||||
// Truncate truncates a string to a given length, adding a tail to the end if
|
||||
@ -99,6 +100,7 @@ func truncate(m Method, s string, length int, tail string) string {
|
||||
|
||||
// increment the index by the length of the cluster
|
||||
i += len(cluster)
|
||||
curWidth += width
|
||||
|
||||
// Are we ignoring? Skip to the next byte
|
||||
if ignoring {
|
||||
@ -107,16 +109,15 @@ func truncate(m Method, s string, length int, tail string) string {
|
||||
|
||||
// Is this gonna be too wide?
|
||||
// If so write the tail and stop collecting.
|
||||
if curWidth+width > length && !ignoring {
|
||||
if curWidth > length && !ignoring {
|
||||
ignoring = true
|
||||
buf.WriteString(tail)
|
||||
}
|
||||
|
||||
if curWidth+width > length {
|
||||
if curWidth > length {
|
||||
continue
|
||||
}
|
||||
|
||||
curWidth += width
|
||||
buf.Write(cluster)
|
||||
|
||||
// Done collecting, now we're back in the ground state.
|
||||
@ -142,6 +143,14 @@ func truncate(m Method, s string, length int, tail string) string {
|
||||
// collects printable ASCII
|
||||
curWidth++
|
||||
fallthrough
|
||||
case parser.ExecuteAction:
|
||||
// execute action will be things like \n, which, if outside the cut,
|
||||
// should be ignored.
|
||||
if ignoring {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
buf.WriteByte(b[i])
|
||||
i++
|
||||
@ -214,14 +223,14 @@ func truncateLeft(m Method, s string, n int, prefix string) string {
|
||||
buf.WriteString(prefix)
|
||||
}
|
||||
|
||||
if ignoring {
|
||||
continue
|
||||
}
|
||||
|
||||
if curWidth > n {
|
||||
buf.Write(cluster)
|
||||
}
|
||||
|
||||
if ignoring {
|
||||
continue
|
||||
}
|
||||
|
||||
pstate = parser.GroundState
|
||||
continue
|
||||
}
|
||||
@ -240,6 +249,14 @@ func truncateLeft(m Method, s string, n int, prefix string) string {
|
||||
continue
|
||||
}
|
||||
|
||||
fallthrough
|
||||
case parser.ExecuteAction:
|
||||
// execute action will be things like \n, which, if outside the cut,
|
||||
// should be ignored.
|
||||
if ignoring {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
buf.WriteByte(b[i])
|
||||
|
18
vendor/github.com/charmbracelet/x/ansi/util.go
generated
vendored
18
vendor/github.com/charmbracelet/x/ansi/util.go
generated
vendored
@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
// colorToHexString returns a hex string representation of a color.
|
||||
func colorToHexString(c color.Color) string {
|
||||
func colorToHexString(c color.Color) string { //nolint:unused
|
||||
if c == nil {
|
||||
return ""
|
||||
}
|
||||
@ -28,7 +28,7 @@ func colorToHexString(c color.Color) string {
|
||||
// rgbToHex converts red, green, and blue values to a hexadecimal value.
|
||||
//
|
||||
// hex := rgbToHex(0, 0, 255) // 0x0000FF
|
||||
func rgbToHex(r, g, b uint32) uint32 {
|
||||
func rgbToHex(r, g, b uint32) uint32 { //nolint:unused
|
||||
return r<<16 + g<<8 + b
|
||||
}
|
||||
|
||||
@ -90,17 +90,3 @@ func XParseColor(s string) color.Color {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ordered interface {
|
||||
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
|
||||
~float32 | ~float64 |
|
||||
~string
|
||||
}
|
||||
|
||||
func max[T ordered](a, b T) T { //nolint:predeclared
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
2
vendor/github.com/charmbracelet/x/ansi/width.go
generated
vendored
2
vendor/github.com/charmbracelet/x/ansi/width.go
generated
vendored
@ -19,7 +19,7 @@ func Strip(s string) string {
|
||||
|
||||
// This implements a subset of the Parser to only collect runes and
|
||||
// printable characters.
|
||||
for i := 0; i < len(s); i++ {
|
||||
for i := range len(s) {
|
||||
if pstate == parser.Utf8State {
|
||||
// During this state, collect rw bytes to form a valid rune in the
|
||||
// buffer. After getting all the rune bytes into the buffer,
|
||||
|
41
vendor/github.com/charmbracelet/x/ansi/wrap.go
generated
vendored
41
vendor/github.com/charmbracelet/x/ansi/wrap.go
generated
vendored
@ -10,7 +10,7 @@ import (
|
||||
"github.com/rivo/uniseg"
|
||||
)
|
||||
|
||||
// nbsp is a non-breaking space
|
||||
// nbsp is a non-breaking space.
|
||||
const nbsp = 0xA0
|
||||
|
||||
// Hardwrap wraps a string or a block of text to a given line length, breaking
|
||||
@ -55,7 +55,7 @@ func hardwrap(m Method, s string, limit int, preserveSpace bool) string {
|
||||
i := 0
|
||||
for i < len(b) {
|
||||
state, action := parser.Table.Transition(pstate, b[i])
|
||||
if state == parser.Utf8State {
|
||||
if state == parser.Utf8State { //nolint:nestif
|
||||
var width int
|
||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
||||
if m == WcWidth {
|
||||
@ -190,7 +190,7 @@ func wordwrap(m Method, s string, limit int, breakpoints string) string {
|
||||
i := 0
|
||||
for i < len(b) {
|
||||
state, action := parser.Table.Transition(pstate, b[i])
|
||||
if state == parser.Utf8State {
|
||||
if state == parser.Utf8State { //nolint:nestif
|
||||
var width int
|
||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
||||
if m == WcWidth {
|
||||
@ -303,20 +303,22 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
}
|
||||
|
||||
var (
|
||||
cluster []byte
|
||||
buf bytes.Buffer
|
||||
word bytes.Buffer
|
||||
space bytes.Buffer
|
||||
curWidth int // written width of the line
|
||||
wordLen int // word buffer len without ANSI escape codes
|
||||
pstate = parser.GroundState // initial state
|
||||
b = []byte(s)
|
||||
cluster []byte
|
||||
buf bytes.Buffer
|
||||
word bytes.Buffer
|
||||
space bytes.Buffer
|
||||
spaceWidth int // width of the space buffer
|
||||
curWidth int // written width of the line
|
||||
wordLen int // word buffer len without ANSI escape codes
|
||||
pstate = parser.GroundState // initial state
|
||||
b = []byte(s)
|
||||
)
|
||||
|
||||
addSpace := func() {
|
||||
curWidth += space.Len()
|
||||
curWidth += spaceWidth
|
||||
buf.Write(space.Bytes())
|
||||
space.Reset()
|
||||
spaceWidth = 0
|
||||
}
|
||||
|
||||
addWord := func() {
|
||||
@ -335,12 +337,13 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
buf.WriteByte('\n')
|
||||
curWidth = 0
|
||||
space.Reset()
|
||||
spaceWidth = 0
|
||||
}
|
||||
|
||||
i := 0
|
||||
for i < len(b) {
|
||||
state, action := parser.Table.Transition(pstate, b[i])
|
||||
if state == parser.Utf8State {
|
||||
if state == parser.Utf8State { //nolint:nestif
|
||||
var width int
|
||||
cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1)
|
||||
if m == WcWidth {
|
||||
@ -353,6 +356,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
case r != utf8.RuneError && unicode.IsSpace(r) && r != nbsp: // nbsp is a non-breaking space
|
||||
addWord()
|
||||
space.WriteRune(r)
|
||||
spaceWidth += width
|
||||
case bytes.ContainsAny(cluster, breakpoints):
|
||||
addSpace()
|
||||
if curWidth+wordLen+width > limit {
|
||||
@ -372,7 +376,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
word.Write(cluster)
|
||||
wordLen += width
|
||||
|
||||
if curWidth+wordLen+space.Len() > limit {
|
||||
if curWidth+wordLen+spaceWidth > limit {
|
||||
addNewline()
|
||||
}
|
||||
}
|
||||
@ -386,13 +390,14 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
switch r := rune(b[i]); {
|
||||
case r == '\n':
|
||||
if wordLen == 0 {
|
||||
if curWidth+space.Len() > limit {
|
||||
if curWidth+spaceWidth > limit {
|
||||
curWidth = 0
|
||||
} else {
|
||||
// preserve whitespaces
|
||||
buf.Write(space.Bytes())
|
||||
}
|
||||
space.Reset()
|
||||
spaceWidth = 0
|
||||
}
|
||||
|
||||
addWord()
|
||||
@ -400,6 +405,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
case unicode.IsSpace(r):
|
||||
addWord()
|
||||
space.WriteRune(r)
|
||||
spaceWidth++
|
||||
case r == '-':
|
||||
fallthrough
|
||||
case runeContainsAny(r, breakpoints):
|
||||
@ -426,7 +432,7 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
addWord()
|
||||
}
|
||||
|
||||
if curWidth+wordLen+space.Len() > limit {
|
||||
if curWidth+wordLen+spaceWidth > limit {
|
||||
addNewline()
|
||||
}
|
||||
}
|
||||
@ -443,13 +449,14 @@ func wrap(m Method, s string, limit int, breakpoints string) string {
|
||||
}
|
||||
|
||||
if wordLen == 0 {
|
||||
if curWidth+space.Len() > limit {
|
||||
if curWidth+spaceWidth > limit {
|
||||
curWidth = 0
|
||||
} else {
|
||||
// preserve whitespaces
|
||||
buf.Write(space.Bytes())
|
||||
}
|
||||
space.Reset()
|
||||
spaceWidth = 0
|
||||
}
|
||||
|
||||
addWord()
|
||||
|
Reference in New Issue
Block a user