summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver Kiddle <opk@zsh.org>2024-02-15 14:48:04 +0100
committerOliver Kiddle <opk@zsh.org>2024-02-15 14:48:04 +0100
commit14c230dc3216b7fe0f63d797347e14178d4ede2b (patch)
tree127a4799cc5db7544bbad9ee20d0592bc96f949f
parent04ae7dc64cde2fa6b7354f685596ff570404a2c9 (diff)
downloadzsh-14c230dc3216b7fe0f63d797347e14178d4ede2b.tar.gz
zsh-14c230dc3216b7fe0f63d797347e14178d4ede2b.zip
52533: add module to provide alternate readonly views of the content of .zle.hlgroups
-rw-r--r--ChangeLog6
-rw-r--r--Src/Modules/hlgroup.c211
-rw-r--r--Src/Modules/hlgroup.mdd7
-rw-r--r--Src/prompt.c28
4 files changed, 252 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 639f19369..6d064eaf6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2024-02-15 Oliver Kiddle <opk@zsh.org>
+
+ * 52533: Src/Modules/hlgroup.c, Src/Modules/hlgroup.mdd,
+ Src/prompt.c: add module to provide alternate readonly views of
+ the content of .zle.hlgroups
+
2024-02-09 Mikael Magnusson <mikachu@gmail.com>
* 52526: Src/Modules/terminfo.c: metafy terminfo capabilities
diff --git a/Src/Modules/hlgroup.c b/Src/Modules/hlgroup.c
new file mode 100644
index 000000000..6382f3216
--- /dev/null
+++ b/Src/Modules/hlgroup.c
@@ -0,0 +1,211 @@
+/*
+ * hlgroup.c - Supporting parameters for highlight groups
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 2024 Oliver Kiddle
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Oliver Kiddle or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Oliver Kiddle and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Oliver Kiddle and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose. The software
+ * provided hereunder is on an "as is" basis, and Oliver Kiddle and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+#include "hlgroup.mdh"
+#include "hlgroup.pro"
+
+#define GROUPVAR ".zle.hlgroups"
+
+static const struct gsu_scalar pmesc_gsu =
+{ strgetfn, nullstrsetfn, nullunsetfn };
+
+/**/
+static char *
+convertattr(char *attrstr, int sgr)
+{
+ zattr atr;
+ char *r, *s;
+ int len;
+
+ match_highlight(attrstr, &atr, NULL);
+ s = zattrescape(atr, sgr ? NULL : &len);
+
+ if (sgr) {
+ char *c = s, *t = s - 1;
+
+ while (c[0] == '\033' && c[1] == '[') {
+ c += 2;
+ while (isdigit(*c) || *c == ';')
+ *++t = *c++;
+ t++;
+ if (*c != 'm')
+ break;
+ *t = ';';
+ c++;
+ }
+ *t = '\0';
+ len = t - s;
+ }
+
+ r = dupstring_wlen(s, len);
+ free(s);
+ return r;
+}
+
+/**/
+static HashNode
+getgroup(const char *name, int sgr)
+{
+ Param pm = NULL;
+ HashNode hn;
+ HashTable hlg;
+ Value v;
+ struct value vbuf;
+ char *var = GROUPVAR;
+
+ pm = (Param) hcalloc(sizeof(struct param));
+ pm->gsu.s = &pmesc_gsu;
+ pm->node.nam = dupstring(name);
+ pm->node.flags = PM_SCALAR|PM_SPECIAL;
+
+ if (!(v = getvalue(&vbuf, &var, 0)) ||
+ PM_TYPE(v->pm->node.flags) != PM_HASHED ||
+ !(hlg = v->pm->gsu.h->getfn(v->pm)) ||
+ !(hn = gethashnode2(hlg, name)))
+ {
+ pm->u.str = dupstring("");
+ pm->node.flags |= PM_UNSET;
+ } else {
+ pm->u.str = convertattr(((Param) hn)->u.str, sgr);
+ }
+
+ return &pm->node;
+}
+
+/**/
+static void
+scangroup(ScanFunc func, int flags, int sgr)
+{
+ struct param pm;
+ int i;
+ HashNode hn;
+ HashTable hlg;
+ Value v;
+ struct value vbuf;
+ char *var = GROUPVAR;
+
+ if (!(v = getvalue(&vbuf, &var, 0)) ||
+ PM_TYPE(v->pm->node.flags) != PM_HASHED)
+ return;
+ hlg = v->pm->gsu.h->getfn(v->pm);
+
+ memset((void *)&pm, 0, sizeof(struct param));
+ pm.node.flags = PM_SCALAR;
+ pm.gsu.s = &pmesc_gsu;
+
+ for (i = 0; i < hlg->hsize; i++)
+ for (hn = hlg->nodes[i]; hn; hn = hn->next) {
+ pm.u.str = convertattr(((Param) hn)->u.str, sgr);
+ pm.node.nam = hn->nam;
+ func(&pm.node, flags);
+ }
+}
+/**/
+static HashNode
+getpmesc(UNUSED(HashTable ht), const char *name)
+{
+ return getgroup(name, 0);
+}
+
+/**/
+static void
+scanpmesc(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ return scangroup(func, flags, 0);
+}
+
+/**/
+static HashNode
+getpmsgr(UNUSED(HashTable ht), const char *name)
+{
+ return getgroup(name, 1);
+}
+
+/**/
+static void
+scanpmsgr(UNUSED(HashTable ht), ScanFunc func, int flags)
+{
+ return scangroup(func, flags, 1);
+}
+
+static struct paramdef partab[] = {
+ SPECIALPMDEF(".zle.esc", PM_READONLY_SPECIAL, 0, getpmesc, scanpmesc),
+ SPECIALPMDEF(".zle.sgr", PM_READONLY_SPECIAL, 0, getpmsgr, scanpmsgr)
+};
+
+static struct features module_features = {
+ NULL, 0,
+ NULL, 0,
+ NULL, 0,
+ partab, sizeof(partab)/sizeof(*partab),
+ 0
+};
+
+/**/
+int
+setup_(UNUSED(Module m))
+{
+ return 0;
+}
+
+/**/
+int
+features_(Module m, char ***features)
+{
+ *features = featuresarray(m, &module_features);
+ return 0;
+}
+
+/**/
+int
+enables_(Module m, int **enables)
+{
+ return handlefeatures(m, &module_features, enables);
+}
+
+/**/
+int
+boot_(UNUSED(Module m))
+{
+ return 0;
+}
+
+/**/
+int
+cleanup_(Module m)
+{
+ return setfeatureenables(m, &module_features, NULL);
+}
+
+/**/
+int
+finish_(UNUSED(Module m))
+{
+ return 0;
+}
diff --git a/Src/Modules/hlgroup.mdd b/Src/Modules/hlgroup.mdd
new file mode 100644
index 000000000..ee3ba7260
--- /dev/null
+++ b/Src/Modules/hlgroup.mdd
@@ -0,0 +1,7 @@
+name=zsh/hlgroup
+link=either
+load=yes
+
+autofeatures="p:.zle.esc p:.zle.sgr"
+
+objects="hlgroup.o"
diff --git a/Src/prompt.c b/Src/prompt.c
index 0d674ceab..7acbe0e47 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -241,6 +241,34 @@ promptexpand(char *s, int ns, char *rs, char *Rs)
return new_vars.buf;
}
+/* Get the escape sequence for a given attribute. */
+/**/
+mod_export char *
+zattrescape(zattr atr, int *len)
+{
+ struct buf_vars new_vars;
+ zattr savecurrent = txtcurrentattrs;
+ zattr saveunknown = txtunknownattrs;
+
+ memset(&new_vars, 0, sizeof(new_vars));
+ new_vars.last = bv;
+ bv = &new_vars;
+ new_vars.bufspc = 256;
+ new_vars.bp = new_vars.bufline = new_vars.buf = zshcalloc(new_vars.bufspc);
+ new_vars.dontcount = 1;
+
+ txtunknownattrs = 0;
+ treplaceattrs(atr);
+ applytextattributes(TSC_PROMPT);
+
+ bv = new_vars.last;
+
+ txtpendingattrs = txtcurrentattrs = savecurrent;
+ txtunknownattrs = saveunknown;
+
+ return unmetafy(new_vars.buf, len);
+}
+
/* Parse the argument for %H */
static char *
parsehighlight(char *arg, char endchar, zattr *atr)