1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-06-06 15:26:04 +02:00

24822: highlighting of isearch matches

unposted: not in NEWS that COMBINING_CHARS is not on by default
This commit is contained in:
Peter Stephenson 2008-04-26 22:52:50 +00:00
parent 8a323cae8c
commit 91a10708b2
5 changed files with 115 additions and 35 deletions

View File

@ -1,5 +1,11 @@
2008-04-26 Peter Stephenson <p.w.stephenson@ntlworld.com>
* unposted: NEWS: note that COMBINING_CHARS is not on by
default.
* 24882: Doc/Zsh/zle.yo, Src/Zle/zle_hist.c, Src/Zle/zle_refresh.c:
highlighting of incremental search match.
* unposted because everyone's seen enough of my mistakes:
Src/pattern.c, Src/Zle/zle_hist.c: with pattern matching the
end position of the match wasn't calculated; we used the

View File

@ -2064,6 +2064,10 @@ The contexts available for highlighting are the following:
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 @@ mode. The actual effect is specific to the terminal; on many terminals it
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 @@ enditem()
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.

3
NEWS
View File

@ -10,7 +10,8 @@ Major changes between versions 4.3.6 and 4.3.7
The option COMBINING_CHARS has been added. When it is set, the
line editor assumes the terminal is capable of displaying zero-width
combining characters (typically accents) correctly as modifications
to the base character, and will act accordingly.
to the base character, and will act accordingly. Note it is not set
by default owing to vagaries of terminals.
The option HIST_FCNTL_LOCK has been added to provide locking of history
files using the system call fcntl(). On recent NFS implementations this

View File

@ -907,6 +907,7 @@ static struct isrch_spot {
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 @@ free_isrch_spots(void)
/**/
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 @@ set_isrch_spot(int num, int hl, int pos, int pat_hl, int pat_pos,
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 @@ set_isrch_spot(int num, int hl, int pos, int pat_hl, int pat_pos,
/**/
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;
@ -1010,6 +1013,9 @@ isearch_newpos(LinkList matchlist, int curpos, int dir,
#define NORM_PROMPT_POS (BAD_TEXT_LEN+1)
#define FIRST_SEARCH_CHAR (NORM_PROMPT_POS + 14)
/**/
int isearch_active, isearch_startpos, isearch_endpos;
/**/
static void
doisearch(char **args, int dir, int pattern)
@ -1087,6 +1093,12 @@ doisearch(char **args, int dir, int pattern)
* case it's OK.
*/
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.
@ -1138,7 +1150,7 @@ doisearch(char **args, int dir, int pattern)
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 @@ doisearch(char **args, int dir, int pattern)
} 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 @@ doisearch(char **args, int dir, int pattern)
*/
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 @@ doisearch(char **args, int dir, int pattern)
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 @@ doisearch(char **args, int dir, int pattern)
} 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 @@ doisearch(char **args, int dir, int pattern)
&& (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 @@ doisearch(char **args, int dir, int pattern)
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 @@ doisearch(char **args, int dir, int pattern)
}
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 @@ doisearch(char **args, int dir, int pattern)
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 @@ doisearch(char **args, int dir, int pattern)
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 @@ doisearch(char **args, int dir, int pattern)
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 @@ doisearch(char **args, int dir, int pattern)
} 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 @@ doisearch(char **args, int dir, int pattern)
} 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 @@ doisearch(char **args, int dir, int pattern)
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 @@ doisearch(char **args, int dir, int pattern)
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.

View File

@ -241,9 +241,16 @@ struct region_highlight {
* via the parameter region_highlight.
*/
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 @@ 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;
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 @@ void zle_set_highlight(void)
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, &region_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 @@ void zle_set_highlight(void)
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 @@ get_region_highlight(UNUSED(Param pm))
/* 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 @@ set_region_highlight(UNUSED(Param pm), char **aval)
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 @@ set_region_highlight(UNUSED(Param pm), char **aval)
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 @@ zrefresh(void)
} 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)) {