1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-06-12 19:38:03 +02:00

52500: add layer token to zle attributes

This provide control over the precedence of highlighting where
different regions overlap.
This commit is contained in:
Oliver Kiddle 2024-01-28 00:47:10 +01:00
parent 3c5dacd503
commit 85545af42b
4 changed files with 88 additions and 46 deletions

View file

@ -1,5 +1,9 @@
2024-01-28 Oliver Kiddle <opk@zsh.org> 2024-01-28 Oliver Kiddle <opk@zsh.org>
* 52500: Src/Zle/zle.h, Src/Zle/zle_refresh.c, Src/prompt.c:
add layer token to zle attributes to provide control over
the precedence of highlighting
* 52499: Src/prompt.c: support highlight groups defined in a * 52499: Src/prompt.c: support highlight groups defined in a
.zle.hlgroups associative array and referenced using %H in .zle.hlgroups associative array and referenced using %H in
prompt strings or hl= in zle_highlight/region_highlight prompt strings or hl= in zle_highlight/region_highlight

View file

@ -435,6 +435,8 @@ enum {
struct region_highlight { struct region_highlight {
/* Attributes turned on in the region */ /* Attributes turned on in the region */
zattr atr; zattr atr;
/* Priority for this region relative to others that overlap */
int layer;
/* Start of the region */ /* Start of the region */
int start; int start;
/* Start of the region in metafied ZLE line */ /* Start of the region in metafied ZLE line */

View file

@ -210,6 +210,12 @@ int predisplaylen, postdisplaylen;
static zattr default_attr, special_attr, ellipsis_attr; static zattr default_attr, special_attr, ellipsis_attr;
/*
* Layer applied to highlighting for special characters
*/
static int special_layer;
/* /*
* Array of region highlights, no special termination. * Array of region highlights, no special termination.
* The first N_SPECIAL_HIGHLIGHTS elements describe special uses of * The first N_SPECIAL_HIGHLIGHTS elements describe special uses of
@ -337,6 +343,13 @@ zle_set_highlight(void)
} }
} }
/* Default layers */
region_highlights[0].layer = 20; /* region */
region_highlights[1].layer = 20; /* isearch */
region_highlights[2].layer = 10; /* suffix */
region_highlights[3].layer = 15; /* paste */
special_layer = 30;
if (atrs) { if (atrs) {
for (; *atrs; atrs++) { for (; *atrs; atrs++) {
if (!strcmp(*atrs, "none")) { if (!strcmp(*atrs, "none")) {
@ -346,30 +359,34 @@ zle_set_highlight(void)
paste_attr_set = region_attr_set = paste_attr_set = region_attr_set =
isearch_attr_set = suffix_attr_set = 1; isearch_attr_set = suffix_attr_set = 1;
} else if (strpfx("default:", *atrs)) { } else if (strpfx("default:", *atrs)) {
match_highlight(*atrs + 8, &default_attr); match_highlight(*atrs + 8, &default_attr, NULL);
} else if (strpfx("special:", *atrs)) { } else if (strpfx("special:", *atrs)) {
match_highlight(*atrs + 8, &special_attr); match_highlight(*atrs + 8, &special_attr, &special_layer);
special_attr_set = 1; special_attr_set = 1;
} else if (strpfx("region:", *atrs)) { } else if (strpfx("region:", *atrs)) {
match_highlight(*atrs + 7, &region_highlights[0].atr); match_highlight(*atrs + 7, &(region_highlights[0].atr),
&(region_highlights[0].layer));
region_attr_set = 1; region_attr_set = 1;
} else if (strpfx("isearch:", *atrs)) { } else if (strpfx("isearch:", *atrs)) {
match_highlight(*atrs + 8, &(region_highlights[1].atr)); match_highlight(*atrs + 8, &(region_highlights[1].atr),
&(region_highlights[1].layer));
isearch_attr_set = 1; isearch_attr_set = 1;
} else if (strpfx("suffix:", *atrs)) { } else if (strpfx("suffix:", *atrs)) {
match_highlight(*atrs + 7, &(region_highlights[2].atr)); match_highlight(*atrs + 7, &(region_highlights[2].atr),
&(region_highlights[2].layer));
suffix_attr_set = 1; suffix_attr_set = 1;
} else if (strpfx("paste:", *atrs)) { } else if (strpfx("paste:", *atrs)) {
match_highlight(*atrs + 6, &(region_highlights[3].atr)); match_highlight(*atrs + 6, &(region_highlights[3].atr),
&(region_highlights[3].layer));
paste_attr_set = 1; paste_attr_set = 1;
} else if (strpfx("ellipsis:", *atrs)) { } else if (strpfx("ellipsis:", *atrs)) {
match_highlight(*atrs + 9, &ellipsis_attr); match_highlight(*atrs + 9, &ellipsis_attr, NULL);
ellipsis_attr_set = 1; ellipsis_attr_set = 1;
} }
} }
} }
/* Defaults */ /* Default attributes */
if (!special_attr_set) if (!special_attr_set)
special_attr = TXTSTANDOUT; special_attr = TXTSTANDOUT;
if (!region_attr_set) if (!region_attr_set)
@ -407,14 +424,13 @@ zle_free_highlight(void)
char ** char **
get_region_highlight(UNUSED(Param pm)) get_region_highlight(UNUSED(Param pm))
{ {
int arrsize = n_region_highlights; int arrsize = n_region_highlights - N_SPECIAL_HIGHLIGHTS;
char **retarr, **arrp; char **retarr, **arrp;
struct region_highlight *rhp; struct region_highlight *rhp;
/* region_highlights may not have been set yet */ /* region_highlights may not have been set yet */
if (!arrsize) if (!n_region_highlights)
return hmkarray(NULL); return hmkarray(NULL);
arrsize -= N_SPECIAL_HIGHLIGHTS;
DPUTS(arrsize < 0, "arrsize is negative from n_region_highlights"); DPUTS(arrsize < 0, "arrsize is negative from n_region_highlights");
arrp = retarr = (char **)zhalloc((arrsize+1)*sizeof(char *)); arrp = retarr = (char **)zhalloc((arrsize+1)*sizeof(char *));
@ -422,20 +438,18 @@ get_region_highlight(UNUSED(Param pm))
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
arrsize--; arrsize--;
rhp++, arrp++) { rhp++, arrp++) {
char digbuf1[DIGBUFSIZE], digbuf2[DIGBUFSIZE]; char digbuf[2 * DIGBUFSIZE], layerbuf[7 + DIGBUFSIZE];
int atrlen, alloclen; int offset;
const char memo_equals[] = "memo="; const char memo_equals[] = " memo=";
int alloclen = sprintf(digbuf, "%d %d", rhp->start, rhp->end) +
sprintf(digbuf1, "%d", rhp->start); output_highlight(rhp->atr, NULL) +
sprintf(digbuf2, "%d", rhp->end); 2; /* space and terminating NUL */
atrlen = output_highlight(rhp->atr, NULL);
alloclen = atrlen + strlen(digbuf1) + strlen(digbuf2) +
3; /* 2 spaces, 1 terminating NUL */
if (rhp->flags & ZRH_PREDISPLAY) if (rhp->flags & ZRH_PREDISPLAY)
alloclen += 2; /* "P " */ alloclen++; /* "P" */
if (rhp->layer != 10)
alloclen += sprintf(layerbuf, ",layer=%d", rhp->layer);
if (rhp->memo) if (rhp->memo)
alloclen += 1 /* space */ + strlen(memo_equals) + strlen(rhp->memo); alloclen += sizeof(memo_equals) - 1 + strlen(rhp->memo);
*arrp = (char *)zhalloc(alloclen * sizeof(char)); *arrp = (char *)zhalloc(alloclen * sizeof(char));
/* /*
* On input we allow a space after the flags. * On input we allow a space after the flags.
@ -444,13 +458,14 @@ get_region_highlight(UNUSED(Param pm))
* into three words, and then check the first to * into three words, and then check the first to
* see if there are flags. However, it's arguable. * see if there are flags. However, it's arguable.
*/ */
sprintf(*arrp, "%s%s %s ", offset = sprintf(*arrp, "%s%s ",
(rhp->flags & ZRH_PREDISPLAY) ? "P" : "", (rhp->flags & ZRH_PREDISPLAY) ? "P" : "",
digbuf1, digbuf2); digbuf);
(void)output_highlight(rhp->atr, *arrp + strlen(*arrp)); (void)output_highlight(rhp->atr, *arrp + offset);
if (rhp->layer != 10)
strcat(*arrp, layerbuf);
if (rhp->memo) { if (rhp->memo) {
strcat(*arrp, " ");
strcat(*arrp, memo_equals); strcat(*arrp, memo_equals);
strcat(*arrp, rhp->memo); strcat(*arrp, rhp->memo);
} }
@ -459,12 +474,10 @@ get_region_highlight(UNUSED(Param pm))
return retarr; return retarr;
} }
/* /*
* The parameter system requires the pm argument, but this * The parameter system requires the pm argument, but this
* may be NULL if called directly. * may be NULL if called directly.
*/ */
/**/ /**/
void void
set_region_highlight(UNUSED(Param pm), char **aval) set_region_highlight(UNUSED(Param pm), char **aval)
@ -523,7 +536,8 @@ set_region_highlight(UNUSED(Param pm), char **aval)
while (inblank(*strp)) while (inblank(*strp))
strp++; strp++;
strp = (char*) match_highlight(strp, &rhp->atr); rhp->layer = 10; /* default */
strp = (char*) match_highlight(strp, &rhp->atr, &rhp->layer);
while (inblank(*strp)) while (inblank(*strp))
strp++; strp++;
@ -1180,27 +1194,40 @@ zrefresh(void)
rpms.s = nbuf[rpms.ln = 0] + lpromptw; rpms.s = nbuf[rpms.ln = 0] + lpromptw;
rpms.sen = *nbuf + winw; rpms.sen = *nbuf + winw;
for (t = tmpline, tmppos = 0; tmppos < tmpll; t++, tmppos++) { for (t = tmpline, tmppos = 0; tmppos < tmpll; t++, tmppos++) {
unsigned ireg;
zattr base_attr = mixattrs(default_attr, prompt_attr); zattr base_attr = mixattrs(default_attr, prompt_attr);
zattr all_attr; zattr all_attr;
struct region_highlight *rhp; struct region_highlight *rhp;
int layer, nextlayer = 0;
/* /*
* Calculate attribute based on region. * Calculate attribute based on region.
*/ */
for (ireg = 0, rhp = region_highlights; do {
ireg < n_region_highlights; unsigned ireg;
ireg++, rhp++) { layer = nextlayer;
int offset; nextlayer = special_layer;
if (rhp->flags & ZRH_PREDISPLAY) for (ireg = 0, rhp = region_highlights;
offset = 0; /* include predisplay in start end */ ireg < n_region_highlights;
else ireg++, rhp++) {
offset = predisplaylen; /* increment over it */ if (rhp->layer == layer) {
if (rhp->start + offset <= tmppos && int offset;
tmppos < rhp->end + offset) { if (rhp->flags & ZRH_PREDISPLAY)
base_attr = mixattrs(rhp->atr, base_attr); offset = 0; /* include predisplay in start end */
else
offset = predisplaylen; /* increment over it */
if (rhp->start + offset <= tmppos &&
tmppos < rhp->end + offset) {
base_attr = mixattrs(rhp->atr, base_attr);
if (layer > special_layer)
all_attr = mixattrs(rhp->atr, all_attr);
}
} else if (rhp->layer > layer && rhp->layer < nextlayer) {
nextlayer = rhp->layer;
}
} }
} if (special_layer == layer) {
all_attr = mixattrs(special_attr, base_attr); all_attr = mixattrs(special_attr, base_attr);
}
} while (nextlayer > layer);
if (t == scs) /* if cursor is here, remember it */ if (t == scs) /* if cursor is here, remember it */
rpms.nvcs = rpms.s - nbuf[rpms.nvln = rpms.ln]; rpms.nvcs = rpms.s - nbuf[rpms.nvln = rpms.ln];

View file

@ -260,7 +260,7 @@ parsehighlight(char *arg, char endchar, zattr *atr)
if ((node = (Param) ht->getnode(ht, arg))) { if ((node = (Param) ht->getnode(ht, arg))) {
attrs = node->gsu.s->getfn(node); attrs = node->gsu.s->getfn(node);
entered = 1; entered = 1;
if (match_highlight(attrs, atr) == attrs) if (match_highlight(attrs, atr, 0) == attrs)
*atr = TXT_ERROR; *atr = TXT_ERROR;
} else } else
*atr = TXT_ERROR; *atr = TXT_ERROR;
@ -1884,12 +1884,13 @@ match_colour(const char **teststrp, int is_fg, int colour)
/* /*
* Match a set of highlights in the given teststr. * Match a set of highlights in the given teststr.
* Set *on_var to reflect the values found. * Set *on_var to reflect the values found.
* Set *layer to the layer
* Return a pointer to the first character not consumed. * Return a pointer to the first character not consumed.
*/ */
/**/ /**/
mod_export const char * mod_export const char *
match_highlight(const char *teststr, zattr *on_var) match_highlight(const char *teststr, zattr *on_var, int *layer)
{ {
int found = 1; int found = 1;
@ -1918,6 +1919,14 @@ match_highlight(const char *teststr, zattr *on_var)
/* skip out of range colours but keep scanning attributes */ /* skip out of range colours but keep scanning attributes */
if (atr != TXT_ERROR) if (atr != TXT_ERROR)
*on_var |= atr; *on_var |= atr;
} else if (layer && strpfx("layer=", teststr)) {
teststr += 6;
*layer = (int) zstrtol(teststr, (char **) &teststr, 10);
if (*teststr == ',')
teststr++;
else if (*teststr && *teststr != ' ')
break;
found = 1;
} else { } else {
for (hl = highlights; hl->name; hl++) { for (hl = highlights; hl->name; hl++) {
if (strpfx(hl->name, teststr)) { if (strpfx(hl->name, teststr)) {