mirror of
https://github.com/tmux/tmux.git
synced 2026-07-03 10:12:31 +00:00
Add nicer dark and light colour sets (themes) used on terminals with 256
or more colours. Currently based these on emacs but they could change. Terminals with fewer colours use the ANSI colours. A new "theme" option overrides the detected theme (set to "terminal" to go back to ANSI colours).
This commit is contained in:
94
colour.c
94
colour.c
@@ -26,6 +26,85 @@
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/* Theme colour slots and their server options. */
|
||||
static const struct {
|
||||
const char *name;
|
||||
const char *dark_option;
|
||||
const char *light_option;
|
||||
int terminal_colour;
|
||||
} colour_theme_table[] = {
|
||||
{ "themeblack",
|
||||
"dark-theme-black",
|
||||
"light-theme-black",
|
||||
0
|
||||
},
|
||||
{ "themewhite",
|
||||
"dark-theme-white",
|
||||
"light-theme-white",
|
||||
7
|
||||
},
|
||||
{ "themelightgrey",
|
||||
"dark-theme-light-grey",
|
||||
"light-theme-light-grey",
|
||||
7
|
||||
},
|
||||
{ "themedarkgrey",
|
||||
"dark-theme-dark-grey",
|
||||
"light-theme-dark-grey",
|
||||
0
|
||||
},
|
||||
{ "themegreen",
|
||||
"dark-theme-green",
|
||||
"light-theme-green",
|
||||
2
|
||||
},
|
||||
{ "themeyellow",
|
||||
"dark-theme-yellow",
|
||||
"light-theme-yellow",
|
||||
3
|
||||
},
|
||||
{ "themered",
|
||||
"dark-theme-red",
|
||||
"light-theme-red",
|
||||
1
|
||||
},
|
||||
{ "themeblue",
|
||||
"dark-theme-blue",
|
||||
"light-theme-blue",
|
||||
4
|
||||
},
|
||||
{ "themecyan",
|
||||
"dark-theme-cyan",
|
||||
"light-theme-cyan",
|
||||
6
|
||||
},
|
||||
{ "thememagenta",
|
||||
"dark-theme-magenta",
|
||||
"light-theme-magenta",
|
||||
5
|
||||
}
|
||||
};
|
||||
|
||||
/* Get theme colour option. */
|
||||
const char *
|
||||
colour_theme_option(u_int n, enum client_theme theme)
|
||||
{
|
||||
if (n >= nitems(colour_theme_table))
|
||||
return (NULL);
|
||||
if (theme == THEME_LIGHT)
|
||||
return (colour_theme_table[n].light_option);
|
||||
return (colour_theme_table[n].dark_option);
|
||||
}
|
||||
|
||||
/* Get theme terminal colour. */
|
||||
int
|
||||
colour_theme_terminal_colour(u_int n)
|
||||
{
|
||||
if (n >= nitems(colour_theme_table))
|
||||
return (8);
|
||||
return (colour_theme_table[n].terminal_colour);
|
||||
}
|
||||
|
||||
static int
|
||||
colour_dist_sq(int R, int G, int B, int r, int g, int b)
|
||||
{
|
||||
@@ -126,7 +205,7 @@ colour_dim(int c, u_int dim)
|
||||
{
|
||||
u_char r, g, b;
|
||||
|
||||
if (dim == 0 || COLOUR_DEFAULT(c))
|
||||
if (dim == 0 || COLOUR_DEFAULT(c) || (c & COLOUR_FLAG_THEME))
|
||||
return (c);
|
||||
if (dim >= 100)
|
||||
return (colour_join_rgb(0, 0, 0));
|
||||
@@ -152,6 +231,13 @@ colour_tostring(int c)
|
||||
if (c == -1)
|
||||
return ("none");
|
||||
|
||||
if (c & COLOUR_FLAG_THEME) {
|
||||
c &= 0xff;
|
||||
if (c >= 0 && (u_int)c < nitems(colour_theme_table))
|
||||
return (colour_theme_table[c].name);
|
||||
return ("invalid");
|
||||
}
|
||||
|
||||
if (c & COLOUR_FLAG_RGB) {
|
||||
colour_split_rgb(c, &r, &g, &b);
|
||||
xsnprintf(s, sizeof s, "#%02x%02x%02x", r, g, b);
|
||||
@@ -252,6 +338,7 @@ colour_fromstring(const char *s)
|
||||
const char *cp;
|
||||
int n;
|
||||
u_char r, g, b;
|
||||
u_int i;
|
||||
|
||||
if (*s == '#' && strlen(s) == 7) {
|
||||
for (cp = s + 1; isxdigit((u_char) *cp); cp++)
|
||||
@@ -282,6 +369,11 @@ colour_fromstring(const char *s)
|
||||
if (strcasecmp(s, "terminal") == 0)
|
||||
return (9);
|
||||
|
||||
for (i = 0; i < nitems(colour_theme_table); i++) {
|
||||
if (strcasecmp(s, colour_theme_table[i].name) == 0)
|
||||
return (i|COLOUR_FLAG_THEME);
|
||||
}
|
||||
|
||||
if (strcasecmp(s, "black") == 0 || strcmp(s, "0") == 0)
|
||||
return (0);
|
||||
if (strcasecmp(s, "red") == 0 || strcmp(s, "1") == 0)
|
||||
|
||||
17
grid.c
17
grid.c
@@ -86,7 +86,8 @@ grid_need_extended_cell(const struct grid_cell_entry *gce,
|
||||
return (1);
|
||||
if (gc->data.size > 1 || gc->data.width > 1)
|
||||
return (1);
|
||||
if ((gc->fg & COLOUR_FLAG_RGB) || (gc->bg & COLOUR_FLAG_RGB))
|
||||
if ((gc->fg & (COLOUR_FLAG_RGB|COLOUR_FLAG_THEME)) ||
|
||||
(gc->bg & (COLOUR_FLAG_RGB|COLOUR_FLAG_THEME)))
|
||||
return (1);
|
||||
if (gc->us != 8) /* only supports 256 or RGB */
|
||||
return (1);
|
||||
@@ -218,7 +219,7 @@ grid_clear_cell(struct grid *gd, u_int px, u_int py, u_int bg, int moved)
|
||||
if (bg != 8)
|
||||
gee->bg = bg;
|
||||
} else if (bg != 8) {
|
||||
if (bg & COLOUR_FLAG_RGB) {
|
||||
if (bg & (COLOUR_FLAG_RGB|COLOUR_FLAG_THEME)) {
|
||||
grid_get_extended_cell(gl, gce, gce->flags);
|
||||
gee = grid_extended_cell(gl, gce, &grid_cleared_cell);
|
||||
gee->bg = bg;
|
||||
@@ -798,7 +799,9 @@ grid_string_cells_fg(const struct grid_cell *gc, int *values)
|
||||
u_char r, g, b;
|
||||
|
||||
n = 0;
|
||||
if (gc->fg & COLOUR_FLAG_256) {
|
||||
if (gc->fg & COLOUR_FLAG_THEME)
|
||||
values[n++] = 39;
|
||||
else if (gc->fg & COLOUR_FLAG_256) {
|
||||
values[n++] = 38;
|
||||
values[n++] = 5;
|
||||
values[n++] = gc->fg & 0xff;
|
||||
@@ -847,7 +850,9 @@ grid_string_cells_bg(const struct grid_cell *gc, int *values)
|
||||
u_char r, g, b;
|
||||
|
||||
n = 0;
|
||||
if (gc->bg & COLOUR_FLAG_256) {
|
||||
if (gc->bg & COLOUR_FLAG_THEME)
|
||||
values[n++] = 49;
|
||||
else if (gc->bg & COLOUR_FLAG_256) {
|
||||
values[n++] = 48;
|
||||
values[n++] = 5;
|
||||
values[n++] = gc->bg & 0xff;
|
||||
@@ -896,7 +901,9 @@ grid_string_cells_us(const struct grid_cell *gc, int *values)
|
||||
u_char r, g, b;
|
||||
|
||||
n = 0;
|
||||
if (gc->us & COLOUR_FLAG_256) {
|
||||
if (gc->us & COLOUR_FLAG_THEME) {
|
||||
values[n++] = 59;
|
||||
} else if (gc->us & COLOUR_FLAG_256) {
|
||||
values[n++] = 58;
|
||||
values[n++] = 5;
|
||||
values[n++] = gc->us & 0xff;
|
||||
|
||||
220
options-table.c
220
options-table.c
@@ -109,6 +109,9 @@ static const char *options_table_extended_keys_format_list[] = {
|
||||
static const char *options_table_allow_passthrough_list[] = {
|
||||
"off", "on", "all", NULL
|
||||
};
|
||||
static const char *options_table_theme_list[] = {
|
||||
"detect", "terminal", "light", "dark", NULL
|
||||
};
|
||||
static const char *options_table_copy_mode_line_numbers_list[] = {
|
||||
"off", "default", "absolute", "relative", "hybrid", NULL
|
||||
};
|
||||
@@ -446,7 +449,7 @@ const struct options_table_entry options_table[] = {
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.default_str = "default",
|
||||
.default_str = "bg=themedarkgrey,fg=themewhite",
|
||||
.separator = ",",
|
||||
.text = "Default style of menu."
|
||||
},
|
||||
@@ -455,7 +458,7 @@ const struct options_table_entry options_table[] = {
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.default_str = "bg=yellow,fg=black",
|
||||
.default_str = "bg=themeyellow,fg=themeblack",
|
||||
.separator = ",",
|
||||
.text = "Default style of selected menu item."
|
||||
},
|
||||
@@ -463,7 +466,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "menu-border-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.default_str = "default",
|
||||
.default_str = "bg=themedarkgrey,fg=themelightgrey",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Default style of menu borders."
|
||||
@@ -538,6 +541,175 @@ const struct options_table_entry options_table[] = {
|
||||
"automatically detected."
|
||||
},
|
||||
|
||||
{ .name = "theme",
|
||||
.type = OPTIONS_TABLE_CHOICE,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.choices = options_table_theme_list,
|
||||
.default_num = 0,
|
||||
.text = "Whether tmux should detect the terminal theme, use terminal "
|
||||
"ANSI colours, or force the light or dark theme."
|
||||
},
|
||||
|
||||
{ .name = "dark-theme-black",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},gray5,black}",
|
||||
.text = "Dark theme colour for black."
|
||||
},
|
||||
|
||||
{ .name = "dark-theme-white",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},gray90,white}",
|
||||
.text = "Dark theme colour for white."
|
||||
},
|
||||
|
||||
{ .name = "dark-theme-light-grey",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},gray70,white}",
|
||||
.text = "Dark theme colour for light grey."
|
||||
},
|
||||
|
||||
{ .name = "dark-theme-dark-grey",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},gray15,black}",
|
||||
.text = "Dark theme colour for dark grey."
|
||||
},
|
||||
|
||||
{ .name = "dark-theme-green",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},palegreen,green}",
|
||||
.text = "Dark theme colour for green."
|
||||
},
|
||||
|
||||
{ .name = "dark-theme-yellow",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},lightgoldenrod,yellow}",
|
||||
.text = "Dark theme colour for yellow."
|
||||
},
|
||||
|
||||
{ .name = "dark-theme-red",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},lightsalmon,red}",
|
||||
.text = "Dark theme colour for red."
|
||||
},
|
||||
|
||||
{ .name = "dark-theme-blue",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},lightskyblue,blue}",
|
||||
.text = "Dark theme colour for blue."
|
||||
},
|
||||
|
||||
{ .name = "dark-theme-cyan",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},aquamarine,cyan}",
|
||||
.text = "Dark theme colour for cyan."
|
||||
},
|
||||
|
||||
{ .name = "dark-theme-magenta",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},plum,magenta}",
|
||||
.text = "Dark theme colour for magenta."
|
||||
},
|
||||
|
||||
{ .name = "light-theme-black",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},gray10,black}",
|
||||
.text = "Light theme colour for black."
|
||||
},
|
||||
|
||||
{ .name = "light-theme-white",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},gray95,white}",
|
||||
.text = "Light theme colour for white."
|
||||
},
|
||||
|
||||
{ .name = "light-theme-light-grey",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},gray80,white}",
|
||||
.text = "Light theme colour for light grey."
|
||||
},
|
||||
|
||||
{ .name = "light-theme-dark-grey",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},gray45,black}",
|
||||
.text = "Light theme colour for dark grey."
|
||||
},
|
||||
|
||||
{ .name = "light-theme-green",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},forestgreen,green}",
|
||||
.text = "Light theme colour for green."
|
||||
},
|
||||
|
||||
{ .name = "light-theme-yellow",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},darkgoldenrod,yellow}",
|
||||
.text = "Light theme colour for yellow."
|
||||
},
|
||||
|
||||
{ .name = "light-theme-red",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},violetred4,red}",
|
||||
.text = "Light theme colour for red."
|
||||
},
|
||||
|
||||
{ .name = "light-theme-blue",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},royalblue,blue}",
|
||||
.text = "Light theme colour for blue."
|
||||
},
|
||||
|
||||
{ .name = "light-theme-cyan",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},darkcyan,cyan}",
|
||||
.text = "Light theme colour for cyan."
|
||||
},
|
||||
|
||||
{ .name = "light-theme-magenta",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "#{?#{e|>=:#{client_colours},256},purple,magenta}",
|
||||
.text = "Light theme colour for magenta."
|
||||
},
|
||||
|
||||
{ .name = "user-keys",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
@@ -639,7 +811,7 @@ const struct options_table_entry options_table[] = {
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SESSION,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "red",
|
||||
.default_str = "themered",
|
||||
.text = "Colour of the active pane for 'display-panes'."
|
||||
},
|
||||
|
||||
@@ -647,7 +819,7 @@ const struct options_table_entry options_table[] = {
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SESSION,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "blue",
|
||||
.default_str = "themeblue",
|
||||
.text = "Colour of not active panes for 'display-panes'."
|
||||
},
|
||||
|
||||
@@ -738,7 +910,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "message-command-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SESSION,
|
||||
.default_str = "bg=black,fg=yellow,fill=black",
|
||||
.default_str = "bg=themegreen,fg=themeblack,fill=themegreen",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of the command prompt when in command mode, if "
|
||||
@@ -767,9 +939,9 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "message-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SESSION,
|
||||
.default_str = "bg=yellow,fg=black,"
|
||||
.default_str = "bg=themeyellow,fg=themeblack,"
|
||||
"#{?#{m/r:(^|#,)IS(PANE|MODE)($|#,),#{prompt_flags}},,"
|
||||
"fill=yellow}",
|
||||
"fill=themeyellow}",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of messages and the command prompt. "
|
||||
@@ -968,7 +1140,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "status-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_SESSION,
|
||||
.default_str = "bg=green,fg=black",
|
||||
.default_str = "bg=themegreen,fg=themeblack",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of the status line."
|
||||
@@ -1152,7 +1324,7 @@ const struct options_table_entry options_table[] = {
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.flags = OPTIONS_TABLE_IS_COLOUR,
|
||||
.default_str = "blue",
|
||||
.default_str = "themeblue",
|
||||
.text = "Colour of the clock in clock mode."
|
||||
},
|
||||
|
||||
@@ -1167,7 +1339,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "copy-mode-match-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.default_str = "bg=cyan,fg=black",
|
||||
.default_str = "bg=themecyan,fg=themeblack",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of search matches in copy mode."
|
||||
@@ -1176,7 +1348,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "copy-mode-current-match-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.default_str = "bg=magenta,fg=black",
|
||||
.default_str = "bg=thememagenta,fg=themeblack",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of the current search match in copy mode."
|
||||
@@ -1185,7 +1357,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "copy-mode-mark-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.default_str = "bg=red,fg=black",
|
||||
.default_str = "bg=themeyellow,fg=themeblack",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of the marked line in copy mode."
|
||||
@@ -1224,7 +1396,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "copy-mode-current-line-number-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.default_str = "fg=yellow",
|
||||
.default_str = "fg=themeyellow",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of current line number in copy mode."
|
||||
@@ -1233,7 +1405,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "copy-mode-line-number-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.default_str = "fg=white,dim",
|
||||
.default_str = "fg=themelightgrey,dim",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of line numbers in copy mode."
|
||||
@@ -1282,7 +1454,7 @@ const struct options_table_entry options_table[] = {
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.default_str = "noattr,bg=yellow,fg=black",
|
||||
.default_str = "noattr,bg=themeyellow,fg=themeblack",
|
||||
.separator = ",",
|
||||
.text = "Style of indicators and highlighting in modes."
|
||||
},
|
||||
@@ -1331,7 +1503,9 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "pane-active-border-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||
.default_str = "#{?pane_in_mode,fg=yellow,#{?synchronize-panes,fg=red,fg=green}}",
|
||||
.default_str = "fg=#{?pane_marked,thememagenta,"
|
||||
"#{?synchronize-panes,themered,"
|
||||
"#{?pane_in_mode,themeyellow,themegreen}}}",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of the active pane border."
|
||||
@@ -1390,7 +1564,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "pane-border-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||
.default_str = "default",
|
||||
.default_str = "fg=themelightgrey",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of the pane status lines."
|
||||
@@ -1415,7 +1589,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "pane-scrollbars-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
|
||||
.default_str = "bg=black,fg=white,width=1,pad=0",
|
||||
.default_str = "bg=themedarkgrey,fg=themelightgrey,width=1,pad=0",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of the pane scrollbar."
|
||||
@@ -1432,7 +1606,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "popup-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.default_str = "default",
|
||||
.default_str = "bg=themedarkgrey,fg=themewhite",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Default style of popups."
|
||||
@@ -1441,7 +1615,7 @@ const struct options_table_entry options_table[] = {
|
||||
{ .name = "popup-border-style",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.default_str = "default",
|
||||
.default_str = "fg=themelightgrey",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Default style of popup borders."
|
||||
@@ -1519,8 +1693,8 @@ const struct options_table_entry options_table[] = {
|
||||
.default_str = "fg=#{?#{||:"
|
||||
"#{&&:#{pane_format},#{pane_active}},"
|
||||
"#{&&:#{window_format},#{window_active}}},"
|
||||
"#{display-panes-active-colour},"
|
||||
"#{display-panes-colour}}",
|
||||
"themered,"
|
||||
"themeblue}",
|
||||
.flags = OPTIONS_TABLE_IS_STYLE,
|
||||
.separator = ",",
|
||||
.text = "Style of preview indicator in tree mode."
|
||||
|
||||
11
options.c
11
options.c
@@ -1214,6 +1214,17 @@ options_push_changes(const char *name)
|
||||
|
||||
log_debug("%s: %s", __func__, name);
|
||||
|
||||
if (strcmp(name, "theme") == 0 ||
|
||||
strncmp(name, "dark-theme-", 11) == 0 ||
|
||||
strncmp(name, "light-theme-", 12) == 0) {
|
||||
TAILQ_FOREACH(loop, &clients, entry) {
|
||||
server_client_update_theme_colours(loop);
|
||||
if (loop->tty.flags & TTY_OPENED)
|
||||
tty_invalidate(&loop->tty);
|
||||
server_redraw_client(loop);
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(name, "automatic-rename") == 0) {
|
||||
RB_FOREACH(w, windows, &windows) {
|
||||
if (w->active == NULL)
|
||||
|
||||
@@ -291,6 +291,7 @@ struct client *
|
||||
server_client_create(int fd)
|
||||
{
|
||||
struct client *c;
|
||||
u_int i;
|
||||
|
||||
setblocking(fd, 0);
|
||||
|
||||
@@ -313,6 +314,9 @@ server_client_create(int fd)
|
||||
|
||||
c->tty.sx = 80;
|
||||
c->tty.sy = 24;
|
||||
|
||||
for (i = 0; i < COLOUR_THEME_COUNT; i++)
|
||||
c->theme_colours[i] = 8;
|
||||
c->theme = THEME_UNKNOWN;
|
||||
|
||||
status_init(c);
|
||||
@@ -364,6 +368,7 @@ server_client_open(struct client *c, char **cause)
|
||||
if (tty_open(&c->tty, cause) != 0)
|
||||
return (-1);
|
||||
|
||||
server_client_update_theme_colours(c);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -1081,6 +1086,52 @@ have_event:
|
||||
return (key);
|
||||
}
|
||||
|
||||
/* Update client theme colours from server options. */
|
||||
void
|
||||
server_client_update_theme_colours(struct client *c)
|
||||
{
|
||||
struct format_tree *ft;
|
||||
const char *name, *value;
|
||||
enum client_theme theme;
|
||||
char *expanded;
|
||||
u_int i;
|
||||
int colour, option;
|
||||
|
||||
if (c == NULL)
|
||||
return;
|
||||
|
||||
option = options_get_number(global_options, "theme");
|
||||
if (option == 1) {
|
||||
for (i = 0; i < COLOUR_THEME_COUNT; i++)
|
||||
c->theme_colours[i] = colour_theme_terminal_colour(i);
|
||||
return;
|
||||
}
|
||||
|
||||
ft = format_create(c, NULL, FORMAT_NONE, FORMAT_NOJOBS);
|
||||
format_defaults(ft, c, NULL, NULL, NULL);
|
||||
|
||||
theme = c->theme;
|
||||
if (option == 2)
|
||||
theme = THEME_LIGHT;
|
||||
else if (option == 3)
|
||||
theme = THEME_DARK;
|
||||
for (i = 0; i < COLOUR_THEME_COUNT; i++) {
|
||||
c->theme_colours[i] = 8;
|
||||
name = colour_theme_option(i, theme);
|
||||
if (name == NULL)
|
||||
continue;
|
||||
value = options_get_string(global_options, name);
|
||||
expanded = format_expand(ft, value);
|
||||
colour = colour_fromstring(expanded);
|
||||
free(expanded);
|
||||
if (colour == -1 || (colour & COLOUR_FLAG_THEME))
|
||||
continue;
|
||||
c->theme_colours[i] = colour;
|
||||
}
|
||||
|
||||
format_free(ft);
|
||||
}
|
||||
|
||||
/* Is this a bracket paste key? */
|
||||
static int
|
||||
server_client_is_bracket_paste(struct client *c, key_code key)
|
||||
@@ -2928,6 +2979,8 @@ out:
|
||||
static void
|
||||
server_client_report_theme(struct client *c, enum client_theme theme)
|
||||
{
|
||||
enum client_theme old = c->theme;
|
||||
|
||||
if (theme == THEME_LIGHT) {
|
||||
c->theme = THEME_LIGHT;
|
||||
notify_client("client-light-theme", c);
|
||||
@@ -2936,6 +2989,17 @@ server_client_report_theme(struct client *c, enum client_theme theme)
|
||||
notify_client("client-dark-theme", c);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the theme has changed, update the theme colours and redraw the
|
||||
* client.
|
||||
*/
|
||||
if (c->theme != old) {
|
||||
server_client_update_theme_colours(c);
|
||||
if (c->tty.flags & TTY_OPENED)
|
||||
tty_invalidate(&c->tty);
|
||||
server_redraw_client(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Request foreground and background colour again. Don't forward 2031 to
|
||||
* panes until a response is received.
|
||||
|
||||
51
tmux.1
51
tmux.1
@@ -4571,6 +4571,57 @@ where the number is a hexadecimal number, or a range of the form
|
||||
Give the command to pipe to if the
|
||||
.Ic copy\-pipe
|
||||
copy mode command is used without arguments.
|
||||
.It Xo Ic theme
|
||||
.Op Ic detect | terminal | light | dark
|
||||
.Xc
|
||||
Whether tmux should use the detected client theme
|
||||
.Pq Ic detect ,
|
||||
use terminal ANSI colours
|
||||
.Pq Ic terminal ,
|
||||
or force the light or dark theme.
|
||||
.It Xo Ic dark\-theme\-black ,
|
||||
.Ic dark\-theme\-white ,
|
||||
.Ic dark\-theme\-light\-grey ,
|
||||
.Ic dark\-theme\-dark\-grey ,
|
||||
.Ic dark\-theme\-green ,
|
||||
.Ic dark\-theme\-yellow ,
|
||||
.Ic dark\-theme\-red ,
|
||||
.Ic dark\-theme\-blue ,
|
||||
.Ic dark\-theme\-cyan ,
|
||||
.Ic dark\-theme\-magenta ,
|
||||
.Ic light\-theme\-black ,
|
||||
.Ic light\-theme\-white ,
|
||||
.Ic light\-theme\-light\-grey ,
|
||||
.Ic light\-theme\-dark\-grey ,
|
||||
.Ic light\-theme\-green ,
|
||||
.Ic light\-theme\-yellow ,
|
||||
.Ic light\-theme\-red ,
|
||||
.Ic light\-theme\-blue ,
|
||||
.Ic light\-theme\-cyan
|
||||
.No and Ic light\-theme\-magenta Ar colour
|
||||
.Xc
|
||||
Set the theme colours.
|
||||
These are the named colours
|
||||
.Ic themeblack ,
|
||||
.Ic themewhite ,
|
||||
.Ic themelightgrey ,
|
||||
.Ic themedarkgrey ,
|
||||
.Ic themegreen ,
|
||||
.Ic themeyellow ,
|
||||
.Ic themered ,
|
||||
.Ic themeblue ,
|
||||
.Ic themecyan
|
||||
and
|
||||
.Ic thememagenta
|
||||
which may be used in styles and elsewhere a
|
||||
.Ar colour
|
||||
is accepted.
|
||||
The
|
||||
.Ic dark\-theme\-*
|
||||
set is used when the client reports a dark background and the
|
||||
.Ic light\-theme\-*
|
||||
set when it reports a light background;
|
||||
an unknown background is treated as dark.
|
||||
.It Ic default\-client\-command Ar command
|
||||
Set the default command to run when tmux is called without a command.
|
||||
The default is
|
||||
|
||||
21
tmux.h
21
tmux.h
@@ -728,10 +728,26 @@ enum hanguljamo_state {
|
||||
/* Colour flags. */
|
||||
#define COLOUR_FLAG_256 0x01000000
|
||||
#define COLOUR_FLAG_RGB 0x02000000
|
||||
#define COLOUR_FLAG_THEME 0x04000000
|
||||
|
||||
/* Special colours. */
|
||||
#define COLOUR_DEFAULT(c) ((c) == 8 || (c) == 9)
|
||||
|
||||
/* Theme colours. */
|
||||
enum colour_theme {
|
||||
COLOUR_THEME_BLACK,
|
||||
COLOUR_THEME_WHITE,
|
||||
COLOUR_THEME_LIGHT_GREY,
|
||||
COLOUR_THEME_DARK_GREY,
|
||||
COLOUR_THEME_GREEN,
|
||||
COLOUR_THEME_YELLOW,
|
||||
COLOUR_THEME_RED,
|
||||
COLOUR_THEME_BLUE,
|
||||
COLOUR_THEME_CYAN,
|
||||
COLOUR_THEME_MAGENTA
|
||||
};
|
||||
#define COLOUR_THEME_COUNT 10
|
||||
|
||||
/* Replacement palette. */
|
||||
struct colour_palette {
|
||||
int fg;
|
||||
@@ -2219,6 +2235,8 @@ struct client {
|
||||
|
||||
int references;
|
||||
|
||||
int theme_colours[COLOUR_THEME_COUNT];
|
||||
|
||||
void *pan_window;
|
||||
u_int pan_ox;
|
||||
u_int pan_oy;
|
||||
@@ -3113,6 +3131,7 @@ void server_client_print(struct client *, int, struct evbuffer *);
|
||||
|
||||
/* server-fn.c */
|
||||
void server_redraw_client(struct client *);
|
||||
void server_client_update_theme_colours(struct client *);
|
||||
void server_status_client(struct client *);
|
||||
void server_redraw_session(struct session *);
|
||||
void server_redraw_session_group(struct session *);
|
||||
@@ -3226,6 +3245,8 @@ int colour_dim(int, u_int);
|
||||
const char *colour_tostring(int);
|
||||
enum client_theme colour_totheme(int);
|
||||
int colour_fromstring(const char *);
|
||||
const char *colour_theme_option(u_int, enum client_theme);
|
||||
int colour_theme_terminal_colour(u_int);
|
||||
int colour_256toRGB(int);
|
||||
int colour_256to16(int);
|
||||
int colour_byname(const char *);
|
||||
|
||||
29
tty.c
29
tty.c
@@ -51,6 +51,7 @@ static void tty_check_bg(struct tty *, struct colour_palette *,
|
||||
struct grid_cell *);
|
||||
static void tty_check_us(struct tty *, struct colour_palette *,
|
||||
struct grid_cell *);
|
||||
static int tty_map_theme_colour(struct tty *, int);
|
||||
static void tty_colours_fg(struct tty *, const struct grid_cell *);
|
||||
static void tty_colours_bg(struct tty *, const struct grid_cell *);
|
||||
static void tty_colours_us(struct tty *, const struct grid_cell *);
|
||||
@@ -2517,6 +2518,9 @@ tty_attributes(struct tty *tty, const struct grid_cell *gc,
|
||||
gc2.bg = changed;
|
||||
}
|
||||
}
|
||||
gc2.fg = tty_map_theme_colour(tty, gc2.fg);
|
||||
gc2.bg = tty_map_theme_colour(tty, gc2.bg);
|
||||
gc2.us = tty_map_theme_colour(tty, gc2.us);
|
||||
if (style_ctx->dim != 0) {
|
||||
gc2.fg = tty_dim_default_colour(tty, gc2.fg, 1);
|
||||
gc2.bg = tty_dim_default_colour(tty, gc2.bg, 0);
|
||||
@@ -2666,6 +2670,28 @@ tty_colours(struct tty *tty, const struct grid_cell *gc)
|
||||
tty_colours_us(tty, gc);
|
||||
}
|
||||
|
||||
static int
|
||||
tty_map_theme_colour(struct tty *tty, int colour)
|
||||
{
|
||||
struct client *c;
|
||||
u_int n;
|
||||
int m;
|
||||
|
||||
if (~colour & COLOUR_FLAG_THEME)
|
||||
return (colour);
|
||||
|
||||
n = colour & 0xff;
|
||||
if (n >= COLOUR_THEME_COUNT)
|
||||
return (8);
|
||||
if (tty == NULL || (c = tty->client) == NULL)
|
||||
return (8);
|
||||
|
||||
m = c->theme_colours[n];
|
||||
if (m == -1 || (m & COLOUR_FLAG_THEME))
|
||||
return (8);
|
||||
return (m);
|
||||
}
|
||||
|
||||
static void
|
||||
tty_check_fg(struct tty *tty, struct colour_palette *palette,
|
||||
struct grid_cell *gc)
|
||||
@@ -2688,6 +2714,7 @@ tty_check_fg(struct tty *tty, struct colour_palette *palette,
|
||||
if ((c = colour_palette_get(palette, c)) != -1)
|
||||
gc->fg = c;
|
||||
}
|
||||
gc->fg = tty_map_theme_colour(tty, gc->fg);
|
||||
|
||||
/* Is this a 24-bit colour? */
|
||||
if (gc->fg & COLOUR_FLAG_RGB) {
|
||||
@@ -2748,6 +2775,7 @@ tty_check_bg(struct tty *tty, struct colour_palette *palette,
|
||||
if ((c = colour_palette_get(palette, gc->bg)) != -1)
|
||||
gc->bg = c;
|
||||
}
|
||||
gc->bg = tty_map_theme_colour(tty, gc->bg);
|
||||
|
||||
/* Is this a 24-bit colour? */
|
||||
if (gc->bg & COLOUR_FLAG_RGB) {
|
||||
@@ -2798,6 +2826,7 @@ tty_check_us(__unused struct tty *tty, struct colour_palette *palette,
|
||||
if ((c = colour_palette_get(palette, gc->us)) != -1)
|
||||
gc->us = c;
|
||||
}
|
||||
gc->us = tty_map_theme_colour(tty, gc->us);
|
||||
|
||||
/* Convert underscore colour if only RGB can be supported. */
|
||||
if (!tty_term_has(tty->term, TTYC_SETULC1)) {
|
||||
|
||||
Reference in New Issue
Block a user