Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions internal/config/colorscheme.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@ func StringToStyle(str string) tcell.Style {
return style
}

func ReverseColor(s tcell.Style) tcell.Style {
_, _, attr := s.Decompose()
attr = attr ^ tcell.AttrReverse
if attr&tcell.AttrReverse == tcell.AttrReverse {
return s.Reverse(true)
} else {
return s.Reverse(false)
}
}

// StringToColor returns a tcell color from a string representation of a color
// We accept either bright... or light... to mean the brighter version of a color
func StringToColor(str string) (tcell.Color, bool) {
Expand Down
5 changes: 3 additions & 2 deletions internal/config/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,9 @@ var DefaultGlobalOnlySettings = map[string]any{
"savehistory": true,
"scrollbarchar": "|",
"sucmd": "sudo",
"tabhighlight": false,
"tabreverse": true,
"tabbarchars": "div=│,active= [] ,inactive= ",
"tabhighlight": true,
"tabreverse": false,
"xterm": false,
}

Expand Down
139 changes: 107 additions & 32 deletions internal/display/tabwindow.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package display

import (
runewidth "github.com/mattn/go-runewidth"
"github.com/micro-editor/tcell/v2"
"github.com/zyedidia/micro/v2/internal/buffer"
"github.com/zyedidia/micro/v2/internal/config"
"github.com/zyedidia/micro/v2/internal/screen"
"github.com/zyedidia/micro/v2/internal/util"
"strings"
"unicode/utf8"
)

type TabWindow struct {
Expand All @@ -30,15 +31,26 @@ func (w *TabWindow) Resize(width, height int) {

func (w *TabWindow) LocFromVisual(vloc buffer.Loc) int {
x := -w.hscroll

tabactiverunes, tabinactiverunes, tabdivrunes := GetTabRunes()
for i, n := range w.Names {
x++
if i == w.active {
x += len(tabactiverunes) / 2
} else {
x += len(tabinactiverunes) / 2
}

s := util.CharacterCountInString(n)
if vloc.Y == w.Y && vloc.X < x+s {
return i
}
x += s
x += 3

if i == w.active {
x += len(tabactiverunes) - len(tabactiverunes)/2
} else {
x += len(tabinactiverunes) - len(tabinactiverunes)/2
}
x += len(tabdivrunes)
if x >= w.Width {
break
}
Expand Down Expand Up @@ -91,35 +103,81 @@ func (w *TabWindow) SetActive(a int) {
}
}

func GetTabRunes() ([]rune, []rune, []rune) {
var tabactivechars string
var tabinactivechars string
var tabdivchars string
for _, entry := range strings.Split(config.GetGlobalOption("tabbarchars").(string), ",") {
split := strings.SplitN(entry, "=", 2)
if len(split) < 2 {
continue
}
key, val := split[0], split[1]
switch key {
case "active":
tabactivechars = val
case "inactive":
tabinactivechars = val
case "div":
tabdivchars = val
}
}

if utf8.RuneCountInString(tabactivechars) < 2 {
tabactivechars = ""
}
if utf8.RuneCountInString(tabinactivechars) < 2 {
tabinactivechars = ""
}

tabactiverunes := []rune(tabactivechars)
tabinactiverunes := []rune(tabinactivechars)
tabdivrunes := []rune(tabdivchars)
return tabactiverunes, tabinactiverunes, tabdivrunes
}

func (w *TabWindow) Display() {
x := -w.hscroll
done := false

globalTabReverse := config.GetGlobalOption("tabreverse").(bool)
globalTabHighlight := config.GetGlobalOption("tabhighlight").(bool)
tabBarStyle := config.DefStyle

// xor of reverse and tab highlight to get tab character (as in filename and surrounding characters) reverse state
tabCharHighlight := (globalTabReverse || globalTabHighlight) && !(globalTabReverse && globalTabHighlight)

reverseStyles := func(reverse bool) (tcell.Style, tcell.Style) {
tabBarStyle := config.DefStyle.Reverse(reverse)
if style, ok := config.Colorscheme["tabbar"]; ok {
tabBarStyle = style
}
tabBarActiveStyle := tabBarStyle
if style, ok := config.Colorscheme["tabbar.active"]; ok {
tabBarActiveStyle = style
}
return tabBarStyle, tabBarActiveStyle
if style, ok := config.Colorscheme["tabbar"]; ok {
tabBarStyle = style
}
if globalTabReverse {
tabBarStyle = config.ReverseColor(tabBarStyle)
}
tabBarActiveStyle := tabBarStyle
if globalTabHighlight {
tabBarActiveStyle = config.ReverseColor(tabBarStyle)
}
if style, ok := config.Colorscheme["tabbar.active"]; ok {
tabBarActiveStyle = style
}
tabBarInactiveStyle := tabBarStyle
if style, ok := config.Colorscheme["tabbar.inactive"]; ok {
tabBarInactiveStyle = style
}
tabBarDivStyle := tabBarStyle
if style, ok := config.Colorscheme["tabbar.div"]; ok {
tabBarDivStyle = style
}

draw := func(r rune, n int, active bool, reversed bool) {
tabBarStyle, tabBarActiveStyle := reverseStyles(reversed)

draw := func(r rune, n int, active bool, tab bool, div bool) {
style := tabBarStyle
if active {
style = tabBarActiveStyle
if tab {
if active {
style = tabBarActiveStyle
} else {
style = tabBarInactiveStyle
}
} else if div {
style = tabBarDivStyle
}

for i := 0; i < n; i++ {
rw := runewidth.RuneWidth(r)
for j := 0; j < rw; j++ {
Expand All @@ -128,11 +186,11 @@ func (w *TabWindow) Display() {
c = ' '
}
if x == w.Width-1 && !done {
screen.SetContent(w.Width-1, w.Y, '>', nil, tabBarStyle)
screen.SetContent(w.Width-1, w.Y, '>', nil, style)
x++
break
} else if x == 0 && w.hscroll > 0 {
screen.SetContent(0, w.Y, '<', nil, tabBarStyle)
screen.SetContent(0, w.Y, '<', nil, style)
} else if x >= 0 && x < w.Width {
screen.SetContent(x, w.Y, c, nil, style)
}
Expand All @@ -141,27 +199,44 @@ func (w *TabWindow) Display() {
}
}

tabactiverunes, tabinactiverunes, tabdivrunes := GetTabRunes()
leftactiverunes := tabactiverunes[0 : len(tabactiverunes)/2]
rightactiverunes := tabactiverunes[len(tabactiverunes)/2:]

leftinactiverunes := tabinactiverunes[0 : len(tabinactiverunes)/2]
rightinactiverunes := tabinactiverunes[len(tabinactiverunes)/2:]

for i, n := range w.Names {
if i == w.active {
draw('[', 1, true, tabCharHighlight)
for j := 0; j < len(leftactiverunes); j++ {
draw(leftactiverunes[j], 1, true, true, false)
}
} else {
draw(' ', 1, false, tabCharHighlight)
for j := 0; j < len(leftinactiverunes); j++ {
draw(leftinactiverunes[j], 1, false, true, false)
}
}

for _, c := range n {
draw(c, 1, i == w.active, tabCharHighlight)
draw(c, 1, i == w.active, true, false)
}

if i == len(w.Names)-1 {
done = true
}

if i == w.active {
draw(']', 1, true, tabCharHighlight)
draw(' ', 2, true, globalTabReverse)
for j := 0; j < len(rightactiverunes); j++ {
draw(rightactiverunes[j], 1, true, true, false)
}
} else {
draw(' ', 1, false, tabCharHighlight)
draw(' ', 2, false, globalTabReverse)
for j := 0; j < len(rightinactiverunes); j++ {
draw(rightinactiverunes[j], 1, false, true, false)
}
}

for j := 0; j < len(tabdivrunes); j++ {
draw(tabdivrunes[j], 1, false, false, true)
}

if x >= w.Width {
Expand All @@ -170,6 +245,6 @@ func (w *TabWindow) Display() {
}

if x < w.Width {
draw(' ', w.Width-x, false, globalTabReverse)
draw(' ', w.Width-x, false, false, false)
}
}
1 change: 1 addition & 0 deletions runtime/colorschemes/gotham.micro
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ color-link cursor-line "#091F2E"
color-link color-column "#11151C"
color-link symbol "#99D1CE,#0C1014"
color-link match-brace "#0C1014,#D26937"
color-link tabbar "#0C1014,#99D1CE"
color-link tab-error "#D75F5F"
color-link trailingws "#D75F5F"
1 change: 1 addition & 0 deletions runtime/colorschemes/monokai-dark.micro
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ color-link cursor-line "#323232"
color-link color-column "#323232"
color-link match-brace "#1D0000,#AE81FF"
color-link tab-error "#D75F5F"
color-link tabbar "#1D0000,#D5D8D6"
color-link trailingws "#D75F5F"
1 change: 1 addition & 0 deletions runtime/colorschemes/sunny-day.micro
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ color-link cursor-line "229"
color-link current-line-number "246"
color-link match-brace "230,22"
color-link tab-error "210"
color-link tabbar "230,0"
color-link trailingws "210"
4 changes: 3 additions & 1 deletion runtime/help/colors.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ color support comes in three flavors.
same regardless of the configured 16-color palette. However, the color
range is fairly limited due to the small number of colors available.
Default 256-color colorschemes include `monokai`, `twilight`, `zenburn`,
`darcula` and more.
`dracula` and more.

* true-color: Some terminals support displaying "true color" with 16 million
colors using standard RGB values. This mode will be able to support
Expand Down Expand Up @@ -179,6 +179,8 @@ Here is a list of the colorscheme groups that you can use:
* statusline.suggestions (Color of the autocomplete suggestions menu)
* tabbar (Color of the tabbar that lists open files)
* tabbar.active (Color of the active tab in the tabbar)
* tabbar.inactive (Color of the inactive tabs in the tabbar)
* tabbar.div (Color of the space/divider between each tab in the tabbar)
* indent-char (Color of the character which indicates tabs if the option is
enabled)
* line-number
Expand Down
26 changes: 20 additions & 6 deletions runtime/help/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -460,20 +460,34 @@ Here are the available options:

default value: `true`

* `tabhighlight`: inverts the tab characters' (filename, save indicator, etc)
colors with respect to the tab bar.
* `tabbarchars`: sets what visual characters to be shown for various tabbar options.
This option is specified in the form of `key1=value1,key2=value2,...`.

default value: `false`
Here are the list of keys:
- `active`: the opening and closing tab characters for the current active tab,
where the values are splitted in half for opening and closing characters.
For example, value of `[[]]` will have `[[` as opening characters and
`]]` as closing characters.
- `div`: the characters to be filled between each tab.
- `inactive`: the opening and closing tab characters for the inactive tabs.
where the values are splitted in half for opening and closing characters.

default value: `div=│,active= [] ,inactive= `

* `tabhighlight`: highlighting the current active tab by using the inverted tab bar color.
Has no effect if `tabbar.active` is present in the current colorscheme.

default value: `true`

* `tabmovement`: navigate spaces at the beginning of lines as if they are tabs
(e.g. move over 4 spaces at once). This option only does anything if
`tabstospaces` is on.

default value: `false`

* `tabreverse`: reverses the tab bar colors when active.
* `tabreverse`: reverses the tab bar colors.

default value: `true`
default value: `false`

* `tabsize`: the size in spaces that a tab character should be displayed with.

Expand Down Expand Up @@ -626,7 +640,7 @@ so that you can see what the formatting should look like.
"statusline": true,
"sucmd": "sudo",
"syntax": true,
"tabhighlight": true,
"tabhighlight": false,
"tabmovement": false,
"tabreverse": false,
"tabsize": 4,
Expand Down