From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-1.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from primenet.com.au (ns1.primenet.com.au [203.24.36.2]) by inbox.vuxu.org (OpenSMTPD) with ESMTP id 10f15e44 for ; Mon, 4 Feb 2019 21:21:55 +0000 (UTC) Received: (qmail 948 invoked by alias); 4 Feb 2019 21:21:32 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: List-Unsubscribe: X-Seq: 44040 Received: (qmail 8000 invoked by uid 1010); 4 Feb 2019 21:21:32 -0000 X-Qmail-Scanner-Diagnostics: from mail-wm1-f65.google.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.100.2/25112. spamassassin: 3.4.2. Clear:RC:0(209.85.128.65):SA:0(-2.0/5.0):. Processed in 3.105865 secs); 04 Feb 2019 21:21:32 -0000 X-Envelope-From: tamelingdaniel@gmail.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:subject:message-id:mail-followup-to:references :mime-version:content-disposition:in-reply-to; bh=FCEysOAjv35F/d5eqwgSNNeue8eACPvCCLVsyCTCUkc=; b=aJvJWDBEvtLB++fwx3Jz4MKp6iFlXaZcAned7BKesrea046/lY24LcQmkmkNyu1Ybp eJrce8g3d7M1Q5qSLgDkB3ezGbsvvZxqMlIAESazrwR0g1z/a1t375wtVNXF4fetmhBa OpY+ED+DrhNAwLQu5hldixtTzUjD2jYIXZCK+g0mIJ7rGFVIsrieUdGoK14vu3Z5Yh6z RobV8FSRremg07kkjDHPQNdAGD0PyO/72wf4rOXS199rl7g4FGMMZKzMRlu0gTYucwap L/U8Au5/KMbEYQWwX6m/rPv99gvRdMbuumj7DnaCypSP8kbcJG6hvxzqXisjfulOY+YK OGtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mail-followup-to :references:mime-version:content-disposition:in-reply-to; bh=FCEysOAjv35F/d5eqwgSNNeue8eACPvCCLVsyCTCUkc=; b=mdw71BeGpaU/vrItjBo8rNwaC4up/GSgwwDiGOivhQVQ7Y+6CCcHS3b9VBgJcAMurp +Euiac0lHu6u6c6YciqJrzsFRneb6UYmmI5XYjCq5RMkKphtkGw2oHW5kUIr/eb9ar4w UgCnvDK4IgcBTxUmQISS8r2hH6MUcNxAwGhPlywTakVUA8UYHxUisZzpM/V8jwgtmy/A RFvrT59NnyRsdiKxXKYz9r8E/7l1zUpYKK60qzEyAv55PtAEiSmj7t2LCH+bCgI3GNHr Iw1m0XtJ6PZ8Djzv2KD0WUVC/KbD3ttZQWfzg1dR0ucd7GUsYrW5nlrspy+5DwY45TlE 1FrQ== X-Gm-Message-State: AHQUAuarce9GFvqmLdSUJsW+U2BXD+0t/yoHMShcKyfH88Ii3s7qIG7T a43pbAmz6u8Ay8klBXSl/okrH/EU X-Google-Smtp-Source: AHgI3IaXMEVVHbQbTfaDv7G1ZF5IDo4iVODr+/XrunEL5UOXF/3O0gQjvzkiCXGkPsEXYWC8WGXerA== X-Received: by 2002:a1c:c60e:: with SMTP id w14mr1085249wmf.18.1549315285359; Mon, 04 Feb 2019 13:21:25 -0800 (PST) Date: Mon, 4 Feb 2019 22:21:23 +0100 From: Daniel Tameling To: zsh-workers@zsh.org Subject: Re: [PATCH] Support true colours via termcap interface Message-ID: <20190204212123.mpzkt4bpajx2cxpw@Daniels-MacBook-Air.local> Mail-Followup-To: zsh-workers@zsh.org References: <20190203215711.sofrde7s4lb7nttb@Daniels-MacBook-Air.local> <20190204061946.dmygdd7n5c2zoi7d@Daniels-MacBook-Air.local> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: On Mon, Feb 04, 2019 at 09:11:04AM +0100, Sebastian Gniazdowski wrote: > On Mon, 4 Feb 2019 at 07:20, Daniel Tameling wrote: > > Btw. I did that deliberately. I didn't want to make the if even more > > complicated and I wanted to use the same code path as for the > > %F{16763955} syntax. Making a small change to match_colour felt nicer > > than to hack around in set_colour_attribute. > > Ahso,,ok, but I don't see the *_TERMCAP code being returned here, > could you explain? The code doesn't return from the function but continues and enters if (!named && tccan(tc)) { and there the else branch where on |= is_fg ? TXT_ATTR_FG_TERMCAP : TXT_ATTR_BG_TERMCAP; is executed. This is the same as for the %F{16763955} syntax. > > Before the patch, the hardcoded escape sequence is used: > > $ TERM=xterm-direct print -P %F{'#ffcc00'} | cat -v > > ^[[38;2;255;204;0m > > > > Afterwards the terminfo entry is used: > > $ TERM=xterm-direct print -P %F{'#ffcc33'} | cat -v > > ^[[38:2::255:204:51m > > > > The former works because xterm understands both escape sequences, but > > Ahso, OK. Let me just point the difference: the second code has two > clons after "38:2". > There are currently three definitions floating around (and also present in ncurses' terminfo): \e38;2;red;green;blue;m \e38:2:red:green:blue:m \e38:2::red:green:blue:m The comments in ncurses terminfo briefly describe the history of these sequences [1], which boils down to the following: The first one is a natural extension of xterm's 256 colour sequences. The last one is specified in a document from the nineties that tried to standardize terminals. The second one stems from overlooking the a colour space identifier in the document. If you want to know more about this you should look at [2] and the comments to [3]. There is currently an argument, whether the first or the last sequence should be used, but it seems that at the moment all terminal support the syntax with semicolons and some support additionally the one with colons. [1]: https://invisible-island.net/ncurses/terminfo.src.html#tic-xterm_direct2 [2]: https://bugs.kde.org/show_bug.cgi?id=107487 [3]: https://gist.github.com/XVilka/8346728 > > That said: does the new X04 test pass with your patch? > Yes, it does. But I noticed that's misleading as the test sets TERM to xterm-256color. If I set it to xterm-direct the test fails even without the patch --- /tmp/zsh.ztst.75451/ztst.out 2019-02-04 20:11:21.000000000 +0100 +++ /tmp/zsh.ztst.75451/ztst.tout 2019-02-04 20:11:21.000000000 +0100 @@ -1 +1 @@ -0m27m24mCDE|3232|trueCDE|39| +0m27m24mtrue Test ./X04zlehighlight.ztst failed: output differs from expected as shown above for: zpty_start zpty_input 'zmodload zsh/nearcolor' zpty_input 'rh_widget() { BUFFER="true"; region_highlight+=( "0 4 fg=#040810" ); }' zpty_input 'zle -N rh_widget' zpty_input 'bindkey "\C-a" rh_widget' zpty_enable_zle zpty_input $'\C-a' # emits newline, which executes BUFFER="true" command zpty_line 1 p # the line of interest, preserving escapes ("p") zpty_stop Was testing: basic region_highlight with near-color (hex-triplets at input) But I also noticed that my patch breaks the is_default_zle_highlight = 0 code. It doesn't set use_truecolor for the #ffcc00 syntax. But that is not the only problem: with a true colour terminal, one expects colours beyond 255 to work, e.g. via fg=273. In that case one also has to use the true colour escape sequence. Then also colours in the range from 8 to 255 should use this sequence. But colours from 0 to 7 should probably still be the standard ansi sequence, like ncurses does it. One could achieve that by modifying the if(use_truecolor) checks when the escape sequence is constructed manually. Alternatively, the patch below should accomplish the same. Now zlehighlight.ztst fails at the same point as without the patch for xterm-direct. It seems that this is because the non-termcap code emits only the standard true colour escape sequence, which cannot be modified like the other ones. -- Best regards, Daniel diff --git a/Src/prompt.c b/Src/prompt.c index f2b3f161e..bef53b148 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -1652,6 +1652,13 @@ match_colour(const char **teststrp, int is_fg, int colour) colour = runhookdef(GETCOLORATTR, &color) - 1; if (colour == -1) { /* no hook function added, try true color (24-bit) */ colour = (((color.red << 8) + color.green) << 8) + color.blue; + /* + * If we have a true colour termcap entry and colour > 7 + * use termcap; for colours 0-7 termcap usually emits the + * standard ANSI sequences; we don't want that. + */ + if (tccolours == 0x1000000 && colour > 7) + on |= is_fg ? TXT_ATTR_FG_TERMCAP : TXT_ATTR_BG_TERMCAP; return on | (is_fg ? TXT_ATTR_FG_24BIT : TXT_ATTR_BG_24BIT) | (zattr)colour << shft; } else if (colour <= -2) { @@ -1668,7 +1675,7 @@ match_colour(const char **teststrp, int is_fg, int colour) } else { colour = (int)zstrtol(*teststrp, (char **)teststrp, 10); - if (colour < 0 || colour >= 256) + if (colour < 0 || colour >= tccolours) return TXT_ERROR; } } @@ -1692,6 +1699,16 @@ match_colour(const char **teststrp, int is_fg, int colour) */ on |= is_fg ? TXT_ATTR_FG_TERMCAP : TXT_ATTR_BG_TERMCAP; + /* + * If our terminal supports more than 256 colours it is + * most likely a true colour terminal (it's not always + * 256*256*256 colours: sometimes tccolours get truncated + * to the largest short, which is significantly smaller); + * if we don't use termcap, we want to emit true colour + * escape sequences for colour > 7. + */ + if (tccolours > 256 && colour > 7) + on |= is_fg ? TXT_ATTR_FG_24BIT : TXT_ATTR_BG_24BIT; } } return on | (zattr)colour << shft; @@ -2039,8 +2056,7 @@ set_colour_attribute(zattr atr, int fg_bg, int flags) * highlighting variables, so much of this shouldn't be * necessary at this point, but we might as well be safe. */ - if (!def && !use_truecolor && - (is_default_zle_highlight && (colour > 7 || use_termcap))) + if (!def && (is_default_zle_highlight && (colour > 7 || use_termcap))) { /* * We can if it's available, and either we couldn't get