From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5451 invoked from network); 1 May 2008 10:37:36 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.4 (2008-01-01) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.4 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.2.4 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 1 May 2008 10:37:36 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 29195 invoked from network); 1 May 2008 10:37:29 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 1 May 2008 10:37:29 -0000 Received: (qmail 1384 invoked by alias); 1 May 2008 10:37:25 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 24899 Received: (qmail 1363 invoked from network); 1 May 2008 10:37:24 -0000 Received: from bifrost.dotsrc.org (130.225.254.106) by sunsite.dk with SMTP; 1 May 2008 10:37:24 -0000 Received: from cluster-d.mailcontrol.com (cluster-d.mailcontrol.com [217.69.20.190]) by bifrost.dotsrc.org (Postfix) with ESMTP id E424880ED173 for ; Thu, 1 May 2008 12:37:19 +0200 (CEST) Received: from cameurexb01.EUROPE.ROOT.PRI ([62.189.241.200]) by rly26d.srv.mailcontrol.com (MailControl) with ESMTP id m41AbAtP024859 for ; Thu, 1 May 2008 11:37:12 +0100 Received: from news01 ([10.103.143.38]) by cameurexb01.EUROPE.ROOT.PRI with Microsoft SMTPSVC(6.0.3790.3959); Thu, 1 May 2008 11:37:06 +0100 Date: Thu, 1 May 2008 11:37:06 +0100 From: Peter Stephenson To: zsh-workers@sunsite.dk Subject: Re: PATCH: isearch match highlighting Message-ID: <20080501113706.4910492b@news01> In-Reply-To: <20080429181022.12809d23@news01> References: <17393e3e0804261727s560acff7sb6125d8f8b46b4b4@mail.gmail.com> <200804271957.m3RJvxiS004075@pws-pc.ntlworld.com> <17393e3e0804271849l30fe20bdp4008fc8247298d12@mail.gmail.com> <20080428102001.7b55074e@news01> <20080429181022.12809d23@news01> Organization: CSR X-Mailer: Claws Mail 3.3.1 (GTK+ 2.12.5; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 01 May 2008 10:37:06.0870 (UTC) FILETIME=[4D6FF560:01C8AB77] X-Scanned-By: MailControl A-08-50-00 (www.mailcontrol.com) on 10.68.0.136 X-Virus-Scanned: ClamAV 0.91.2/7006/Thu May 1 12:01:28 2008 on bifrost X-Virus-Status: Clean On Tue, 29 Apr 2008 18:10:22 +0100 Peter Stephenson wrote: > I would like at the least to make the use of the ANSI escapes > configurable. They are in completion listings, but unfortunately that's > tied to the variable interface for GNU ls colouring which doesn't really > fit the case here. I suppose special values in zle_highlight would be > suitable (with bindkey escapes). I've done this. Looks suspiciously like overkill, but it's probably best to be general. I've also added handling of names for ANSI colours. Index: Doc/Zsh/zle.yo =================================================================== RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v retrieving revision 1.65 diff -u -r1.65 zle.yo --- Doc/Zsh/zle.yo 29 Apr 2008 17:19:26 -0000 1.65 +++ Doc/Zsh/zle.yo 1 May 2008 10:35:05 -0000 @@ -2088,6 +2088,39 @@ ) enditem() +tt(zle_highlight) may contain additional fields for controlling how +terminal sequences to change colours are output. Each of the following is +followed by a colon and a string in the same form as for key bindings. +This will not be necessary for the vast majority of terminals as the +defaults shown in parentheses are widely used. + +startitem() +cindex(escape sequences, terminal, for highlighting) +cindex(terminal escape sequences for highlighting) +item(tt(fg_start_code) (tt(\e[3)))( +The start of the escape sequence for the foreground colour. +This is followed by an ASCII digit representing the colour. +) +item(tt(fg_default_code) (tt(9)))( +The number to use instead of the colour to reset the default foreground +colour. +) +item(tt(fg_end_code) (tt(m)))( +The end of the escape sequence for the foreground colour. +) +item(tt(bg_start_code) (tt(\e[4)))( +The start of the escape sequence for the background colour. +This is followed by an ASCII digit representing the colour. +) +item(tt(bg_default_code) (tt(9)))( +The number to use instead of the colour to reset the default +background colour. +) +item(tt(bg_end_code) (tt(m)))( +The end of the escape sequence for the background colour. +) +enditem() + The available types of highlighting are the following. Note that not all types of highlighting are available on all terminals: @@ -2098,11 +2131,19 @@ a default. ) item(tt(fg=)var(colour))( -The foreground colour should be set to var(colour), a decimal integer. Not -all terminals support this, and of those that do not all provide facilities -to test the support, hence the user should decide based on the terminal -type. Most terminals with colour support accept the numbers 0 to 7, and -may generate additional colours if the tt(bold) attributes is also present. +The foreground colour should be set to var(colour), a decimal integer +or the name of one of the eight most widely-supported colours. + +Not all terminals support this and, of those that do, not all provide +facilities to test the support, hence the user should decide based on the +terminal type. Most terminals with colour support accept the numbers 0 to +7, and may generate additional colours if the tt(bold) attributes is also +present. Most terminals also have a standard range of colours for those +numbers (though the interpretation of the colour can vary); these colours +can be set by one of the names tt(black), tt(red), tt(green), tt(yellow), +tt(blue), tt(magenta), tt(cyan) and tt(white). Abbreviations are +allowed; tt(b) or tt(bl) selects black. + On recent terminals and on systems with an up-to-date terminal database the number of colours supported may be tested by with the command `tt(echotc Co)'; if this succeeds, it indicates a limit on the number of colours which @@ -2112,7 +2153,7 @@ Colour is also known as color. ) item(tt(bg=)var(colour))( -The background colour should be set to var(colour), a decimal integer. +The background colour should be set to var(colour). This works similarly to the foreground colour, except the background is not usually affected by the bold attribute. ) @@ -2144,12 +2185,18 @@ `tt(^)' followed by the base character. ) item(Unprintable multibyte characters)( -If the tt(MULTIBYTE) option is in effect, -multibyte characters not in the ASCII character set that are reported as -having zero width are shown as a hexadecimal number between -angle brackets. The number is the code point of the character in -the wide character set; this may or may not be Unicode, depending -on the operating system. +This item applies to control characters not in the ASCII range, +plus other characters as follows. If the tt(MULTIBYTE) option is in +effect, multibyte characters not in the ASCII character set that are +reported as having zero width are treated as combining characters when the +option tt(COMBINING_CHARS) is on. If the option is off, or if a character +appears where a combining character is not valid, the character +is treated as unprintable. + +Unprintable multibyte characters are shown as a hexadecimal number between +angle brackets. The number is the code point of the character in the wide +character set; this may or may not be Unicode, depending on the operating +system. ) enditem() Index: Src/Zle/zle_main.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v retrieving revision 1.110 diff -u -r1.110 zle_main.c --- Src/Zle/zle_main.c 20 Apr 2008 21:17:29 -0000 1.110 +++ Src/Zle/zle_main.c 1 May 2008 10:35:06 -0000 @@ -1903,6 +1903,7 @@ addhookfunc("before_trap", (Hookfn) zlebeforetrap); addhookfunc("after_trap", (Hookfn) zleaftertrap); (void)addhookdefs(m, zlehooks, sizeof(zlehooks)/sizeof(*zlehooks)); + zle_refresh_boot(); return 0; } Index: Src/Zle/zle_refresh.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_refresh.c,v retrieving revision 1.64 diff -u -r1.64 zle_refresh.c --- Src/Zle/zle_refresh.c 29 Apr 2008 17:19:27 -0000 1.64 +++ Src/Zle/zle_refresh.c 1 May 2008 10:35:06 -0000 @@ -326,6 +326,11 @@ #define ZR_START_ELLIPSIS_SIZE \ ((int)(sizeof(zr_start_ellipsis)/sizeof(zr_start_ellipsis[0]))) +/* Defines standard ANSI colour names in index order */ +static const char *ansi_colours[] = { + "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", + NULL +}; /* Defines the available types of highlighting */ struct highlight { @@ -342,6 +347,101 @@ { NULL, 0, 0 } }; +/* Structure and array for holding special colour terminal sequences */ + +/* Start of escape sequence for foreground colour */ +#define TC_COL_FG_START "\033[3" +/* End of escape sequence for foreground colour */ +#define TC_COL_FG_END "m" +/* Code to reset foreground colour */ +#define TC_COL_FG_DEFAULT "9" + +/* Start of escape sequence for background colour */ +#define TC_COL_BG_START "\033[4" +/* End of escape sequence for background colour */ +#define TC_COL_BG_END "m" +/* Code to reset background colour */ +#define TC_COL_BG_DEFAULT "9" + +struct colour_sequences { + char *start; /* Escape sequence start */ + char *end; /* Escape sequence terminator */ + char *def; /* Code to reset default colour */ +}; +struct colour_sequences fg_bg_sequences[2]; + +#define COL_SEQ_FG (0) +#define COL_SEQ_BG (1) +#define COL_SEQ_COUNT (2) + +/* + * We need a buffer for colour sequence compostion. It may + * vary depending on the sequences set. However, it's inefficient + * allocating it separately every time we send a colour sequence, + * so do it once per refresh. + */ +static char *colseq_buf; + +static void +set_default_colour_sequences(void) +{ + fg_bg_sequences[COL_SEQ_FG].start = ztrdup(TC_COL_FG_START); + fg_bg_sequences[COL_SEQ_FG].end = ztrdup(TC_COL_FG_END); + fg_bg_sequences[COL_SEQ_FG].def = ztrdup(TC_COL_FG_DEFAULT); + + fg_bg_sequences[COL_SEQ_BG].start = ztrdup(TC_COL_BG_START); + fg_bg_sequences[COL_SEQ_BG].end = ztrdup(TC_COL_BG_END); + fg_bg_sequences[COL_SEQ_BG].def = ztrdup(TC_COL_BG_DEFAULT); +} + +static void +free_colour_sequences(void) +{ + int i; + + for (i = 0; i < COL_SEQ_COUNT; i++) { + zsfree(fg_bg_sequences[i].start); + zsfree(fg_bg_sequences[i].end); + zsfree(fg_bg_sequences[i].def); + } +} + +/* + * Return index of ANSI colour for which *teststrp is an abbreviation. + * Any non-alphabetic character ends the abbreviation. + */ + +static int +match_colour(const char **teststrp) +{ + const char *teststr = *teststrp, *end, **cptr; + int len; + + for (end = teststr; ialpha(*end); end++) + ; + len = end - teststr; + *teststrp = end; + + for (cptr = ansi_colours; *cptr; cptr++) { + if (!strncmp(teststr, *cptr, len)) + return cptr - ansi_colours; + } + + return -1; +} + +static void +set_colour_code(char *str, char **var) +{ + char *keyseq; + int len; + + zsfree(*var); + keyseq = getkeystring(str, &len, GETKEYS_BINDKEY, NULL); + *var = metafy(keyseq, len, META_DUP); +} + + /* * Match a set of highlights in the given teststr. * Set *on_var to reflect the values found. @@ -359,15 +459,20 @@ found = 0; if (strpfx("fg=", teststr) || strpfx("bg=", teststr)) { int is_fg = (teststr[0] == 'f'); - int colour = (int)zstrtol(teststr+3, (char **)&teststr, 10); - int shft, on; + int colour, shft, on; + + teststr += 3; + if (ialpha(*teststr)) + colour = match_colour(&teststr); + else + colour = (int)zstrtol(teststr, (char **)&teststr, 10); if (*teststr == ',') teststr++; else if (*teststr) break; found = 1; /* skip out of range colours but keep scanning attributes */ - if (colour >= 256) + if (colour < 0 || colour >= 256) continue; if (is_fg) { shft = TXT_ATTR_FG_COL_SHIFT; @@ -404,12 +509,14 @@ */ /**/ -void zle_set_highlight(void) +static void +zle_set_highlight(void) { char **atrs = getaparam("zle_highlight"); int special_atr_on_set = 0; int region_atr_on_set = 0; int isearch_atr_on_set = 0; + int lenfg, lenbg, len; struct region_highlight *rhp; special_atr_on = 0; @@ -442,6 +549,18 @@ } else if (strpfx("isearch:", *atrs)) { match_highlight(*atrs + 8, &(region_highlights[1].atr)); isearch_atr_on_set = 1; + } else if (strpfx("fg_start_code:", *atrs)) { + set_colour_code(*atrs + 14, &fg_bg_sequences[COL_SEQ_FG].start); + } else if (strpfx("fg_default_code:", *atrs)) { + set_colour_code(*atrs + 16, &fg_bg_sequences[COL_SEQ_FG].def); + } else if (strpfx("fg_end_code:", *atrs)) { + set_colour_code(*atrs + 12, &fg_bg_sequences[COL_SEQ_FG].end); + } else if (strpfx("bg_start_code:", *atrs)) { + set_colour_code(*atrs + 14, &fg_bg_sequences[COL_SEQ_BG].start); + } else if (strpfx("bg_default_code:", *atrs)) { + set_colour_code(*atrs + 16, &fg_bg_sequences[COL_SEQ_BG].def); + } else if (strpfx("bg_end_code:", *atrs)) { + set_colour_code(*atrs + 12, &fg_bg_sequences[COL_SEQ_BG].end); } } } @@ -453,9 +572,35 @@ region_highlights->atr = TXTSTANDOUT; if (!isearch_atr_on_set) region_highlights[1].atr = TXTUNDERLINE; + + /* Allocate buffer for colour code composition */ + lenfg = strlen(fg_bg_sequences[COL_SEQ_FG].def); + /* always need 1 character for non-default code */ + if (lenfg < 1) + lenfg = 1; + lenfg += strlen(fg_bg_sequences[COL_SEQ_FG].start) + + strlen(fg_bg_sequences[COL_SEQ_FG].end); + + lenbg = strlen(fg_bg_sequences[COL_SEQ_BG].def); + /* always need 1 character for non-default code */ + if (lenbg < 1) + lenbg = 1; + lenbg += strlen(fg_bg_sequences[COL_SEQ_BG].start) + + strlen(fg_bg_sequences[COL_SEQ_BG].end); + + len = lenfg > lenbg ? lenfg : lenbg; + colseq_buf = (char *)zalloc(len+1); } +/**/ +static void +zle_free_highlight(void) +{ + /* Free buffer for colour code composition */ + free(colseq_buf); +} + /* * Interface to the region_highlight ZLE parameter. * Converts betwen a format like "P32 42 underline,bold" to @@ -942,26 +1087,12 @@ rpms->sen = rpms->s + winw; } -/* - * HERE: these need to be made configurable, somehow. - * Ideally we need to make the complist stuff use the - * same system, but that may be too much tied to the GNU ls - * interface to make that possible. - */ -/* Start of escape sequence for foreground colour */ -#define TC_COL_FG_START "\033[3" -/* Start of escape sequence for background colour */ -#define TC_COL_BG_START "\033[4" -/* End of either escape sequence */ -#define TC_COL_END "m" -/* Numeric code (to be turned into ASCII) to reset default colour */ -#define TC_COL_DEFAULT 9 static void -setcolourattribute(int colour, char *start, int tc, int def, +setcolourattribute(int colour, int fg_bg, int tc, int def, int use_termcap) { - char out[16], *ptr; + char *ptr; /* * If we're not restoring the default, and either have a * colour value that is too large for ANSI, or have been told @@ -980,14 +1111,17 @@ return; } - strcpy(out, start); - if (def) - colour = TC_COL_DEFAULT; - - ptr = out + strlen(start); - *ptr++ = colour + '0'; - strcpy(ptr, TC_COL_END); - tputs(out, 1, putshout); + strcpy(colseq_buf, fg_bg_sequences[fg_bg].start); + + ptr = colseq_buf + strlen(colseq_buf); + if (def) { + strcpy(ptr, fg_bg_sequences[fg_bg].def); + while (*ptr) + ptr++; + } else + *ptr++ = colour + '0'; + strcpy(ptr, fg_bg_sequences[fg_bg].end); + tputs(colseq_buf, 1, putshout); } /**/ @@ -1008,13 +1142,13 @@ tsetcap(TCUNDERLINEBEG, 0); if (txtchangeisset(atr, TXTFGCOLOUR|TXTNOFGCOLOUR)) { setcolourattribute(txtchangeget(atr, TXT_ATTR_FG_COL), - TC_COL_FG_START, TCFGCOLOUR, + COL_SEQ_FG, TCFGCOLOUR, txtchangeisset(atr, TXTNOFGCOLOUR), txtchangeisset(atr, TXT_ATTR_FG_TERMCAP)); } if (txtchangeisset(atr, TXTBGCOLOUR|TXTNOBGCOLOUR)) { setcolourattribute(txtchangeget(atr, TXT_ATTR_BG_COL), - TC_COL_BG_START, TCBGCOLOUR, + COL_SEQ_BG, TCBGCOLOUR, txtchangeisset(atr, TXTNOBGCOLOUR), txtchangeisset(atr, TXT_ATTR_BG_TERMCAP)); } @@ -1796,6 +1930,8 @@ if (tmpalloced) zfree(tmpline, tmpll * sizeof(*tmpline)); + zle_free_highlight(); + /* if we have a new list showing, note it; if part of the list has been overwritten, redisplay it. We have to metafy line back before calling completion code */ @@ -2711,6 +2847,15 @@ vcs = pos; } +/* Provided for loading the module in a modular fashion */ + +/**/ +void +zle_refresh_boot(void) +{ + set_default_colour_sequences(); +} + /* Provided for unloading the module in a modular fashion */ /**/ @@ -2722,4 +2867,6 @@ if (region_highlights) zfree(region_highlights, sizeof(struct region_highlight) * n_region_highlights); + + free_colour_sequences(); }