mirror of
https://github.com/0intro/wmii
synced 2024-11-22 05:42:05 +03:00
Experimental new /rules file to replace /tagrules. Case insensitive ctl file writes.
This commit is contained in:
parent
612b959af5
commit
0801547846
@ -95,9 +95,9 @@ bar_create(Bar **bp, const char *name) {
|
||||
utflcpy(b->name, name, sizeof b->name);
|
||||
b->col = def.normcolor;
|
||||
|
||||
strlcat(b->buf, b->col.colstr, sizeof(b->buf));
|
||||
strlcat(b->buf, " ", sizeof(b->buf));
|
||||
strlcat(b->buf, b->text, sizeof(b->buf));
|
||||
strlcat(b->buf, b->col.colstr, sizeof b->buf);
|
||||
strlcat(b->buf, " ", sizeof b->buf);
|
||||
strlcat(b->buf, b->text, sizeof b->buf);
|
||||
|
||||
SET(i);
|
||||
for(sp=screens; (s = *sp); sp++) {
|
||||
|
@ -197,7 +197,21 @@ client_create(XWindow w, XWindowAttributes *wa) {
|
||||
|
||||
static bool
|
||||
apply_rules(Client *c) {
|
||||
IxpMsg m;
|
||||
Rule *r;
|
||||
Ruleval *rv;
|
||||
|
||||
if(def.rules.string)
|
||||
for(r=def.rules.rule; r; r=r->next)
|
||||
if(regexec(r->regex, c->props, nil, 0)) {
|
||||
for(rv=r->values; rv; rv=rv->next) {
|
||||
bufclear();
|
||||
bufprint("%s %s", rv->key, rv->value);
|
||||
m = ixp_message(buffer, sizeof buffer, MsgPack);
|
||||
message_client(c, &m);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(def.tagrules.string)
|
||||
for(r=def.tagrules.rule; r; r=r->next)
|
||||
@ -1116,10 +1130,10 @@ client_applytags(Client *c, const char *tags) {
|
||||
found = false;
|
||||
|
||||
j = 0;
|
||||
while(buf[n] && n < sizeof(buf) && j < 32) {
|
||||
while(buf[n] && n < sizeof buf && j < 32) {
|
||||
/* Check for regex. */
|
||||
if(buf[n] == '/') {
|
||||
for(i=n+1; i < sizeof(buf) - 1; i++)
|
||||
for(i=n+1; i < sizeof buf - 1; i++)
|
||||
if(buf[i] == '/') break;
|
||||
if(buf[i] == '/') {
|
||||
i++;
|
||||
@ -1140,7 +1154,7 @@ client_applytags(Client *c, const char *tags) {
|
||||
}
|
||||
}
|
||||
|
||||
for(i = n; i < sizeof(buf) - 1; i++)
|
||||
for(i = n; i < sizeof buf - 1; i++)
|
||||
if(buf[i] == '+'
|
||||
|| buf[i] == '-'
|
||||
|| buf[i] == '\0')
|
||||
|
@ -59,11 +59,14 @@ enum {
|
||||
|
||||
extern char* modes[];
|
||||
|
||||
#define toggle(val, x) \
|
||||
((x) == On ? true : \
|
||||
(x) == Off ? false : \
|
||||
(x) == Toggle ? !(val) : (val))
|
||||
#define TOGGLE(x) \
|
||||
(x == On ? "on" : \
|
||||
x == Off ? "off" : \
|
||||
x == Toggle ? "toggle" : \
|
||||
"<toggle>")
|
||||
((x) == On ? "on" : \
|
||||
(x) == Off ? "off" : \
|
||||
(x) == Toggle ? "toggle" : "<toggle>")
|
||||
enum {
|
||||
Off,
|
||||
On,
|
||||
@ -240,7 +243,7 @@ struct Ruleval {
|
||||
Ruleval* next;
|
||||
char* key;
|
||||
char* value;
|
||||
}
|
||||
};
|
||||
|
||||
struct Strut {
|
||||
Rectangle left;
|
||||
|
@ -208,6 +208,7 @@ char* message_client(Client*, IxpMsg*);
|
||||
char* message_root(void*, IxpMsg*);
|
||||
char* message_view(View*, IxpMsg*);
|
||||
char* msg_debug(IxpMsg*);
|
||||
void msg_eatrunes(IxpMsg*, int (*)(Rune), int);
|
||||
char* msg_getword(IxpMsg*);
|
||||
char* msg_parsecolors(IxpMsg*, CTuple*);
|
||||
char* msg_selectarea(Area*, IxpMsg*);
|
||||
@ -249,7 +250,7 @@ int ownerscreen(Rectangle);
|
||||
|
||||
/* rule.c */
|
||||
void trim(char *str, const char *chars);
|
||||
void update_rules(Rule**, const char*);
|
||||
void update_rules(Rule**, char*);
|
||||
|
||||
/* view.c */
|
||||
void view_arrange(View*);
|
||||
|
@ -339,7 +339,7 @@ lookup_file(IxpFileId *parent, char *name)
|
||||
file->p.rule = &def.colrules;
|
||||
break;
|
||||
case FsFRules:
|
||||
file->p.rule = &def.tagrules;
|
||||
file->p.rule = &def.rules;
|
||||
break;
|
||||
case FsFTagRules:
|
||||
file->p.rule = &def.tagrules;
|
||||
@ -534,7 +534,7 @@ fs_write(Ixp9Req *r) {
|
||||
case FsFClabel:
|
||||
ixp_srv_data2cstring(r);
|
||||
utfecpy(f->p.client->name,
|
||||
f->p.client->name+sizeof(client->name),
|
||||
f->p.client->name + sizeof client->name,
|
||||
r->ifcall.io.data);
|
||||
frame_draw(f->p.client->sel);
|
||||
update_class(f->p.client);
|
||||
|
@ -24,8 +24,6 @@ static char
|
||||
|
||||
/* Edit |sort Edit |sed 's/"([^"]+)"/L\1/g' | tr 'a-z' 'A-Z' */
|
||||
enum {
|
||||
LFULLSCREEN,
|
||||
LURGENT,
|
||||
LBAR,
|
||||
LBORDER,
|
||||
LCLIENT,
|
||||
@ -33,9 +31,11 @@ enum {
|
||||
LDEBUG,
|
||||
LDOWN,
|
||||
LEXEC,
|
||||
LFLOATING,
|
||||
LFOCUSCOLORS,
|
||||
LFONT,
|
||||
LFONTPAD,
|
||||
LFULLSCREEN,
|
||||
LGRABMOD,
|
||||
LGROW,
|
||||
LINCMODE,
|
||||
@ -53,14 +53,14 @@ enum {
|
||||
LSLAY,
|
||||
LSPAWN,
|
||||
LSWAP,
|
||||
LTAGS,
|
||||
LTOGGLE,
|
||||
LUP,
|
||||
LURGENT,
|
||||
LVIEW,
|
||||
LTILDE,
|
||||
};
|
||||
char *symtab[] = {
|
||||
"Fullscreen",
|
||||
"Urgent",
|
||||
"bar",
|
||||
"border",
|
||||
"client",
|
||||
@ -68,9 +68,11 @@ char *symtab[] = {
|
||||
"debug",
|
||||
"down",
|
||||
"exec",
|
||||
"floating",
|
||||
"focuscolors",
|
||||
"font",
|
||||
"fontpad",
|
||||
"fullscreen",
|
||||
"grabmod",
|
||||
"grow",
|
||||
"incmode",
|
||||
@ -88,8 +90,10 @@ char *symtab[] = {
|
||||
"slay",
|
||||
"spawn",
|
||||
"swap",
|
||||
"tags",
|
||||
"toggle",
|
||||
"up",
|
||||
"urgent",
|
||||
"view",
|
||||
"~",
|
||||
};
|
||||
@ -113,11 +117,13 @@ static char* incmodetab[] = {
|
||||
"show",
|
||||
"squeeze",
|
||||
};
|
||||
#ifdef notdef
|
||||
static char* toggletab[] = {
|
||||
"off",
|
||||
"on",
|
||||
"toggle",
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Edit ,y/^[a-zA-Z].*\n.* {\n/d
|
||||
* Edit s/^([a-zA-Z].*)\n(.*) {\n/\1 \2;\n/
|
||||
@ -125,17 +131,30 @@ static char* toggletab[] = {
|
||||
*/
|
||||
|
||||
static int
|
||||
_bsearch(char *s, char **tab, int ntab) {
|
||||
_bsearch(char *from, char **tab, int ntab) {
|
||||
int i, n, m, cmp;
|
||||
char *to, *end;
|
||||
Rune r;
|
||||
|
||||
if(s == nil)
|
||||
if(from == nil)
|
||||
return -1;
|
||||
|
||||
end = buffer + sizeof buffer - UTFmax - 1;
|
||||
for(to=buffer; *from && to < end;) {
|
||||
from += chartorune(&r, from);
|
||||
if(r != 0x80) {
|
||||
r = tolowerrune(r);
|
||||
to += runetochar(to, &r);
|
||||
}
|
||||
}
|
||||
*to = '\0';
|
||||
to = buffer;
|
||||
|
||||
n = ntab;
|
||||
i = 0;
|
||||
while(n) {
|
||||
m = n/2;
|
||||
cmp = strcmp(s, tab[i+m]);
|
||||
cmp = strcmp(to, tab[i+m]);
|
||||
if(cmp == 0)
|
||||
return i+m;
|
||||
if(cmp < 0 || m == 0)
|
||||
@ -189,8 +208,8 @@ getdirection(IxpMsg *m) {
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eatrunes(IxpMsg *m, int (*p)(Rune), int val) {
|
||||
void
|
||||
msg_eatrunes(IxpMsg *m, int (*p)(Rune), int val) {
|
||||
Rune r;
|
||||
int n;
|
||||
|
||||
@ -210,13 +229,13 @@ msg_getword(IxpMsg *m) {
|
||||
Rune r;
|
||||
int n;
|
||||
|
||||
eatrunes(m, isspacerune, true);
|
||||
msg_eatrunes(m, isspacerune, true);
|
||||
ret = m->pos;
|
||||
eatrunes(m, isspacerune, false);
|
||||
msg_eatrunes(m, isspacerune, false);
|
||||
n = chartorune(&r, m->pos);
|
||||
*m->pos = '\0';
|
||||
m->pos += n;
|
||||
eatrunes(m, isspacerune, true);
|
||||
msg_eatrunes(m, isspacerune, true);
|
||||
|
||||
/* Filter out comments. */
|
||||
if(*ret == '#') {
|
||||
@ -339,11 +358,13 @@ char*
|
||||
readctl_client(Client *c) {
|
||||
bufclear();
|
||||
bufprint("%#C\n", c);
|
||||
bufprint("floating %s\n", TOGGLE(c->floating));
|
||||
if(c->fullscreen >= 0)
|
||||
bufprint("Fullscreen %d\n", c->fullscreen);
|
||||
bufprint("fullscreen %d\n", c->fullscreen);
|
||||
else
|
||||
bufprint("Fullscreen off\n");
|
||||
bufprint("Urgent %s\n", toggletab[(int)c->urgent]);
|
||||
bufprint("fullscreen off\n");
|
||||
bufprint("tags %s\n", c->tags);
|
||||
bufprint("urgent %s\n", TOGGLE(c->urgent));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -360,13 +381,18 @@ message_client(Client *c, IxpMsg *m) {
|
||||
* | off
|
||||
* | toggle
|
||||
* | <screen>
|
||||
* Fullscreen <toggle>
|
||||
* Urgent <toggle>
|
||||
* floating <toggle>
|
||||
* fullscreen <toggle>
|
||||
* kill
|
||||
* slay
|
||||
* tags <tags>
|
||||
* urgent <toggle>
|
||||
*/
|
||||
|
||||
switch(getsym(s)) {
|
||||
case LFLOATING:
|
||||
c->floating = toggle(c->floating, gettoggle(m->pos));
|
||||
break;
|
||||
case LFULLSCREEN:
|
||||
s = msg_getword(m);
|
||||
if(getlong(s, &l))
|
||||
@ -384,6 +410,9 @@ message_client(Client *c, IxpMsg *m) {
|
||||
case LSLAY:
|
||||
client_kill(c, false);
|
||||
break;
|
||||
case LTAGS:
|
||||
client_applytags(c, m->pos);
|
||||
break;
|
||||
case LURGENT:
|
||||
i = gettoggle(msg_getword(m));
|
||||
if(i == -1)
|
||||
@ -812,7 +841,7 @@ msg_parsecolors(IxpMsg *m, CTuple *col) {
|
||||
*p = c;
|
||||
|
||||
m->pos = p;
|
||||
eatrunes(m, isspacerune, true);
|
||||
msg_eatrunes(m, isspacerune, true);
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
211
cmd/wmii/rule.c
211
cmd/wmii/rule.c
@ -23,140 +23,103 @@ trim(char *str, const char *chars) {
|
||||
}
|
||||
|
||||
void
|
||||
update_rules(Rule **rule, const char *data) {
|
||||
#define putc(m, c) BLOCK(if(m.pos < m.end) *m.pos++ = c)
|
||||
#define getc(m) (m.pos < m.end ? *m.pos++ : 0)
|
||||
#define ungetc(m) BLOCK(if(m.pos > m.data) --m.pos)
|
||||
IxpMsg buf, outbuf, rebuf;
|
||||
char regex[256];
|
||||
char c;
|
||||
update_rules(Rule **rule, char *data) {
|
||||
#define putc(m, c) BLOCK(if((m)->pos < (m)->end) *(m)->pos++ = c;)
|
||||
#define getc(m) ((m)->pos < (m)->end ? *(m)->pos++ : 0)
|
||||
#define ungetc(m) BLOCK(if((m)->pos > (m)->data) --(m)->pos)
|
||||
|
||||
buf = ixp_message(data, strlen(data), MsgUnpack);
|
||||
}
|
||||
|
||||
/* XXX: I hate this. --KM */
|
||||
void
|
||||
update_rules(Rule **rule, const char *data) {
|
||||
enum {
|
||||
COMMENT,
|
||||
IGNORE,
|
||||
REGEX,
|
||||
VALUE,
|
||||
WAIT,
|
||||
};
|
||||
int state, old_state;
|
||||
IxpMsg m;
|
||||
IxpMsg buf, valuebuf, rebuf;
|
||||
Reprog *re;
|
||||
Rule *r;
|
||||
Ruleval **rvp;
|
||||
Ruleval *rv;
|
||||
Rule *rul;
|
||||
char regex[256];
|
||||
char *regex_end = regex + sizeof(regex) - 1;
|
||||
char *value_end = buffer + sizeof(buffer) - 1;
|
||||
char *r, *v;
|
||||
const char *p;
|
||||
char *w;
|
||||
char regexp[256];
|
||||
char c;
|
||||
int len;
|
||||
|
||||
#define NEXT(next) BLOCK( \
|
||||
old_state = state \
|
||||
state = next; \
|
||||
continue; \
|
||||
)
|
||||
|
||||
SET(r);
|
||||
SET(v);
|
||||
SET(old_state);
|
||||
|
||||
if(!data || !strlen(data))
|
||||
return;
|
||||
while((rul = *rule)) {
|
||||
*rule = rul->next;
|
||||
while((rv = rul->values)) {
|
||||
rul->values = rv->next;
|
||||
while((r = *rule)) {
|
||||
*rule = r->next;
|
||||
while((rv = r->values)) {
|
||||
r->values = rv->next;
|
||||
free(rv);
|
||||
}
|
||||
free(rul->regex);
|
||||
free(rul);
|
||||
free(r->regex);
|
||||
free(r->value);
|
||||
free(r);
|
||||
}
|
||||
state = IGNORE;
|
||||
for(p = data; (c = *p); p++)
|
||||
switch(state) {
|
||||
case COMMENT:
|
||||
if(c == '\n')
|
||||
state = old_state;
|
||||
break;
|
||||
case IGNORE:
|
||||
if(c == '#')
|
||||
goto comment;
|
||||
else if(c == '/') {
|
||||
r = regex;
|
||||
state = REGEX;
|
||||
}
|
||||
else if(c == '>') {
|
||||
value[0] = 0;
|
||||
v = value;
|
||||
state = VALUE;
|
||||
}
|
||||
break;
|
||||
case REGEX:
|
||||
if(c == '\\' && p[1] == '/')
|
||||
p++;
|
||||
else if(c == '\\' && p[1] == '\\' && p[2] == '/')
|
||||
p++;
|
||||
else if(c == '\\' && r < regex_end)
|
||||
*r++ = *p++;
|
||||
else if(c == '/') {
|
||||
*r = 0;
|
||||
state = IGNORE;
|
||||
|
||||
if(!data || !data[0])
|
||||
return;
|
||||
|
||||
buf = ixp_message(data, strlen(data), MsgUnpack);
|
||||
|
||||
begin:
|
||||
msg_eatrunes(&buf, isspacerune, true);
|
||||
if(getc(&buf) == '/')
|
||||
goto regexp;
|
||||
/* Regexp not at begining of the line. Rest of the line is junk. */
|
||||
while((c = getc(&buf)))
|
||||
if(c == '\n')
|
||||
goto begin;
|
||||
goto done;
|
||||
|
||||
regexp:
|
||||
rebuf = ixp_message(regexp, sizeof regexp - 1, MsgPack);
|
||||
while((c = getc(&buf)))
|
||||
if(c == '/')
|
||||
goto value;
|
||||
else if(c != '\\')
|
||||
putc(&rebuf, c);
|
||||
else if(buf.pos[1] == '/' || buf.pos[1] == '\\' && buf.pos[2] == '/')
|
||||
putc(&rebuf, getc(&buf));
|
||||
else {
|
||||
putc(&rebuf, c);
|
||||
putc(&rebuf, getc(&buf));
|
||||
}
|
||||
goto done;
|
||||
|
||||
value:
|
||||
valuebuf = ixp_message(buffer, sizeof buffer - 1, MsgPack);
|
||||
while((c = getc(&buf))) {
|
||||
if(c == '\n') {
|
||||
putc(&valuebuf, ' ');
|
||||
msg_eatrunes(&buf, isspacerune, true);
|
||||
if((c = getc(&buf)) == '/') {
|
||||
ungetc(&buf);
|
||||
break;
|
||||
}
|
||||
if(r < regex_end)
|
||||
*r++ = c;
|
||||
break;
|
||||
case VALUE:
|
||||
if(c == '#')
|
||||
NEXT(COMMENT);
|
||||
if(c == '\n')
|
||||
NEXT(WAIT);
|
||||
if(v < value_end)
|
||||
*v++ = c;
|
||||
break;
|
||||
case WAIT:
|
||||
if(c == '#')
|
||||
NEXT(COMMENT);
|
||||
if(c == '/') {
|
||||
state =
|
||||
break;
|
||||
default: /* can't happen */
|
||||
die("invalid state");
|
||||
accept:
|
||||
|
||||
*v = 0;
|
||||
*rule = emallocz(sizeof **rule);
|
||||
(*rule)->regex = regcomp(regex);
|
||||
if((*rule)->regex) {
|
||||
(*rule)->value = strdup(buffer);
|
||||
trim((*rule)->value, " \t");
|
||||
|
||||
rvp = &(*rule)->values;
|
||||
m = ixp_message(buffer, v - buffer, MsgUnpack);
|
||||
while((r = msg_getword(&m)))
|
||||
if((v = strchr(r, '='))) {
|
||||
len = strlen(r) + 1;
|
||||
*rvp = rv = emalloc(sizeof *rv + len);
|
||||
rvp = &rv->next;
|
||||
|
||||
memcpy(&rv[1], r, len);
|
||||
tokenize(&rv->key, 2, (char*)&rv[1], '=');
|
||||
}
|
||||
|
||||
|
||||
rule = &(*rule)->next;
|
||||
}else
|
||||
free(*rule);
|
||||
|
||||
r = regex;
|
||||
|
||||
break;
|
||||
}
|
||||
putc(&valuebuf, c);
|
||||
}
|
||||
|
||||
putc(&rebuf, '\0');
|
||||
re = regcomp(regexp);
|
||||
if(!re)
|
||||
goto begin;
|
||||
r = emallocz(sizeof *r);
|
||||
*rule = r;
|
||||
rule = &r->next;
|
||||
r->regex = re;
|
||||
|
||||
valuebuf.end = valuebuf.pos;
|
||||
valuebuf.pos = valuebuf.data;
|
||||
rvp = &r->values;
|
||||
while((w = msg_getword(&valuebuf))) {
|
||||
free(r->value);
|
||||
r->value = estrdup(w);
|
||||
if(strchr(w, '=')) {
|
||||
len = strlen(w) + 1;
|
||||
*rvp = rv = emallocz(sizeof *rv + len);
|
||||
rvp = &rv->next;
|
||||
|
||||
memcpy(&rv[1], w, len);
|
||||
tokenize(&rv->key, 2, (char*)&rv[1], '=');
|
||||
}
|
||||
}
|
||||
goto begin;
|
||||
|
||||
done:
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user