From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1655 invoked from network); 26 Apr 2008 22:49:42 -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.5 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; 26 Apr 2008 22:49:42 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 48146 invoked from network); 26 Apr 2008 22:49:35 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 26 Apr 2008 22:49:35 -0000 Received: (qmail 27691 invoked by alias); 26 Apr 2008 22:49:31 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 24882 Received: (qmail 27668 invoked from network); 26 Apr 2008 22:49:31 -0000 Received: from bifrost.dotsrc.org (130.225.254.106) by sunsite.dk with SMTP; 26 Apr 2008 22:49:31 -0000 Received: from mtaout01-winn.ispmail.ntl.com (mtaout01-winn.ispmail.ntl.com [81.103.221.47]) by bifrost.dotsrc.org (Postfix) with ESMTP id D59ED808A38A for ; Sun, 27 Apr 2008 00:49:26 +0200 (CEST) Received: from aamtaout02-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout01-winn.ispmail.ntl.com with ESMTP id <20080426225241.HSCN27050.mtaout01-winn.ispmail.ntl.com@aamtaout02-winn.ispmail.ntl.com> for ; Sat, 26 Apr 2008 23:52:41 +0100 Received: from pws-pc.ntlworld.com ([81.107.40.67]) by aamtaout02-winn.ispmail.ntl.com with ESMTP id <20080426225149.IDUN17393.aamtaout02-winn.ispmail.ntl.com@pws-pc.ntlworld.com> for ; Sat, 26 Apr 2008 23:51:49 +0100 Received: from pws-pc (pws-pc [127.0.0.1]) by pws-pc.ntlworld.com (8.14.2/8.14.2) with ESMTP id m3QMmd5X004828 for ; Sat, 26 Apr 2008 23:48:39 +0100 From: Peter Stephenson To: zsh-workers@sunsite.dk (Zsh hackers list) Subject: PATCH: isearch match highlighting X-Mailer: MH-E 8.0.3; nmh 1.2-20070115cvs; GNU Emacs 22.1.1 Date: Sat, 26 Apr 2008 23:48:39 +0100 Message-ID: <4827.1209250119@pws-pc> X-Virus-Scanned: ClamAV 0.91.2/6957/Sat Apr 26 20:28:22 2008 on bifrost X-Virus-Status: Clean This one is worth posting. With pattern matching in isearch, it's now quite useful to have the matched string highlighted. I've made the default underlining rather than standout because of the annoyance that standout on a cursor that's shown in inverse video flips it to normal video, then when you've just matched one character there's nothing at all on the line. This seems to be common behaviour. You could argue that if highlighting is done this way it would make more sense for the cursor position to be where the user is typing, but I it's non-trivial to change, hard to be sure the highlighting selected is going to work, incompatible with usage when there's no highlighting, and I don't feel like monkeying with it anyway. I can't help feeling I must have screwed up this one somehow. Index: Doc/Zsh/zle.yo =================================================================== RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v retrieving revision 1.63 diff -u -r1.63 zle.yo --- Doc/Zsh/zle.yo 26 Apr 2008 19:51:09 -0000 1.63 +++ Doc/Zsh/zle.yo 26 Apr 2008 22:41:58 -0000 @@ -2064,6 +2064,10 @@ startitem() cindex(region, highlighting) cindex(highlighting, region) +item(tt(isearch))( +When one of the incremental history search widgets is active, the +area of the command line matched by the search string or pattern. +) item(tt(region))( The region between the cursor (point) and the mark as set with tt(set-mark-command). The region is only highlighted if it is active, @@ -2102,7 +2106,7 @@ is inverse video. On some such terminals, where the cursor does not blink it appears with standout mode negated, making it less than clear where the cursor actually is. On such terminals one of the other effects -may be preferable for highlighting the region. +may be preferable for highlighting the region and matched search string. ) item(tt(underline))( The characters in the given context are shown underlined. Some @@ -2133,7 +2137,8 @@ If tt(zle_highlight) is not set or no value applies to a particular context, the defaults applied are equivalent to -example(zle_highlight=LPAR()region:standout special:standout+RPAR()) +example(zle_highlight=LPAR()region:standout special:standout +isearch:underline+RPAR()) i.e. both the region and special characters are shown in standout mode. Index: Src/Zle/zle_hist.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_hist.c,v retrieving revision 1.48 diff -u -r1.48 zle_hist.c --- Src/Zle/zle_hist.c 26 Apr 2008 21:26:28 -0000 1.48 +++ Src/Zle/zle_hist.c 26 Apr 2008 22:41:59 -0000 @@ -907,6 +907,7 @@ int pat_hl; /* histline where pattern search started */ unsigned short pos; /* The search position in our metafied str */ unsigned short pat_pos; /* pos where pattern search started */ + unsigned short end_pos; /* The position of the end of the matched str */ unsigned short cs; /* The visible search position to the user */ unsigned short len; /* The search string's length */ unsigned short flags; /* This spot's flags */ @@ -928,7 +929,7 @@ /**/ static void set_isrch_spot(int num, int hl, int pos, int pat_hl, int pat_pos, - int cs, int len, int dir, int nomatch) + int end_pos, int cs, int len, int dir, int nomatch) { if (num >= max_spot) { if (!isrch_spots) { @@ -944,6 +945,7 @@ isrch_spots[num].pos = (unsigned short)pos; isrch_spots[num].pat_hl = pat_hl; isrch_spots[num].pat_pos = (unsigned short)pat_pos; + isrch_spots[num].end_pos = (unsigned short)end_pos; isrch_spots[num].cs = (unsigned short)cs; isrch_spots[num].len = (unsigned short)len; isrch_spots[num].flags = (dir > 0? ISS_FORWARD : 0) @@ -953,12 +955,13 @@ /**/ static void get_isrch_spot(int num, int *hlp, int *posp, int *pat_hlp, int *pat_posp, - int *csp, int *lenp, int *dirp, int *nomatch) + int *end_posp, int *csp, int *lenp, int *dirp, int *nomatch) { *hlp = isrch_spots[num].hl; *posp = (int)isrch_spots[num].pos; *pat_hlp = isrch_spots[num].pat_hl; *pat_posp = (int)isrch_spots[num].pat_pos; + *end_posp = (int)isrch_spots[num].end_pos; *csp = (int)isrch_spots[num].cs; *lenp = (int)isrch_spots[num].len; *dirp = (isrch_spots[num].flags & ISS_FORWARD)? 1 : -1; @@ -1011,6 +1014,9 @@ #define FIRST_SEARCH_CHAR (NORM_PROMPT_POS + 14) /**/ +int isearch_active, isearch_startpos, isearch_endpos; + +/**/ static void doisearch(char **args, int dir, int pattern) { @@ -1088,6 +1094,12 @@ */ int dup_ok = 0; /* + * End position of the match. + * When forward matching, this is the position for the cursor. + * When backward matching, the cursor position is pos. + */ + int end_pos = 0; + /* * savekeys records the unget buffer, so that if we have arguments * they don't pollute the input. * feep indicates we should feep. This is a well-known word @@ -1138,7 +1150,7 @@ pat_pos = pos = zlemetacs; for (;;) { /* Remember the current values in case search fails (doesn't push). */ - set_isrch_spot(top_spot, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); if (sbptr == 1 && sbuf[0] == '^') { zlemetacs = 0; @@ -1147,11 +1159,6 @@ } else if (sbptr > 0) { /* The matched text, used as flag that we matched */ char *t = NULL; - /* - * When forward matching, position for the cursor. - * When backward matching, the position is pos. - */ - int forwardmatchpos = 0; last_line = zt; sbuf[sbptr] = '\0'; @@ -1233,7 +1240,7 @@ */ if (!skip_pos && pattryrefs(patprog, zt, -1, -1, 0, NULL, NULL, - &forwardmatchpos)) + &end_pos)) t = zt; } else { if (!matchlist && !skip_pos) { @@ -1268,7 +1275,7 @@ newpos = pos + 1; } newpos = isearch_newpos(matchlist, newpos, - dir, &forwardmatchpos); + dir, &end_pos); /* need a new list next time if off the end */ if (newpos < 0) { freematchlist(matchlist); @@ -1316,7 +1323,7 @@ } else t = zlinefind(zt, pos, sbuf, dir, sens); if (t) - forwardmatchpos = pos + sbptr - (sbuf[0] == '^'); + end_pos = pos + sbptr - (sbuf[0] == '^'); } } if (t) { @@ -1333,7 +1340,8 @@ && (isrch_spots[top_spot-1].flags >> ISS_NOMATCH_SHIFT)) top_spot--; get_isrch_spot(top_spot, &hl, &pos, &pat_hl, &pat_pos, - &zlemetacs, &sbptr, &dir, &nomatch); + &end_pos, &zlemetacs, &sbptr, &dir, + &nomatch); if (!nomatch) { feep = 1; nomatch = 1; @@ -1366,7 +1374,7 @@ if (t || (nosearch && !nomatch)) { zle_setline(he); if (dir == 1) - zlemetacs = forwardmatchpos; + zlemetacs = end_pos; else zlemetacs = pos; statusline = ibuf + NORM_PROMPT_POS; @@ -1384,11 +1392,39 @@ } sbuf[sbptr] = '_'; sbuf[sbptr+1] = '\0'; + if (!nomatch && sbptr && (sbptr > 1 || sbuf[0] != '^')) { +#ifdef MULTIBYTE_SUPPORT + int charpos = 0, charcount = 0, ret; + wint_t wc; + mbstate_t mbs; + + /* + * Count unmetafied character positions for the + * start and end of the match for the benefit of + * highlighting. + */ + memset(&mbs, 0, sizeof(mbs)); + while (charpos < end_pos) { + ret = mb_metacharlenconv_r(zlemetaline + charpos, &wc, &mbs); + if (charpos <= pos && pos < charpos + ret) + isearch_startpos = charcount; + charcount++; + charpos += ret; + } + isearch_endpos = charcount; +#else + isearch_startpos = ztrsub(zlemetaline + pos, zlemetaline); + isearch_endpos = ztrsub(zlemetaline + end_pos, + zlemetaline); +#endif + isearch_active = 1; + } else + isearch_active = 0; ref: zrefresh(); if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) { int i; - get_isrch_spot(0, &hl, &pos, &pat_hl, &pat_pos, + get_isrch_spot(0, &hl, &pos, &pat_hl, &pat_pos, &end_pos, &i, &sbptr, &dir, &nomatch); he = quietgethist(hl); zle_setline(he); @@ -1410,7 +1446,7 @@ cmd == Th(z_backwarddeletechar)) { if (top_spot) { get_isrch_spot(--top_spot, &hl, &pos, &pat_hl, &pat_pos, - &zlemetacs, &sbptr, &dir, &nomatch); + &end_pos, &zlemetacs, &sbptr, &dir, &nomatch); patprog = NULL; nosearch = 1; } else @@ -1452,7 +1488,7 @@ cmd == Th(z_historyincrementalpatternsearchbackward)) { pat_hl = hl; pat_pos = pos; - set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); if (dir != -1) dir = -1; @@ -1463,7 +1499,7 @@ cmd == Th(z_historyincrementalpatternsearchforward)) { pat_hl = hl; pat_pos = pos; - set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); if (dir != 1) dir = 1; @@ -1473,7 +1509,7 @@ } else if(cmd == Th(z_virevrepeatsearch)) { pat_hl = hl; pat_pos = pos; - set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); dir = -odir; skip_pos = 1; @@ -1481,7 +1517,7 @@ } else if(cmd == Th(z_virepeatsearch)) { pat_hl = hl; pat_pos = pos; - set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); dir = odir; skip_pos = 1; @@ -1534,7 +1570,7 @@ feep = 1; continue; } - set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, + set_isrch_spot(top_spot++, hl, pos, pat_hl, pat_pos, end_pos, zlemetacs, sbptr, dir, nomatch); if (sbptr >= sibuf - FIRST_SEARCH_CHAR - 2 #ifdef MULTIBYTE_SUPPORT @@ -1569,6 +1605,7 @@ zsfree(okeymap); if (matchlist) freematchlist(matchlist); + isearch_active = 0; /* * Don't allow unused characters provided as a string to the * widget to overflow and be used as separated commands. Index: Src/Zle/zle_refresh.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_refresh.c,v retrieving revision 1.61 diff -u -r1.61 zle_refresh.c --- Src/Zle/zle_refresh.c 22 Apr 2008 15:08:14 -0000 1.61 +++ Src/Zle/zle_refresh.c 26 Apr 2008 22:42:00 -0000 @@ -242,8 +242,15 @@ */ struct region_highlight *region_highlights; /* + * Count of special uses of region highlighting, which account + * for the first few elements of region_highlights. + * 0: region between point and mark + * 1: isearch region + */ +#define N_SPECIAL_HIGHLIGHTS (2) +/* * Number of elements in region_highlights. - * This includes the region between point and mark, element 0. + * This includes the special elements above. */ int n_region_highlights; @@ -380,12 +387,14 @@ char **atrs = getaparam("zle_highlight"); int special_atr_on_set = 0; int region_atr_on_set = 0; + int isearch_atr_on_set = 0; + struct region_highlight *rhp; special_atr_on = 0; if (!region_highlights) { region_highlights = (struct region_highlight *) - zshcalloc(sizeof(struct region_highlight)); - n_region_highlights = 1; + zshcalloc(N_SPECIAL_HIGHLIGHTS*sizeof(struct region_highlight)); + n_region_highlights = N_SPECIAL_HIGHLIGHTS; } else { region_highlights->atr = 0; } @@ -394,14 +403,23 @@ for (; *atrs; atrs++) { if (!strcmp(*atrs, "none")) { /* reset attributes for consistency... usually unnecessary */ - special_atr_on = region_highlights->atr = 0; - special_atr_on_set = region_atr_on_set = 1; + special_atr_on = 0; + special_atr_on_set = region_atr_on_set = + isearch_atr_on_set = 1; + for (rhp = region_highlights; + rhp < region_highlights + N_SPECIAL_HIGHLIGHTS; + rhp++) { + rhp->atr = 0; + } } else if (strpfx("special:", *atrs)) { match_highlight(*atrs + 8, &special_atr_on); special_atr_on_set = 1; } else if (strpfx("region:", *atrs)) { match_highlight(*atrs + 7, ®ion_highlights->atr); region_atr_on_set = 1; + } else if (strpfx("isearch:", *atrs)) { + match_highlight(*atrs + 8, &(region_highlights[1].atr)); + isearch_atr_on_set = 1; } } } @@ -411,6 +429,8 @@ special_atr_on = TXTSTANDOUT; if (!region_atr_on_set) region_highlights->atr = TXTSTANDOUT; + if (!isearch_atr_on_set) + region_highlights[1].atr = TXTUNDERLINE; special_atr_off = special_atr_on << TXT_ATTR_OFF_ON_SHIFT; } @@ -432,15 +452,17 @@ /* region_highlights may not have been set yet */ if (!arrsize) - arrsize = 1; + arrsize = N_SPECIAL_HIGHLIGHTS; arrp = retarr = (char **)zhalloc(arrsize*sizeof(char *)); /* ignore NULL termination */ arrsize--; if (arrsize) { struct region_highlight *rhp; - /* ignore point/mark at start */ - for (rhp = region_highlights+1; arrsize--; rhp++, arrp++) { + /* ignore special highlighting */ + for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; + arrsize--; + rhp++, arrp++) { char digbuf1[DIGBUFSIZE], digbuf2[DIGBUFSIZE]; int atrlen = 0, alloclen, done1; const struct highlight *hp; @@ -503,9 +525,9 @@ struct region_highlight *rhp; len = aval ? arrlen(aval) : 0; - if (n_region_highlights != len + 1) { - /* no null termination, but include point/mark region at start */ - n_region_highlights = len + 1; + if (n_region_highlights != len + N_SPECIAL_HIGHLIGHTS) { + /* no null termination, but include special highlighting at start */ + n_region_highlights = len + N_SPECIAL_HIGHLIGHTS; region_highlights = (struct region_highlight *) zrealloc(region_highlights, sizeof(struct region_highlight) * n_region_highlights); @@ -514,7 +536,9 @@ if (!aval) return; - for (rhp = region_highlights + 1; *aval; rhp++, aval++) { + for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; + *aval; + rhp++, aval++) { char *strp, *oldstrp; oldstrp = *aval; @@ -1050,6 +1074,13 @@ } else { region_highlights->start = region_highlights->end = -1; } + /* check for isearch string to highlight */ + if (isearch_active) { + region_highlights[1].start = isearch_startpos; + region_highlights[1].end = isearch_endpos; + } else { + region_highlights[1].start = region_highlights[1].end = -1; + } if (clearlist && listshown > 0) { if (tccan(TCCLEAREOD)) { -- Peter Stephenson Web page now at http://homepage.ntlworld.com/p.w.stephenson/