diff --git a/cmd-list-keys.c b/cmd-list-keys.c index 0817afd04..d34c15a83 100644 --- a/cmd-list-keys.c +++ b/cmd-list-keys.c @@ -251,7 +251,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item) n = 1; ft = format_create(cmdq_get_client(item), item, FORMAT_NONE, 0); - format_defaults(ft, NULL, NULL, NULL, NULL); + format_defaults(ft, tc, NULL, NULL, NULL); format_add(ft, "notes_only", "%d", notes_only); format_add(ft, "key_has_repeat", "%d", key_bindings_has_repeat(l, n)); format_add(ft, "key_string_width", "%u", cmd_list_keys_get_width(l, n)); diff --git a/colour.c b/colour.c index 0db080fc4..b37882a88 100644 --- a/colour.c +++ b/colour.c @@ -290,6 +290,58 @@ colour_tostring(int c) return ("invalid"); } +/* Convert colour to an SGR escape sequence. */ +const char * +colour_toescape(struct client *c, int colour, int bg) +{ + static char s[32]; + u_char r, g, b; + int n, flags = (TERM_256COLOURS|TERM_RGBCOLOURS); + u_int o = (bg ? 40 : 30); + + if (c != NULL && (c->tty.flags & TTY_OPENED) && c->tty.term != NULL) + flags = c->tty.term->flags; + + if (colour & COLOUR_FLAG_THEME) { + n = colour & 0xff; + if (c != NULL && (u_int)n < COLOUR_THEME_COUNT) + colour = c->theme_colours[n]; + else + colour = colour_theme_terminal_colour(n); + } + + if (colour == 8 || colour == 9) { + xsnprintf(s, sizeof s, "\033[%dm", o + 9); + return (s); + } + + if ((~flags & TERM_RGBCOLOURS) & (colour & COLOUR_FLAG_RGB)) { + colour_split_rgb(colour, &r, &g, &b); + colour = colour_find_rgb(r, g, b); + } + if ((~flags & TERM_256COLOURS) & (colour & COLOUR_FLAG_256)) + colour = colour_256to16(colour); + + if (colour & COLOUR_FLAG_RGB) { + colour_split_rgb(colour, &r, &g, &b); + xsnprintf(s, sizeof s, "\033[%d;2;%u;%u;%um", o + 8, r, g, b); + return (s); + } + if (colour & COLOUR_FLAG_256) { + xsnprintf(s, sizeof s, "\033[%d;5;%um", o + 8, colour & 0xff); + return (s); + } + if (colour >= 0 && colour <= 7) { + xsnprintf(s, sizeof s, "\033[%dm", colour + o); + return (s); + } + if (colour >= 90 && colour <= 97) { + xsnprintf(s, sizeof s, "\033[%dm", colour + o - 30); + return (s); + } + return (NULL); +} + /* Convert background colour to theme. */ enum client_theme colour_totheme(int c) diff --git a/format.c b/format.c index 8d8dfec94..88ffaa0b8 100644 --- a/format.c +++ b/format.c @@ -121,6 +121,8 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2) #define FORMAT_CLIENT_TERMCAP 0x1000000 #define FORMAT_CLIENT_TERMFEAT 0x2000000 #define FORMAT_CLIENT_ENVIRON 0x4000000 +#define FORMAT_COLOUR_ESC_FG 0x8000000 +#define FORMAT_COLOUR_ESC_BG 0x10000000 /* Limit on recursion. */ #define FORMAT_LOOP_LIMIT 100 @@ -4472,7 +4474,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s, break; /* Check single character modifiers with no arguments. */ - if (strchr("labcdnwETSWPL!<>", cp[0]) != NULL && + if (strchr("labdnwETSWPL!<>", cp[0]) != NULL && format_is_end(cp[1])) { format_add_modifier(&list, count, cp, 1, NULL, 0); cp++; @@ -4494,7 +4496,7 @@ format_build_modifiers(struct format_expand_state *es, const char **s, } /* Now try single character with arguments. */ - if (strchr("ImCLNPSst=pReqW", cp[0]) == NULL) + if (strchr("ImCLNPSst=pReqWc", cp[0]) == NULL) break; c = cp[0]; @@ -5272,6 +5274,12 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, break; case 'c': modifiers |= FORMAT_COLOUR; + if (fm->argc < 1) + break; + if (strchr(fm->argv[0], 'f') != NULL) + modifiers |= FORMAT_COLOUR_ESC_FG; + if (strchr(fm->argv[0], 'b') != NULL) + modifiers |= FORMAT_COLOUR_ESC_BG; break; case 'd': modifiers |= FORMAT_DIRNAME; @@ -5470,11 +5478,28 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen, /* Is this a colour? */ if (modifiers & FORMAT_COLOUR) { new = format_expand1(es, copy); - c = colour_fromstring(new); - if (c == -1 || (c = colour_force_rgb(c)) == -1) - value = xstrdup(""); - else - xasprintf(&value, "%06x", c & 0xffffff); + if (modifiers & (FORMAT_COLOUR_ESC_FG|FORMAT_COLOUR_ESC_BG)) { + if (strcasecmp(new, "none") == 0) + value = xstrdup("\033[0m"); + else if ((c = colour_fromstring(new)) == -1) + value = xstrdup(""); + else { + if (modifiers & FORMAT_COLOUR_ESC_BG) + cp = colour_toescape(ft->c, c, 1); + else + cp = colour_toescape(ft->c, c, 0); + if (cp == NULL) + value = xstrdup(""); + else + value = xstrdup(cp); + } + } else { + c = colour_fromstring(new); + if (c == -1 || (c = colour_force_rgb(c)) == -1) + value = xstrdup(""); + else + xasprintf(&value, "%06x", c & 0xffffff); + } free(new); goto done; } diff --git a/tmux.1 b/tmux.1 index f04c09c32..3df357e1a 100644 --- a/tmux.1 +++ b/tmux.1 @@ -6698,6 +6698,12 @@ results in replaces a .Nm colour by its six-digit hexadecimal RGB value. +If an argument of +.Ql f +or +.Ql b +is given, it will instead produce the SGR escape sequence to set the foreground +or background colour respectively. .Pp A limit may be placed on the length of the resultant string by prefixing it by an diff --git a/tmux.h b/tmux.h index c9facd44c..af1b59793 100644 --- a/tmux.h +++ b/tmux.h @@ -3250,6 +3250,7 @@ void colour_split_rgb(int, u_char *, u_char *, u_char *); int colour_force_rgb(int); int colour_dim(int, u_int); const char *colour_tostring(int); +const char *colour_toescape(struct client *, int, int); enum client_theme colour_totheme(int); int colour_fromstring(const char *); const char *colour_theme_option(u_int, enum client_theme);