Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: highlight groups (was Re: Why are prompt expansions of %v sequences quoted in bindkey style?)



[ moved to -workers ]

Marlon Richert wrote:
> Thanks, I think that might work for me. 
>
> I am indeed trying to use $psvar to dynamically update my prompt’s visual formatting, without the use of prompsubst or changing $PS1.

The following is something which I've been intending to add since the
attribute code refactoring from a year ago which added support for
italic and faint without adding new prompt escapes. The hardest part
of adding those now would be finding unused available letters and a
separate abstraction layer for visual attributes is rather more useful.

Highlight-groups is the term used by vim for its similar feature. What
this does is support an associative array named .zle.hlgroups and if
you refer to keys from that associative array with %H{...} in a prompt
or hl=... in zle_highlight, it will look up the actual attributes in
the associative array expecting the same format as zle_highlight (e.g.
fg=blue,bg=108,italic).

There is no corresponding end escape. %h is already taken for the
history event number. And while I could have used %A and %a, I'm not
quite sure what exactly the behaviour of %a should even be. %r (for
reset) which resets all attributes (or reverts to whatever the prompt
tag in zle_highlight specifies) might be more useful. Note that %H will
replace all attributes. With default: in zle_highlight, there
is some mixing of attributes with prompt leftovers that exists for
backward compatibility.

It is intentional that unrecognised strings at the end of attributes are
ignored without error to allow some forward compatibility with future
extensions. Recursion is blocked: you can't use hl= in .zle.hlgroups.

Oliver

diff --git a/Src/prompt.c b/Src/prompt.c
index 39fcf5eb7..e4c213a13 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -241,6 +241,39 @@ promptexpand(char *s, int ns, char *rs, char *Rs)
     return new_vars.buf;
 }
 
+/* Parse the argument for %H */
+static char *
+parsehighlight(char *arg, char endchar, zattr *atr)
+{
+    static int entered = 0;
+    char *var = ".zle.hlgroups";
+    struct value vbuf;
+    Value v;
+    char *ep, *attrs;
+    if ((ep = strchr(arg, endchar)))
+	*ep = '\0';
+    if (!entered && (v = getvalue(&vbuf, &var, 0)) &&
+	    PM_TYPE(v->pm->node.flags) == PM_HASHED)
+    {
+	Param node;
+	HashTable ht = v->pm->gsu.h->getfn(v->pm);
+	if ((node = (Param) ht->getnode(ht, arg))) {
+	    attrs = node->gsu.s->getfn(node);
+	    entered = 1;
+	    if (match_highlight(attrs, atr) == attrs)
+		*atr = TXT_ERROR;
+	} else
+	    *atr = TXT_ERROR;
+    } else
+	*atr = TXT_ERROR;
+    if (ep)
+	*ep = endchar;
+    else
+	ep = strchr(arg, '\0') - 1;
+    entered = 0;
+    return ep;
+}
+
 /* Parse the argument for %F and %K */
 static zattr
 parsecolorchar(zattr arg, int is_fg)
@@ -571,6 +604,13 @@ putpromptchar(int doprint, int endchar)
 		tunsetattrs(TXTBGCOLOUR);
 	        applytextattributes(TSC_PROMPT);
 		break;
+	    case 'H':
+		bv->fm = parsehighlight(bv->fm + 2, '}', &atr);
+		if (atr != TXT_ERROR) {
+		    treplaceattrs(atr);
+		    applytextattributes(TSC_PROMPT);
+		}
+		break;
 	    case '[':
 		if (idigit(*++bv->fm))
 		    arg = zstrtol(bv->fm, &bv->fm, 10);
@@ -1856,11 +1896,17 @@ match_highlight(const char *teststr, zattr *on_var)
     *on_var = 0;
     while (found && *teststr) {
 	const struct highlight *hl;
+	zattr atr = 0;
 
 	found = 0;
-	if (strpfx("fg=", teststr) || strpfx("bg=", teststr)) {
+	if (strpfx("hl=", teststr)) {
+	    teststr += 3;
+	    teststr = parsehighlight((char *)teststr, ',', &atr);
+	    if (atr != TXT_ERROR)
+		*on_var = atr;
+	    found = 1;
+	} else if (strpfx("fg=", teststr) || strpfx("bg=", teststr)) {
 	    int is_fg = (teststr[0] == 'f');
-	    zattr atr;
 
 	    teststr += 3;
 	    atr = match_colour(&teststr, is_fg, 0);




Messages sorted by: Reverse Date, Date, Thread, Author