Experimental new /rules file to replace /tagrules. Case insensitive ctl file writes.

This commit is contained in:
Kris Maglione 2010-05-30 23:33:19 -04:00
parent 612b959af5
commit 0801547846
7 changed files with 166 additions and 156 deletions

View File

@ -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++) {

View File

@ -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')

View File

@ -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;

View File

@ -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*);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
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");
if(!data || !data[0])
return;
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);
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;
}
}
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], r, len);
memcpy(&rv[1], w, len);
tokenize(&rv->key, 2, (char*)&rv[1], '=');
}
rule = &(*rule)->next;
}else
free(*rule);
r = regex;
break;
}
goto begin;
done:
return;
}