aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandy Palamar <randy@rnpnr.xyz>2023-10-19 07:19:00 -0600
committerRandy Palamar <randy@rnpnr.xyz>2024-03-25 21:09:42 -0600
commit95bf9f59f8a9a37148bdc0787db378d62c7cd032 (patch)
tree01c8c6e8f51260cef7fa048d0f7472ab93a4a327
parent49442e5178296a58f8ca2e267a93b89c5cca8e5b (diff)
downloadvis-95bf9f59f8a9a37148bdc0787db378d62c7cd032.tar.gz
vis-95bf9f59f8a9a37148bdc0787db378d62c7cd032.tar.xz
ui: refactor style handling
The old style handling had a lot edge cases where one of the colours or the attribute wouldn't get applied correctly. This commit adds a new style_set() method to the Ui which should be called instead of manually touching a cell's style. This also means that the Cell struct can be made opaque since all the handling is now done inside the ui-terminal files. With this it is now viable to combine the light and dark 16 colour themes into a single base-16 theme. This theme works very well with the Linux virtual console and will now be the default theme regardless of if the terminal supports 256 colours or not. This should address the common complaints about vis not respecting the users default terminal colours. fixes #1151: Theming is sometimes partially applied or ignored see #1103: terminal no longer has transparency/opacity see #1040: Transparent background and setting options by default
-rw-r--r--lua/themes/base-16.lua (renamed from lua/themes/dark-16.lua)15
l---------lua/themes/default-16.lua1
l---------lua/themes/default-256.lua1
l---------lua/themes/default.lua1
-rw-r--r--lua/themes/light-16.lua37
-rw-r--r--lua/vis-std.lua4
-rw-r--r--ui-terminal-curses.c27
-rw-r--r--ui-terminal-vt100.c18
-rw-r--r--ui-terminal.c17
-rw-r--r--ui.h14
-rw-r--r--view.c7
-rw-r--r--view.h5
-rw-r--r--vis.c68
13 files changed, 89 insertions, 126 deletions
diff --git a/lua/themes/dark-16.lua b/lua/themes/base-16.lua
index fd7e1db..f334e11 100644
--- a/lua/themes/dark-16.lua
+++ b/lua/themes/base-16.lua
@@ -1,8 +1,7 @@
-- Eight-color scheme
local lexers = vis.lexers
--- dark
-lexers.STYLE_DEFAULT ='back:black,fore:white'
-lexers.STYLE_NOTHING = 'back:black'
+lexers.STYLE_DEFAULT =''
+lexers.STYLE_NOTHING = ''
lexers.STYLE_CLASS = 'fore:yellow,bold'
lexers.STYLE_COMMENT = 'fore:blue,bold'
lexers.STYLE_CONSTANT = 'fore:cyan,bold'
@@ -21,17 +20,17 @@ lexers.STYLE_TYPE = 'fore:green,bold'
lexers.STYLE_VARIABLE = 'fore:blue,bold'
lexers.STYLE_WHITESPACE = ''
lexers.STYLE_EMBEDDED = 'back:blue,bold'
-lexers.STYLE_IDENTIFIER = 'fore:white'
+lexers.STYLE_IDENTIFIER = ''
-lexers.STYLE_LINENUMBER = 'fore:white'
+lexers.STYLE_LINENUMBER = ''
lexers.STYLE_LINENUMBER_CURSOR = lexers.STYLE_LINENUMBER
-lexers.STYLE_CURSOR = 'reverse'
+lexers.STYLE_CURSOR = 'back:white,fore:black'
lexers.STYLE_CURSOR_PRIMARY = lexers.STYLE_CURSOR..',fore:yellow'
lexers.STYLE_CURSOR_LINE = 'underlined'
lexers.STYLE_COLOR_COLUMN = 'back:red'
-lexers.STYLE_SELECTION = 'back:white'
+lexers.STYLE_SELECTION = 'back:white,bold'
lexers.STYLE_STATUS = 'reverse'
lexers.STYLE_STATUS_FOCUSED = 'reverse,bold'
lexers.STYLE_SEPARATOR = lexers.STYLE_DEFAULT
-lexers.STYLE_INFO = 'fore:default,back:default,bold'
+lexers.STYLE_INFO = 'bold'
lexers.STYLE_EOF = ''
diff --git a/lua/themes/default-16.lua b/lua/themes/default-16.lua
deleted file mode 120000
index 51192b4..0000000
--- a/lua/themes/default-16.lua
+++ /dev/null
@@ -1 +0,0 @@
-dark-16.lua \ No newline at end of file
diff --git a/lua/themes/default-256.lua b/lua/themes/default-256.lua
deleted file mode 120000
index e12776c..0000000
--- a/lua/themes/default-256.lua
+++ /dev/null
@@ -1 +0,0 @@
-zenburn.lua \ No newline at end of file
diff --git a/lua/themes/default.lua b/lua/themes/default.lua
new file mode 120000
index 0000000..2813d85
--- /dev/null
+++ b/lua/themes/default.lua
@@ -0,0 +1 @@
+base-16.lua \ No newline at end of file
diff --git a/lua/themes/light-16.lua b/lua/themes/light-16.lua
deleted file mode 100644
index 53d0e45..0000000
--- a/lua/themes/light-16.lua
+++ /dev/null
@@ -1,37 +0,0 @@
--- Eight-color scheme
-local lexers = vis.lexers
--- light
-lexers.STYLE_DEFAULT = 'back:white,fore:black'
-lexers.STYLE_NOTHING = 'back:white'
-lexers.STYLE_CLASS = 'fore:yellow,bold'
-lexers.STYLE_COMMENT = 'fore:blue,bold'
-lexers.STYLE_CONSTANT = 'fore:cyan,bold'
-lexers.STYLE_DEFINITION = 'fore:blue,bold'
-lexers.STYLE_ERROR = 'fore:red,italics'
-lexers.STYLE_FUNCTION = 'fore:blue,bold'
-lexers.STYLE_KEYWORD = 'fore:yellow,bold'
-lexers.STYLE_LABEL = 'fore:green,bold'
-lexers.STYLE_NUMBER = 'fore:red,bold'
-lexers.STYLE_OPERATOR = 'fore:cyan,bold'
-lexers.STYLE_REGEX = 'fore:green,bold'
-lexers.STYLE_STRING = 'fore:red,bold'
-lexers.STYLE_PREPROCESSOR = 'fore:magenta,bold'
-lexers.STYLE_TAG = 'fore:red,bold'
-lexers.STYLE_TYPE = 'fore:green,bold'
-lexers.STYLE_VARIABLE = 'fore:blue,bold'
-lexers.STYLE_WHITESPACE = ''
-lexers.STYLE_EMBEDDED = 'back:blue,bold'
-lexers.STYLE_IDENTIFIER = 'fore:black'
-
-lexers.STYLE_LINENUMBER = 'fore:black'
-lexers.STYLE_LINENUMBER_CURSOR = lexers.STYLE_LINENUMBER
-lexers.STYLE_CURSOR = 'reverse'
-lexers.STYLE_CURSOR_PRIMARY = lexers.STYLE_CURSOR..',fore:yellow'
-lexers.STYLE_CURSOR_LINE = 'underlined'
-lexers.STYLE_COLOR_COLUMN = 'back:red'
-lexers.STYLE_SELECTION = 'back:black'
-lexers.STYLE_STATUS = 'reverse'
-lexers.STYLE_STATUS_FOCUSED = 'reverse,bold'
-lexers.STYLE_SEPARATOR = lexers.STYLE_DEFAULT
-lexers.STYLE_INFO = 'fore:default,back:default,bold'
-lexers.STYLE_EOF = ''
diff --git a/lua/vis-std.lua b/lua/vis-std.lua
index 971d247..8b5715b 100644
--- a/lua/vis-std.lua
+++ b/lua/vis-std.lua
@@ -2,9 +2,9 @@
vis.events.subscribe(vis.events.INIT, function()
if os.getenv("TERM_PROGRAM") == "Apple_Terminal" then
- vis:command("set change256colors false");
+ vis:command("set change256colors false")
end
- vis:command("set theme ".. (vis.ui.colors <= 16 and "default-16" or "default-256"))
+ vis:command("set theme default")
end)
vis:option_register("theme", "string", function(name)
diff --git a/ui-terminal-curses.c b/ui-terminal-curses.c
index 0e7a4f1..b89d9b5 100644
--- a/ui-terminal-curses.c
+++ b/ui-terminal-curses.c
@@ -51,9 +51,13 @@
#define MAX_COLOR_CLOBBER 240
-static short color_clobber_idx = 0;
-static uint32_t clobbering_colors[MAX_COLOR_CLOBBER];
static int change_colors = -1;
+static short default_fg = -1;
+static short default_bg = -1;
+
+static inline bool cell_color_equal(CellColor c1, CellColor c2) {
+ return c1 == c2;
+}
/* Calculate r,g,b components of one of the standard upper 240 colors */
static void get_6cube_rgb(unsigned int n, int *r, int *g, int *b)
@@ -83,10 +87,13 @@ static void undo_palette(void)
/* Work out the nearest color from the 256 color set, or perhaps exactly. */
static CellColor color_rgb(UiTerm *ui, uint8_t r, uint8_t g, uint8_t b)
{
+ static short color_clobber_idx = 0;
+ static uint32_t clobbering_colors[MAX_COLOR_CLOBBER];
+
if (change_colors == -1)
change_colors = ui->vis->change_colors && can_change_color() && COLORS >= 256;
if (change_colors) {
- uint32_t hexrep = ((r << 16) | (g << 8) | b) + 1;
+ uint32_t hexrep = (r << 16) | (g << 8) | b;
for (short i = 0; i < MAX_COLOR_CLOBBER; ++i) {
if (clobbering_colors[i] == hexrep)
return i + 16;
@@ -170,7 +177,7 @@ static inline unsigned int color_pair_hash(short fg, short bg) {
static short color_pair_get(short fg, short bg) {
static bool has_default_colors;
- static short *color2palette, default_fg, default_bg;
+ static short *color2palette;
static short color_pairs_max, color_pair_current;
if (!color2palette) {
@@ -300,3 +307,15 @@ static void ui_curses_free(UiTerm *term) {
bool is_default_color(CellColor c) {
return c == CELL_COLOR_DEFAULT;
}
+
+static bool is_default_bg(CellColor c) {
+ if (change_colors == 1)
+ return c == default_bg;
+ return is_default_color(c);
+}
+
+static bool is_default_fg(CellColor c) {
+ if (change_colors == 1)
+ return c == default_fg;
+ return is_default_color(c);
+}
diff --git a/ui-terminal-vt100.c b/ui-terminal-vt100.c
index 3c785b8..565313f 100644
--- a/ui-terminal-vt100.c
+++ b/ui-terminal-vt100.c
@@ -75,7 +75,13 @@ typedef struct {
UiTerm uiterm;
Buffer buf;
} UiVt100;
-
+
+static inline bool cell_color_equal(CellColor c1, CellColor c2) {
+ if (c1.index != (uint8_t)-1 || c2.index != (uint8_t)-1)
+ return c1.index == c2.index;
+ return c1.r == c2.r && c1.g == c2.g && c1.b == c2.b;
+}
+
static CellColor color_rgb(UiTerm *ui, uint8_t r, uint8_t g, uint8_t b) {
return (CellColor){ .r = r, .g = g, .b = b, .index = (uint8_t)-1 };
}
@@ -219,6 +225,14 @@ static void ui_vt100_free(UiTerm *tui) {
buffer_release(&vtui->buf);
}
-bool is_default_color(CellColor c) {
+static bool is_default_color(CellColor c) {
return c.index == ((CellColor) CELL_COLOR_DEFAULT).index;
}
+
+static bool is_default_fg(CellColor c) {
+ return is_default_color(c);
+}
+
+static bool is_default_bg(CellColor c) {
+ return is_default_color(c);
+}
diff --git a/ui-terminal.c b/ui-terminal.c
index 264c6d3..cf34378 100644
--- a/ui-terminal.c
+++ b/ui-terminal.c
@@ -286,10 +286,21 @@ static void ui_window_draw(UiWin *w) {
}
}
-static CellStyle ui_window_style_get(UiWin *w, enum UiStyle style) {
+static void ui_window_style_set(UiWin *w, Cell *cell, enum UiStyle id) {
UiTermWin *win = (UiTermWin*)w;
UiTerm *tui = win->ui;
- return tui->styles[win->id * UI_STYLE_MAX + style];
+ CellStyle set, style = tui->styles[win->id * UI_STYLE_MAX + id];
+
+ if (id == UI_STYLE_DEFAULT) {
+ memcpy(&cell->style, &style, sizeof(CellStyle));
+ return;
+ }
+
+ set.fg = is_default_fg(style.fg)? cell->style.fg : style.fg;
+ set.bg = is_default_bg(style.bg)? cell->style.bg : style.bg;
+ set.attr = cell->style.attr | style.attr;
+
+ memcpy(&cell->style, &set, sizeof(CellStyle));
}
static void ui_window_status(UiWin *w, const char *status) {
@@ -520,7 +531,7 @@ static UiWin *ui_window_new(Ui *ui, Win *w, enum UiOption options) {
return NULL;
win->uiwin = (UiWin) {
- .style_get = ui_window_style_get,
+ .style_set = ui_window_style_set,
.status = ui_window_status,
.options_set = ui_window_options_set,
.options_get = ui_window_options_get,
diff --git a/ui.h b/ui.h
index ce98af1..76bdcce 100644
--- a/ui.h
+++ b/ui.h
@@ -54,23 +54,12 @@ enum UiStyle {
#if CONFIG_CURSES
typedef uint64_t CellAttr;
typedef short CellColor;
-
-static inline bool cell_color_equal(CellColor c1, CellColor c2) {
- return c1 == c2;
-}
#else
typedef uint8_t CellAttr;
typedef struct {
uint8_t r, g, b;
uint8_t index;
} CellColor;
-
-static inline bool cell_color_equal(CellColor c1, CellColor c2) {
- if (c1.index != (uint8_t)-1 || c2.index != (uint8_t)-1)
- return c1.index == c2.index;
- return c1.r == c2.r && c1.g == c2.g && c1.b == c2.b;
-}
-
#endif
typedef struct {
@@ -107,7 +96,7 @@ struct Ui {
};
struct UiWin {
- CellStyle (*style_get)(UiWin*, enum UiStyle);
+ void (*style_set)(UiWin*, Cell*, enum UiStyle);
void (*status)(UiWin*, const char *txt);
void (*options_set)(UiWin*, enum UiOption);
enum UiOption (*options_get)(UiWin*);
@@ -116,7 +105,6 @@ struct UiWin {
int (*window_height)(UiWin*);
};
-bool is_default_color(CellColor c);
enum UiLayout ui_layout_get(Ui *ui);
#endif
diff --git a/view.c b/view.c
index 4ae4b87..df7906b 100644
--- a/view.c
+++ b/view.c
@@ -170,7 +170,7 @@ static void view_clear(View *view) {
view->wrapcol = 0;
view->prevch_breakat = false;
if (view->ui)
- view->cell_blank.style = view->ui->style_get(view->ui, UI_STYLE_DEFAULT);
+ view->ui->style_set(view->ui, &view->cell_blank, UI_STYLE_DEFAULT);
}
Filerange view_viewport_get(View *view) {
@@ -1405,11 +1405,10 @@ bool view_style_define(View *view, enum UiStyle id, const char *style) {
return view->ui->style_define(view->ui, id, style);
}
-void view_style(View *view, enum UiStyle style_id, size_t start, size_t end) {
+void view_style(View *view, enum UiStyle style, size_t start, size_t end) {
if (end < view->start || start > view->end)
return;
- CellStyle style = view->ui->style_get(view->ui, style_id);
size_t pos = view->start;
Line *line = view->topline;
@@ -1435,7 +1434,7 @@ void view_style(View *view, enum UiStyle style_id, size_t start, size_t end) {
do {
while (pos <= end && col < width) {
pos += line->cells[col].len;
- line->cells[col++].style = style;
+ view->ui->style_set(view->ui, &line->cells[col++], style);
}
col = 0;
} while (pos <= end && (line = line->next));
diff --git a/view.h b/view.h
index 95df58b..68eeb4b 100644
--- a/view.h
+++ b/view.h
@@ -6,6 +6,7 @@
typedef struct View View;
typedef struct Selection Selection;
+typedef struct Cell Cell;
#include "text.h"
#include "ui.h"
@@ -16,7 +17,7 @@ typedef struct {
Mark cursor;
} SelectionRegion;
-typedef struct {
+struct Cell {
char data[16]; /* utf8 encoded character displayed in this cell (might be more than
one Unicode codepoint. might also not be the same as in the
underlying text, for example tabs get expanded */
@@ -26,7 +27,7 @@ typedef struct {
occupied by the same character have a length of 0. */
int width; /* display width i.e. number of columns occupied by this character */
CellStyle style; /* colors and attributes used to display this cell */
-} Cell;
+};
typedef struct Line Line;
struct Line { /* a line on the screen, *not* in the file */
diff --git a/vis.c b/vis.c
index 8d68907..e287405 100644
--- a/vis.c
+++ b/vis.c
@@ -297,7 +297,6 @@ static void window_draw_colorcolumn(Win *win) {
int cc = view_colorcolumn_get(view);
if (cc <= 0)
return;
- CellStyle style = win->ui->style_get(win->ui, UI_STYLE_COLOR_COLUMN);
size_t lineno = 0;
int line_cols = 0; /* Track the number of columns we've passed on each line */
bool line_cc_set = false; /* Has the colorcolumn attribute been set for this line yet */
@@ -315,10 +314,7 @@ static void window_draw_colorcolumn(Win *win) {
/* This screen line contains the cell we want to highlight */
if (cc <= line_cols + width) {
- CellStyle *orig = &l->cells[cc - 1 - line_cols].style;
- orig->attr = style.attr;
- orig->fg = is_default_color(style.fg) ? orig->fg : style.fg;
- orig->bg = is_default_color(style.bg) ? orig->bg : style.bg;
+ win->ui->style_set(win->ui, &l->cells[cc - 1 - line_cols], UI_STYLE_COLOR_COLUMN);
line_cc_set = true;
} else {
line_cols += width;
@@ -338,22 +334,20 @@ static void window_draw_cursorline(Win *win) {
return;
int width = view_width_get(view);
- CellStyle style = win->ui->style_get(win->ui, UI_STYLE_CURSOR_LINE);
Selection *sel = view_selections_primary_get(view);
size_t lineno = view_cursors_line_get(sel)->lineno;
for (Line *l = view_lines_first(view); l; l = l->next) {
if (l->lineno == lineno) {
- for (int x = 0; x < width; x++) {
- l->cells[x].style.attr |= style.attr;
- l->cells[x].style.bg = style.bg;
- }
+ for (int x = 0; x < width; x++)
+ win->ui->style_set(win->ui, &l->cells[x], UI_STYLE_CURSOR_LINE);
} else if (l->lineno > lineno) {
break;
}
}
}
-static void window_draw_selection(View *view, Selection *cur, CellStyle *style) {
+static void window_draw_selection(Win *win, Selection *cur) {
+ View *view = win->view;
Filerange sel = view_selections_get(cur);
if (!text_range_valid(&sel))
return;
@@ -374,25 +368,12 @@ static void window_draw_selection(View *view, Selection *cur, CellStyle *style)
for (Line *l = start_line; l != end_line->next; l = l->next) {
int col = (l == start_line) ? start_col : 0;
int end = (l == end_line) ? end_col : l->width;
- while (col < end) {
- if (cell_color_equal(l->cells[col].style.fg, style->bg)) {
- CellStyle old = l->cells[col].style;
- if (!cell_color_equal(old.fg, old.bg)) {
- l->cells[col].style.fg = old.bg;
- l->cells[col].style.bg = old.fg;
- } else {
- l->cells[col].style.attr = style->attr;
- }
- } else {
- l->cells[col].style.bg = style->bg;
- l->cells[col].style.fg = style->fg;
- }
- col++;
- }
+ while (col < end)
+ win->ui->style_set(win->ui, &l->cells[col++], UI_STYLE_SELECTION);
}
}
-static void window_draw_cursor_matching(Win *win, Selection *cur, CellStyle *style) {
+static void window_draw_cursor_matching(Win *win, Selection *cur) {
if (win->vis->mode->visual)
return;
Line *line_match; int col_match;
@@ -403,25 +384,18 @@ static void window_draw_cursor_matching(Win *win, Selection *cur, CellStyle *sty
return;
if (!view_coord_get(win->view, pos_match, &line_match, NULL, &col_match))
return;
- if (cell_color_equal(line_match->cells[col_match].style.fg, style->fg)) {
- CellStyle old = line_match->cells[col_match].style;
- line_match->cells[col_match].style.fg = old.bg;
- line_match->cells[col_match].style.bg = old.fg;
- } else {
- line_match->cells[col_match].style.bg = style->bg;
- line_match->cells[col_match].style.fg = style->fg;
- }
+ win->ui->style_set(win->ui, &line_match->cells[col_match], UI_STYLE_SELECTION);
}
-static void window_draw_cursor(Win *win, Selection *cur, CellStyle *style, CellStyle *sel_style) {
+static void window_draw_cursor(Win *win, Selection *cur) {
if (win->vis->win != win)
return;
Line *line = view_cursors_line_get(cur);
int col = view_cursors_cell_get(cur);
if (!line || col == -1)
return;
- line->cells[col].style = *style;
- window_draw_cursor_matching(win, cur, sel_style);
+ win->ui->style_set(win->ui, &line->cells[col], UI_STYLE_CURSOR);
+ window_draw_cursor_matching(win, cur);
return;
}
@@ -429,24 +403,21 @@ static void window_draw_selections(Win *win) {
View *view = win->view;
Filerange viewport = view_viewport_get(view);
Selection *sel = view_selections_primary_get(view);
- CellStyle style_cursor = win->ui->style_get(win->ui, UI_STYLE_CURSOR);
- CellStyle style_cursor_primary = win->ui->style_get(win->ui, UI_STYLE_CURSOR_PRIMARY);
- CellStyle style_selection = win->ui->style_get(win->ui, UI_STYLE_SELECTION);
for (Selection *s = view_selections_prev(sel); s; s = view_selections_prev(s)) {
- window_draw_selection(win->view, s, &style_selection);
+ window_draw_selection(win, s);
size_t pos = view_cursors_pos(s);
if (pos < viewport.start)
break;
- window_draw_cursor(win, s, &style_cursor, &style_selection);
+ window_draw_cursor(win, s);
}
- window_draw_selection(win->view, sel, &style_selection);
- window_draw_cursor(win, sel, &style_cursor_primary, &style_selection);
+ window_draw_selection(win, sel);
+ window_draw_cursor(win, sel);
for (Selection *s = view_selections_next(sel); s; s = view_selections_next(s)) {
- window_draw_selection(win->view, s, &style_selection);
+ window_draw_selection(win, s);
size_t pos = view_cursors_pos(s);
if (pos > viewport.end)
break;
- window_draw_cursor(win, s, &style_cursor, &style_selection);
+ window_draw_cursor(win, s);
}
}
@@ -454,10 +425,9 @@ static void window_draw_eof(Win *win) {
View *view = win->view;
if (view_width_get(view) == 0)
return;
- CellStyle style = win->ui->style_get(win->ui, UI_STYLE_EOF);
for (Line *l = view_lines_last(view)->next; l; l = l->next) {
strncpy(l->cells[0].data, view_symbol_eof_get(view), sizeof(l->cells[0].data)-1);
- l->cells[0].style = style;
+ win->ui->style_set(win->ui, &l->cells[0], UI_STYLE_EOF);
}
}