1
0
mirror of https://github.com/taigrr/wtf synced 2026-04-01 20:38:43 -07:00

CmdRunner now displays ANSI color codes

This commit is contained in:
Chris Cummer
2018-07-18 16:16:28 -07:00
parent 31e77a59ad
commit 6e6d918bfe
25 changed files with 813 additions and 100 deletions

View File

@@ -71,7 +71,7 @@ Add your issue here on GitHub. Feel free to get in touch if you have any questio
- `Flex` and `Grid` don't clear their background per default, thus allowing for custom modals. See the [Wiki](https://github.com/rivo/tview/wiki/Modal) for an example.
- v0.14 (2018-04-13)
- Added an `Escape()` function which keep strings like color or region tags from being recognized as such.
- Added `ANSIIWriter()` and `TranslateANSII()` which convert ANSII escape sequences to `tview` color tags.
- Added `ANSIWriter()` and `TranslateANSI()` which convert ANSI escape sequences to `tview` color tags.
- v0.13 (2018-04-01)
- Added background colors and text attributes to color tags.
- v0.12 (2018-03-13)

View File

@@ -8,44 +8,44 @@ import (
"strings"
)
// The states of the ANSII escape code parser.
// The states of the ANSI escape code parser.
const (
ansiiText = iota
ansiiEscape
ansiiSubstring
ansiiControlSequence
ansiText = iota
ansiEscape
ansiSubstring
ansiControlSequence
)
// ansii is a io.Writer which translates ANSII escape codes into tview color
// ansi is a io.Writer which translates ANSI escape codes into tview color
// tags.
type ansii struct {
type ansi struct {
io.Writer
// Reusable buffers.
buffer *bytes.Buffer // The entire output text of one Write().
csiParameter, csiIntermediate *bytes.Buffer // Partial CSI strings.
// The current state of the parser. One of the ansii constants.
// The current state of the parser. One of the ansi constants.
state int
}
// ANSIIWriter returns an io.Writer which translates any ANSII escape codes
// ANSIWriter returns an io.Writer which translates any ANSI escape codes
// written to it into tview color tags. Other escape codes don't have an effect
// and are simply removed. The translated text is written to the provided
// writer.
func ANSIIWriter(writer io.Writer) io.Writer {
return &ansii{
func ANSIWriter(writer io.Writer) io.Writer {
return &ansi{
Writer: writer,
buffer: new(bytes.Buffer),
csiParameter: new(bytes.Buffer),
csiIntermediate: new(bytes.Buffer),
state: ansiiText,
state: ansiText,
}
}
// Write parses the given text as a string of runes, translates ANSII escape
// Write parses the given text as a string of runes, translates ANSI escape
// codes to color tags and writes them to the output writer.
func (a *ansii) Write(text []byte) (int, error) {
func (a *ansi) Write(text []byte) (int, error) {
defer func() {
a.buffer.Reset()
}()
@@ -54,23 +54,23 @@ func (a *ansii) Write(text []byte) (int, error) {
switch a.state {
// We just entered an escape sequence.
case ansiiEscape:
case ansiEscape:
switch r {
case '[': // Control Sequence Introducer.
a.csiParameter.Reset()
a.csiIntermediate.Reset()
a.state = ansiiControlSequence
a.state = ansiControlSequence
case 'c': // Reset.
fmt.Fprint(a.buffer, "[-:-:-]")
a.state = ansiiText
a.state = ansiText
case 'P', ']', 'X', '^', '_': // Substrings and commands.
a.state = ansiiSubstring
a.state = ansiSubstring
default: // Ignore.
a.state = ansiiText
a.state = ansiText
}
// CSI Sequences.
case ansiiControlSequence:
case ansiControlSequence:
switch {
case r >= 0x30 && r <= 0x3f: // Parameter bytes.
if _, err := a.csiParameter.WriteRune(r); err != nil {
@@ -194,22 +194,22 @@ func (a *ansii) Write(text []byte) (int, error) {
fmt.Fprintf(a.buffer, "[%s:%s%s]", foreground, background, attributes)
}
}
a.state = ansiiText
a.state = ansiText
default: // Undefined byte.
a.state = ansiiText // Abort CSI.
a.state = ansiText // Abort CSI.
}
// We just entered a substring/command sequence.
case ansiiSubstring:
case ansiSubstring:
if r == 27 { // Most likely the end of the substring.
a.state = ansiiEscape
a.state = ansiEscape
} // Ignore all other characters.
// "ansiiText" and all others.
// "ansiText" and all others.
default:
if r == 27 {
// This is the start of an escape sequence.
a.state = ansiiEscape
a.state = ansiEscape
} else {
// Just a regular rune. Send to buffer.
if _, err := a.buffer.WriteRune(r); err != nil {
@@ -227,11 +227,11 @@ func (a *ansii) Write(text []byte) (int, error) {
return len(text), nil
}
// TranslateANSII replaces ANSII escape sequences found in the provided string
// TranslateANSI replaces ANSI escape sequences found in the provided string
// with tview's color tags and returns the resulting string.
func TranslateANSII(text string) string {
func TranslateANSI(text string) string {
var buffer bytes.Buffer
writer := ANSIIWriter(&buffer)
writer := ANSIWriter(&buffer)
writer.Write([]byte(text))
return buffer.String()
}

39
vendor/github.com/rivo/tview/form.go generated vendored
View File

@@ -218,6 +218,25 @@ func (f *Form) AddButton(label string, selected func()) *Form {
return f
}
// RemoveButton removes the button at the specified position, starting with 0
// for the button that was added first.
func (f *Form) RemoveButton(index int) *Form {
f.buttons = append(f.buttons[:index], f.buttons[index+1:]...)
return f
}
// GetButtonIndex returns the index of the button with the given label, starting
// with 0 for the button that was added first. If no such label was found, -1
// is returned.
func (f *Form) GetButtonIndex(label string) int {
for index, button := range f.buttons {
if button.GetLabel() == label {
return index
}
}
return -1
}
// Clear removes all input elements from the form, including the buttons if
// specified.
func (f *Form) Clear(includeButtons bool) *Form {
@@ -251,6 +270,14 @@ func (f *Form) GetFormItem(index int) FormItem {
return f.items[index]
}
// RemoveFormItem removes the form element at the given position, starting with
// index 0. Elements are referenced in the order they were added. Buttons are
// not included.
func (f *Form) RemoveFormItem(index int) *Form {
f.items = append(f.items[:index], f.items[index+1:]...)
return f
}
// GetFormItemByLabel returns the first form element with the given label. If
// no such element is found, nil is returned. Buttons are not searched and will
// therefore not be returned.
@@ -263,6 +290,18 @@ func (f *Form) GetFormItemByLabel(label string) FormItem {
return nil
}
// GetFormItemIndex returns the index of the first form element with the given
// label. If no such element is found, -1 is returned. Buttons are not searched
// and will therefore not be returned.
func (f *Form) GetFormItemIndex(label string) int {
for index, item := range f.items {
if item.GetLabel() == label {
return index
}
}
return -1
}
// SetCancelFunc sets a handler which is called when the user hits the Escape
// key.
func (f *Form) SetCancelFunc(callback func()) *Form {