mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-17 07:43:39 -05:00
Motivation: `--color base16` can be a better default than `dark` or `light`, since it uses the colors defined by the current theme. This usually blends in more naturally and works well in both light and dark modes. However, some elements were previously hard-coded with white or black foreground colors, which can cause rendering issues in certain terminal themes.
1219 lines
33 KiB
Go
1219 lines
33 KiB
Go
package tui
|
|
|
|
import (
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/junegunn/fzf/src/util"
|
|
"github.com/rivo/uniseg"
|
|
)
|
|
|
|
// Types of user action
|
|
//
|
|
//go:generate stringer -type=EventType
|
|
type EventType int
|
|
|
|
const (
|
|
Rune EventType = iota
|
|
|
|
CtrlA
|
|
CtrlB
|
|
CtrlC
|
|
CtrlD
|
|
CtrlE
|
|
CtrlF
|
|
CtrlG
|
|
CtrlH
|
|
Tab
|
|
CtrlJ
|
|
CtrlK
|
|
CtrlL
|
|
Enter
|
|
CtrlN
|
|
CtrlO
|
|
CtrlP
|
|
CtrlQ
|
|
CtrlR
|
|
CtrlS
|
|
CtrlT
|
|
CtrlU
|
|
CtrlV
|
|
CtrlW
|
|
CtrlX
|
|
CtrlY
|
|
CtrlZ
|
|
Esc
|
|
CtrlSpace
|
|
|
|
// https://apple.stackexchange.com/questions/24261/how-do-i-send-c-that-is-control-slash-to-the-terminal
|
|
CtrlBackSlash
|
|
CtrlRightBracket
|
|
CtrlCaret
|
|
CtrlSlash
|
|
|
|
ShiftTab
|
|
Backspace
|
|
|
|
Delete
|
|
PageUp
|
|
PageDown
|
|
|
|
Up
|
|
Down
|
|
Left
|
|
Right
|
|
Home
|
|
End
|
|
Insert
|
|
|
|
ShiftUp
|
|
ShiftDown
|
|
ShiftLeft
|
|
ShiftRight
|
|
ShiftDelete
|
|
ShiftHome
|
|
ShiftEnd
|
|
ShiftPageUp
|
|
ShiftPageDown
|
|
|
|
F1
|
|
F2
|
|
F3
|
|
F4
|
|
F5
|
|
F6
|
|
F7
|
|
F8
|
|
F9
|
|
F10
|
|
F11
|
|
F12
|
|
|
|
AltBackspace
|
|
|
|
AltUp
|
|
AltDown
|
|
AltLeft
|
|
AltRight
|
|
AltDelete
|
|
AltHome
|
|
AltEnd
|
|
AltPageUp
|
|
AltPageDown
|
|
|
|
AltShiftUp
|
|
AltShiftDown
|
|
AltShiftLeft
|
|
AltShiftRight
|
|
AltShiftDelete
|
|
AltShiftHome
|
|
AltShiftEnd
|
|
AltShiftPageUp
|
|
AltShiftPageDown
|
|
|
|
CtrlUp
|
|
CtrlDown
|
|
CtrlLeft
|
|
CtrlRight
|
|
CtrlHome
|
|
CtrlEnd
|
|
CtrlBackspace
|
|
CtrlDelete
|
|
CtrlPageUp
|
|
CtrlPageDown
|
|
|
|
Alt
|
|
CtrlAlt
|
|
|
|
CtrlAltUp
|
|
CtrlAltDown
|
|
CtrlAltLeft
|
|
CtrlAltRight
|
|
CtrlAltHome
|
|
CtrlAltEnd
|
|
CtrlAltBackspace
|
|
CtrlAltDelete
|
|
CtrlAltPageUp
|
|
CtrlAltPageDown
|
|
|
|
CtrlShiftUp
|
|
CtrlShiftDown
|
|
CtrlShiftLeft
|
|
CtrlShiftRight
|
|
CtrlShiftHome
|
|
CtrlShiftEnd
|
|
CtrlShiftDelete
|
|
CtrlShiftPageUp
|
|
CtrlShiftPageDown
|
|
|
|
CtrlAltShiftUp
|
|
CtrlAltShiftDown
|
|
CtrlAltShiftLeft
|
|
CtrlAltShiftRight
|
|
CtrlAltShiftHome
|
|
CtrlAltShiftEnd
|
|
CtrlAltShiftDelete
|
|
CtrlAltShiftPageUp
|
|
CtrlAltShiftPageDown
|
|
|
|
Invalid
|
|
Fatal
|
|
BracketedPasteBegin
|
|
BracketedPasteEnd
|
|
|
|
Mouse
|
|
DoubleClick
|
|
LeftClick
|
|
RightClick
|
|
SLeftClick
|
|
SRightClick
|
|
ScrollUp
|
|
ScrollDown
|
|
SScrollUp
|
|
SScrollDown
|
|
PreviewScrollUp
|
|
PreviewScrollDown
|
|
|
|
// Events
|
|
Resize
|
|
Change
|
|
BackwardEOF
|
|
Start
|
|
Load
|
|
Focus
|
|
One
|
|
Zero
|
|
Result
|
|
Jump
|
|
JumpCancel
|
|
ClickHeader
|
|
ClickFooter
|
|
Multi
|
|
)
|
|
|
|
func (t EventType) AsEvent() Event {
|
|
return Event{t, 0, nil}
|
|
}
|
|
|
|
func (t EventType) Int() int {
|
|
return int(t)
|
|
}
|
|
|
|
func (t EventType) Byte() byte {
|
|
return byte(t)
|
|
}
|
|
|
|
func (e Event) Comparable() Event {
|
|
// Ignore MouseEvent pointer
|
|
return Event{e.Type, e.Char, nil}
|
|
}
|
|
|
|
func (e Event) KeyName() string {
|
|
if me := e.MouseEvent; me != nil {
|
|
return me.Name()
|
|
}
|
|
|
|
if e.Type >= Invalid {
|
|
return ""
|
|
}
|
|
|
|
switch e.Type {
|
|
case Rune:
|
|
if e.Char == ' ' {
|
|
return "space"
|
|
}
|
|
return string(e.Char)
|
|
case Alt:
|
|
return "alt-" + string(e.Char)
|
|
case CtrlAlt:
|
|
return "ctrl-alt-" + string(e.Char)
|
|
case CtrlBackSlash:
|
|
return "ctrl-\\"
|
|
case CtrlRightBracket:
|
|
return "ctrl-]"
|
|
case CtrlCaret:
|
|
return "ctrl-^"
|
|
case CtrlSlash:
|
|
return "ctrl-/"
|
|
}
|
|
|
|
return util.ToKebabCase(e.Type.String())
|
|
}
|
|
|
|
func Key(r rune) Event {
|
|
return Event{Rune, r, nil}
|
|
}
|
|
|
|
func AltKey(r rune) Event {
|
|
return Event{Alt, r, nil}
|
|
}
|
|
|
|
func CtrlAltKey(r rune) Event {
|
|
return Event{CtrlAlt, r, nil}
|
|
}
|
|
|
|
const (
|
|
doubleClickDuration = 500 * time.Millisecond
|
|
)
|
|
|
|
type Color int32
|
|
|
|
func (c Color) IsDefault() bool {
|
|
return c == colDefault
|
|
}
|
|
|
|
func (c Color) is24() bool {
|
|
return c > 0 && (c&(1<<24)) > 0
|
|
}
|
|
|
|
type ColorAttr struct {
|
|
Color Color
|
|
Attr Attr
|
|
}
|
|
|
|
func (a ColorAttr) IsColorDefined() bool {
|
|
return a.Color != colUndefined
|
|
}
|
|
|
|
func NewColorAttr() ColorAttr {
|
|
return ColorAttr{Color: colUndefined, Attr: AttrUndefined}
|
|
}
|
|
|
|
func (a ColorAttr) Merge(other ColorAttr) ColorAttr {
|
|
if other.Color != colUndefined {
|
|
a.Color = other.Color
|
|
}
|
|
if other.Attr != AttrUndefined {
|
|
a.Attr = a.Attr.Merge(other.Attr)
|
|
}
|
|
return a
|
|
}
|
|
|
|
const (
|
|
colUndefined Color = -2
|
|
colDefault Color = -1
|
|
)
|
|
|
|
const (
|
|
colBlack Color = iota
|
|
colRed
|
|
colGreen
|
|
colYellow
|
|
colBlue
|
|
colMagenta
|
|
colCyan
|
|
colWhite
|
|
colGrey
|
|
colBrightRed
|
|
colBrightGreen
|
|
colBrightYellow
|
|
colBrightBlue
|
|
colBrightMagenta
|
|
colBrightCyan
|
|
colBrightWhite
|
|
)
|
|
|
|
type FillReturn int
|
|
|
|
const (
|
|
FillContinue FillReturn = iota
|
|
FillNextLine
|
|
FillSuspend
|
|
)
|
|
|
|
type ColorPair struct {
|
|
fg Color
|
|
bg Color
|
|
attr Attr
|
|
}
|
|
|
|
func HexToColor(rrggbb string) Color {
|
|
r, _ := strconv.ParseInt(rrggbb[1:3], 16, 0)
|
|
g, _ := strconv.ParseInt(rrggbb[3:5], 16, 0)
|
|
b, _ := strconv.ParseInt(rrggbb[5:7], 16, 0)
|
|
return Color((1 << 24) + (r << 16) + (g << 8) + b)
|
|
}
|
|
|
|
func NewColorPair(fg Color, bg Color, attr Attr) ColorPair {
|
|
return ColorPair{fg, bg, attr}
|
|
}
|
|
|
|
func NoColorPair() ColorPair {
|
|
return ColorPair{-1, -1, 0}
|
|
}
|
|
|
|
func (p ColorPair) Fg() Color {
|
|
return p.fg
|
|
}
|
|
|
|
func (p ColorPair) Bg() Color {
|
|
return p.bg
|
|
}
|
|
|
|
func (p ColorPair) Attr() Attr {
|
|
return p.attr
|
|
}
|
|
|
|
func (p ColorPair) IsFullBgMarker() bool {
|
|
return p.attr&FullBg > 0
|
|
}
|
|
|
|
func (p ColorPair) HasBg() bool {
|
|
return p.attr&Reverse == 0 && p.bg != colDefault ||
|
|
p.attr&Reverse > 0 && p.fg != colDefault
|
|
}
|
|
|
|
func (p ColorPair) merge(other ColorPair, except Color) ColorPair {
|
|
dup := p
|
|
dup.attr = dup.attr.Merge(other.attr)
|
|
if other.fg != except {
|
|
dup.fg = other.fg
|
|
}
|
|
if other.bg != except {
|
|
dup.bg = other.bg
|
|
}
|
|
return dup
|
|
}
|
|
|
|
func (p ColorPair) WithAttr(attr Attr) ColorPair {
|
|
dup := p
|
|
dup.attr = dup.attr.Merge(attr)
|
|
return dup
|
|
}
|
|
|
|
func (p ColorPair) WithBg(bg ColorAttr) ColorPair {
|
|
dup := p
|
|
bgPair := ColorPair{colUndefined, bg.Color, bg.Attr}
|
|
return dup.Merge(bgPair)
|
|
}
|
|
|
|
func (p ColorPair) MergeAttr(other ColorPair) ColorPair {
|
|
return p.WithAttr(other.attr)
|
|
}
|
|
|
|
func (p ColorPair) Merge(other ColorPair) ColorPair {
|
|
return p.merge(other, colUndefined)
|
|
}
|
|
|
|
func (p ColorPair) MergeNonDefault(other ColorPair) ColorPair {
|
|
return p.merge(other, colDefault)
|
|
}
|
|
|
|
type ColorTheme struct {
|
|
Colored bool
|
|
Input ColorAttr
|
|
Ghost ColorAttr
|
|
Disabled ColorAttr
|
|
Fg ColorAttr
|
|
Bg ColorAttr
|
|
ListFg ColorAttr
|
|
ListBg ColorAttr
|
|
AltBg ColorAttr
|
|
Nth ColorAttr
|
|
SelectedFg ColorAttr
|
|
SelectedBg ColorAttr
|
|
SelectedMatch ColorAttr
|
|
PreviewFg ColorAttr
|
|
PreviewBg ColorAttr
|
|
DarkBg ColorAttr
|
|
Gutter ColorAttr
|
|
Prompt ColorAttr
|
|
InputBg ColorAttr
|
|
InputBorder ColorAttr
|
|
InputLabel ColorAttr
|
|
Match ColorAttr
|
|
Current ColorAttr
|
|
CurrentMatch ColorAttr
|
|
Spinner ColorAttr
|
|
Info ColorAttr
|
|
Cursor ColorAttr
|
|
Marker ColorAttr
|
|
Header ColorAttr
|
|
HeaderBg ColorAttr
|
|
HeaderBorder ColorAttr
|
|
HeaderLabel ColorAttr
|
|
Footer ColorAttr
|
|
FooterBg ColorAttr
|
|
FooterBorder ColorAttr
|
|
FooterLabel ColorAttr
|
|
Separator ColorAttr
|
|
Scrollbar ColorAttr
|
|
Border ColorAttr
|
|
PreviewBorder ColorAttr
|
|
PreviewLabel ColorAttr
|
|
PreviewScrollbar ColorAttr
|
|
BorderLabel ColorAttr
|
|
ListLabel ColorAttr
|
|
ListBorder ColorAttr
|
|
GapLine ColorAttr
|
|
}
|
|
|
|
type Event struct {
|
|
Type EventType
|
|
Char rune
|
|
MouseEvent *MouseEvent
|
|
}
|
|
|
|
type MouseEvent struct {
|
|
Y int
|
|
X int
|
|
S int
|
|
Left bool
|
|
Down bool
|
|
Double bool
|
|
Ctrl bool
|
|
Alt bool
|
|
Shift bool
|
|
}
|
|
|
|
func (e MouseEvent) Mod() bool {
|
|
return e.Ctrl || e.Alt || e.Shift
|
|
}
|
|
|
|
func (e MouseEvent) Name() string {
|
|
name := ""
|
|
if e.Down {
|
|
return name
|
|
}
|
|
|
|
if e.Ctrl {
|
|
name += "ctrl-"
|
|
}
|
|
if e.Alt {
|
|
name += "alt-"
|
|
}
|
|
if e.Shift {
|
|
name += "shift-"
|
|
}
|
|
if e.Double {
|
|
name += "double-"
|
|
}
|
|
if !e.Left {
|
|
name += "right-"
|
|
}
|
|
return name + "click"
|
|
}
|
|
|
|
type BorderShape int
|
|
|
|
const (
|
|
BorderUndefined BorderShape = iota
|
|
BorderLine
|
|
BorderNone
|
|
BorderPhantom
|
|
BorderRounded
|
|
BorderSharp
|
|
BorderBold
|
|
BorderBlock
|
|
BorderThinBlock
|
|
BorderDouble
|
|
BorderHorizontal
|
|
BorderVertical
|
|
BorderTop
|
|
BorderBottom
|
|
BorderLeft
|
|
BorderRight
|
|
)
|
|
|
|
func (s BorderShape) HasLeft() bool {
|
|
switch s {
|
|
case BorderNone, BorderPhantom, BorderLine, BorderRight, BorderTop, BorderBottom, BorderHorizontal: // No Left
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (s BorderShape) HasRight() bool {
|
|
switch s {
|
|
case BorderNone, BorderPhantom, BorderLine, BorderLeft, BorderTop, BorderBottom, BorderHorizontal: // No right
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (s BorderShape) HasTop() bool {
|
|
switch s {
|
|
case BorderNone, BorderPhantom, BorderLine, BorderLeft, BorderRight, BorderBottom, BorderVertical: // No top
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (s BorderShape) HasBottom() bool {
|
|
switch s {
|
|
case BorderNone, BorderPhantom, BorderLine, BorderLeft, BorderRight, BorderTop, BorderVertical: // No bottom
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (s BorderShape) Visible() bool {
|
|
return s != BorderNone
|
|
}
|
|
|
|
type BorderStyle struct {
|
|
shape BorderShape
|
|
top rune
|
|
bottom rune
|
|
left rune
|
|
right rune
|
|
topLeft rune
|
|
topRight rune
|
|
bottomLeft rune
|
|
bottomRight rune
|
|
}
|
|
|
|
type BorderCharacter int
|
|
|
|
func MakeBorderStyle(shape BorderShape, unicode bool) BorderStyle {
|
|
if shape == BorderNone || shape == BorderPhantom {
|
|
return BorderStyle{
|
|
shape: BorderNone,
|
|
top: ' ',
|
|
bottom: ' ',
|
|
left: ' ',
|
|
right: ' ',
|
|
topLeft: ' ',
|
|
topRight: ' ',
|
|
bottomLeft: ' ',
|
|
bottomRight: ' '}
|
|
}
|
|
if !unicode {
|
|
return BorderStyle{
|
|
shape: shape,
|
|
top: '-',
|
|
bottom: '-',
|
|
left: '|',
|
|
right: '|',
|
|
topLeft: '+',
|
|
topRight: '+',
|
|
bottomLeft: '+',
|
|
bottomRight: '+',
|
|
}
|
|
}
|
|
switch shape {
|
|
case BorderSharp:
|
|
return BorderStyle{
|
|
shape: shape,
|
|
top: '─',
|
|
bottom: '─',
|
|
left: '│',
|
|
right: '│',
|
|
topLeft: '┌',
|
|
topRight: '┐',
|
|
bottomLeft: '└',
|
|
bottomRight: '┘',
|
|
}
|
|
case BorderBold:
|
|
return BorderStyle{
|
|
shape: shape,
|
|
top: '━',
|
|
bottom: '━',
|
|
left: '┃',
|
|
right: '┃',
|
|
topLeft: '┏',
|
|
topRight: '┓',
|
|
bottomLeft: '┗',
|
|
bottomRight: '┛',
|
|
}
|
|
case BorderBlock:
|
|
// ▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜
|
|
// ▌ ▐
|
|
// ▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟
|
|
return BorderStyle{
|
|
shape: shape,
|
|
top: '▀',
|
|
bottom: '▄',
|
|
left: '▌',
|
|
right: '▐',
|
|
topLeft: '▛',
|
|
topRight: '▜',
|
|
bottomLeft: '▙',
|
|
bottomRight: '▟',
|
|
}
|
|
|
|
case BorderThinBlock:
|
|
// 🭽▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔🭾
|
|
// ▏ ▕
|
|
// 🭼▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁🭿
|
|
return BorderStyle{
|
|
shape: shape,
|
|
top: '▔',
|
|
bottom: '▁',
|
|
left: '▏',
|
|
right: '▕',
|
|
topLeft: '🭽',
|
|
topRight: '🭾',
|
|
bottomLeft: '🭼',
|
|
bottomRight: '🭿',
|
|
}
|
|
|
|
case BorderDouble:
|
|
return BorderStyle{
|
|
shape: shape,
|
|
top: '═',
|
|
bottom: '═',
|
|
left: '║',
|
|
right: '║',
|
|
topLeft: '╔',
|
|
topRight: '╗',
|
|
bottomLeft: '╚',
|
|
bottomRight: '╝',
|
|
}
|
|
}
|
|
return BorderStyle{
|
|
shape: shape,
|
|
top: '─',
|
|
bottom: '─',
|
|
left: '│',
|
|
right: '│',
|
|
topLeft: '╭',
|
|
topRight: '╮',
|
|
bottomLeft: '╰',
|
|
bottomRight: '╯',
|
|
}
|
|
}
|
|
|
|
type TermSize struct {
|
|
Lines int
|
|
Columns int
|
|
PxWidth int
|
|
PxHeight int
|
|
}
|
|
|
|
type WindowType int
|
|
|
|
const (
|
|
WindowBase WindowType = iota
|
|
WindowList
|
|
WindowPreview
|
|
WindowInput
|
|
WindowHeader
|
|
WindowFooter
|
|
)
|
|
|
|
type Renderer interface {
|
|
DefaultTheme() *ColorTheme
|
|
Init() error
|
|
Resize(maxHeightFunc func(int) int)
|
|
Pause(clear bool)
|
|
Resume(clear bool, sigcont bool)
|
|
Clear()
|
|
RefreshWindows(windows []Window)
|
|
Refresh()
|
|
Close()
|
|
PassThrough(string)
|
|
NeedScrollbarRedraw() bool
|
|
ShouldEmitResizeEvent() bool
|
|
Bell()
|
|
HideCursor()
|
|
ShowCursor()
|
|
|
|
GetChar() Event
|
|
|
|
Top() int
|
|
MaxX() int
|
|
MaxY() int
|
|
|
|
Size() TermSize
|
|
|
|
NewWindow(top int, left int, width int, height int, windowType WindowType, borderStyle BorderStyle, erase bool) Window
|
|
}
|
|
|
|
type Window interface {
|
|
Top() int
|
|
Left() int
|
|
Width() int
|
|
Height() int
|
|
|
|
DrawBorder()
|
|
DrawHBorder()
|
|
Refresh()
|
|
FinishFill()
|
|
|
|
X() int
|
|
Y() int
|
|
EncloseX(x int) bool
|
|
EncloseY(y int) bool
|
|
Enclose(y int, x int) bool
|
|
|
|
Move(y int, x int)
|
|
MoveAndClear(y int, x int)
|
|
Print(text string)
|
|
CPrint(color ColorPair, text string)
|
|
Fill(text string) FillReturn
|
|
CFill(fg Color, bg Color, attr Attr, text string) FillReturn
|
|
LinkBegin(uri string, params string)
|
|
LinkEnd()
|
|
Erase()
|
|
EraseMaybe() bool
|
|
|
|
SetWrapSign(string, int)
|
|
}
|
|
|
|
type FullscreenRenderer struct {
|
|
theme *ColorTheme
|
|
mouse bool
|
|
forceBlack bool
|
|
prevDownTime time.Time
|
|
clicks [][2]int
|
|
showCursor bool
|
|
}
|
|
|
|
func NewFullscreenRenderer(theme *ColorTheme, forceBlack bool, mouse bool) Renderer {
|
|
r := &FullscreenRenderer{
|
|
theme: theme,
|
|
mouse: mouse,
|
|
forceBlack: forceBlack,
|
|
prevDownTime: time.Unix(0, 0),
|
|
clicks: [][2]int{},
|
|
showCursor: true}
|
|
return r
|
|
}
|
|
|
|
var (
|
|
Default16 *ColorTheme
|
|
Dark256 *ColorTheme
|
|
Light256 *ColorTheme
|
|
|
|
ColPrompt ColorPair
|
|
ColNormal ColorPair
|
|
ColInput ColorPair
|
|
ColDisabled ColorPair
|
|
ColGhost ColorPair
|
|
ColMatch ColorPair
|
|
ColCursor ColorPair
|
|
ColCursorEmpty ColorPair
|
|
ColCursorEmptyChar ColorPair
|
|
ColMarker ColorPair
|
|
ColSelected ColorPair
|
|
ColSelectedMatch ColorPair
|
|
ColCurrent ColorPair
|
|
ColCurrentMatch ColorPair
|
|
ColCurrentCursor ColorPair
|
|
ColCurrentCursorEmpty ColorPair
|
|
ColCurrentMarker ColorPair
|
|
ColCurrentSelectedEmpty ColorPair
|
|
ColSpinner ColorPair
|
|
ColInfo ColorPair
|
|
ColHeader ColorPair
|
|
ColHeaderBorder ColorPair
|
|
ColHeaderLabel ColorPair
|
|
ColFooter ColorPair
|
|
ColFooterBorder ColorPair
|
|
ColFooterLabel ColorPair
|
|
ColSeparator ColorPair
|
|
ColScrollbar ColorPair
|
|
ColGapLine ColorPair
|
|
ColBorder ColorPair
|
|
ColPreview ColorPair
|
|
ColPreviewBorder ColorPair
|
|
ColBorderLabel ColorPair
|
|
ColPreviewLabel ColorPair
|
|
ColPreviewScrollbar ColorPair
|
|
ColPreviewSpinner ColorPair
|
|
ColListBorder ColorPair
|
|
ColListLabel ColorPair
|
|
ColInputBorder ColorPair
|
|
ColInputLabel ColorPair
|
|
)
|
|
|
|
func EmptyTheme() *ColorTheme {
|
|
return &ColorTheme{
|
|
Colored: true,
|
|
Input: ColorAttr{colUndefined, AttrUndefined},
|
|
Fg: ColorAttr{colUndefined, AttrUndefined},
|
|
Bg: ColorAttr{colUndefined, AttrUndefined},
|
|
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
|
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
|
AltBg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
|
DarkBg: ColorAttr{colUndefined, AttrUndefined},
|
|
Prompt: ColorAttr{colUndefined, AttrUndefined},
|
|
Match: ColorAttr{colUndefined, AttrUndefined},
|
|
Current: ColorAttr{colUndefined, AttrUndefined},
|
|
CurrentMatch: ColorAttr{colUndefined, AttrUndefined},
|
|
Spinner: ColorAttr{colUndefined, AttrUndefined},
|
|
Info: ColorAttr{colUndefined, AttrUndefined},
|
|
Cursor: ColorAttr{colUndefined, AttrUndefined},
|
|
Marker: ColorAttr{colUndefined, AttrUndefined},
|
|
Header: ColorAttr{colUndefined, AttrUndefined},
|
|
Footer: ColorAttr{colUndefined, AttrUndefined},
|
|
Border: ColorAttr{colUndefined, AttrUndefined},
|
|
BorderLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
ListLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
ListBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
Ghost: ColorAttr{colUndefined, Dim},
|
|
Disabled: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewFg: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewBg: ColorAttr{colUndefined, AttrUndefined},
|
|
Gutter: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewScrollbar: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
Separator: ColorAttr{colUndefined, AttrUndefined},
|
|
Scrollbar: ColorAttr{colUndefined, AttrUndefined},
|
|
InputBg: ColorAttr{colUndefined, AttrUndefined},
|
|
InputBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
InputLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderBg: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterBg: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
GapLine: ColorAttr{colUndefined, AttrUndefined},
|
|
Nth: ColorAttr{colUndefined, AttrUndefined},
|
|
}
|
|
}
|
|
|
|
func NoColorTheme() *ColorTheme {
|
|
return &ColorTheme{
|
|
Colored: false,
|
|
Input: ColorAttr{colDefault, AttrUndefined},
|
|
Fg: ColorAttr{colDefault, AttrUndefined},
|
|
Bg: ColorAttr{colDefault, AttrUndefined},
|
|
ListFg: ColorAttr{colDefault, AttrUndefined},
|
|
ListBg: ColorAttr{colDefault, AttrUndefined},
|
|
AltBg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedFg: ColorAttr{colDefault, AttrUndefined},
|
|
SelectedBg: ColorAttr{colDefault, AttrUndefined},
|
|
SelectedMatch: ColorAttr{colDefault, AttrUndefined},
|
|
DarkBg: ColorAttr{colDefault, AttrUndefined},
|
|
Prompt: ColorAttr{colDefault, AttrUndefined},
|
|
Match: ColorAttr{colDefault, Underline},
|
|
Current: ColorAttr{colDefault, Reverse},
|
|
CurrentMatch: ColorAttr{colDefault, Reverse | Underline},
|
|
Spinner: ColorAttr{colDefault, AttrUndefined},
|
|
Info: ColorAttr{colDefault, AttrUndefined},
|
|
Cursor: ColorAttr{colDefault, AttrUndefined},
|
|
Marker: ColorAttr{colDefault, AttrUndefined},
|
|
Header: ColorAttr{colDefault, AttrUndefined},
|
|
Border: ColorAttr{colDefault, AttrUndefined},
|
|
BorderLabel: ColorAttr{colDefault, AttrUndefined},
|
|
Ghost: ColorAttr{colDefault, Dim},
|
|
Disabled: ColorAttr{colDefault, AttrUndefined},
|
|
PreviewFg: ColorAttr{colDefault, AttrUndefined},
|
|
PreviewBg: ColorAttr{colDefault, AttrUndefined},
|
|
Gutter: ColorAttr{colDefault, AttrUndefined},
|
|
PreviewBorder: ColorAttr{colDefault, AttrUndefined},
|
|
PreviewScrollbar: ColorAttr{colDefault, AttrUndefined},
|
|
PreviewLabel: ColorAttr{colDefault, AttrUndefined},
|
|
ListLabel: ColorAttr{colDefault, AttrUndefined},
|
|
ListBorder: ColorAttr{colDefault, AttrUndefined},
|
|
Separator: ColorAttr{colDefault, AttrUndefined},
|
|
Scrollbar: ColorAttr{colDefault, AttrUndefined},
|
|
InputBg: ColorAttr{colDefault, AttrUndefined},
|
|
InputBorder: ColorAttr{colDefault, AttrUndefined},
|
|
InputLabel: ColorAttr{colDefault, AttrUndefined},
|
|
HeaderBg: ColorAttr{colDefault, AttrUndefined},
|
|
HeaderBorder: ColorAttr{colDefault, AttrUndefined},
|
|
HeaderLabel: ColorAttr{colDefault, AttrUndefined},
|
|
FooterBg: ColorAttr{colDefault, AttrUndefined},
|
|
FooterBorder: ColorAttr{colDefault, AttrUndefined},
|
|
FooterLabel: ColorAttr{colDefault, AttrUndefined},
|
|
GapLine: ColorAttr{colDefault, AttrUndefined},
|
|
Nth: ColorAttr{colUndefined, AttrUndefined},
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
Default16 = &ColorTheme{
|
|
Colored: true,
|
|
Input: ColorAttr{colDefault, AttrUndefined},
|
|
Fg: ColorAttr{colDefault, AttrUndefined},
|
|
Bg: ColorAttr{colDefault, AttrUndefined},
|
|
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
|
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
|
AltBg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
|
DarkBg: ColorAttr{colGrey, AttrUndefined},
|
|
Prompt: ColorAttr{colBlue, AttrUndefined},
|
|
Match: ColorAttr{colGreen, AttrUndefined},
|
|
Current: ColorAttr{colBrightWhite, AttrUndefined},
|
|
CurrentMatch: ColorAttr{colBrightGreen, AttrUndefined},
|
|
Spinner: ColorAttr{colGreen, AttrUndefined},
|
|
Info: ColorAttr{colYellow, AttrUndefined},
|
|
Cursor: ColorAttr{colRed, AttrUndefined},
|
|
Marker: ColorAttr{colMagenta, AttrUndefined},
|
|
Header: ColorAttr{colCyan, AttrUndefined},
|
|
Footer: ColorAttr{colCyan, AttrUndefined},
|
|
Border: ColorAttr{colDefault, Dim},
|
|
BorderLabel: ColorAttr{colDefault, AttrUndefined},
|
|
Ghost: ColorAttr{colUndefined, Dim},
|
|
Disabled: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewFg: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewBg: ColorAttr{colUndefined, AttrUndefined},
|
|
Gutter: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewScrollbar: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
ListLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
ListBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
Separator: ColorAttr{colUndefined, AttrUndefined},
|
|
Scrollbar: ColorAttr{colUndefined, AttrUndefined},
|
|
InputBg: ColorAttr{colUndefined, AttrUndefined},
|
|
InputBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
InputLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderBg: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterBg: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
GapLine: ColorAttr{colUndefined, AttrUndefined},
|
|
Nth: ColorAttr{colUndefined, AttrUndefined},
|
|
}
|
|
Dark256 = &ColorTheme{
|
|
Colored: true,
|
|
Input: ColorAttr{colDefault, AttrUndefined},
|
|
Fg: ColorAttr{colDefault, AttrUndefined},
|
|
Bg: ColorAttr{colDefault, AttrUndefined},
|
|
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
|
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
|
AltBg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
|
DarkBg: ColorAttr{236, AttrUndefined},
|
|
Prompt: ColorAttr{110, AttrUndefined},
|
|
Match: ColorAttr{108, AttrUndefined},
|
|
Current: ColorAttr{254, AttrUndefined},
|
|
CurrentMatch: ColorAttr{151, AttrUndefined},
|
|
Spinner: ColorAttr{148, AttrUndefined},
|
|
Info: ColorAttr{144, AttrUndefined},
|
|
Cursor: ColorAttr{161, AttrUndefined},
|
|
Marker: ColorAttr{168, AttrUndefined},
|
|
Header: ColorAttr{109, AttrUndefined},
|
|
Footer: ColorAttr{109, AttrUndefined},
|
|
Border: ColorAttr{59, AttrUndefined},
|
|
BorderLabel: ColorAttr{145, AttrUndefined},
|
|
Ghost: ColorAttr{colUndefined, Dim},
|
|
Disabled: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewFg: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewBg: ColorAttr{colUndefined, AttrUndefined},
|
|
Gutter: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewScrollbar: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
ListLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
ListBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
Separator: ColorAttr{colUndefined, AttrUndefined},
|
|
Scrollbar: ColorAttr{colUndefined, AttrUndefined},
|
|
InputBg: ColorAttr{colUndefined, AttrUndefined},
|
|
InputBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
InputLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderBg: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterBg: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
GapLine: ColorAttr{colUndefined, AttrUndefined},
|
|
Nth: ColorAttr{colUndefined, AttrUndefined},
|
|
}
|
|
Light256 = &ColorTheme{
|
|
Colored: true,
|
|
Input: ColorAttr{colDefault, AttrUndefined},
|
|
Fg: ColorAttr{colDefault, AttrUndefined},
|
|
Bg: ColorAttr{colDefault, AttrUndefined},
|
|
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
|
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
|
AltBg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
|
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
|
DarkBg: ColorAttr{251, AttrUndefined},
|
|
Prompt: ColorAttr{25, AttrUndefined},
|
|
Match: ColorAttr{66, AttrUndefined},
|
|
Current: ColorAttr{237, AttrUndefined},
|
|
CurrentMatch: ColorAttr{23, AttrUndefined},
|
|
Spinner: ColorAttr{65, AttrUndefined},
|
|
Info: ColorAttr{101, AttrUndefined},
|
|
Cursor: ColorAttr{161, AttrUndefined},
|
|
Marker: ColorAttr{168, AttrUndefined},
|
|
Header: ColorAttr{31, AttrUndefined},
|
|
Footer: ColorAttr{31, AttrUndefined},
|
|
Border: ColorAttr{145, AttrUndefined},
|
|
BorderLabel: ColorAttr{59, AttrUndefined},
|
|
Ghost: ColorAttr{colUndefined, Dim},
|
|
Disabled: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewFg: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewBg: ColorAttr{colUndefined, AttrUndefined},
|
|
Gutter: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewScrollbar: ColorAttr{colUndefined, AttrUndefined},
|
|
PreviewLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
ListLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
ListBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
Separator: ColorAttr{colUndefined, AttrUndefined},
|
|
Scrollbar: ColorAttr{colUndefined, AttrUndefined},
|
|
InputBg: ColorAttr{colUndefined, AttrUndefined},
|
|
InputBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
InputLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderBg: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
HeaderLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterBg: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterBorder: ColorAttr{colUndefined, AttrUndefined},
|
|
FooterLabel: ColorAttr{colUndefined, AttrUndefined},
|
|
GapLine: ColorAttr{colUndefined, AttrUndefined},
|
|
Nth: ColorAttr{colUndefined, AttrUndefined},
|
|
}
|
|
}
|
|
|
|
func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInputWindow bool, hasHeaderWindow bool) {
|
|
if forceBlack {
|
|
theme.Bg = ColorAttr{colBlack, AttrUndefined}
|
|
}
|
|
|
|
o := func(a ColorAttr, b ColorAttr) ColorAttr {
|
|
c := a
|
|
if b.Color != colUndefined {
|
|
c.Color = b.Color
|
|
}
|
|
if b.Attr != AttrUndefined {
|
|
c.Attr = b.Attr
|
|
}
|
|
return c
|
|
}
|
|
theme.Input = o(baseTheme.Input, theme.Input)
|
|
theme.Fg = o(baseTheme.Fg, theme.Fg)
|
|
theme.Bg = o(baseTheme.Bg, theme.Bg)
|
|
theme.DarkBg = o(baseTheme.DarkBg, theme.DarkBg)
|
|
theme.Prompt = o(baseTheme.Prompt, theme.Prompt)
|
|
theme.Match = o(baseTheme.Match, theme.Match)
|
|
// Inherit from 'fg', so that we don't have to write 'current-fg:dim'
|
|
// e.g. fzf --delimiter / --nth -1 --color fg:dim,nth:regular
|
|
theme.Current = theme.Fg.Merge(o(baseTheme.Current, theme.Current))
|
|
theme.CurrentMatch = o(baseTheme.CurrentMatch, theme.CurrentMatch)
|
|
theme.Spinner = o(baseTheme.Spinner, theme.Spinner)
|
|
theme.Info = o(baseTheme.Info, theme.Info)
|
|
theme.Cursor = o(baseTheme.Cursor, theme.Cursor)
|
|
theme.Marker = o(baseTheme.Marker, theme.Marker)
|
|
theme.Header = o(baseTheme.Header, theme.Header)
|
|
theme.Footer = o(baseTheme.Footer, theme.Footer)
|
|
theme.Border = o(baseTheme.Border, theme.Border)
|
|
theme.BorderLabel = o(baseTheme.BorderLabel, theme.BorderLabel)
|
|
|
|
undefined := NewColorAttr()
|
|
scrollbarDefined := theme.Scrollbar != undefined
|
|
previewBorderDefined := theme.PreviewBorder != undefined
|
|
|
|
// These colors are not defined in the base themes
|
|
theme.ListFg = o(theme.Fg, theme.ListFg)
|
|
theme.ListBg = o(theme.Bg, theme.ListBg)
|
|
theme.SelectedFg = o(theme.ListFg, theme.SelectedFg)
|
|
theme.SelectedBg = o(theme.ListBg, theme.SelectedBg)
|
|
theme.SelectedMatch = o(theme.Match, theme.SelectedMatch)
|
|
theme.Ghost = o(theme.Input, theme.Ghost)
|
|
theme.Disabled = o(theme.Input, theme.Disabled)
|
|
theme.Gutter = o(theme.DarkBg, theme.Gutter)
|
|
theme.PreviewFg = o(theme.Fg, theme.PreviewFg)
|
|
theme.PreviewBg = o(theme.Bg, theme.PreviewBg)
|
|
theme.PreviewLabel = o(theme.BorderLabel, theme.PreviewLabel)
|
|
theme.PreviewBorder = o(theme.Border, theme.PreviewBorder)
|
|
theme.ListLabel = o(theme.BorderLabel, theme.ListLabel)
|
|
theme.ListBorder = o(theme.Border, theme.ListBorder)
|
|
theme.Separator = o(theme.ListBorder, theme.Separator)
|
|
theme.Scrollbar = o(theme.ListBorder, theme.Scrollbar)
|
|
theme.GapLine = o(theme.ListBorder, theme.GapLine)
|
|
/*
|
|
--color list-border:green
|
|
--color scrollbar:red
|
|
--color scrollbar:red,list-border:green
|
|
--color scrollbar:red,preview-border:green
|
|
*/
|
|
if scrollbarDefined && !previewBorderDefined {
|
|
theme.PreviewScrollbar = o(theme.Scrollbar, theme.PreviewScrollbar)
|
|
} else {
|
|
theme.PreviewScrollbar = o(theme.PreviewBorder, theme.PreviewScrollbar)
|
|
}
|
|
if hasInputWindow {
|
|
theme.InputBg = o(theme.Bg, theme.InputBg)
|
|
} else {
|
|
// We shouldn't use input-bg if there's no separate input window
|
|
// e.g. fzf --color 'list-bg:green,input-bg:red' --no-input-border
|
|
theme.InputBg = o(theme.Bg, theme.ListBg)
|
|
}
|
|
theme.InputBorder = o(theme.Border, theme.InputBorder)
|
|
theme.InputLabel = o(theme.BorderLabel, theme.InputLabel)
|
|
if hasHeaderWindow {
|
|
theme.HeaderBg = o(theme.Bg, theme.HeaderBg)
|
|
} else {
|
|
theme.HeaderBg = o(theme.Bg, theme.ListBg)
|
|
}
|
|
theme.HeaderBorder = o(theme.Border, theme.HeaderBorder)
|
|
theme.HeaderLabel = o(theme.BorderLabel, theme.HeaderLabel)
|
|
|
|
theme.FooterBg = o(theme.Bg, theme.FooterBg)
|
|
theme.FooterBorder = o(theme.Border, theme.FooterBorder)
|
|
theme.FooterLabel = o(theme.BorderLabel, theme.FooterLabel)
|
|
|
|
initPalette(theme)
|
|
}
|
|
|
|
func initPalette(theme *ColorTheme) {
|
|
pair := func(fg, bg ColorAttr) ColorPair {
|
|
if fg.Color == colDefault && (fg.Attr&Reverse) > 0 {
|
|
bg.Color = colDefault
|
|
}
|
|
return ColorPair{fg.Color, bg.Color, fg.Attr}
|
|
}
|
|
blank := theme.ListFg
|
|
blank.Attr = AttrRegular
|
|
|
|
ColPrompt = pair(theme.Prompt, theme.InputBg)
|
|
ColNormal = pair(theme.ListFg, theme.ListBg)
|
|
ColSelected = pair(theme.SelectedFg, theme.SelectedBg)
|
|
ColInput = pair(theme.Input, theme.InputBg)
|
|
ColGhost = pair(theme.Ghost, theme.InputBg)
|
|
ColDisabled = pair(theme.Disabled, theme.InputBg)
|
|
ColMatch = pair(theme.Match, theme.ListBg)
|
|
ColSelectedMatch = pair(theme.SelectedMatch, theme.SelectedBg)
|
|
ColCursor = pair(theme.Cursor, theme.Gutter)
|
|
ColCursorEmpty = pair(blank, theme.Gutter)
|
|
ColCursorEmptyChar = pair(theme.Gutter, theme.ListBg)
|
|
if theme.SelectedBg.Color != theme.ListBg.Color {
|
|
ColMarker = pair(theme.Marker, theme.SelectedBg)
|
|
} else {
|
|
ColMarker = pair(theme.Marker, theme.ListBg)
|
|
}
|
|
ColCurrent = pair(theme.Current, theme.DarkBg)
|
|
ColCurrentMatch = pair(theme.CurrentMatch, theme.DarkBg)
|
|
ColCurrentCursor = pair(theme.Cursor, theme.DarkBg)
|
|
ColCurrentCursorEmpty = pair(blank, theme.DarkBg)
|
|
ColCurrentMarker = pair(theme.Marker, theme.DarkBg)
|
|
ColCurrentSelectedEmpty = pair(blank, theme.DarkBg)
|
|
ColSpinner = pair(theme.Spinner, theme.InputBg)
|
|
ColInfo = pair(theme.Info, theme.InputBg)
|
|
ColSeparator = pair(theme.Separator, theme.InputBg)
|
|
ColScrollbar = pair(theme.Scrollbar, theme.ListBg)
|
|
ColGapLine = pair(theme.GapLine, theme.ListBg)
|
|
ColBorder = pair(theme.Border, theme.Bg)
|
|
ColBorderLabel = pair(theme.BorderLabel, theme.Bg)
|
|
ColPreviewLabel = pair(theme.PreviewLabel, theme.PreviewBg)
|
|
ColPreview = pair(theme.PreviewFg, theme.PreviewBg)
|
|
ColPreviewBorder = pair(theme.PreviewBorder, theme.PreviewBg)
|
|
ColPreviewScrollbar = pair(theme.PreviewScrollbar, theme.PreviewBg)
|
|
ColPreviewSpinner = pair(theme.Spinner, theme.PreviewBg)
|
|
ColListLabel = pair(theme.ListLabel, theme.ListBg)
|
|
ColListBorder = pair(theme.ListBorder, theme.ListBg)
|
|
ColInputBorder = pair(theme.InputBorder, theme.InputBg)
|
|
ColInputLabel = pair(theme.InputLabel, theme.InputBg)
|
|
ColHeader = pair(theme.Header, theme.HeaderBg)
|
|
ColHeaderBorder = pair(theme.HeaderBorder, theme.HeaderBg)
|
|
ColHeaderLabel = pair(theme.HeaderLabel, theme.HeaderBg)
|
|
ColFooter = pair(theme.Footer, theme.FooterBg)
|
|
ColFooterBorder = pair(theme.FooterBorder, theme.FooterBg)
|
|
ColFooterLabel = pair(theme.FooterLabel, theme.FooterBg)
|
|
}
|
|
|
|
func runeWidth(r rune) int {
|
|
return uniseg.StringWidth(string(r))
|
|
}
|