Update dependencies
This commit is contained in:
parent
576bab9e2e
commit
e48ff5bea4
2
Gopkg.lock
generated
2
Gopkg.lock
generated
@ -139,7 +139,7 @@
|
||||
branch = "master"
|
||||
name = "maunium.net/go/tview"
|
||||
packages = ["."]
|
||||
revision = "6146b7fe2331e23a78e217016705bc6801bfc55a"
|
||||
revision = "7eabba90a261a481d36ace89daa79c56582238d7"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
|
5
vendor/maunium.net/go/tview/README.md
generated
vendored
5
vendor/maunium.net/go/tview/README.md
generated
vendored
@ -64,6 +64,11 @@ Add your issue here on GitHub. Feel free to get in touch if you have any questio
|
||||
|
||||
(There are no corresponding tags in the project. I only keep such a history in this README.)
|
||||
|
||||
- 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.
|
||||
- v0.13 (2018-04-01)
|
||||
- Added background colors and text attributes to color tags.
|
||||
- v0.12 (2018-03-13)
|
||||
- Added "suspended mode" to `Application`.
|
||||
- v0.11 (2018-03-02)
|
||||
|
237
vendor/maunium.net/go/tview/ansii.go
generated
vendored
Normal file
237
vendor/maunium.net/go/tview/ansii.go
generated
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
package tview
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// The states of the ANSII escape code parser.
|
||||
const (
|
||||
ansiiText = iota
|
||||
ansiiEscape
|
||||
ansiiSubstring
|
||||
ansiiControlSequence
|
||||
)
|
||||
|
||||
// ansii is a io.Writer which translates ANSII escape codes into tview color
|
||||
// tags.
|
||||
type ansii 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.
|
||||
state int
|
||||
}
|
||||
|
||||
// ANSIIWriter returns an io.Writer which translates any ANSII 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{
|
||||
Writer: writer,
|
||||
buffer: new(bytes.Buffer),
|
||||
csiParameter: new(bytes.Buffer),
|
||||
csiIntermediate: new(bytes.Buffer),
|
||||
state: ansiiText,
|
||||
}
|
||||
}
|
||||
|
||||
// Write parses the given text as a string of runes, translates ANSII escape
|
||||
// codes to color tags and writes them to the output writer.
|
||||
func (a *ansii) Write(text []byte) (int, error) {
|
||||
defer func() {
|
||||
a.buffer.Reset()
|
||||
}()
|
||||
|
||||
for _, r := range string(text) {
|
||||
switch a.state {
|
||||
|
||||
// We just entered an escape sequence.
|
||||
case ansiiEscape:
|
||||
switch r {
|
||||
case '[': // Control Sequence Introducer.
|
||||
a.csiParameter.Reset()
|
||||
a.csiIntermediate.Reset()
|
||||
a.state = ansiiControlSequence
|
||||
case 'c': // Reset.
|
||||
fmt.Fprint(a.buffer, "[-:-:-]")
|
||||
a.state = ansiiText
|
||||
case 'P', ']', 'X', '^', '_': // Substrings and commands.
|
||||
a.state = ansiiSubstring
|
||||
default: // Ignore.
|
||||
a.state = ansiiText
|
||||
}
|
||||
|
||||
// CSI Sequences.
|
||||
case ansiiControlSequence:
|
||||
switch {
|
||||
case r >= 0x30 && r <= 0x3f: // Parameter bytes.
|
||||
if _, err := a.csiParameter.WriteRune(r); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
case r >= 0x20 && r <= 0x2f: // Intermediate bytes.
|
||||
if _, err := a.csiIntermediate.WriteRune(r); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
case r >= 0x40 && r <= 0x7e: // Final byte.
|
||||
switch r {
|
||||
case 'E': // Next line.
|
||||
count, _ := strconv.Atoi(a.csiParameter.String())
|
||||
if count == 0 {
|
||||
count = 1
|
||||
}
|
||||
fmt.Fprint(a.buffer, strings.Repeat("\n", count))
|
||||
case 'm': // Select Graphic Rendition.
|
||||
var (
|
||||
background, foreground, attributes string
|
||||
clearAttributes bool
|
||||
)
|
||||
fields := strings.Split(a.csiParameter.String(), ";")
|
||||
if len(fields) == 0 || len(fields) == 1 && fields[0] == "0" {
|
||||
// Reset.
|
||||
if _, err := a.buffer.WriteString("[-:-:-]"); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
break
|
||||
}
|
||||
lookupColor := func(colorNumber int, bright bool) string {
|
||||
if colorNumber < 0 || colorNumber > 7 {
|
||||
return "black"
|
||||
}
|
||||
if bright {
|
||||
colorNumber += 8
|
||||
}
|
||||
return [...]string{
|
||||
"black",
|
||||
"red",
|
||||
"green",
|
||||
"yellow",
|
||||
"blue",
|
||||
"darkmagenta",
|
||||
"darkcyan",
|
||||
"white",
|
||||
"#7f7f7f",
|
||||
"#ff0000",
|
||||
"#00ff00",
|
||||
"#ffff00",
|
||||
"#5c5cff",
|
||||
"#ff00ff",
|
||||
"#00ffff",
|
||||
"#ffffff",
|
||||
}[colorNumber]
|
||||
}
|
||||
for index, field := range fields {
|
||||
switch field {
|
||||
case "1", "01":
|
||||
attributes += "b"
|
||||
case "2", "02":
|
||||
attributes += "d"
|
||||
case "4", "04":
|
||||
attributes += "u"
|
||||
case "5", "05":
|
||||
attributes += "l"
|
||||
case "7", "07":
|
||||
attributes += "7"
|
||||
case "22", "24", "25", "27":
|
||||
clearAttributes = true
|
||||
case "30", "31", "32", "33", "34", "35", "36", "37":
|
||||
colorNumber, _ := strconv.Atoi(field)
|
||||
foreground = lookupColor(colorNumber-30, false)
|
||||
case "40", "41", "42", "43", "44", "45", "46", "47":
|
||||
colorNumber, _ := strconv.Atoi(field)
|
||||
background = lookupColor(colorNumber-40, false)
|
||||
case "90", "91", "92", "93", "94", "95", "96", "97":
|
||||
colorNumber, _ := strconv.Atoi(field)
|
||||
foreground = lookupColor(colorNumber-90, true)
|
||||
case "100", "101", "102", "103", "104", "105", "106", "107":
|
||||
colorNumber, _ := strconv.Atoi(field)
|
||||
background = lookupColor(colorNumber-100, true)
|
||||
case "38", "48":
|
||||
var color string
|
||||
if len(fields) > index+1 {
|
||||
if fields[index+1] == "5" && len(fields) > index+2 { // 8-bit colors.
|
||||
colorNumber, _ := strconv.Atoi(fields[index+2])
|
||||
if colorNumber <= 7 {
|
||||
color = lookupColor(colorNumber, false)
|
||||
} else if colorNumber <= 15 {
|
||||
color = lookupColor(colorNumber, true)
|
||||
} else if colorNumber <= 231 {
|
||||
red := (colorNumber - 16) / 36
|
||||
green := ((colorNumber - 16) / 6) % 6
|
||||
blue := (colorNumber - 16) % 6
|
||||
color = fmt.Sprintf("%02x%02x%02x", 255*red/5, 255*green/5, 255*blue/5)
|
||||
} else if colorNumber <= 255 {
|
||||
grey := 255 * (colorNumber - 232) / 23
|
||||
color = fmt.Sprintf("%02x%02x%02x", grey, grey, grey)
|
||||
}
|
||||
} else if fields[index+1] == "2" && len(fields) > index+4 { // 24-bit colors.
|
||||
red, _ := strconv.Atoi(fields[index+2])
|
||||
green, _ := strconv.Atoi(fields[index+3])
|
||||
blue, _ := strconv.Atoi(fields[index+4])
|
||||
color = fmt.Sprintf("%02x%02x%02x", red, green, blue)
|
||||
}
|
||||
}
|
||||
if len(color) > 0 {
|
||||
if field == "38" {
|
||||
foreground = color
|
||||
} else {
|
||||
background = color
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(attributes) > 0 || clearAttributes {
|
||||
attributes = ":" + attributes
|
||||
}
|
||||
if len(foreground) > 0 || len(background) > 0 || len(attributes) > 0 {
|
||||
fmt.Fprintf(a.buffer, "[%s:%s%s]", foreground, background, attributes)
|
||||
}
|
||||
}
|
||||
a.state = ansiiText
|
||||
default: // Undefined byte.
|
||||
a.state = ansiiText // Abort CSI.
|
||||
}
|
||||
|
||||
// We just entered a substring/command sequence.
|
||||
case ansiiSubstring:
|
||||
if r == 27 { // Most likely the end of the substring.
|
||||
a.state = ansiiEscape
|
||||
} // Ignore all other characters.
|
||||
|
||||
// "ansiiText" and all others.
|
||||
default:
|
||||
if r == 27 {
|
||||
// This is the start of an escape sequence.
|
||||
a.state = ansiiEscape
|
||||
} else {
|
||||
// Just a regular rune. Send to buffer.
|
||||
if _, err := a.buffer.WriteRune(r); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write buffer to target writer.
|
||||
n, err := a.buffer.WriteTo(a.Writer)
|
||||
if err != nil {
|
||||
return int(n), err
|
||||
}
|
||||
return len(text), nil
|
||||
}
|
||||
|
||||
// TranslateANSII replaces ANSII escape sequences found in the provided string
|
||||
// with tview's color tags and returns the resulting string.
|
||||
func TranslateANSII(text string) string {
|
||||
var buffer bytes.Buffer
|
||||
writer := ANSIIWriter(&buffer)
|
||||
writer.Write([]byte(text))
|
||||
return buffer.String()
|
||||
}
|
20
vendor/maunium.net/go/tview/application.go
generated
vendored
20
vendor/maunium.net/go/tview/application.go
generated
vendored
@ -38,6 +38,8 @@ type Application struct {
|
||||
// be forwarded).
|
||||
mouseCapture func(event *tcell.EventMouse) *tcell.EventMouse
|
||||
|
||||
pasteCapture func(event *tcell.EventPaste) *tcell.EventPaste
|
||||
|
||||
// An optional callback function which is invoked just before the root
|
||||
// primitive is drawn.
|
||||
beforeDraw func(screen tcell.Screen) bool
|
||||
@ -190,6 +192,24 @@ func (a *Application) Run() error {
|
||||
//a.Draw()
|
||||
}
|
||||
}
|
||||
case *tcell.EventPaste:
|
||||
a.RLock()
|
||||
p := a.focus
|
||||
a.RUnlock()
|
||||
|
||||
if a.pasteCapture != nil {
|
||||
event = a.pasteCapture(event)
|
||||
if event == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if p != nil {
|
||||
if handler := p.PasteHandler(); handler != nil {
|
||||
handler(event)
|
||||
a.Draw()
|
||||
}
|
||||
}
|
||||
case *tcell.EventResize:
|
||||
a.Lock()
|
||||
screen := a.screen
|
||||
|
32
vendor/maunium.net/go/tview/box.go
generated
vendored
32
vendor/maunium.net/go/tview/box.go
generated
vendored
@ -62,6 +62,8 @@ type Box struct {
|
||||
// nothing should be forwarded).
|
||||
mouseCapture func(event *tcell.EventMouse) *tcell.EventMouse
|
||||
|
||||
pasteCapture func(event *tcell.EventPaste) *tcell.EventPaste
|
||||
|
||||
// An optional function which is called before the box is drawn.
|
||||
draw func(screen tcell.Screen, x, y, width, height int) (int, int, int, int)
|
||||
}
|
||||
@ -218,6 +220,36 @@ func (b *Box) GetMouseCapture() func(event *tcell.EventMouse) *tcell.EventMouse
|
||||
return b.mouseCapture
|
||||
}
|
||||
|
||||
func (b *Box) WrapPasteHandler(pasteHandler func(*tcell.EventPaste)) func(*tcell.EventPaste) {
|
||||
return func(event *tcell.EventPaste) {
|
||||
if b.pasteCapture != nil {
|
||||
event = b.pasteCapture(event)
|
||||
}
|
||||
if event != nil && pasteHandler != nil {
|
||||
pasteHandler(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Box) PasteHandler() func(event *tcell.EventPaste) {
|
||||
return b.WrapPasteHandler(func(event *tcell.EventPaste) {
|
||||
// Default paste handler just calls input handler with each character.
|
||||
inputHandler := b.InputHandler()
|
||||
for _, char := range event.Text() {
|
||||
inputHandler(tcell.NewEventKey(tcell.KeyRune, char, tcell.ModNone), nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (b *Box) SetPasteCapture(capture func(event *tcell.EventPaste) *tcell.EventPaste) *Box {
|
||||
b.pasteCapture = capture
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *Box) GetPasteCapture() func(event *tcell.EventPaste) *tcell.EventPaste {
|
||||
return b.pasteCapture
|
||||
}
|
||||
|
||||
// SetBackgroundColor sets the box's background color.
|
||||
func (b *Box) SetBackgroundColor(color tcell.Color) *Box {
|
||||
b.backgroundColor = color
|
||||
|
36
vendor/maunium.net/go/tview/checkbox.go
generated
vendored
36
vendor/maunium.net/go/tview/checkbox.go
generated
vendored
@ -17,6 +17,10 @@ type Checkbox struct {
|
||||
// The text to be displayed before the input area.
|
||||
label string
|
||||
|
||||
// The screen width of the label area. A value of 0 means use the width of
|
||||
// the label text.
|
||||
labelWidth int
|
||||
|
||||
// The label color.
|
||||
labelColor tcell.Color
|
||||
|
||||
@ -34,6 +38,10 @@ type Checkbox struct {
|
||||
// are done entering text. The key which was pressed is provided (tab,
|
||||
// shift-tab, or escape).
|
||||
done func(tcell.Key)
|
||||
|
||||
// A callback function set by the Form class and called when the user leaves
|
||||
// this form item.
|
||||
finished func(tcell.Key)
|
||||
}
|
||||
|
||||
// NewCheckbox returns a new input field.
|
||||
@ -68,6 +76,13 @@ func (c *Checkbox) GetLabel() string {
|
||||
return c.label
|
||||
}
|
||||
|
||||
// SetLabelWidth sets the screen width of the label. A value of 0 will cause the
|
||||
// primitive to use the width of the label string.
|
||||
func (c *Checkbox) SetLabelWidth(width int) *Checkbox {
|
||||
c.labelWidth = width
|
||||
return c
|
||||
}
|
||||
|
||||
// SetLabelColor sets the color of the label.
|
||||
func (c *Checkbox) SetLabelColor(color tcell.Color) *Checkbox {
|
||||
c.labelColor = color
|
||||
@ -87,8 +102,8 @@ func (c *Checkbox) SetFieldTextColor(color tcell.Color) *Checkbox {
|
||||
}
|
||||
|
||||
// SetFormAttributes sets attributes shared by all form items.
|
||||
func (c *Checkbox) SetFormAttributes(label string, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem {
|
||||
c.label = label
|
||||
func (c *Checkbox) SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem {
|
||||
c.labelWidth = labelWidth
|
||||
c.labelColor = labelColor
|
||||
c.backgroundColor = bgColor
|
||||
c.fieldTextColor = fieldTextColor
|
||||
@ -121,9 +136,10 @@ func (c *Checkbox) SetDoneFunc(handler func(key tcell.Key)) *Checkbox {
|
||||
return c
|
||||
}
|
||||
|
||||
// SetFinishedFunc calls SetDoneFunc().
|
||||
// SetFinishedFunc sets a callback invoked when the user leaves this form item.
|
||||
func (c *Checkbox) SetFinishedFunc(handler func(key tcell.Key)) FormItem {
|
||||
return c.SetDoneFunc(handler)
|
||||
c.finished = handler
|
||||
return c
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
@ -138,8 +154,17 @@ func (c *Checkbox) Draw(screen tcell.Screen) {
|
||||
}
|
||||
|
||||
// Draw label.
|
||||
if c.labelWidth > 0 {
|
||||
labelWidth := c.labelWidth
|
||||
if labelWidth > rightLimit-x {
|
||||
labelWidth = rightLimit - x
|
||||
}
|
||||
Print(screen, c.label, x, y, labelWidth, AlignLeft, c.labelColor)
|
||||
x += labelWidth
|
||||
} else {
|
||||
_, drawnWidth := Print(screen, c.label, x, y, rightLimit-x, AlignLeft, c.labelColor)
|
||||
x += drawnWidth
|
||||
}
|
||||
|
||||
// Draw checkbox.
|
||||
fieldStyle := tcell.StyleDefault.Background(c.fieldBackgroundColor).Foreground(c.fieldTextColor)
|
||||
@ -170,6 +195,9 @@ func (c *Checkbox) InputHandler() func(event *tcell.EventKey, setFocus func(p Pr
|
||||
if c.done != nil {
|
||||
c.done(key)
|
||||
}
|
||||
if c.finished != nil {
|
||||
c.finished(key)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
42
vendor/maunium.net/go/tview/doc.go
generated
vendored
42
vendor/maunium.net/go/tview/doc.go
generated
vendored
@ -77,13 +77,53 @@ applies to almost everything from box titles, list text, form item labels, to
|
||||
table cells. In a TextView, this functionality has to be switched on explicitly.
|
||||
See the TextView documentation for more information.
|
||||
|
||||
Color tags may contain not just the foreground (text) color but also the
|
||||
background color and additional flags. In fact, the full definition of a color
|
||||
tag is as follows:
|
||||
|
||||
[<foreground>:<background>:<flags>]
|
||||
|
||||
Each of the three fields can be left blank and trailing fields can be ommitted.
|
||||
(Empty square brackets "[]", however, are not considered color tags.) Colors
|
||||
that are not specified will be left unchanged. A field with just a dash ("-")
|
||||
means "reset to default".
|
||||
|
||||
You can specify the following flags (some flags may not be supported by your
|
||||
terminal):
|
||||
|
||||
l: blink
|
||||
b: bold
|
||||
d: dim
|
||||
r: reverse (switch foreground and background color)
|
||||
u: underline
|
||||
|
||||
Examples:
|
||||
|
||||
[yellow]Yellow text
|
||||
[yellow:red]Yellow text on red background
|
||||
[:red]Red background, text color unchanged
|
||||
[yellow::u]Yellow text underlined
|
||||
[::bl]Bold, blinking text
|
||||
[::-]Colors unchanged, flags reset
|
||||
[-]Reset foreground color
|
||||
[-:-:-]Reset everything
|
||||
[:]No effect
|
||||
[]Not a valid color tag, will print square brackets as they are
|
||||
|
||||
In the rare event that you want to display a string such as "[red]" or
|
||||
"[#00ff1a]" without applying its effect, you need to put an opening square
|
||||
bracket before the closing square bracket. Examples:
|
||||
bracket before the closing square bracket. Note that the text inside the
|
||||
brackets will be matched less strictly than region or colors tags. I.e. any
|
||||
character that may be used in color or region tags will be recognized. Examples:
|
||||
|
||||
[red[] will be output as [red]
|
||||
["123"[] will be output as ["123"]
|
||||
[#6aff00[[] will be output as [#6aff00[]
|
||||
[a#"[[[] will be output as [a#"[[]
|
||||
[] will be output as [] (see color tags above)
|
||||
[[] will be output as [[] (not an escaped tag)
|
||||
|
||||
You can use the Escape() function to insert brackets automatically where needed.
|
||||
|
||||
Styles
|
||||
|
||||
|
36
vendor/maunium.net/go/tview/dropdown.go
generated
vendored
36
vendor/maunium.net/go/tview/dropdown.go
generated
vendored
@ -51,6 +51,10 @@ type DropDown struct {
|
||||
// The color for prefixes.
|
||||
prefixTextColor tcell.Color
|
||||
|
||||
// The screen width of the label area. A value of 0 means use the width of
|
||||
// the label text.
|
||||
labelWidth int
|
||||
|
||||
// The screen width of the input area. A value of 0 means extend as much as
|
||||
// possible.
|
||||
fieldWidth int
|
||||
@ -59,6 +63,10 @@ type DropDown struct {
|
||||
// are done selecting options. The key which was pressed is provided (tab,
|
||||
// shift-tab, or escape).
|
||||
done func(tcell.Key)
|
||||
|
||||
// A callback function set by the Form class and called when the user leaves
|
||||
// this form item.
|
||||
finished func(tcell.Key)
|
||||
}
|
||||
|
||||
// NewDropDown returns a new drop-down.
|
||||
@ -113,6 +121,13 @@ func (d *DropDown) GetLabel() string {
|
||||
return d.label
|
||||
}
|
||||
|
||||
// SetLabelWidth sets the screen width of the label. A value of 0 will cause the
|
||||
// primitive to use the width of the label string.
|
||||
func (d *DropDown) SetLabelWidth(width int) *DropDown {
|
||||
d.labelWidth = width
|
||||
return d
|
||||
}
|
||||
|
||||
// SetLabelColor sets the color of the label.
|
||||
func (d *DropDown) SetLabelColor(color tcell.Color) *DropDown {
|
||||
d.labelColor = color
|
||||
@ -140,8 +155,8 @@ func (d *DropDown) SetPrefixTextColor(color tcell.Color) *DropDown {
|
||||
}
|
||||
|
||||
// SetFormAttributes sets attributes shared by all form items.
|
||||
func (d *DropDown) SetFormAttributes(label string, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem {
|
||||
d.label = label
|
||||
func (d *DropDown) SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem {
|
||||
d.labelWidth = labelWidth
|
||||
d.labelColor = labelColor
|
||||
d.backgroundColor = bgColor
|
||||
d.fieldTextColor = fieldTextColor
|
||||
@ -210,9 +225,10 @@ func (d *DropDown) SetDoneFunc(handler func(key tcell.Key)) *DropDown {
|
||||
return d
|
||||
}
|
||||
|
||||
// SetFinishedFunc calls SetDoneFunc().
|
||||
// SetFinishedFunc sets a callback invoked when the user leaves this form item.
|
||||
func (d *DropDown) SetFinishedFunc(handler func(key tcell.Key)) FormItem {
|
||||
return d.SetDoneFunc(handler)
|
||||
d.finished = handler
|
||||
return d
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
@ -227,8 +243,17 @@ func (d *DropDown) Draw(screen tcell.Screen) {
|
||||
}
|
||||
|
||||
// Draw label.
|
||||
if d.labelWidth > 0 {
|
||||
labelWidth := d.labelWidth
|
||||
if labelWidth > rightLimit-x {
|
||||
labelWidth = rightLimit - x
|
||||
}
|
||||
Print(screen, d.label, x, y, labelWidth, AlignLeft, d.labelColor)
|
||||
x += labelWidth
|
||||
} else {
|
||||
_, drawnWidth := Print(screen, d.label, x, y, rightLimit-x, AlignLeft, d.labelColor)
|
||||
x += drawnWidth
|
||||
}
|
||||
|
||||
// What's the longest option text?
|
||||
maxWidth := 0
|
||||
@ -359,6 +384,9 @@ func (d *DropDown) InputHandler() func(event *tcell.EventKey, setFocus func(p Pr
|
||||
if d.done != nil {
|
||||
d.done(key)
|
||||
}
|
||||
if d.finished != nil {
|
||||
d.finished(key)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
4
vendor/maunium.net/go/tview/flex.go
generated
vendored
4
vendor/maunium.net/go/tview/flex.go
generated
vendored
@ -69,8 +69,8 @@ func (f *Flex) SetFullScreen(fullScreen bool) *Flex {
|
||||
// that its size is flexible and may be changed. The "proportion" argument
|
||||
// defines the relative size of the item compared to other flexible-size items.
|
||||
// For example, items with a proportion of 2 will be twice as large as items
|
||||
// with a proportion of 1. Must be at least 1 if fixedSize > 0 (ignored
|
||||
// otherwise)
|
||||
// with a proportion of 1. The proportion must be at least 1 if fixedSize == 0
|
||||
// (ignored otherwise).
|
||||
//
|
||||
// If "focus" is set to true, the item will receive focus when the Flex
|
||||
// primitive receives focus. If multiple items have the "focus" flag set to
|
||||
|
36
vendor/maunium.net/go/tview/form.go
generated
vendored
36
vendor/maunium.net/go/tview/form.go
generated
vendored
@ -1,8 +1,6 @@
|
||||
package tview
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"maunium.net/go/tcell"
|
||||
)
|
||||
|
||||
@ -20,7 +18,7 @@ type FormItem interface {
|
||||
GetLabel() string
|
||||
|
||||
// SetFormAttributes sets a number of item attributes at once.
|
||||
SetFormAttributes(label string, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem
|
||||
SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem
|
||||
|
||||
// GetFieldWidth returns the width of the form item's field (the area which
|
||||
// is manipulated by the user) in number of screen cells. A value of 0
|
||||
@ -233,7 +231,14 @@ func (f *Form) Clear(includeButtons bool) *Form {
|
||||
|
||||
// AddFormItem adds a new item to the form. This can be used to add your own
|
||||
// objects to the form. Note, however, that the Form class will override some
|
||||
// of its attributes to make it work in the form context.
|
||||
// of its attributes to make it work in the form context. Specifically, these
|
||||
// are:
|
||||
//
|
||||
// - The label width
|
||||
// - The label color
|
||||
// - The background color
|
||||
// - The field text color
|
||||
// - The field background color
|
||||
func (f *Form) AddFormItem(item FormItem) *Form {
|
||||
f.items = append(f.items, item)
|
||||
return f
|
||||
@ -246,6 +251,18 @@ func (f *Form) GetFormItem(index int) FormItem {
|
||||
return f.items[index]
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (f *Form) GetFormItemByLabel(label string) FormItem {
|
||||
for _, item := range f.items {
|
||||
if item.GetLabel() == label {
|
||||
return item
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetCancelFunc sets a handler which is called when the user hits the Escape
|
||||
// key.
|
||||
func (f *Form) SetCancelFunc(callback func()) *Form {
|
||||
@ -267,8 +284,7 @@ func (f *Form) Draw(screen tcell.Screen) {
|
||||
// Find the longest label.
|
||||
var maxLabelWidth int
|
||||
for _, item := range f.items {
|
||||
label := strings.TrimSpace(item.GetLabel())
|
||||
labelWidth := StringWidth(label)
|
||||
labelWidth := StringWidth(item.GetLabel())
|
||||
if labelWidth > maxLabelWidth {
|
||||
maxLabelWidth = labelWidth
|
||||
}
|
||||
@ -280,20 +296,18 @@ func (f *Form) Draw(screen tcell.Screen) {
|
||||
var focusedPosition struct{ x, y, width, height int }
|
||||
for index, item := range f.items {
|
||||
// Calculate the space needed.
|
||||
label := strings.TrimSpace(item.GetLabel())
|
||||
labelWidth := StringWidth(label)
|
||||
labelWidth := StringWidth(item.GetLabel())
|
||||
var itemWidth int
|
||||
if f.horizontal {
|
||||
fieldWidth := item.GetFieldWidth()
|
||||
if fieldWidth == 0 {
|
||||
fieldWidth = DefaultFormFieldWidth
|
||||
}
|
||||
label += " "
|
||||
labelWidth++
|
||||
itemWidth = labelWidth + fieldWidth
|
||||
} else {
|
||||
// We want all fields to align vertically.
|
||||
label += strings.Repeat(" ", maxLabelWidth-labelWidth)
|
||||
labelWidth = maxLabelWidth
|
||||
itemWidth = width
|
||||
}
|
||||
|
||||
@ -308,7 +322,7 @@ func (f *Form) Draw(screen tcell.Screen) {
|
||||
itemWidth = rightLimit - x
|
||||
}
|
||||
item.SetFormAttributes(
|
||||
label,
|
||||
labelWidth,
|
||||
f.labelColor,
|
||||
f.backgroundColor,
|
||||
f.fieldTextColor,
|
||||
|
2
vendor/maunium.net/go/tview/grid.go
generated
vendored
2
vendor/maunium.net/go/tview/grid.go
generated
vendored
@ -258,7 +258,7 @@ func (g *Grid) HasFocus() bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return g.hasFocus
|
||||
}
|
||||
|
||||
// InputHandler returns the handler for this primitive.
|
||||
|
44
vendor/maunium.net/go/tview/inputfield.go
generated
vendored
44
vendor/maunium.net/go/tview/inputfield.go
generated
vendored
@ -41,6 +41,10 @@ type InputField struct {
|
||||
// The text color of the placeholder.
|
||||
placeholderTextColor tcell.Color
|
||||
|
||||
// The screen width of the label area. A value of 0 means use the width of
|
||||
// the label text.
|
||||
labelWidth int
|
||||
|
||||
// The screen width of the input area. A value of 0 means extend as much as
|
||||
// possible.
|
||||
fieldWidth int
|
||||
@ -59,6 +63,10 @@ type InputField struct {
|
||||
// are done entering text. The key which was pressed is provided (tab,
|
||||
// shift-tab, enter, or escape).
|
||||
done func(tcell.Key)
|
||||
|
||||
// A callback function set by the Form class and called when the user leaves
|
||||
// this form item.
|
||||
finished func(tcell.Key)
|
||||
}
|
||||
|
||||
// NewInputField returns a new input field.
|
||||
@ -97,6 +105,13 @@ func (i *InputField) GetLabel() string {
|
||||
return i.label
|
||||
}
|
||||
|
||||
// SetLabelWidth sets the screen width of the label. A value of 0 will cause the
|
||||
// primitive to use the width of the label string.
|
||||
func (i *InputField) SetLabelWidth(width int) *InputField {
|
||||
i.labelWidth = width
|
||||
return i
|
||||
}
|
||||
|
||||
// SetPlaceholder sets the text to be displayed when the input text is empty.
|
||||
func (i *InputField) SetPlaceholder(text string) *InputField {
|
||||
i.placeholder = text
|
||||
@ -121,15 +136,15 @@ func (i *InputField) SetFieldTextColor(color tcell.Color) *InputField {
|
||||
return i
|
||||
}
|
||||
|
||||
// SetPlaceholderExtColor sets the text color of placeholder text.
|
||||
func (i *InputField) SetPlaceholderExtColor(color tcell.Color) *InputField {
|
||||
// SetPlaceholderTextColor sets the text color of placeholder text.
|
||||
func (i *InputField) SetPlaceholderTextColor(color tcell.Color) *InputField {
|
||||
i.placeholderTextColor = color
|
||||
return i
|
||||
}
|
||||
|
||||
// SetFormAttributes sets attributes shared by all form items.
|
||||
func (i *InputField) SetFormAttributes(label string, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem {
|
||||
i.label = label
|
||||
func (i *InputField) SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem {
|
||||
i.labelWidth = labelWidth
|
||||
i.labelColor = labelColor
|
||||
i.backgroundColor = bgColor
|
||||
i.fieldTextColor = fieldTextColor
|
||||
@ -186,9 +201,10 @@ func (i *InputField) SetDoneFunc(handler func(key tcell.Key)) *InputField {
|
||||
return i
|
||||
}
|
||||
|
||||
// SetFinishedFunc calls SetDoneFunc().
|
||||
// SetFinishedFunc sets a callback invoked when the user leaves this form item.
|
||||
func (i *InputField) SetFinishedFunc(handler func(key tcell.Key)) FormItem {
|
||||
return i.SetDoneFunc(handler)
|
||||
i.finished = handler
|
||||
return i
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
@ -203,8 +219,17 @@ func (i *InputField) Draw(screen tcell.Screen) {
|
||||
}
|
||||
|
||||
// Draw label.
|
||||
if i.labelWidth > 0 {
|
||||
labelWidth := i.labelWidth
|
||||
if labelWidth > rightLimit-x {
|
||||
labelWidth = rightLimit - x
|
||||
}
|
||||
Print(screen, i.label, x, y, labelWidth, AlignLeft, i.labelColor)
|
||||
x += labelWidth
|
||||
} else {
|
||||
_, drawnWidth := Print(screen, i.label, x, y, rightLimit-x, AlignLeft, i.labelColor)
|
||||
x += drawnWidth
|
||||
}
|
||||
|
||||
// Draw input area.
|
||||
fieldWidth := i.fieldWidth
|
||||
@ -280,7 +305,11 @@ func (i *InputField) setCursor(screen tcell.Screen) {
|
||||
if i.fieldWidth > 0 && fieldWidth > i.fieldWidth-1 {
|
||||
fieldWidth = i.fieldWidth - 1
|
||||
}
|
||||
if i.labelWidth > 0 {
|
||||
x += i.labelWidth + fieldWidth
|
||||
} else {
|
||||
x += StringWidth(i.label) + fieldWidth
|
||||
}
|
||||
if x >= rightLimit {
|
||||
x = rightLimit - 1
|
||||
}
|
||||
@ -323,6 +352,9 @@ func (i *InputField) InputHandler() func(event *tcell.EventKey, setFocus func(p
|
||||
if i.done != nil {
|
||||
i.done(key)
|
||||
}
|
||||
if i.finished != nil {
|
||||
i.finished(key)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
20
vendor/maunium.net/go/tview/list.go
generated
vendored
20
vendor/maunium.net/go/tview/list.go
generated
vendored
@ -173,6 +173,26 @@ func (l *List) AddItem(mainText, secondaryText string, shortcut rune, selected f
|
||||
return l
|
||||
}
|
||||
|
||||
// GetItemCount returns the number of items in the list.
|
||||
func (l *List) GetItemCount() int {
|
||||
return len(l.items)
|
||||
}
|
||||
|
||||
// GetItemText returns an item's texts (main and secondary). Panics if the index
|
||||
// is out of range.
|
||||
func (l *List) GetItemText(index int) (main, secondary string) {
|
||||
return l.items[index].MainText, l.items[index].SecondaryText
|
||||
}
|
||||
|
||||
// SetItemText sets an item's main and secondary text. Panics if the index is
|
||||
// out of range.
|
||||
func (l *List) SetItemText(index int, main, secondary string) *List {
|
||||
item := l.items[index]
|
||||
item.MainText = main
|
||||
item.SecondaryText = secondary
|
||||
return l
|
||||
}
|
||||
|
||||
// Clear removes all items from the list.
|
||||
func (l *List) Clear() *List {
|
||||
l.items = nil
|
||||
|
2
vendor/maunium.net/go/tview/primitive.go
generated
vendored
2
vendor/maunium.net/go/tview/primitive.go
generated
vendored
@ -36,6 +36,8 @@ type Primitive interface {
|
||||
|
||||
MouseHandler() func(event *tcell.EventMouse, setFocus func(p Primitive))
|
||||
|
||||
PasteHandler() func(event *tcell.EventPaste)
|
||||
|
||||
// Focus is called by the application when the primitive receives focus.
|
||||
// Implementers may call delegate() to pass the focus on to another primitive.
|
||||
Focus(delegate func(p Primitive))
|
||||
|
2
vendor/maunium.net/go/tview/table.go
generated
vendored
2
vendor/maunium.net/go/tview/table.go
generated
vendored
@ -590,7 +590,7 @@ ColumnLoop:
|
||||
expansion := 0
|
||||
for _, row := range rows {
|
||||
if cell := getCell(row, column); cell != nil {
|
||||
cellWidth := StringWidth(cell.Text)
|
||||
_, _, _, _, cellWidth := decomposeString(cell.Text)
|
||||
if cell.MaxWidth > 0 && cell.MaxWidth < cellWidth {
|
||||
cellWidth = cell.MaxWidth
|
||||
}
|
||||
|
71
vendor/maunium.net/go/tview/textview.go
generated
vendored
71
vendor/maunium.net/go/tview/textview.go
generated
vendored
@ -8,6 +8,7 @@ import (
|
||||
"unicode/utf8"
|
||||
|
||||
"maunium.net/go/tcell"
|
||||
"github.com/lucasb-eyer/go-colorful"
|
||||
runewidth "github.com/mattn/go-runewidth"
|
||||
)
|
||||
|
||||
@ -21,7 +22,9 @@ type textViewIndex struct {
|
||||
Pos int // The index into the "buffer" string (byte position).
|
||||
NextPos int // The (byte) index of the next character in this buffer line.
|
||||
Width int // The screen width of this line.
|
||||
Color tcell.Color // The starting color.
|
||||
ForegroundColor string // The starting foreground color ("" = don't change, "-" = reset).
|
||||
BackgroundColor string // The starting background color ("" = don't change, "-" = reset).
|
||||
Attributes string // The starting attributes ("" = don't change, "-" = reset).
|
||||
Region string // The starting region ID.
|
||||
}
|
||||
|
||||
@ -499,7 +502,6 @@ func (t *TextView) reindexBuffer(width int) {
|
||||
// Initial states.
|
||||
regionID := ""
|
||||
var highlighted bool
|
||||
color := t.textColor
|
||||
|
||||
// Go through each line in the buffer.
|
||||
for bufferIndex, str := range t.buffer {
|
||||
@ -507,11 +509,10 @@ func (t *TextView) reindexBuffer(width int) {
|
||||
var (
|
||||
colorTagIndices [][]int
|
||||
colorTags [][]string
|
||||
escapeIndices [][]int
|
||||
)
|
||||
if t.dynamicColors {
|
||||
colorTagIndices = colorPattern.FindAllStringIndex(str, -1)
|
||||
colorTags = colorPattern.FindAllStringSubmatch(str, -1)
|
||||
str = colorPattern.ReplaceAllString(str, "")
|
||||
colorTagIndices, colorTags, escapeIndices, str, _ = decomposeString(str)
|
||||
}
|
||||
|
||||
// Find all regions in this line. Then remove them.
|
||||
@ -523,14 +524,12 @@ func (t *TextView) reindexBuffer(width int) {
|
||||
regionIndices = regionPattern.FindAllStringIndex(str, -1)
|
||||
regions = regionPattern.FindAllStringSubmatch(str, -1)
|
||||
str = regionPattern.ReplaceAllString(str, "")
|
||||
}
|
||||
|
||||
// Find all replace tags in this line. Then replace them.
|
||||
var escapeIndices [][]int
|
||||
if t.dynamicColors || t.regions {
|
||||
if !t.dynamicColors {
|
||||
// We haven't detected escape tags yet. Do it now.
|
||||
escapeIndices = escapePattern.FindAllStringIndex(str, -1)
|
||||
str = escapePattern.ReplaceAllString(str, "[$1$2]")
|
||||
}
|
||||
}
|
||||
|
||||
// Split the line if required.
|
||||
var splitLines []string
|
||||
@ -559,12 +558,17 @@ func (t *TextView) reindexBuffer(width int) {
|
||||
}
|
||||
|
||||
// Create index from split lines.
|
||||
var originalPos, colorPos, regionPos, escapePos int
|
||||
var (
|
||||
originalPos, colorPos, regionPos, escapePos int
|
||||
foregroundColor, backgroundColor, attributes string
|
||||
)
|
||||
for _, splitLine := range splitLines {
|
||||
line := &textViewIndex{
|
||||
Line: bufferIndex,
|
||||
Pos: originalPos,
|
||||
Color: color,
|
||||
ForegroundColor: foregroundColor,
|
||||
BackgroundColor: backgroundColor,
|
||||
Attributes: attributes,
|
||||
Region: regionID,
|
||||
}
|
||||
|
||||
@ -574,7 +578,7 @@ func (t *TextView) reindexBuffer(width int) {
|
||||
if colorPos < len(colorTagIndices) && colorTagIndices[colorPos][0] <= originalPos+lineLength {
|
||||
// Process color tags.
|
||||
originalPos += colorTagIndices[colorPos][1] - colorTagIndices[colorPos][0]
|
||||
color = tcell.GetColor(colorTags[colorPos][1])
|
||||
foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colorTags[colorPos])
|
||||
colorPos++
|
||||
} else if regionPos < len(regionIndices) && regionIndices[regionPos][0] <= originalPos+lineLength {
|
||||
// Process region tags.
|
||||
@ -712,6 +716,7 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
||||
}
|
||||
|
||||
// Draw the buffer.
|
||||
defaultStyle := tcell.StyleDefault.Foreground(t.textColor)
|
||||
for line := t.lineOffset; line < len(t.index); line++ {
|
||||
// Are we done?
|
||||
if line-t.lineOffset >= height {
|
||||
@ -721,17 +726,19 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
||||
// Get the text for this line.
|
||||
index := t.index[line]
|
||||
text := t.buffer[index.Line][index.Pos:index.NextPos]
|
||||
color := index.Color
|
||||
foregroundColor := index.ForegroundColor
|
||||
backgroundColor := index.BackgroundColor
|
||||
attributes := index.Attributes
|
||||
regionID := index.Region
|
||||
|
||||
// Get color tags.
|
||||
var (
|
||||
colorTagIndices [][]int
|
||||
colorTags [][]string
|
||||
escapeIndices [][]int
|
||||
)
|
||||
if t.dynamicColors {
|
||||
colorTagIndices = colorPattern.FindAllStringIndex(text, -1)
|
||||
colorTags = colorPattern.FindAllStringSubmatch(text, -1)
|
||||
colorTagIndices, colorTags, escapeIndices, _, _ = decomposeString(text)
|
||||
}
|
||||
|
||||
// Get regions.
|
||||
@ -742,13 +749,10 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
||||
if t.regions {
|
||||
regionIndices = regionPattern.FindAllStringIndex(text, -1)
|
||||
regions = regionPattern.FindAllStringSubmatch(text, -1)
|
||||
}
|
||||
|
||||
// Get escape tags.
|
||||
var escapeIndices [][]int
|
||||
if t.dynamicColors || t.regions {
|
||||
if !t.dynamicColors {
|
||||
escapeIndices = escapePattern.FindAllStringIndex(text, -1)
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the position of the line.
|
||||
var skip, posX int
|
||||
@ -770,7 +774,7 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
||||
// Get the color.
|
||||
if currentTag < len(colorTags) && pos >= colorTagIndices[currentTag][0] && pos < colorTagIndices[currentTag][1] {
|
||||
if pos == colorTagIndices[currentTag][1]-1 {
|
||||
color = tcell.GetColor(colorTags[currentTag][1])
|
||||
foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colorTags[currentTag])
|
||||
currentTag++
|
||||
}
|
||||
continue
|
||||
@ -811,13 +815,32 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
||||
break
|
||||
}
|
||||
|
||||
// Mix the existing style with the new style.
|
||||
_, _, existingStyle, _ := screen.GetContent(x+posX, y+line-t.lineOffset)
|
||||
_, background, _ := existingStyle.Decompose()
|
||||
style := overlayStyle(background, defaultStyle, foregroundColor, backgroundColor, attributes)
|
||||
|
||||
// Do we highlight this character?
|
||||
style := tcell.StyleDefault.Background(t.backgroundColor).Foreground(color)
|
||||
var highlighted bool
|
||||
if len(regionID) > 0 {
|
||||
if _, ok := t.highlights[regionID]; ok {
|
||||
style = tcell.StyleDefault.Background(color).Foreground(t.backgroundColor)
|
||||
highlighted = true
|
||||
}
|
||||
}
|
||||
if highlighted {
|
||||
fg, bg, _ := style.Decompose()
|
||||
if bg == tcell.ColorDefault {
|
||||
r, g, b := fg.RGB()
|
||||
c := colorful.Color{R: float64(r) / 255, G: float64(g) / 255, B: float64(b) / 255}
|
||||
_, _, li := c.Hcl()
|
||||
if li < .5 {
|
||||
bg = tcell.ColorWhite
|
||||
} else {
|
||||
bg = tcell.ColorBlack
|
||||
}
|
||||
}
|
||||
style = style.Background(fg).Foreground(bg)
|
||||
}
|
||||
|
||||
// Draw the character.
|
||||
for offset := 0; offset < chWidth; offset++ {
|
||||
|
216
vendor/maunium.net/go/tview/util.go
generated
vendored
216
vendor/maunium.net/go/tview/util.go
generated
vendored
@ -1,6 +1,7 @@
|
||||
package tview
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@ -104,13 +105,21 @@ var joints = map[string]rune{
|
||||
|
||||
// Common regular expressions.
|
||||
var (
|
||||
colorPattern = regexp.MustCompile(`\[([a-zA-Z]+|#[0-9a-zA-Z]{6})\]`)
|
||||
colorPattern = regexp.MustCompile(`\[([a-zA-Z]+|#[0-9a-zA-Z]{6}|\-)?(:([a-zA-Z]+|#[0-9a-zA-Z]{6}|\-)?(:([lbdru]+|\-)?)?)?\]`)
|
||||
regionPattern = regexp.MustCompile(`\["([a-zA-Z0-9_,;: \-\.]*)"\]`)
|
||||
escapePattern = regexp.MustCompile(`\[("[a-zA-Z0-9_,;: \-\.]*"|[a-zA-Z]+|#[0-9a-zA-Z]{6})\[(\[*)\]`)
|
||||
escapePattern = regexp.MustCompile(`\[([a-zA-Z0-9_,;: \-\."#]+)\[(\[*)\]`)
|
||||
nonEscapePattern = regexp.MustCompile(`(\[[a-zA-Z0-9_,;: \-\."#]+\[*)\]`)
|
||||
boundaryPattern = regexp.MustCompile("([[:punct:]]\\s*|\\s+)")
|
||||
spacePattern = regexp.MustCompile(`\s+`)
|
||||
)
|
||||
|
||||
// Positions of substrings in regular expressions.
|
||||
const (
|
||||
colorForegroundPos = 1
|
||||
colorBackgroundPos = 3
|
||||
colorFlagPos = 5
|
||||
)
|
||||
|
||||
// Predefined InputField acceptance functions.
|
||||
var (
|
||||
// InputFieldInteger accepts integers.
|
||||
@ -150,40 +159,168 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
// styleFromTag takes the given style, defined by a foreground color (fgColor),
|
||||
// a background color (bgColor), and style attributes, and modifies it based on
|
||||
// the substrings (tagSubstrings) extracted by the regular expression for color
|
||||
// tags. The new colors and attributes are returned where empty strings mean
|
||||
// "don't modify" and a dash ("-") means "reset to default".
|
||||
func styleFromTag(fgColor, bgColor, attributes string, tagSubstrings []string) (newFgColor, newBgColor, newAttributes string) {
|
||||
if tagSubstrings[colorForegroundPos] != "" {
|
||||
color := tagSubstrings[colorForegroundPos]
|
||||
if color == "-" {
|
||||
fgColor = "-"
|
||||
} else if color != "" {
|
||||
fgColor = color
|
||||
}
|
||||
}
|
||||
|
||||
if tagSubstrings[colorBackgroundPos-1] != "" {
|
||||
color := tagSubstrings[colorBackgroundPos]
|
||||
if color == "-" {
|
||||
bgColor = "-"
|
||||
} else if color != "" {
|
||||
bgColor = color
|
||||
}
|
||||
}
|
||||
|
||||
if tagSubstrings[colorFlagPos-1] != "" {
|
||||
flags := tagSubstrings[colorFlagPos]
|
||||
if flags == "-" {
|
||||
attributes = "-"
|
||||
} else if flags != "" {
|
||||
attributes = flags
|
||||
}
|
||||
}
|
||||
|
||||
return fgColor, bgColor, attributes
|
||||
}
|
||||
|
||||
// overlayStyle mixes a background color with a foreground color (fgColor),
|
||||
// a (possibly new) background color (bgColor), and style attributes, and
|
||||
// returns the resulting style. For a definition of the colors and attributes,
|
||||
// see styleFromTag(). Reset instructions cause the corresponding part of the
|
||||
// default style to be used.
|
||||
func overlayStyle(background tcell.Color, defaultStyle tcell.Style, fgColor, bgColor, attributes string) tcell.Style {
|
||||
defFg, defBg, defAttr := defaultStyle.Decompose()
|
||||
style := defaultStyle.Background(background)
|
||||
|
||||
if fgColor == "-" {
|
||||
style = style.Foreground(defFg)
|
||||
} else if fgColor != "" {
|
||||
style = style.Foreground(tcell.GetColor(fgColor))
|
||||
}
|
||||
|
||||
if bgColor == "-" {
|
||||
style = style.Background(defBg)
|
||||
} else if bgColor != "" {
|
||||
style = style.Background(tcell.GetColor(bgColor))
|
||||
}
|
||||
|
||||
if attributes == "-" {
|
||||
style = style.Bold(defAttr&tcell.AttrBold > 0)
|
||||
style = style.Blink(defAttr&tcell.AttrBlink > 0)
|
||||
style = style.Reverse(defAttr&tcell.AttrReverse > 0)
|
||||
style = style.Underline(defAttr&tcell.AttrUnderline > 0)
|
||||
style = style.Dim(defAttr&tcell.AttrDim > 0)
|
||||
} else if attributes != "" {
|
||||
style = style.Normal()
|
||||
for _, flag := range attributes {
|
||||
switch flag {
|
||||
case 'l':
|
||||
style = style.Blink(true)
|
||||
case 'b':
|
||||
style = style.Bold(true)
|
||||
case 'd':
|
||||
style = style.Dim(true)
|
||||
case 'r':
|
||||
style = style.Reverse(true)
|
||||
case 'u':
|
||||
style = style.Underline(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return style
|
||||
}
|
||||
|
||||
// decomposeString returns information about a string which may contain color
|
||||
// tags. It returns the indices of the color tags (as returned by
|
||||
// re.FindAllStringIndex()), the color tags themselves (as returned by
|
||||
// re.FindAllStringSubmatch()), the indices of an escaped tags, the string
|
||||
// stripped by any color tags and escaped, and the screen width of the stripped
|
||||
// string.
|
||||
func decomposeString(text string) (colorIndices [][]int, colors [][]string, escapeIndices [][]int, stripped string, width int) {
|
||||
// Get positions of color and escape tags.
|
||||
colorIndices = colorPattern.FindAllStringIndex(text, -1)
|
||||
colors = colorPattern.FindAllStringSubmatch(text, -1)
|
||||
escapeIndices = escapePattern.FindAllStringIndex(text, -1)
|
||||
|
||||
// Because the color pattern detects empty tags, we need to filter them out.
|
||||
for i := len(colorIndices) - 1; i >= 0; i-- {
|
||||
if colorIndices[i][1]-colorIndices[i][0] == 2 {
|
||||
colorIndices = append(colorIndices[:i], colorIndices[i+1:]...)
|
||||
colors = append(colors[:i], colors[i+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the color tags from the original string.
|
||||
var from int
|
||||
buf := make([]byte, 0, len(text))
|
||||
for _, indices := range colorIndices {
|
||||
buf = append(buf, []byte(text[from:indices[0]])...)
|
||||
from = indices[1]
|
||||
}
|
||||
buf = append(buf, text[from:]...)
|
||||
|
||||
// Escape string.
|
||||
stripped = string(escapePattern.ReplaceAll(buf, []byte("[$1$2]")))
|
||||
|
||||
// Get the width of the stripped string.
|
||||
width = runewidth.StringWidth(stripped)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Print prints text onto the screen into the given box at (x,y,maxWidth,1),
|
||||
// not exceeding that box. "align" is one of AlignLeft, AlignCenter, or
|
||||
// AlignRight. The screen's background color will not be changed.
|
||||
//
|
||||
// You can change the text color mid-text by inserting a color tag. See the
|
||||
// package description for details.
|
||||
// You can change the colors and text styles mid-text by inserting a color tag.
|
||||
// See the package description for details.
|
||||
//
|
||||
// Returns the number of actual runes printed (not including color tags) and the
|
||||
// actual width used for the printed runes.
|
||||
func Print(screen tcell.Screen, text string, x, y, maxWidth, align int, color tcell.Color) (int, int) {
|
||||
return printWithStyle(screen, text, x, y, maxWidth, align, tcell.StyleDefault.Foreground(color))
|
||||
}
|
||||
|
||||
// printWithStyle works like Print() but it takes a style instead of just a
|
||||
// foreground color.
|
||||
func printWithStyle(screen tcell.Screen, text string, x, y, maxWidth, align int, style tcell.Style) (int, int) {
|
||||
if maxWidth < 0 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
// Get positions of color and escape tags. Remove them from original string.
|
||||
colorIndices := colorPattern.FindAllStringIndex(text, -1)
|
||||
colors := colorPattern.FindAllStringSubmatch(text, -1)
|
||||
escapeIndices := escapePattern.FindAllStringIndex(text, -1)
|
||||
strippedText := escapePattern.ReplaceAllString(colorPattern.ReplaceAllString(text, ""), "[$1$2]")
|
||||
// Decompose the text.
|
||||
colorIndices, colors, escapeIndices, strippedText, _ := decomposeString(text)
|
||||
|
||||
// We deal with runes, not with bytes.
|
||||
runes := []rune(strippedText)
|
||||
|
||||
// This helper function takes positions for a substring of "runes" and a start
|
||||
// color and returns the substring with the original tags and the new start
|
||||
// color.
|
||||
substring := func(from, to int, color tcell.Color) (string, tcell.Color) {
|
||||
var colorPos, escapePos, runePos, startPos int
|
||||
// This helper function takes positions for a substring of "runes" and returns
|
||||
// a new string corresponding to this substring, making sure printing that
|
||||
// substring will observe color tags.
|
||||
substring := func(from, to int) string {
|
||||
var (
|
||||
colorPos, escapePos, runePos, startPos int
|
||||
foregroundColor, backgroundColor, attributes string
|
||||
)
|
||||
for pos := range text {
|
||||
// Handle color tags.
|
||||
if colorPos < len(colorIndices) && pos >= colorIndices[colorPos][0] && pos < colorIndices[colorPos][1] {
|
||||
if pos == colorIndices[colorPos][1]-1 {
|
||||
if runePos <= from {
|
||||
color = tcell.GetColor(colors[colorPos][1])
|
||||
foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colors[colorPos])
|
||||
}
|
||||
colorPos++
|
||||
}
|
||||
@ -203,13 +340,13 @@ func Print(screen tcell.Screen, text string, x, y, maxWidth, align int, color tc
|
||||
if runePos == from {
|
||||
startPos = pos
|
||||
} else if runePos >= to {
|
||||
return text[startPos:pos], color
|
||||
return fmt.Sprintf(`[%s:%s:%s]%s`, foregroundColor, backgroundColor, attributes, text[startPos:pos])
|
||||
}
|
||||
|
||||
runePos++
|
||||
}
|
||||
|
||||
return text[startPos:], color
|
||||
return fmt.Sprintf(`[%s:%s:%s]%s`, foregroundColor, backgroundColor, attributes, text[startPos:])
|
||||
}
|
||||
|
||||
// We want to reduce everything to AlignLeft.
|
||||
@ -224,17 +361,16 @@ func Print(screen tcell.Screen, text string, x, y, maxWidth, align int, color tc
|
||||
width += w
|
||||
start = index
|
||||
}
|
||||
text, color = substring(start, len(runes), color)
|
||||
return Print(screen, text, x+maxWidth-width, y, width, AlignLeft, color)
|
||||
return printWithStyle(screen, substring(start, len(runes)), x+maxWidth-width, y, width, AlignLeft, style)
|
||||
} else if align == AlignCenter {
|
||||
width := runewidth.StringWidth(strippedText)
|
||||
if width == maxWidth {
|
||||
// Use the exact space.
|
||||
return Print(screen, text, x, y, maxWidth, AlignLeft, color)
|
||||
return printWithStyle(screen, text, x, y, maxWidth, AlignLeft, style)
|
||||
} else if width < maxWidth {
|
||||
// We have more space than we need.
|
||||
half := (maxWidth - width) / 2
|
||||
return Print(screen, text, x+half, y, maxWidth-half, AlignLeft, color)
|
||||
return printWithStyle(screen, text, x+half, y, maxWidth-half, AlignLeft, style)
|
||||
} else {
|
||||
// Chop off runes until we have a perfect fit.
|
||||
var choppedLeft, choppedRight, leftIndex, rightIndex int
|
||||
@ -250,20 +386,22 @@ func Print(screen tcell.Screen, text string, x, y, maxWidth, align int, color tc
|
||||
rightIndex--
|
||||
}
|
||||
}
|
||||
text, color = substring(leftIndex, rightIndex, color)
|
||||
return Print(screen, text, x, y, maxWidth, AlignLeft, color)
|
||||
return printWithStyle(screen, substring(leftIndex, rightIndex), x, y, maxWidth, AlignLeft, style)
|
||||
}
|
||||
}
|
||||
|
||||
// Draw text.
|
||||
drawn := 0
|
||||
drawnWidth := 0
|
||||
var colorPos, escapePos int
|
||||
var (
|
||||
colorPos, escapePos int
|
||||
foregroundColor, backgroundColor, attributes string
|
||||
)
|
||||
for pos, ch := range text {
|
||||
// Handle color tags.
|
||||
if colorPos < len(colorIndices) && pos >= colorIndices[colorPos][0] && pos < colorIndices[colorPos][1] {
|
||||
if pos == colorIndices[colorPos][1]-1 {
|
||||
color = tcell.GetColor(colors[colorPos][1])
|
||||
foregroundColor, backgroundColor, attributes = styleFromTag(foregroundColor, backgroundColor, attributes, colors[colorPos])
|
||||
colorPos++
|
||||
}
|
||||
continue
|
||||
@ -286,11 +424,12 @@ func Print(screen tcell.Screen, text string, x, y, maxWidth, align int, color tc
|
||||
finalX := x + drawnWidth
|
||||
|
||||
// Print the rune.
|
||||
_, _, style, _ := screen.GetContent(finalX, y)
|
||||
style = style.Foreground(color)
|
||||
_, _, finalStyle, _ := screen.GetContent(finalX, y)
|
||||
_, background, _ := finalStyle.Decompose()
|
||||
finalStyle = overlayStyle(background, style, foregroundColor, backgroundColor, attributes)
|
||||
for offset := 0; offset < chWidth; offset++ {
|
||||
// To avoid undesired effects, we place the same character in all cells.
|
||||
screen.SetContent(finalX+offset, y, ch, nil, style)
|
||||
screen.SetContent(finalX+offset, y, ch, nil, finalStyle)
|
||||
}
|
||||
|
||||
drawn++
|
||||
@ -308,7 +447,8 @@ func PrintSimple(screen tcell.Screen, text string, x, y int) {
|
||||
// StringWidth returns the width of the given string needed to print it on
|
||||
// screen. The text may contain color tags which are not counted.
|
||||
func StringWidth(text string) int {
|
||||
return runewidth.StringWidth(escapePattern.ReplaceAllString(colorPattern.ReplaceAllString(text, ""), "[$1$2]"))
|
||||
_, _, _, _, width := decomposeString(text)
|
||||
return width
|
||||
}
|
||||
|
||||
// WordWrap splits a text such that each resulting line does not exceed the
|
||||
@ -319,13 +459,7 @@ func StringWidth(text string) int {
|
||||
//
|
||||
// Text is always split at newline characters ('\n').
|
||||
func WordWrap(text string, width int) (lines []string) {
|
||||
// Strip color tags.
|
||||
strippedText := escapePattern.ReplaceAllString(colorPattern.ReplaceAllString(text, ""), "[$1$2]")
|
||||
|
||||
// Keep track of color tags and escape patterns so we can restore the original
|
||||
// indices.
|
||||
colorTagIndices := colorPattern.FindAllStringIndex(text, -1)
|
||||
escapeIndices := escapePattern.FindAllStringIndex(text, -1)
|
||||
colorTagIndices, _, escapeIndices, strippedText, _ := decomposeString(text)
|
||||
|
||||
// Find candidate breakpoints.
|
||||
breakPoints := boundaryPattern.FindAllStringIndex(strippedText, -1)
|
||||
@ -454,3 +588,13 @@ func PrintJoinedBorder(screen tcell.Screen, x, y int, ch rune, color tcell.Color
|
||||
// We only print something if we have something.
|
||||
screen.SetContent(x, y, result, nil, style)
|
||||
}
|
||||
|
||||
// Escape escapes the given text such that color and/or region tags are not
|
||||
// recognized and substituted by the print functions of this package. For
|
||||
// example, to include a tag-like string in a box title or in a TextView:
|
||||
//
|
||||
// box.SetTitle(tview.Escape("[squarebrackets]"))
|
||||
// fmt.Fprint(textView, tview.Escape(`["quoted"]`))
|
||||
func Escape(text string) string {
|
||||
return nonEscapePattern.ReplaceAllString(text, "$1[]")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user