You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
zsh/Src/Modules/hlgroup.c

217 lines
4.5 KiB
C

/*
* 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++;
}
if (t <= s) { /* always return at least "0" */
*s = '0';
t = s + 1;
}
*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)) ||
(((Param) hn)->node.flags & PM_UNSET))
{
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)
{
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)
{
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;
}