diff options
author | Junegunn Choi <junegunn.c@gmail.com> | 2016-10-21 19:35:59 +0900 |
---|---|---|
committer | Junegunn Choi <junegunn.c@gmail.com> | 2016-10-21 19:35:59 +0900 |
commit | 0a8d2996dcb3cd3ebf55b783b08667fa3740433b (patch) | |
tree | 62b1268f394dfd5bed28398fbd3ca379b8c87953 | |
parent | cfdb00b9718822b6ab2018a47288d5be3a32d07c (diff) |
Set foreground color without affecting background
Close #712
-rw-r--r-- | src/curses/curses.go | 117 | ||||
-rw-r--r-- | src/options.go | 2 | ||||
-rw-r--r-- | src/options_test.go | 10 | ||||
-rw-r--r-- | src/result.go | 12 | ||||
-rw-r--r-- | src/result_test.go | 2 | ||||
-rw-r--r-- | src/terminal.go | 6 |
6 files changed, 73 insertions, 76 deletions
diff --git a/src/curses/curses.go b/src/curses/curses.go index 700e6670..638a8629 100644 --- a/src/curses/curses.go +++ b/src/curses/curses.go @@ -113,7 +113,8 @@ const ( // Pallete const ( - ColNormal = iota + _ = iota + ColNormal ColPrompt ColMatch ColCurrent @@ -134,7 +135,6 @@ const ( ) type ColorTheme struct { - UseDefault bool Fg int16 Bg int16 DarkBg int16 @@ -168,7 +168,8 @@ type MouseEvent struct { var ( _buf []byte _in *os.File - _color func(int, Attr) C.int + _color bool + _colorFn func(int, Attr) C.int _colorMap map[int]int _prevDownTime time.Time _clickY []int @@ -176,10 +177,6 @@ var ( Default16 *ColorTheme Dark256 *ColorTheme Light256 *ColorTheme - FG int - CurrentFG int - BG int - DarkBG int ) type Window struct { @@ -192,12 +189,16 @@ type Window struct { func NewWindow(top int, left int, width int, height int, border bool) *Window { win := C.newwin(C.int(height), C.int(width), C.int(top), C.int(left)) + if _color { + C.wbkgd(win, C.chtype(C.COLOR_PAIR(ColNormal))) + } if border { - attr := _color(ColBorder, 0) + attr := _colorFn(ColBorder, 0) C.wattron(win, attr) C.box(win, 0, 0) C.wattroff(win, attr) } + return &Window{ win: win, Top: top, @@ -209,7 +210,6 @@ func NewWindow(top int, left int, width int, height int, border bool) *Window { func EmptyTheme() *ColorTheme { return &ColorTheme{ - UseDefault: true, Fg: colUndefined, Bg: colUndefined, DarkBg: colUndefined, @@ -230,9 +230,8 @@ func init() { _clickY = []int{} _colorMap = make(map[int]int) Default16 = &ColorTheme{ - UseDefault: true, - Fg: 15, - Bg: 0, + Fg: colDefault, + Bg: colDefault, DarkBg: C.COLOR_BLACK, Prompt: C.COLOR_BLUE, Match: C.COLOR_GREEN, @@ -245,9 +244,8 @@ func init() { Header: C.COLOR_CYAN, Border: C.COLOR_BLACK} Dark256 = &ColorTheme{ - UseDefault: true, - Fg: 15, - Bg: 0, + Fg: colDefault, + Bg: colDefault, DarkBg: 236, Prompt: 110, Match: 108, @@ -260,9 +258,8 @@ func init() { Header: 109, Border: 59} Light256 = &ColorTheme{ - UseDefault: true, - Fg: 15, - Bg: 0, + Fg: colDefault, + Bg: colDefault, DarkBg: 251, Prompt: 25, Match: 66, @@ -278,7 +275,7 @@ func init() { func attrColored(pair int, a Attr) C.int { var attr C.int - if pair > ColNormal { + if pair > 0 { attr = C.COLOR_PAIR(C.int(pair)) } return attr | C.int(a) @@ -344,7 +341,8 @@ func Init(theme *ColorTheme, black bool, mouse bool) { C.noecho() C.raw() // stty dsusp undef - if theme != nil { + _color = theme != nil + if _color { C.start_color() var baseTheme *ColorTheme if C.tigetnum(C.CString("colors")) >= 256 { @@ -353,52 +351,57 @@ func Init(theme *ColorTheme, black bool, mouse bool) { baseTheme = Default16 } initPairs(baseTheme, theme, black) - _color = attrColored + C.bkgd(C.chtype(C.COLOR_PAIR(ColNormal))) + _colorFn = attrColored } else { - _color = attrMono + _colorFn = attrMono } } -func override(a int16, b int16) C.short { - if b == colUndefined { - return C.short(a) +func override(baseTheme *ColorTheme, theme *ColorTheme) { + o := func(a int16, b int16) int16 { + if b == colUndefined { + return a + } + return b } - return C.short(b) + 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) + theme.Current = 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.Selected = o(baseTheme.Selected, theme.Selected) + theme.Header = o(baseTheme.Header, theme.Header) + theme.Border = o(baseTheme.Border, theme.Border) } func initPairs(baseTheme *ColorTheme, theme *ColorTheme, black bool) { - fg := override(baseTheme.Fg, theme.Fg) - bg := override(baseTheme.Bg, theme.Bg) if black { - bg = C.COLOR_BLACK - } else if theme.UseDefault { - fg = colDefault - bg = colDefault - C.use_default_colors() - } - if theme.UseDefault { - FG = colDefault - BG = colDefault - } else { - FG = int(fg) - BG = int(bg) - C.assume_default_colors(C.int(override(baseTheme.Fg, theme.Fg)), C.int(bg)) + theme.Bg = C.COLOR_BLACK } + // Updates theme + override(baseTheme, theme) - currentFG := override(baseTheme.Current, theme.Current) - darkBG := override(baseTheme.DarkBg, theme.DarkBg) - CurrentFG = int(currentFG) - DarkBG = int(darkBG) - C.init_pair(ColPrompt, override(baseTheme.Prompt, theme.Prompt), bg) - C.init_pair(ColMatch, override(baseTheme.Match, theme.Match), bg) - C.init_pair(ColCurrent, currentFG, darkBG) - C.init_pair(ColCurrentMatch, override(baseTheme.CurrentMatch, theme.CurrentMatch), darkBG) - C.init_pair(ColSpinner, override(baseTheme.Spinner, theme.Spinner), bg) - C.init_pair(ColInfo, override(baseTheme.Info, theme.Info), bg) - C.init_pair(ColCursor, override(baseTheme.Cursor, theme.Cursor), darkBG) - C.init_pair(ColSelected, override(baseTheme.Selected, theme.Selected), darkBG) - C.init_pair(ColHeader, override(baseTheme.Header, theme.Header), bg) - C.init_pair(ColBorder, override(baseTheme.Border, theme.Border), bg) + C.assume_default_colors(C.int(theme.Fg), C.int(theme.Bg)) + initPair := func(group C.short, fg int16, bg int16) { + C.init_pair(group, C.short(fg), C.short(bg)) + } + initPair(ColNormal, theme.Fg, theme.Bg) + initPair(ColPrompt, theme.Prompt, theme.Bg) + initPair(ColMatch, theme.Match, theme.Bg) + initPair(ColCurrent, theme.Current, theme.DarkBg) + initPair(ColCurrentMatch, theme.CurrentMatch, theme.DarkBg) + initPair(ColSpinner, theme.Spinner, theme.Bg) + initPair(ColInfo, theme.Info, theme.Bg) + initPair(ColCursor, theme.Cursor, theme.DarkBg) + initPair(ColSelected, theme.Selected, theme.DarkBg) + initPair(ColHeader, theme.Header, theme.Bg) + initPair(ColBorder, theme.Border, theme.Bg) } func Close() { @@ -656,7 +659,7 @@ func (w *Window) Print(text string) { } func (w *Window) CPrint(pair int, a Attr, text string) { - attr := _color(pair, a) + attr := _colorFn(pair, a) C.wattron(w.win, attr) w.Print(text) C.wattroff(w.win, attr) @@ -683,7 +686,7 @@ func (w *Window) Fill(str string) bool { } func (w *Window) CFill(str string, fg int, bg int, a Attr) bool { - attr := _color(PairFor(fg, bg), a) + attr := _colorFn(PairFor(fg, bg), a) C.wattron(w.win, attr) ret := w.Fill(str) C.wattroff(w.win, attr) diff --git a/src/options.go b/src/options.go index a7f01887..c5e6d7b7 100644 --- a/src/options.go +++ b/src/options.go @@ -499,10 +499,8 @@ func parseTheme(defaultTheme *curses.ColorTheme, str string) *curses.ColorTheme switch pair[0] { case "fg": theme.Fg = ansi - theme.UseDefault = theme.UseDefault && ansi < 0 case "bg": theme.Bg = ansi - theme.UseDefault = theme.UseDefault && ansi < 0 case "fg+": theme.Current = ansi case "bg+": diff --git a/src/options_test.go b/src/options_test.go index cc4d07c5..60136173 100644 --- a/src/options_test.go +++ b/src/options_test.go @@ -299,20 +299,14 @@ func TestColorSpec(t *testing.T) { } customized.Fg = curses.Dark256.Fg customized.Bg = curses.Dark256.Bg - if *curses.Dark256 == *customized { - t.Errorf("colors should now be equivalent") + if *curses.Dark256 != *customized { + t.Errorf("colors should now be equivalent: %v, %v", curses.Dark256, customized) } customized = parseTheme(theme, "fg:231,dark,bg:232") if customized.Fg != curses.Dark256.Fg || customized.Bg == curses.Dark256.Bg { t.Errorf("color not customized") } - if customized.UseDefault { - t.Errorf("not using default colors") - } - if !curses.Dark256.UseDefault { - t.Errorf("using default colors") - } } func TestParseNilTheme(t *testing.T) { diff --git a/src/result.go b/src/result.go index 347cf599..69e83f85 100644 --- a/src/result.go +++ b/src/result.go @@ -92,13 +92,13 @@ func minRank() rank { return rank{index: 0, points: [4]uint16{math.MaxUint16, 0, 0, 0}} } -func (result *Result) colorOffsets(matchOffsets []Offset, color int, attr curses.Attr, current bool) []colorOffset { +func (result *Result) colorOffsets(matchOffsets []Offset, theme *curses.ColorTheme, color int, attr curses.Attr, current bool) []colorOffset { itemColors := result.item.Colors() + // No ANSI code, or --color=no if len(itemColors) == 0 { var offsets []colorOffset for _, off := range matchOffsets { - offsets = append(offsets, colorOffset{offset: [2]int32{off[0], off[1]}, color: color, attr: attr}) } return offsets @@ -149,17 +149,17 @@ func (result *Result) colorOffsets(matchOffsets []Offset, color int, attr curses fg := ansi.color.fg if fg == -1 { if current { - fg = curses.CurrentFG + fg = int(theme.Current) } else { - fg = curses.FG + fg = int(theme.Fg) } } bg := ansi.color.bg if bg == -1 { if current { - bg = curses.DarkBG + bg = int(theme.DarkBg) } else { - bg = curses.BG + bg = int(theme.Bg) } } colors = append(colors, colorOffset{ diff --git a/src/result_test.go b/src/result_test.go index 46c20fd9..645684dd 100644 --- a/src/result_test.go +++ b/src/result_test.go @@ -103,7 +103,7 @@ func TestColorOffset(t *testing.T) { ansiOffset{[2]int32{33, 40}, ansiState{4, 8, curses.Bold}}}}} // [{[0 5] 9 false} {[5 15] 99 false} {[15 20] 9 false} {[22 25] 10 true} {[25 35] 99 false} {[35 40] 11 true}] - colors := item.colorOffsets(offsets, 99, 0, true) + colors := item.colorOffsets(offsets, curses.Dark256, 99, 0, true) assert := func(idx int, b int32, e int32, c int, bold bool) { var attr curses.Attr if bold { diff --git a/src/terminal.go b/src/terminal.go index e07eb3ce..2abe62ee 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -90,6 +90,7 @@ type Terminal struct { suppress bool startChan chan bool slab *util.Slab + theme *C.ColorTheme } type selectedItem struct { @@ -295,6 +296,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal { mutex: sync.Mutex{}, suppress: true, slab: util.MakeSlab(slab16Size, slab32Size), + theme: opts.Theme, startChan: make(chan bool, 1), initFunc: func() { C.Init(opts.Theme, opts.Black, opts.Mouse) @@ -637,7 +639,7 @@ func (t *Terminal) printItem(result *Result, i int, current bool) { } else { t.window.Print(" ") } - t.printHighlighted(result, 0, 0, C.ColMatch, false) + t.printHighlighted(result, 0, C.ColNormal, C.ColMatch, false) } } @@ -718,7 +720,7 @@ func (t *Terminal) printHighlighted(result *Result, attr C.Attr, col1 int, col2 maxe = util.Max(maxe, int(offset[1])) } - offsets := result.colorOffsets(charOffsets, col2, attr, current) + offsets := result.colorOffsets(charOffsets, t.theme, col2, attr, current) maxWidth := t.window.Width - 3 maxe = util.Constrain(maxe+util.Min(maxWidth/2-2, t.hscrollOff), 0, len(text)) if overflow(text, maxWidth) { |