diff options
| author | Oliver Kiddle <opk@zsh.org> | 2025-11-10 21:02:20 +0100 |
|---|---|---|
| committer | Oliver Kiddle <opk@zsh.org> | 2025-11-10 21:02:20 +0100 |
| commit | 37acbc87ad76699679ccb8b567effac9177c33de (patch) | |
| tree | 0d7cc02860e91a370c7a2ea595e1f647526df831 | |
| parent | 54057: enable assignment through named reference to change type of the referent (diff) | |
| download | zsh-37acbc87ad76699679ccb8b567effac9177c33de.tar zsh-37acbc87ad76699679ccb8b567effac9177c33de.tar.gz zsh-37acbc87ad76699679ccb8b567effac9177c33de.tar.bz2 zsh-37acbc87ad76699679ccb8b567effac9177c33de.tar.lz zsh-37acbc87ad76699679ccb8b567effac9177c33de.tar.xz zsh-37acbc87ad76699679ccb8b567effac9177c33de.tar.zst zsh-37acbc87ad76699679ccb8b567effac9177c33de.zip | |
53372, 53375: query terminal properties on ZLE startup
| -rw-r--r-- | ChangeLog | 6 | ||||
| -rw-r--r-- | Doc/Zsh/params.yo | 71 | ||||
| -rw-r--r-- | Src/Zle/termquery.c | 510 | ||||
| -rw-r--r-- | Src/Zle/zle.mdd | 2 | ||||
| -rw-r--r-- | Src/Zle/zle_main.c | 4 | ||||
| -rw-r--r-- | Test/X04zlehighlight.ztst | 1 | ||||
| -rw-r--r-- | Test/X06termquery.ztst | 89 |
7 files changed, 682 insertions, 1 deletions
@@ -1,3 +1,9 @@ +2025-11-10 Oliver Kiddle <opk@zsh.org> + + * 53372, 53375: Doc/Zsh/params.yo, Src/Zle/termquery.c, + Src/Zle/zle.mdd, Src/Zle/zle_main.c, Test/X04zlehighlight.ztst, + Test/X06termquery.ztst: query terminal properties on ZLE startup + 2025-11-09 Bart Schaefer <schaefer@zsh.org> * Philippe: 54057: Src/params.c, Src/zsh.h, Test/K01nameref.ztst: diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index dd4519622..90ed6e5d1 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -965,6 +965,40 @@ there is a block of reserved or unused signal numbers before the POSIX real-time signals so the array index can't be used as an accurate indicator of their signal number. Use, for example, tt(kill -l SIGRTMIN) instead. ) +vindex(.term.bg) +item(tt(.term.bg))( +The background color of the terminal if the terminal supports the +necessary interface for retrieving this information. + +See also the tt(.term.extensions) parameter. +) +vindex(.term.fg) +item(tt(.term.fg))( +Like tt(.term.bg) but for the foreground color. +) +vindex(.term.id) +item(tt(.term.id))( +Like the tt(TERM) parameter, this identifies the terminal but is obtained by +querying the terminal. Many terminals name a different common terminal in +tt(TERM) that they then emulate, often imperfectly. This allows them to work +without the need to distribute updates to terminal capability databases. The +more accurate identification in this parameter may be useful when configuring +aspects of the shell differently for specific terminals. + +See also the tt(.term.extensions) parameter. +) +vindex(.term.version) +item(tt(.term.version))( +The version number of the terminal application, set in conjunction with +tt(.term.id). +) +vindex(.term.mode) +item(tt(.term.mode))( +Either tt(light) or tt(dark). In cases where the terminal background color is +detected and set in tt(.term.bg), this is set to provide a basic indication of +how light that color is. This may help with configuring readable color +combinations. +) vindex(TRY_BLOCK_ERROR) item(tt(TRY_BLOCK_ERROR) <S>)( In an tt(always) block, indicates whether the preceding list of code @@ -1695,6 +1729,43 @@ causes the shell to reinitialise the terminal, making the workaround `tt(TERM=$TERM)' unnecessary. Note that unlike other colon-separated arrays this is not tied to a zsh array. ) +vindex(.term.extensions) +item(tt(.term.extensions))( +An array containing a list of extension features of the terminal to be enabled +or disabled (prefixed with `tt(-)'). When ZLE starts, it will add entries for +features that were auto-detected. This auto-detection uses extensions itself, +all named with a `tt(query)' prefix. As these are used when ZLE starts they +would need to be disabled early in the startup files if they are to be +disabled. A value of `tt(-query)' will disable all terminal queries on +startup. Extensions can be any of the following, where the marks `<D>' and +`<E>' indicate whether they are disabled or enabled by default: + +startitem() +item(tt(query-bg) <E>)( +Query the terminal background color which is used for tt(.term.bg) and +tt(.term.mode). +) +item(tt(query-fg) <E>)( +Query the terminal foreground color which is used for tt(.term.fg). +) +item(tt(query-id) <E>)( +Query the terminal identification which is used for tt(.term.id) and +tt(.term.version). +) +xitem(tt(modkeys-kitty) <D>) +item(tt(query-modkeys-kitty) <E>)( +Support for the kitty keyboard handling protocol which enables reporting of a +wider range of key combinations and resolves problems with ambiguous key +sequences. Currently there is only support for detecting whether the terminal +supports this feature. +) +xitem(tt(truecolor) <E>) +item(tt(query-truecolor) <E>)( +Support for 24-bit truecolor escape sequences. Auto-detection also tries +termcap and the tt(COLORTERM) environment variable. +) +enditem() +) vindex(TIMEFMT) item(tt(TIMEFMT))( The format of process time reports with the tt(time) keyword. diff --git a/Src/Zle/termquery.c b/Src/Zle/termquery.c new file mode 100644 index 000000000..2488319e2 --- /dev/null +++ b/Src/Zle/termquery.c @@ -0,0 +1,510 @@ +/* + * termquery.c - terminal feature probes + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 2025 Oliver Kiddle + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and to distribute modified versions of this software for any + * purpose, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * In no event shall Oliver Kiddle or the Zsh Development Group be liable + * to any party for direct, indirect, special, incidental, or consequential + * damages arising out of the use of this software and its documentation, + * even if Oliver Kiddle and the Zsh Development Group have been advised of + * the possibility of such damage. + * + * Oliver Kiddle and the Zsh Development Group specifically disclaim any + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose. The software + * provided hereunder is on an "as is" basis, and Oliver Kiddle and the + * Zsh Development Group have no obligation to provide maintenance, + * support, updates, enhancements, or modifications. + * + */ + +#include "zle.mdh" +#include "termquery.pro" + +/* On a 9600 serial link, 0.2 seconds is about the minimum to safely work. + * 0.5s should be generous enough. We only incur this delay on a terminal + * that doesn't respond to device attributes requests. */ +#define TIMEOUT -51L + +#define TAG (1 << 7) +#define SEQ (TAG | (1 << 6)) + +/* tags */ +#define T_BEGIN 0x80 /* group start */ +#define T_END 0x81 /* group end */ +#define T_OR 0x82 /* alternation (within group) */ +#define T_REPEAT 0x83 /* repeat preceding block */ +#define T_NUM 0x84 /* decimal number, defaults to 0 if absent */ +#define T_HEX 0x85 /* hexadecimal digit used as part of a number */ +#define T_HEXCH 0x86 /* hexadecimal digit that is thrown away */ +#define T_WILDCARD 0x87 /* match any character */ +#define T_RECORD 0x88 /* start text capture */ +#define T_CAPTURE 0x89 /* end text capture */ +#define T_DROP 0x91 /* drop input + restart without matching a sequence */ +#define T_CONTINUE 0x92 /* when matching don't go back to first state */ +#define T_NEXT 0x94 /* advance to next stored number */ + +typedef const unsigned char seqstate_t; + +/* macros for entries in the parse state table */ +#define OR "\x82" +#define NUM "\x84" +#define HEX "\x85" +#define HEXCH "\x86" +#define WILDCARD "\x87" +#define RECORD "\x88" +#define CAPTURE "\x89" +#define EITHER(group) "\x80" group "\x81" +#define OPT(opt) EITHER( opt OR EITHER() ) +#define REPEAT(r) EITHER( r ) "\x83" /* would use OPT() but done in C code */ +/* Sequence completion tags and other actions need to precede the state + * where the final character is matched. This macro just reverses the + * order so that they come in a more logical order. */ +#define MATCH(ch, arg) arg ch +#define DROP "\x91" +#define CONTINUE "\x92" +#define NEXT "\x94" +#define DA "\xc0" +#define COLOR "\xc1" +#define KITTY "\xc2" +#define TINFO "\xc3" +#define XTID "\xc4" +#define XTVER "\xc5" + +/* Deterministic finite state automata for parsing terminal response sequences. + * - alternatives decided by the first character (no back-tracking) + * - matching literal characters is 7-bit ASCII only + */ +#define QUERY_STATES \ + "\033" \ + EITHER( /* default terminal colours */ \ + "]1" NUM ";" \ + EITHER( "rgb:" \ + HEX OPT( HEX ) OPT( HEXCH HEXCH ) "/" \ + HEX OPT( HEX ) OPT( HEXCH HEXCH ) "/" \ + HEX OPT( HEX ) OPT( HEXCH HEXCH ) \ + OR "#" \ + HEX HEX NEXT HEX HEX NEXT HEX HEX ) \ + EITHER( \ + MATCH("\033", COLOR CONTINUE ) \ + MATCH("\\", DROP) /* urxvt 9.31 has bug: it omits the backslash */ \ + OR MATCH("\007", COLOR ) ) \ + OR "P" /* DCS */ \ + EITHER( /* terminal name and version */ \ + ">|" RECORD \ + REPEAT( \ + CAPTURE EITHER( MATCH("(", XTID CONTINUE) \ + OR MATCH(" ", XTID CONTINUE) ) RECORD \ + OR \ + CAPTURE OPT( ")" ) "\033" MATCH( "\\", XTVER ) \ + OR \ + WILDCARD \ + ) \ + OR /* 24-bit colour support */ \ + EITHER( \ + "0+r" OPT( "524742" ) /* mlterm responds without numbers */ \ + "\033" MATCH("\\", DROP) /* kitty does 24-bit but 0 => no */ \ + OR "1+r524742=" REPEAT( HEXCH HEXCH ) /* hex encoded bytes */ \ + "\033" MATCH("\\", TINFO) )) /* any value => truecolor */ \ + OR /* keyboard protocol and device attributes */ \ + "[?" \ + REPEAT( NUM \ + EITHER( ";" \ + OR MATCH("u", KITTY ) \ + OR MATCH("c", DA) ))) + +static char *EXTVAR = ".term.extensions"; +static char *IDVAR = ".term.id"; +static char *VERVAR = ".term.version"; +static char *BGVAR = ".term.bg"; +static char *FGVAR = ".term.fg"; +static char *MODEVAR = ".term.mode"; + +/* Query sequences + * using ESC\\ as ST instead of BEL because the bell was emitted on + * old xterm. */ + +/* Terminal default colors. Probably best that these are queried first + * because tmux will need to pass these on. */ +#define TQ_BGCOLOR "\033]11;?\033\\" +#define TQ_FGCOLOR "\033]10;?\033\\" + +/* Kitty / fixterms keyboard protocol which allows wider support for keys + * and modifiers. This clears the screen in terminology. */ +#define TQ_KITTYKB "\033[?u" + +/* Query for 24-bit color support, This is an XTTERMCAP sequence which with + * some terminals allows terminfo entries to be retrieved. */ +#define TQ_RGB "\033P+q524742\033\\" + +/* Query terminal name and version which is useful with terminals that + * lie in $TERM so that they work without terminfo entries. */ +#define TQ_XTVERSION "\033[>0q" + +/* Device attributes, Response isn't especially interesting but we get a + * response from most terminals so by putting this last we can short-circuit + * the time delay waiting for less well-supported responses that might never + * come. + * Following two spaces + CR works to clear fragments of sequences that + * appeared. GNU screen is an example terminal that needs this. */ +#define TQ_DA "\033[c \r" + +static seqstate_t* +find_branch(seqstate_t* pos) +{ + int nested = 0; + seqstate_t* cur = pos + 1; + + for (; *cur && (nested || (*cur != T_END && *cur != T_OR)); cur++) { + if (*cur == T_BEGIN) + nested++; + else if (*cur == T_END) + nested--; + } + return cur; +} + +static seqstate_t* +find_matching(seqstate_t* pos, int direction) +{ + int nested = 1; + seqstate_t* cur = pos + direction; + + for (; *cur && nested; cur += direction) { + if (*cur == T_BEGIN && !(nested += direction)) { + break; /* going backward, stop on begin */ + } else if (*cur == T_END) + nested -= direction; + } + return cur; +} + +static void +probe_terminal(const char *tquery, seqstate_t *states, + void (*handle_seq) (int seq, int *numbers, int len, + char *capture, int clen)) +{ + size_t blen = 256, nlen = 16; + char *buf = zhalloc(blen); + char *start = buf, *current = buf, *illgotten = buf; + size_t record = 0, capture = 0; + int *numbers = hcalloc(nlen * sizeof(int)); + int *num = numbers; + int finish = 0, number = 0; + int ch; + struct ttyinfo ti; + + seqstate_t *curstate = states; + + gettyinfo(&ti); +#ifdef HAS_TIO + ti.tio.c_lflag &= (~ECHO & ~ICANON & ~ISIG); + ti.tio.c_iflag &= ~ICRNL; +#else + ti.sgttyb.sg_flags &= ~ECHO; + ti.sgttyb.sg_flags |= CBREAK; +#endif + settyinfo(&ti); + + fputs(tquery, shout); + fflush(shout); + + while (!finish && *curstate) { + int consumed = 0; /* whether an input token has been matched */ + int branches = 1; /* count of untried paths encountered */ + int triedstart = curstate == states; /* current char tried at start */ + unsigned char action = 0, sequence = 0; + + if (illgotten < current) { + ch = *illgotten++; + } else { + if (current == buf + blen) { + current = hrealloc(buf, blen, blen * 2); + illgotten = current + (illgotten - buf); + start = current + (start - buf); + buf = current; + current = buf + blen; + memset(current, 0, blen); + blen *= 2; + } + if ((ch = getbyte(TIMEOUT, 0, 1)) == EOF) + break; + *current++ = ch; + illgotten = current; + } + + while (!consumed && branches >= 1 && *curstate) { + int increment = 0, base = 1, tryhere = 0; + + do { + switch (*curstate) { + case T_BEGIN: + branches++; + curstate++; + break; + case T_END: + branches--; + sequence = action = 0; + curstate++; + break; + case T_OR: + curstate = find_matching(curstate, 1); + break; + case T_REPEAT: + sequence = action = 0; + if (branches > 1) { + branches--; + curstate++; + } else { + branches++; + curstate = find_matching(curstate - 1, -1); + } + break; + case T_NUM: + if (!(tryhere = (ch >= '0' && ch <= '9'))) + curstate++; + break; + case T_RECORD: + record = current - buf - 1; + curstate++; + break; + case T_CAPTURE: + capture = current - buf - 1; + curstate++; + break; + case T_DROP: + case T_CONTINUE: + case T_NEXT: + action |= *curstate; + curstate++; + break; + default: + if ((*curstate & SEQ) == SEQ) { + sequence = *curstate; + curstate++; + } else { + tryhere = 1; + } + } + } while (!tryhere); + + switch (*curstate) { + case T_HEX: + if (ch >= '0' && ch <= '9') { + increment = ch - '0'; + } else if (ch >= 'a' && ch <= 'f') { + increment = ch - 'a' + 10; + } else if (ch >= 'A' && ch <= 'F') { + increment = ch - 'A' + 10; + } else + break; + consumed = number = 1; + base = 16; + if (action & 4) /* NEXT was used */ + ++num; + break; + case T_HEXCH: + consumed = (ch >= '0' && ch <= '9') || + (ch >= 'a' && ch <= 'f') || + (ch >= 'A' && ch <= 'F'); + if (consumed && number) { + ++num; + number = 0; + } + break; + case T_NUM: + if (ch >= '0' && ch <= '9') { + increment = ch - '0'; + base = 10; + consumed = number = 1; + curstate--; /* allow repetition */ + } + break; + case T_WILDCARD: + consumed = 1; + if (number) { + ++num; + number = 0; + } + break; + default: + if (!(*curstate & TAG) && (consumed = (*curstate == ch)) && + number) + { + ++num; + number = 0; + } + break; + } + if (num == numbers + nlen) { + numbers = hrealloc((char *) numbers, nlen * sizeof(int), + sizeof(int) * nlen * 2); + memset(numbers + nlen, 0, nlen * sizeof(int)); + num = numbers + nlen; /* restore relative position */; + nlen *= 2; + } + if (number) + *num = *num * base + increment; + + /* if it didn't match, move to the next OR */ + if (!consumed && branches > 1) { + sequence = action = 0; + for (; branches > 1; branches--) { + curstate = find_branch(curstate); + if (*curstate == T_OR) { + curstate++; + break; + /* repeated group can match zero times */ + } else if (curstate[1] == T_REPEAT) + break; + } + } + /* Retry character at the start if it is the only buffered + * character and was tried from a later state. */ + if (!consumed && branches <= 1) { + if (triedstart || start + 1 != current) + break; + branches = 1; + curstate = states; + triedstart = 1; + memset((num = numbers), 0, nlen * sizeof(int)); + sequence = action = number = 0; + } + } + + if (!consumed) { + illgotten = ++start; + curstate = states; /* return to first state */ + memset((num = numbers), 0, nlen * sizeof(int)); + number = 0; + } else { + if (sequence && !(finish = sequence == SEQ)) + handle_seq(sequence & ~SEQ, numbers, num - numbers, + buf + record, capture - record); + + if ((sequence || (action & 1)) && + (current = start) && /* drop input from sequence */ + (!(action & 2))) + { + curstate = states; + memset((num = numbers), 0, nlen * sizeof(int)); + number = 0; + } else { /* CONTINUE */ + while (*++curstate == T_END) + ; + } + } + } + + /* put back any type-ahead text */ + if (current > buf) + ungetbytes(buf, current - buf); + + settyinfo(&shttyinfo); +} + +static void +handle_color(int bg, int red, int green, int blue) +{ + char *colour; + + switch (bg) { + case 1: /* background color */ + /* scale by Rec.709 coefficients for lightness */ + setsparam(MODEVAR, ztrdup( + 0.2126f * red + 0.7152f * green + 0.0722f * blue <= 127 ? + "dark" : "light")); + /* fall-through */ + case 0: + colour = zalloc(8); + sprintf(colour, "#%02x%02x%02x", red, green, blue); + setsparam(bg ? BGVAR : FGVAR, colour); + break; + default: break; + } +} + +/* roughly corresponding feature names */ +static const char *features[] = + { "bg", "fg", "modkeys-kitty", "truecolor", "id" }; +static const char *queries[] = + { TQ_BGCOLOR, TQ_FGCOLOR, TQ_KITTYKB, TQ_RGB, TQ_XTVERSION, TQ_DA }; + +static void +handle_query(int sequence, int *numbers, int len, char *capture, int clen) +{ + char **feat; + + switch (sequence) { + case 1: /* default colour */ + if (len == 4) + handle_color(numbers[0], numbers[1], numbers[2], numbers[3]); + break; + case 2: /* kitty keyboard */ + feat = zshcalloc(2 * sizeof(char *)); + *feat = ztrdup(features[2]); + assignaparam(EXTVAR, feat, ASSPM_WARN|ASSPM_AUGMENT); + break; + case 3: /* truecolor */ + feat = zshcalloc(2 * sizeof(char *)); + *feat = ztrdup(features[3]); + assignaparam(EXTVAR, feat, ASSPM_WARN|ASSPM_AUGMENT); + break; + case 4: /* id */ + setsparam(IDVAR, ztrduppfx(capture, clen)); + break; + case 5: /* version */ + setsparam(VERVAR, ztrduppfx(capture, clen)); + break; + } +} + +/**/ +void +query_terminal(void) { + char tquery[sizeof(TQ_BGCOLOR TQ_FGCOLOR TQ_KITTYKB TQ_RGB TQ_XTVERSION TQ_DA)]; + char *tqend = tquery; + static seqstate_t states[] = QUERY_STATES; + char **f, **flist = getaparam(EXTVAR); + size_t i; + + for (f = flist; f && *f; f++) + if (!strcmp(*f, "-query")) + return; /* disable all queries */ + + for (i=0; i < sizeof(queries)/sizeof(*queries); i++) { + int last = i >= sizeof(features)/sizeof(*features); + int found = (last && tqend == tquery); + char *cterm; + + /* skip if the query or corresponding feature is already in the list */ + for (f = flist; !last && !found && f && *f; f++) + found = !strcmp(*f + (**f == '-'), features[i]) || + (!strncmp(*f, "-query-", 7) && !strcmp(*f + 7, features[i])); + if (found) + continue; + /* if termcap indicates 24-bit color, assume support - even + * though this is only based on the initial $TERM + * failing that, check $COLORTERM */ + if (i == 3 && (tccolours == 1 << 24 || + ((cterm = getsparam("COLORTERM")) && + (!strcmp(cterm, "truecolor") || + !strcmp(cterm, "24bit"))))) + handle_query(3, 0, 0, 0, 0); + else + struncpy(&tqend, (char *) queries[i], /* collate escape sequences */ + sizeof(tquery) - (tqend - tquery)); + } + + if (tqend != tquery) /* unless nothing left after filtering */ + probe_terminal(tquery, states, &handle_query); +} diff --git a/Src/Zle/zle.mdd b/Src/Zle/zle.mdd index dd69eff2c..c7c914712 100644 --- a/Src/Zle/zle.mdd +++ b/Src/Zle/zle.mdd @@ -8,7 +8,7 @@ autofeatures="b:bindkey b:vared b:zle" objects="zle_bindings.o zle_hist.o zle_keymap.o zle_main.o \ zle_misc.o zle_move.o zle_params.o zle_refresh.o \ zle_thingy.o zle_tricky.o zle_utils.o zle_vi.o zle_word.o \ -textobjects.o" +termquery.o textobjects.o" headers="zle.h zle_things.h" diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index ab0b51374..99ee3c804 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -2239,6 +2239,10 @@ setup_(UNUSED(Module m)) comprecursive = 0; rdstrs = NULL; + /* detect terminal color and features */ + if (shout) + query_terminal(); + /* initialise the keymap system */ init_keymaps(); diff --git a/Test/X04zlehighlight.ztst b/Test/X04zlehighlight.ztst index 87a59fde5..723bb05d7 100644 --- a/Test/X04zlehighlight.ztst +++ b/Test/X04zlehighlight.ztst @@ -12,6 +12,7 @@ zpty zsh "${(q)ZTST_testdir}/../Src/zsh -fiV +Z" zpty -w zsh "module_path=( ${(j< >)${(@q-)module_path}} \$module_path )" zpty -w zsh 'zle_highlight=( fg_start_code:"CDE|3" fg_end_code:"|" bg_start_code:"BCDE|4" bg_end_code:"|" )' + zpty -w zsh '.term.extensions=( -query )' } zpty_input() { zpty ${${(M)2:#nonl}:+-n} -w zsh "$1" diff --git a/Test/X06termquery.ztst b/Test/X06termquery.ztst new file mode 100644 index 000000000..52f39ddf1 --- /dev/null +++ b/Test/X06termquery.ztst @@ -0,0 +1,89 @@ +# Tests for handling terminal responses to escape sequences +%prep + + if zmodload zsh/zpty 2> /dev/null; then + termresp() { + setopt localoptions extendedglob + export PS1= PS2= COLORTERM= TERM= + typeset +x -m .term.\* + zpty -d + zpty zsh "${(q)ZTST_testdir}/../Src/zsh -fiV +Z" + zpty -w zsh "module_path=( ${(j< >)${(@q-)module_path}} \$module_path )" + zpty -w zsh "setopt zle" + zpty -r zsh REPLY $'\e*\r' + zpty -n -w zsh "$1" + zpty -w zsh "typeset -p -m .term.\*" + zpty -w zsh 'exit' + { zpty -r zsh } | tr -d '\015' | grep -v '^ ' + zpty -d + } + else + ZTST_unimplemented='the zsh/zpty module is not available' + fi + +%test + + termresp $'\e]11;rgb:ffff/ffff/dddd\e\\\e]10;rgb:0000/0000/0000\e\\\e[?0u\eP1+r524742=38\e\\\eP>|foot(1.20.2)\e\\\e[?62;4;22;28c' +0:foot response to terminal queries +>typeset .term.id=foot +>typeset .term.fg='#000000' +>typeset .term.bg='#ffffdd' +>typeset .term.version=1.20.2 +>typeset .term.mode=light +>typeset -a .term.extensions=( modkeys-kitty truecolor ) + + termresp $'\e]11;rgb:0/0/0\e\\\e]10;rgb:ff/ff/ff\e\\\eP>|Wayst(0.0.0)\e\\\e[?63;1;4c' +0:wayst response to terminal queries (shorter colour sequences) +>typeset .term.id=Wayst +>typeset .term.fg='#ffffff' +>typeset .term.bg='#000000' +>typeset .term.version=0.0.0 +>typeset .term.mode=dark + + termresp $'\e]11;rgb:0000/0000/0000\e\\\e]10;rgb:b2b2/b2b2/b2b2\e\\\eP1+r524742=382F382F38\e\\\eP>|WezTerm 20240203-110809-5046fc22\e\\\e[?65;4;6;18;22c' +0:WezTerm response to terminal queries (space separates version and longer RGB response) +>typeset .term.id=WezTerm +>typeset .term.fg='#b2b2b2' +>typeset .term.bg='#000000' +>typeset .term.version=20240203-110809-5046fc22 +>typeset .term.mode=dark +>typeset -a .term.extensions=( truecolor ) + + termresp $'\e]11;rgb:9600/8700/7900\e\e]10;rgb:0000/0000/0000\e\e[?1;2c' +0:urxvt response to terminal queries (bug in end of colour sequences) +>typeset .term.fg='#000000' +>typeset .term.bg='#968779' +>typeset .term.mode=light + + termresp $'\e]11;rgb:0000/0000/0000\e\\\e]10;rgb:dddd/dddd/dddd\e\\\e[?0u\eP0+r524742\e\\\eP>|kitty(0.36.4)\e\\\e[?62;c' +0:kitty response to terminal queries (responds with error to RGB request) +>typeset .term.id=kitty +>typeset .term.fg='#dddddd' +>typeset .term.bg='#000000' +>typeset .term.version=0.36.4 +>typeset .term.mode=dark +>typeset -a .term.extensions=( modkeys-kitty ) + + termresp $'\e]11;rgb:0000/ffff/8c8c\e\\\e]10;rgb:0000/0000/0000\e\\\eP1+r524742=38\e\\\eP>|XTerm(396)\e\\\e[?64;1;2;6;9;15;16;17;18;21;22;28c' +0:xterm response to terminal queries +>typeset .term.id=XTerm +>typeset .term.fg='#000000' +>typeset .term.bg='#00ff8c' +>typeset .term.version=396 +>typeset .term.mode=light +>typeset -a .term.extensions=( truecolor ) + + termresp $'echo type\e]11;rgb:0/0/0\aah\e]10;rgb:A/B/C\aea\e[?0u\eP0+r\e\\d\n\e[?0;c' +0:type-ahead +>typeahead +>typeset .term.fg='#0a0b0c' +>typeset .term.bg='#000000' +>typeset .term.mode=dark +>typeset -a .term.extensions=( modkeys-kitty ) + + termresp '' +0:no response - timeout + +%clean + + zmodload -ui zsh/zpty |
