Tags can be turned off for List and Autocomplete; also added Unescape function. Fixes #1016

This commit is contained in:
Oliver 2024-11-03 12:33:52 +01:00
parent 65faf5cfc7
commit ad9e2501de
4 changed files with 56 additions and 10 deletions

View File

@ -1,6 +1,7 @@
package tview
import (
"math"
"strconv"
"strings"
"sync"
@ -99,6 +100,7 @@ type InputField struct {
main tcell.Style
selected tcell.Style
background tcell.Color
useTags bool
}
// An optional function which is called when the user selects an
@ -146,6 +148,7 @@ func NewInputField() *InputField {
i.autocompleteStyles.main = tcell.StyleDefault.Background(Styles.MoreContrastBackgroundColor).Foreground(Styles.PrimitiveBackgroundColor)
i.autocompleteStyles.selected = tcell.StyleDefault.Background(Styles.PrimaryTextColor).Foreground(Styles.PrimitiveBackgroundColor)
i.autocompleteStyles.background = Styles.MoreContrastBackgroundColor
i.autocompleteStyles.useTags = true
return i
}
@ -256,6 +259,13 @@ func (i *InputField) SetAutocompleteStyles(background tcell.Color, main, selecte
return i
}
// SetAutocompleteUseTags sets whether or not the autocomplete entries may
// contain style tags affecting their appearance. The default is true.
func (i *InputField) SetAutocompleteUseTags(useTags bool) *InputField {
i.autocompleteStyles.useTags = useTags
return i
}
// SetFormAttributes sets attributes shared by all form items.
func (i *InputField) SetFormAttributes(labelWidth int, labelColor, bgColor, fieldTextColor, fieldBgColor tcell.Color) FormItem {
i.textArea.SetFormAttributes(labelWidth, labelColor, bgColor, fieldTextColor, fieldBgColor)
@ -363,13 +373,14 @@ func (i *InputField) Autocomplete() *InputField {
i.autocompleteList.ShowSecondaryText(false).
SetMainTextStyle(i.autocompleteStyles.main).
SetSelectedStyle(i.autocompleteStyles.selected).
SetUseStyleTags(i.autocompleteStyles.useTags, i.autocompleteStyles.useTags).
SetHighlightFullLine(true).
SetBackgroundColor(i.autocompleteStyles.background)
}
// Fill it with the entries.
currentEntry := -1
suffixLength := 9999 // I'm just waiting for the day somebody opens an issue with this number being too small.
suffixLength := math.MaxInt
i.autocompleteList.Clear()
for index, entry := range entries {
i.autocompleteList.AddItem(entry, "", 0, nil)

39
list.go
View File

@ -30,6 +30,9 @@ type listItem struct {
// - Right / left: Scroll horizontally. Only if the list is wider than the
// available space.
//
// By default, list item texts can contain style tags. Use
// [List.SetUseStyleTags] to disable this feature.
//
// See [List.SetChangedFunc] for a way to be notified when the user navigates
// to a list item. See [List.SetSelectedFunc] for a way to be notified when a
// list item was selected.
@ -65,6 +68,12 @@ type List struct {
// If true, the entire row is highlighted when selected.
highlightFullLine bool
// Whether or not style tags can be used in the main text.
mainStyleTags bool
// Whether or not style tags can be used in the secondary text.
secondaryStyleTags bool
// Whether or not navigating the list will wrap around.
wrapAround bool
@ -98,6 +107,8 @@ func NewList() *List {
secondaryTextStyle: tcell.StyleDefault.Foreground(Styles.TertiaryTextColor).Background(Styles.PrimitiveBackgroundColor),
shortcutStyle: tcell.StyleDefault.Foreground(Styles.SecondaryTextColor).Background(Styles.PrimitiveBackgroundColor),
selectedStyle: tcell.StyleDefault.Foreground(Styles.PrimitiveBackgroundColor).Background(Styles.PrimaryTextColor),
mainStyleTags: true,
secondaryStyleTags: true,
}
}
@ -268,6 +279,14 @@ func (l *List) SetSelectedStyle(style tcell.Style) *List {
return l
}
// SetUseStyleTags sets a flag which determines whether style tags are used in
// the main and secondary texts. The default is true.
func (l *List) SetUseStyleTags(mainStyleTags, secondaryStyleTags bool) *List {
l.mainStyleTags = mainStyleTags
l.secondaryStyleTags = secondaryStyleTags
return l
}
// SetSelectedFocusOnly sets a flag which determines when the currently selected
// list item is highlighted. If set to true, selected items are only highlighted
// when the list has focus. If set to false, they are always highlighted.
@ -328,7 +347,7 @@ func (l *List) SetDoneFunc(handler func()) *List {
return l
}
// AddItem calls InsertItem() with an index of -1.
// AddItem calls [List.InsertItem] with an index of -1.
func (l *List) AddItem(mainText, secondaryText string, shortcut rune, selected func()) *List {
l.InsertItem(-1, mainText, secondaryText, shortcut, selected)
return l
@ -336,8 +355,8 @@ func (l *List) AddItem(mainText, secondaryText string, shortcut rune, selected f
// InsertItem adds a new item to the list at the specified index. An index of 0
// will insert the item at the beginning, an index of 1 before the second item,
// and so on. An index of GetItemCount() or higher will insert the item at the
// end of the list. Negative indices are also allowed: An index of -1 will
// and so on. An index of [List.GetItemCount] or higher will insert the item at
// the end of the list. Negative indices are also allowed: An index of -1 will
// insert the item at the end of the list, an index of -2 before the last item,
// and so on. An index of -GetItemCount()-1 or lower will insert the item at the
// beginning.
@ -351,7 +370,7 @@ func (l *List) AddItem(mainText, secondaryText string, shortcut rune, selected f
//
// The "selected" callback will be invoked when the user selects the item. You
// may provide nil if no such callback is needed or if all events are handled
// through the selected callback set with SetSelectedFunc().
// through the selected callback set with [List.SetSelectedFunc].
//
// The currently selected item will shift its position accordingly. If the list
// was previously empty, a "changed" event is fired because the new item becomes
@ -511,7 +530,11 @@ func (l *List) Draw(screen tcell.Screen) {
if selected {
style = l.selectedStyle
}
_, _, printedWidth := printWithStyle(screen, item.MainText, x, y, l.horizontalOffset, width, AlignLeft, style, false)
mainText := item.MainText
if !l.mainStyleTags {
mainText = Escape(mainText)
}
_, _, printedWidth := printWithStyle(screen, mainText, x, y, l.horizontalOffset, width, AlignLeft, style, false)
if printedWidth > maxWidth {
maxWidth = printedWidth
}
@ -530,7 +553,11 @@ func (l *List) Draw(screen tcell.Screen) {
// Secondary text.
if l.showSecondaryText {
_, _, printedWidth := printWithStyle(screen, item.SecondaryText, x, y, l.horizontalOffset, width, AlignLeft, l.secondaryTextStyle, false)
secondaryText := item.SecondaryText
if !l.secondaryStyleTags {
secondaryText = Escape(secondaryText)
}
_, _, printedWidth := printWithStyle(screen, secondaryText, x, y, l.horizontalOffset, width, AlignLeft, l.secondaryTextStyle, false)
if printedWidth > maxWidth {
maxWidth = printedWidth
}

View File

@ -593,7 +593,12 @@ func WordWrap(text string, width int) (lines []string) {
// box.SetTitle(tview.Escape("[squarebrackets]"))
// fmt.Fprint(textView, tview.Escape(`["quoted"]`))
func Escape(text string) string {
return nonEscapePattern.ReplaceAllString(text, "$1[]")
return escapePattern.ReplaceAllString(text, "$1[]")
}
// Unescape unescapes text previously escaped with [Escape].
func Unescape(text string) string {
return unescapePattern.ReplaceAllString(text, "$1]")
}
// stripTags strips style tags from the given string. (Region tags are not

View File

@ -19,7 +19,10 @@ const (
var (
// Regular expression used to escape style/region tags.
nonEscapePattern = regexp.MustCompile(`(\[[a-zA-Z0-9_,;: \-\."#]+\[*)\]`)
escapePattern = regexp.MustCompile(`(\[[a-zA-Z0-9_,;: \-\."#]+\[*)\]`)
// Regular expression used to unescape escaped style/region tags.
unescapePattern = regexp.MustCompile(`(\[[a-zA-Z0-9_,;: \-\."#]+\[*)\[\]`)
// The number of colors available in the terminal.
availableColors = 256
@ -48,7 +51,7 @@ func Print(screen tcell.Screen, text string, x, y, maxWidth, align int, color tc
return end - start, width
}
// printWithStyle works like Print() but it takes a style instead of just a
// printWithStyle works like [Print] but it takes a style instead of just a
// foreground color. The skipWidth parameter specifies the number of cells
// skipped at the beginning of the text. It returns the start index, end index
// (exclusively), and screen width of the text actually printed. If