[hackers] [wmii] Change format of bar files. Refactor fs.c. Add M-n/M-b to rc scripts. Add showkeys to plan9port rc. Update docs. Linkify code fragments in wmii.tex. || Kris Maglione

From: <hg_AT_suckless.org>
Date: Fri, 25 Jun 2010 21:22:23 +0000 (UTC)

changeset: 2743:9d31d13386b8
tag: tip
user: Kris Maglione <kris_AT_suckless.org>
date: Fri Jun 25 17:21:12 2010 -0400
files: alternative_wmiircs/plan9port/wmiirc alternative_wmiircs/python/pygmi/fs.py cmd/wmii.rc.rc cmd/wmii.sh.sh cmd/wmii/bar.c cmd/wmii/dat.h cmd/wmii/fns.h cmd/wmii/fs.c cmd/wmii/message.c doc/wmii.tex include/stuff/base.h man/wmii.man1 rc/wmiirc.sh
description:
Change format of bar files. Refactor fs.c. Add M-n/M-b to rc scripts. Add showkeys to plan9port rc. Update docs. Linkify code fragments in wmii.tex.

diff -r b69ff38fcfd3 -r 9d31d13386b8 alternative_wmiircs/plan9port/wmiirc
--- a/alternative_wmiircs/plan9port/wmiirc Thu Jun 24 11:03:52 2010 -0400
+++ b/alternative_wmiircs/plan9port/wmiirc Fri Jun 25 17:21:12 2010 -0400
@@ -61,8 +61,8 @@
 
 # Status Bar Info
 fn status {
- echo -n `{uptime | sed 's/.*://; s/,//g'} '|' \
- `{date} }
+ echo -n label `{uptime | sed 's/.*://; s/,//g'} '|' \
+ `{date} }
 
 # Generic overridable startup details
 fn startup { witray & }
@@ -86,19 +86,19 @@
         wi_cleankeys}
 
 fn Event-CreateTag {
- echo $wmiinormcol $* | wmiir create /lbar/$"*}
+ echo colors $wmiinormcol $wi_newline label $* | wmiir create /lbar/$"*}
 fn Event-DestroyTag {
         wmiir remove /lbar/$"*}
 fn Event-FocusTag {
- wmiir xwrite /lbar/$"* $wmiifocuscol $*}
+ wmiir xwrite /lbar/$"* colors $wmiifocuscol}
 fn Event-UnfocusTag {
- wmiir xwrite /lbar/$"* $wmiinormcol $*}
+ wmiir xwrite /lbar/$"* colors $wmiinormcol}
 fn Event-UrgentTag {
         shift
- wmiir xwrite /lbar/$"* '*'$"*}
+ wmiir xwrite /lbar/$"* label '*'$"*}
 fn Event-NotUrgentTag {
         shift
- wmiir xwrite /lbar/$"* $"*}
+ wmiir xwrite /lbar/$"* label $"*}
 fn Event-AreaFocus {
         if(~ $1 '~')
                 setbackground $wmiifloatbackground
@@ -116,7 +116,7 @@
                         wmiir xwrite /client/$client/ctl slay
         }&}
 fn Event-Notice {
- wmiir xwrite $noticebar $wi_arg
+ wmiir xwrite $noticebar label $wi_arg
 
         /bin/kill $xpid >[2]/dev/null # Let's hope this isn't reused...
         { sleep $noticetimeout; wmiir xwrite $noticebar ' ' }& # Bug...
@@ -152,21 +152,24 @@
         wi_fnmenu LBar $* &}
 
 # Actions
+fn Action-exec {
+ wmiir xwrite /ctl exec $*}
+fn Action-quit {
+ wmiir xwrite /ctl quit}
 fn Action-rehash {
         comm -23 <{ls `{namespace}^/proglist.* >[2]/dev/null | awk -F'.' '{print $NF}'} \
                  <{ps | awk '{print $2}'} |
         while(id=`{read})
                 rm `{namespace}^/proglist.$id
         wi_proglist $PATH >$progs_file}
-fn Action-quit {
- wmiir xwrite /ctl quit}
-fn Action-exec {
- wmiir xwrite /ctl exec $*}
+fn Action-showkeys {
+ echo $wmiikeyhelp | xmessage -file -
+}
 fn Action-status {
         flag x -; flag r -
         if(wmiir remove /rbar/status >[2]/dev/null)
                 sleep 2
- echo $wmiinormcol | wmiir create /rbar/status
+ echo colors $wmiinormcol | wmiir create /rbar/status
         while(status | wmiir write /rbar/status)
                 sleep 1
 }
@@ -181,14 +184,77 @@
 
 # Key Bindings
 _keys = `{wi_getfuns Key}
+fn keygroup {
+ wmiikeyhelp = $wmiikeyhelp ^ $wi_newline ^ ' ' ^ $"* ^ $wi_newline}
 fn key {
+ help=$1; shift
         key=()
- for(k) if(! ~ $k $_keys) key = ($key Key-$k)
+ for(k) {
+ if(! ~ $k $_keys) {
+ ifs=() { wmiikeyhelp = `{awk 'BEGIN {
+ printf "%s %- 20s %s\n", ENVIRON["wmiikeyhelp"], ENVIRON["k"], ENVIRON["help"]
+ exit }'} }
+ key = ($key Key-$k)}}
         ~ $#key 0}
 
-# This is... ugly.
+keygroup Moving around
+key 'Select the client to the left' $MODKEY-$LEFT || fn $key {
+ wmiir xwrite /tag/sel/ctl select left}
+key 'Select the client to the right' $MODKEY-$RIGHT || fn $key {
+ wmiir xwrite /tag/sel/ctl select right}
+key 'Select the client below' $MODKEY-$DOWN || fn $key {
+ wmiir xwrite /tag/sel/ctl select down}
+key 'Select the client above' $MODKEY-$UP || fn $key {
+ wmiir xwrite /tag/sel/ctl select up}
 
-key $MODKEY-Control-t || fn $key {
+key 'Toggle between floating and managed layers' $MODKEY-space || fn $key {
+ wmiir xwrite /tag/sel/ctl select toggle}
+
+keygroup Moving through stacks
+key 'Select the stack below' $MODKEY-Control-$DOWN || fn $key {
+ wmiir xwrite /tag/sel/ctl select down stack}
+key 'Select the stack above' $MODKEY-Control-$UP || fn $key {
+ wmiir xwrite /tag/sel/ctl select up stack}
+
+keygroup Moving clients around
+key 'Move selected client to the left' $MODKEY-Shift-$LEFT || fn $key {
+ wmiir xwrite /tag/sel/ctl send sel left}
+key 'Move selected client to the right' $MODKEY-Shift-$RIGHT || fn $key {
+ wmiir xwrite /tag/sel/ctl send sel right}
+key 'Move selected client down' $MODKEY-Shift-$DOWN || fn $key {
+ wmiir xwrite /tag/sel/ctl send sel down}
+key 'Move selected client up' $MODKEY-Shift-$UP || fn $key {
+ wmiir xwrite /tag/sel/ctl send sel up}
+
+key 'Toggle selected client between floating and managed layers' $MODKEY-Shift-space || fn $key {
+ wmiir xwrite /tag/sel/ctl send sel toggle}
+
+keygroup Client actions
+key 'Toggle selected client''s fullsceen state' $MODKEY-f || fn $key {
+ wmiir xwrite /client/sel/ctl Fullscreen toggle}
+key 'Close client' $MODKEY-Shift-c || fn $key {
+ wmiir xwrite /client/sel/ctl kill}
+
+keygroup Changing column modes
+key 'Set column to default mode' $MODKEY-d || fn $key {
+ wmiir xwrite /tag/sel/ctl colmode sel default-max}
+key 'Toggle between floating and managed layers' $MODKEY-s || fn $key {
+ wmiir xwrite /tag/sel/ctl colmode sel stack-max}
+key 'Set column to max mode' $MODKEY-m || fn $key {
+ wmiir xwrite /tag/sel/ctl colmode sel stack+max}
+
+keygroup Running programs
+key 'Open wmii actions menu' $MODKEY-a || fn $key {
+ Action `{wi_actions | wimenu -h $hist.action -n $histlen} &}
+key 'Open program menu' $MODKEY-p || fn $key {
+ ifs=() { cmd = `{wimenu -h $hist.prog -n $histlen <$progs_file} }
+ wi_runcmd $cmd & }
+
+key 'Launch a terminal' $MODKEY-Return || fn $key {
+ wi_runcmd $WMII_TERM &}
+
+keygroup Other
+key 'Toggle all other key bindings' $MODKEY-Control-t || fn $key {
         switch(`{wmiir read /keys | wc -l}) {
         case 0 1
                 wmiir xwrite /keys $keys
@@ -199,66 +265,22 @@
                 wmiir xwrite /ctl grabmod Mod3
         }}
 
-key $MODKEY-$LEFT || fn $key {
- wmiir xwrite /tag/sel/ctl select left}
-key $MODKEY-$RIGHT || fn $key {
- wmiir xwrite /tag/sel/ctl select right}
-key $MODKEY-$DOWN || fn $key {
- wmiir xwrite /tag/sel/ctl select down}
-key $MODKEY-$UP || fn $key {
- wmiir xwrite /tag/sel/ctl select up}
-key $MODKEY-Control-$DOWN || fn $key {
- wmiir xwrite /tag/sel/ctl select down stack}
-key $MODKEY-Control-$UP || fn $key {
- wmiir xwrite /tag/sel/ctl select up stack}
-
-key $MODKEY-Shift-$LEFT || fn $key {
- wmiir xwrite /tag/sel/ctl send sel left}
-key $MODKEY-Shift-$RIGHT || fn $key {
- wmiir xwrite /tag/sel/ctl send sel right}
-key $MODKEY-Shift-$DOWN || fn $key {
- wmiir xwrite /tag/sel/ctl send sel down}
-key $MODKEY-Shift-$UP || fn $key {
- wmiir xwrite /tag/sel/ctl send sel up}
-
-key $MODKEY-f || fn $key {
- wmiir xwrite /client/sel/ctl Fullscreen toggle}
-
-key $MODKEY-space || fn $key {
- wmiir xwrite /tag/sel/ctl select toggle}
-key $MODKEY-Shift-space || fn $key {
- wmiir xwrite /tag/sel/ctl send sel toggle}
-key $MODKEY-d || fn $key {
- wmiir xwrite /tag/sel/ctl colmode sel default-max}
-key $MODKEY-s || fn $key {
- wmiir xwrite /tag/sel/ctl colmode sel stack-max}
-key $MODKEY-m || fn $key {
- wmiir xwrite /tag/sel/ctl colmode sel stack+max}
-
-key $MODKEY-Shift-c || fn $key {
- wmiir xwrite /client/sel/ctl kill}
-
-key $MODKEY-a || fn $key {
- Action `{wi_actions | wimenu -h $hist.action -n $histlen} &}
-key $MODKEY-p || fn $key {
- ifs=() { cmd = `{wimenu -h $hist.prog -n $histlen <$progs_file} }
- wi_runcmd $cmd & }
-
-key $MODKEY-Return || fn $key {
- wi_runcmd $WMII_TERM &}
-
-key $MODKEY-t || fn $key {
+keygroup Tag actions
+key 'Change to another tag' $MODKEY-t || fn $key {
         tag=`{wi_tags | wimenu -h $hist.tag -n 50} && wmiir xwrite /ctl view $tag &}
-key $MODKEY-Shift-t || fn $key {
+key 'Retag the selected client' $MODKEY-Shift-t || fn $key {
         sel=`{wi_selclient} {
         tag=`{wi_tags | wimenu -h $hist.tag -n 50} && wmiir xwrite /client/$sel/tags $tag } &}
+key 'Move to the next tag' $MODKEY-n || fn $key {
+ wmiir xwrite /ctl view `{wi_tags | wi_nexttag}}
+key 'Move to the previous tag' $MODKEY-b || fn $key {
+ wmiir xwrite /ctl view `{wi_tags | sort -r | wi_nexttag}}
 
-key $MODKEY-^`{seq 0 9} || fn $key {
+key 'Move to the numbered view' $MODKEY-^`{seq 0 9} || fn $key {
         wmiir xwrite /ctl view `{echo $1 | sed 's/.*-//'}}
-key Shift-$MODKEY-^`{seq 0 9} || fn $key {
+key 'Retag selected client with the numbered tag' Shift-$MODKEY-^`{seq 0 9} || fn $key {
         wmiir xwrite /client/sel/tags `{echo $1 | sed 's/.*-//'}}
-
-#` WM Configuration
+# WM Configuration
 wmiir write /ctl <<!
         grabmod $MODKEY
         border 2
@@ -286,10 +308,8 @@
         seltag=`{wi_seltag}
         for(tag in `{wi_tags}) {{
                 if(~ $tag $seltag)
- echo $wmiifocuscol $tag
+ echo colors $wmiifocuscol $wi_newline label $tag
                 if not
- echo $wmiinormcol $tag
+ echo colors $wmiinormcol $wi_newline label $tag
                 } | wmiir create /lbar/$tag}}
-
 wi_eventloop
-
diff -r b69ff38fcfd3 -r 9d31d13386b8 alternative_wmiircs/python/pygmi/fs.py
--- a/alternative_wmiircs/python/pygmi/fs.py Thu Jun 24 11:03:52 2010 -0400
+++ b/alternative_wmiircs/python/pygmi/fs.py Fri Jun 25 17:21:12 2010 -0400
@@ -452,82 +452,6 @@
         frame = self.framespec(frame)
         self['grow'] = '%s %s %s' % (frame, dir, str(amount or ''))
 
-class Button(object):
- sides = {
- 'left': 'lbar',
- 'right': 'rbar',
- }
- def __init__(self, side, name, colors=None, label=None):
- self.side = side
- self.name = name
- self.base_path = self.sides[side]
- self.path = '%s/%s' % (self.base_path, self.name)
- self.file = None
- self._colors = wmii.cache['normcolors']
- self._label = ''
- if colors or label:
- self.create(colors, label)
-
- def create(self, colors=None, label=None):
- def fail(resp, exc, tb):
- self.file = None
- if not self.file:
- self.file = client.create(self.path, ORDWR)
- if colors or label:
- self.file.awrite(self.getval(colors, label), offset=0, fail=fail)
-
- def remove(self):
- if self.file:
- self.file.aremove()
- self.file = None
-
- def getval(self, colors=None, label=None):
- if label is not None:
- self._label = label
- if colors is not None:
- self._colors = colors
- return ' '.join([Color(c).hex for c in self._colors or self.colors] + [unicode(self._label or '')])
-
- colors = property(
- lambda self: self.file and Colors(self.file.read(offset=0).split(' ')[:3]) or (),
- lambda self, val: self.create(colors=val))
-
- label = property(
- lambda self: self.file and self.file.read(offset=0).split(' ', 3)[3] or '',
- lambda self, val: self.create(label=val))
-
- @classmethod
- def all(cls, side):
- return (Button(side, s.name)
- for s in client.readdir(cls.sides[side])
- if s.name != 'sel')
-
-class Colors(utf8):
- def __init__(self, foreground=None, background=None, border=None):
- vals = foreground, background, border
- self.vals = tuple(map(Color, vals))
-
- def __iter__(self):
- return iter(self.vals)
- def __list__(self):
- return list(self.vals)
- def __tuple__(self):
- return self.vals
-
- @classmethod
- def from_string(cls, val):
- return cls(*val.split(' '))
-
- def __getitem__(self, key):
- if isinstance(key, basestring):
- key = {'foreground': 0, 'background': 1, 'border': 2}[key]
- return self.vals[key]
-
- def __unicode__(self):
- return ' '.join(c.hex for c in self.vals)
- def __repr__(self):
- return 'Colors(%s, %s, %s)' % tuple(repr(c.rgb) for c in self.vals)
-
 class Color(utf8):
     def __init__(self, colors):
         if isinstance(colors, Color):
@@ -563,6 +487,73 @@
     def __repr__(self):
         return 'Color(%s)' % repr(self.rgb)
 
+class Colors(utf8):
+ def __init__(self, foreground=None, background=None, border=None):
+ vals = foreground, background, border
+ self.vals = tuple(map(Color, vals))
+
+ def __iter__(self):
+ return iter(self.vals)
+ def __list__(self):
+ return list(self.vals)
+ def __tuple__(self):
+ return self.vals
+
+ @classmethod
+ def from_string(cls, val):
+ return cls(*val.split(' '))
+
+ def __getitem__(self, key):
+ if isinstance(key, basestring):
+ key = {'foreground': 0, 'background': 1, 'border': 2}[key]
+ return self.vals[key]
+
+ def __unicode__(self):
+ return ' '.join(c.hex for c in self.vals)
+ def __repr__(self):
+ return 'Colors(%s, %s, %s)' % tuple(repr(c.rgb) for c in self.vals)
+
+class Button(Ctl):
+ sides = {
+ 'left': 'lbar',
+ 'right': 'rbar',
+ }
+ ctl_types = {
+ 'colors': (Colors.from_string, lambda c: str(Colors(*c))),
+ }
+ colors = Dir.ctl_property('colors')
+ label = Dir.ctl_property('label')
+
+ def __init__(self, side, name, colors=None, label=None):
+ super(Button, self).__init__()
+ self.side = side
+ self.name = name
+ self.base_path = self.sides[side]
+ self.ctl_path = '%s/%s' % (self.base_path, self.name)
+ self.file = None
+ self.create(colors, label)
+
+ def create(self, colors=None, label=None):
+ def fail(resp, exc, tb):
+ self.file = None
+ if not self.file:
+ self.file = client.create(self.ctl_path, ORDWR)
+ if colors:
+ self.colors = colors
+ if label:
+ self.label = label
+
+ def remove(self):
+ if self.file:
+ self.file.aremove()
+ self.file = None
+
+ @classmethod
+ def all(cls, side):
+ return (Button(side, s.name)
+ for s in client.readdir(cls.sides[side])
+ if s.name != 'sel')
+
 class Rules(collections.MutableMapping, utf8):
 
     _items = ()
diff -r b69ff38fcfd3 -r 9d31d13386b8 cmd/wmii.rc.rc
--- a/cmd/wmii.rc.rc Thu Jun 24 11:03:52 2010 -0400
+++ b/cmd/wmii.rc.rc Fri Jun 25 17:21:12 2010 -0400
@@ -9,6 +9,7 @@
 
 wmiiscript=$1
 wmiikeys=()
+wmiikeyhelp=''
 
 wi_newline='
 '
@@ -134,15 +135,21 @@
         wmiir read /client/sel/ctl | sed 1q
 }
 
-fn wi_readevent {
- wmiir read /event
+fn wi_nexttag {
+ awk -v 'curtag='^`{wi_seltag} '
+ NR==1 {first = $0}
+ $0==curtag { if(getline) print $0; else print first; exit }'
 }
 
 fn wi_eventloop {
         wi_initkeys
 
- wi_readevent |
- while(ifs=$wi_ewlinel{wi_event=`{read}}) {
+ {
+ if(~ $1 -i)
+ cat
+ if not
+ wmiir read /event
+ } | while(ifs=$wi_newline{wi_event=`{read}}) {
                 ifs=$wi_newline{
                         wi_arg=`{echo $wi_event | sed 's/^[^ ]+ //'}}
                 * = `{echo $wi_event}
diff -r b69ff38fcfd3 -r 9d31d13386b8 cmd/wmii.sh.sh
--- a/cmd/wmii.sh.sh Thu Jun 24 11:03:52 2010 -0400
+++ b/cmd/wmii.sh.sh Fri Jun 25 17:21:12 2010 -0400
@@ -86,10 +86,6 @@
 
 _wi_text() {
         cat <<'!'
-Event Start
- if [ "$1" = "$wmiiscript" ]; then
- exit
- fi
 Event Key
         Key "$@"
 !
@@ -188,6 +184,12 @@
         wmiir read /client/sel/ctl | sed 1q | tr -d '\012'
 }
 
+wi_nexttag() {
+ awk -v curtag=$(wi_seltag) '
+ NR==1 {first = $0}
+ $0==curtag { if(getline) print $0; else print first; exit }'
+}
+
 wi_eventloop() {
         echo "$Keys" | wmiir write /keys
 
@@ -201,6 +203,8 @@
                 unset IFS
                 set -- $wi_event
                 event=$1; shift
+ [ "$event" = Start -a "$1" = "$wmiiscript" ] &&
+ exit
                 ( Event $event "$@" )
         done
         true
diff -r b69ff38fcfd3 -r 9d31d13386b8 cmd/wmii/bar.c
--- a/cmd/wmii/bar.c Thu Jun 24 11:03:52 2010 -0400
+++ b/cmd/wmii/bar.c Fri Jun 25 17:21:12 2010 -0400
@@ -194,34 +194,6 @@
         copyimage(s->barwin, r, disp.ibuf, ZP);
 }
 
-void
-bar_load(Bar *b) {
- IxpMsg m;
- char *p, *q;
-
- p = b->buf;
- m = ixp_message(p, strlen(p), 0);
-
- if(!waserror()) { /* Ignore errors. */
- msg_parsecolors(&m, &b->col);
- poperror();
- }
-
- q = (char*)m.end-1;
- while(q >= (char*)m.pos && *q == '\n')
- *q-- = '\0';
-
- q = b->text;
- utflcpy(q, (char*)m.pos, sizeof b->text);
-
- p[0] = '\0';
- strlcat(p, b->col.colstr, sizeof b->buf);
- strlcat(p, " ", sizeof b->buf);
- strlcat(p, b->text, sizeof b->buf);
-
- bar_draw(b->screen);
-}
-
 Bar*
 bar_find(Bar *bp, const char *name) {
         Bar *b;
diff -r b69ff38fcfd3 -r 9d31d13386b8 cmd/wmii/dat.h
--- a/cmd/wmii/dat.h Thu Jun 24 11:03:52 2010 -0400
+++ b/cmd/wmii/dat.h Fri Jun 25 17:21:12 2010 -0400
@@ -303,7 +303,8 @@
 #endif
 
 /* global variables */
-EXTERN struct {
+typedef struct Defs Defs;
+EXTERN struct Defs {
         CTuple focuscolor;
         CTuple normcolor;
         Font* font;
diff -r b69ff38fcfd3 -r 9d31d13386b8 cmd/wmii/fns.h
--- a/cmd/wmii/fns.h Thu Jun 24 11:03:52 2010 -0400
+++ b/cmd/wmii/fns.h Fri Jun 25 17:21:12 2010 -0400
@@ -69,7 +69,6 @@
 void bar_draw(WMScreen*);
 Bar* bar_find(Bar*, const char*);
 void bar_init(WMScreen*);
-void bar_load(Bar*);
 void bar_resize(WMScreen*);
 void bar_sety(WMScreen*, int);
 void bar_setbounds(WMScreen*, int, int);
@@ -210,6 +209,7 @@
 
 /* message.c */
 char* mask(char**, int*, int*);
+char* message_bar(Bar*, IxpMsg*);
 char* message_client(Client*, IxpMsg*);
 char* message_root(void*, IxpMsg*);
 char* message_view(View*, IxpMsg*);
@@ -219,6 +219,7 @@
 void msg_parsecolors(IxpMsg*, CTuple*);
 char* msg_selectarea(Area*, IxpMsg*);
 char* msg_sendclient(View*, IxpMsg*, bool swap);
+char* readctl_bar(Bar*);
 char* readctl_client(Client*);
 char* readctl_root(void);
 char* readctl_view(View*);
diff -r b69ff38fcfd3 -r 9d31d13386b8 cmd/wmii/fs.c
--- a/cmd/wmii/fs.c Thu Jun 24 11:03:52 2010 -0400
+++ b/cmd/wmii/fs.c Fri Jun 25 17:21:12 2010 -0400
@@ -123,6 +123,28 @@
         [FsDTag] = dirtab_tag,
 };
 typedef char* (*MsgFunc)(void*, IxpMsg*);
+typedef char* (*BufFunc)(void*);
+
+typedef struct ActionTab ActionTab;
+static struct ActionTab {
+ MsgFunc msg;
+ BufFunc read;
+ size_t buffer;
+ size_t size;
+ int max;
+} actiontab[] = {
+ [FsFBar] = { .msg = (MsgFunc)message_bar, .read = (BufFunc)readctl_bar },
+ [FsFCctl] = { .msg = (MsgFunc)message_client, .read = (BufFunc)readctl_client },
+ [FsFRctl] = { .msg = (MsgFunc)message_root, .read = (BufFunc)readctl_root },
+ [FsFTctl] = { .msg = (MsgFunc)message_view, .read = (BufFunc)readctl_view },
+ [FsFTindex] = { .msg = (MsgFunc)0, .read = (BufFunc)view_index },
+ [FsFColRules] = { .buffer = offsetof(Ruleset, string), .size = offsetof(Ruleset, size) },
+ [FsFKeys] = { .buffer = offsetof(Defs, keys), .size = offsetof(Defs, keyssz) },
+ [FsFRules] = { .buffer = offsetof(Ruleset, string), .size = offsetof(Ruleset, size) },
+ [FsFClabel] = { .buffer = offsetof(Client, name), .max = sizeof ((Client*)0)->name },
+ [FsFCtags] = { .buffer = offsetof(Client, tags), .max = sizeof ((Client*)0)->tags },
+ [FsFprops] = { .buffer = offsetof(Client, props), .max = sizeof ((Client*)0)->props },
+};
 
 void
 event(const char *format, ...) {
@@ -335,6 +357,9 @@
                         case FsFColRules:
                                 file->p.rule = &def.colrules;
                                 break;
+ case FsFKeys:
+ file->p.ref = &def;
+ break;
                         case FsFRules:
                                 file->p.rule = &def.rules;
                                 break;
@@ -374,21 +399,19 @@
 
 static uint
 fs_size(IxpFileId *f) {
- switch(f->tab.type) {
- default:
- return 0;
- case FsFColRules:
- case FsFRules:
- return f->p.rule->size;
- case FsFKeys:
- return def.keyssz;
- case FsFCtags:
- return strlen(f->p.client->tags);
- case FsFClabel:
- return strlen(f->p.client->name);
- case FsFprops:
- return strlen(f->p.client->props);
- }
+ ActionTab *t;
+
+ t = &actiontab[f->tab.type];
+ if(f->tab.type < nelem(actiontab))
+ if(t->size)
+ return structmember(f->p.ref, int, t->size);
+ else if(t->buffer && t->max)
+ return strlen(structptr(f->p.ref, char, t->buffer));
+ else if(t->buffer)
+ return strlen(structmember(f->p.ref, char*, t->buffer));
+ else if(t->read)
+ return strlen(t->read(f->p.ref));
+ return 0;
 }
 
 void
@@ -422,9 +445,11 @@
 fs_read(Ixp9Req *r) {
         char *buf;
         IxpFileId *f;
- int n;
+ ActionTab *t;
+ int n, found;
 
         f = r->fid->aux;
+ found = 0;
 
         if(!ixp_srv_verifyfile(f, lookup_file)) {
                 ixp_respond(r, Enofile);
@@ -440,53 +465,26 @@
                         ixp_pending_respond(r);
                         return;
                 }
- switch(f->tab.type) {
- case FsFprops:
- ixp_srv_readbuf(r, f->p.client->props, strlen(f->p.client->props));
- ixp_respond(r, nil);
- return;
- case FsFColRules:
- case FsFRules:
- ixp_srv_readbuf(r, f->p.rule->string, f->p.rule->size);
- ixp_respond(r, nil);
- return;
- case FsFKeys:
- ixp_srv_readbuf(r, def.keys, def.keyssz);
- ixp_respond(r, nil);
- return;
- case FsFCtags:
- ixp_srv_readbuf(r, f->p.client->tags, strlen(f->p.client->tags));
- ixp_respond(r, nil);
- return;
- case FsFClabel:
- ixp_srv_readbuf(r, f->p.client->name, strlen(f->p.client->name));
- ixp_respond(r, nil);
- return;
- case FsFBar:
- ixp_srv_readbuf(r, f->p.bar->buf, strlen(f->p.bar->buf));
- ixp_respond(r, nil);
- return;
- case FsFRctl:
- buf = readctl_root();
- ixp_srv_readbuf(r, buf, strlen(buf));
- ixp_respond(r, nil);
- return;
- case FsFCctl:
- buf = readctl_client(f->p.client);
- ixp_srv_readbuf(r, buf, strlen(buf));
- ixp_respond(r, nil);
- return;
- case FsFTindex:
- buf = view_index(f->p.view);
- ixp_srv_readbuf(r, buf, strlen(buf));
- ixp_respond(r, nil);
- return;
- case FsFTctl:
- buf = readctl_view(f->p.view);
- n = strlen(buf);
+ t = &actiontab[f->tab.type];
+ if(f->tab.type < nelem(actiontab)) {
+ if(t->read)
+ buf = t->read(f->p.ref);
+ else if(t->buffer && t->max)
+ buf = structptr(f->p.ref, char, t->buffer);
+ else if(t->buffer)
+ buf = structmember(f->p.ref, char*, t->buffer);
+ else
+ goto done;
+ n = t->size ? structmember(f->p.ref, int, t->size) : strlen(buf);
                         ixp_srv_readbuf(r, buf, n);
                         ixp_respond(r, nil);
- return;
+ found++;
+ }
+ done:
+ switch(f->tab.type) {
+ default:
+ if(found)
+ return;
                 }
         }
         /* This should not be called if the file is not open for reading. */
@@ -495,12 +493,13 @@
 
 void
 fs_write(Ixp9Req *r) {
- MsgFunc mf;
         IxpFileId *f;
+ ActionTab *t;
         char *errstr;
- char *p;
- uint i;
+ int found;
 
+ found = 0;
+ errstr = nil;
         if(r->ifcall.io.count == 0) {
                 ixp_respond(r, nil);
                 return;
@@ -517,25 +516,30 @@
                 return;
         }
 
+ t = &actiontab[f->tab.type];
+ if(f->tab.type < nelem(actiontab)) {
+ if(t->msg) {
+ errstr = ixp_srv_writectl(r, t->msg);
+ r->ofcall.io.count = r->ifcall.io.count;
+ }
+ else if(t->buffer && t->max)
+ ixp_srv_writebuf(r, (char*[]){ structptr(f->p.ref, char, t->buffer) },
+ t->size ? structptr(f->p.ref, uint, t->size) : nil,
+ t->max);
+ else if(t->buffer)
+ ixp_srv_writebuf(r, structptr(f->p.ref, char*, t->buffer),
+ t->size ? structptr(f->p.ref, uint, t->size) : nil,
+ t->max);
+ else
+ goto done;
+ ixp_respond(r, nil);
+ found++;
+ }
+done:
         switch(f->tab.type) {
- case FsFColRules:
- case FsFRules:
- ixp_srv_writebuf(r, &f->p.rule->string, &f->p.rule->size, 0);
- ixp_respond(r, nil);
- break;
- case FsFKeys:
- ixp_srv_writebuf(r, &def.keys, &def.keyssz, 0);
- ixp_respond(r, nil);
- break;
         case FsFClabel:
- ixp_srv_data2cstring(r);
- utfecpy(f->p.client->name,
- f->p.client->name + sizeof client->name,
- r->ifcall.io.data);
                 frame_draw(f->p.client->sel);
                 update_class(f->p.client);
- r->ofcall.io.count = r->ifcall.io.count;
- ixp_respond(r, nil);
                 break;
         case FsFCtags:
                 ixp_srv_data2cstring(r);
@@ -543,28 +547,6 @@
                 r->ofcall.io.count = r->ifcall.io.count;
                 ixp_respond(r, nil);
                 break;
- case FsFBar:
- i = strlen(f->p.bar->buf);
- p = f->p.bar->buf;
- ixp_srv_writebuf(r, &p, &i, 279);
- bar_load(f->p.bar);
- r->ofcall.io.count = i - r->ifcall.io.offset;
- ixp_respond(r, nil);
- break;
- case FsFCctl:
- mf = (MsgFunc)message_client;
- goto msg;
- case FsFTctl:
- mf = (MsgFunc)message_view;
- goto msg;
- case FsFRctl:
- mf = (MsgFunc)message_root;
- goto msg;
- msg:
- errstr = ixp_srv_writectl(r, mf);
- r->ofcall.io.count = r->ifcall.io.count;
- ixp_respond(r, errstr);
- break;
         case FsFEvent:
                 if(r->ifcall.io.data[r->ifcall.io.count-1] == '\n')
                         event("%.*s", (int)r->ifcall.io.count, r->ifcall.io.data);
@@ -575,7 +557,8 @@
                 break;
         default:
                 /* This should not be called if the file is not open for writing. */
- die("Write called on an unwritable file");
+ if(!found)
+ die("Write called on an unwritable file");
         }
         poperror();
         return;
@@ -652,7 +635,6 @@
                 return;
         }
 
-
         switch(f->tab.type) {
         default:
                 ixp_respond(r, Enoperm);
@@ -661,9 +643,12 @@
                 s = f->p.bar->screen;
                 bar_destroy(f->next->p.bar_p, f->p.bar);
                 bar_draw(s);
- ixp_respond(r, nil);
+ break;
+ case FsDClient:
+ client_kill(f->p.client, true);
                 break;
         }
+ ixp_respond(r, nil);
 }
 
 void
diff -r b69ff38fcfd3 -r 9d31d13386b8 cmd/wmii/message.c
--- a/cmd/wmii/message.c Thu Jun 24 11:03:52 2010 -0400
+++ b/cmd/wmii/message.c Fri Jun 25 17:21:12 2010 -0400
@@ -29,6 +29,7 @@
         LBORDER,
         LCLIENT,
         LCOLMODE,
+ LCOLORS,
         LDEBUG,
         LDOWN,
         LEXEC,
@@ -42,6 +43,7 @@
         LGROW,
         LINCMODE,
         LKILL,
+ LLABEL,
         LLEFT,
         LNORMCOLORS,
         LNUDGE,
@@ -68,6 +70,7 @@
         "border",
         "client",
         "colmode",
+ "colors",
         "debug",
         "down",
         "exec",
@@ -81,6 +84,7 @@
         "grow",
         "incmode",
         "kill",
+ "label",
         "left",
         "normcolors",
         "nudge",
@@ -472,6 +476,31 @@
 }
 
 char*
+readctl_bar(Bar *b) {
+ bufclear();
+ bufprint("colors %s\n", b->col.colstr);
+ bufprint("label %s\n", b->text);
+ return buffer;
+}
+
+char*
+message_bar(Bar *b, IxpMsg *m) {
+
+ switch(getsym(msg_getword(m, nil))) {
+ case LCOLORS:
+ msg_parsecolors(m, &b->col);
+ break;
+ case LLABEL:
+ utflcpy(b->text, (char*)m->pos, sizeof b->text);
+ break;
+ default:
+ error(Ebadvalue);
+ }
+ bar_draw(b->screen);
+ return nil;
+}
+
+char*
 readctl_client(Client *c) {
         bufclear();
         bufprint("%#C\n", c);
diff -r b69ff38fcfd3 -r 9d31d13386b8 doc/wmii.tex
--- a/doc/wmii.tex Thu Jun 24 11:03:52 2010 -0400
+++ b/doc/wmii.tex Fri Jun 25 17:21:12 2010 -0400
@@ -13,7 +13,12 @@
 \usepackage{xcolor}
 \usepackage[xetex,breaklinks,colorlinks,linkcolor=black]{hyperref}
 
-% Indexes
+\let\EA=\expandafter
+
+\newif\ifexpandfragments
+\newif\ifdefinefragments
+
+%% Indexes
 \makeindex
 \let\primary=\textbf
 
@@ -26,36 +31,63 @@
 
 \def\man#1#2{#2\textbf{(#1)}}
 
-% Key specs
+\makeatletter
+
+%% Key specs
 \def\key#1{{\small$\langle$\addfontfeature{Numbers=Lining}#1\/$\rangle$}}
 \let\<=<
 \catcode`\<=\active
 \def<#1>{\key{#1}}
 
-% Display ‹...› and «...» as text in left and right pointing
-% angle brackets. I use «» and ‹› because my terminal doesn't
-% display left and right pointing angle brackets properly, and
-% Xorg's compose maps don't provide them, anyway.
+%% Display ‹...› and «...» as text in left and right pointing
+%% angle brackets. I use «» and ‹› because my terminal doesn't
+%% display left and right pointing angle brackets properly, and
+%% Xorg's compose maps don't provide them, anyway.
+\def\«{«}\def\‹{‹}
 \catcode`\«=\active
 \catcode`\‹=\active
 \def‹#1›{$\langle${\itshape#1}$\rangle$}
 \def«#1»{$\langle\langle${\itshape#1}$\rangle\rangle$}
 
+\catcode`\∅=\active
+\def∅{\box0}
+\def«{%
+ \let\dofragment_AT_target=\hyperlink%
+ \@ifnextchar*\dofragment@@\dofragment@}
+\def\dofragment@@*{%
+ \let\dofragment_AT_target=\hypertarget%
+ \dofragment@}
+\def\dofragment@#1»{%
+ \setbox0=\hbox{$\langle\langle${\itshape#1}$\rangle\rangle$}%
+ \ifexpandfragments%
+ \def\a{\sp\sp\comment \boxzero^^J}%
+ \begingroup%
+ \def\ { }\xdef\@frag_AT_name{#1}%
+ \endgroup%
+ \UseFragment{∅}\@frag_AT_name%
+ \else%
+ \dofragment_AT_target{frag:#1}{\box0}%
+ \fi}
+
 % Display |...| as verbatim, teletype text.
 \DefineShortVerb{\|}
 
-\makeatletter
 \let\idx@@heading\chapter
-\let\:=:
-\catcode`\:=\active
-\def:{\@ifnextchar:{\coloncoloneq}{\:}}
-\def\coloncoloneq#1{\@ifnextchar={$\Coloneqq$\coloncoloneqq}{\:\:}}
-\def\coloncoloneqq#1{}
+\def\:{:}
+\iffalse
+ \catcode`\:=\active
+ \gdef:{\@ifnextchar:{\coloncoloneq}{\:}}
+ \gdef\coloncoloneq#1{\@ifnextchar={$\Coloneqq$\coloncoloneqq}{\:\:}}
+ \gdef\coloncoloneqq#1{}
+\fi
+\def\≔{≔}
+\catcode`\≔=\active
+\def≔{\ensuremath{\Coloneqq}}
 
-% Create a verbatim {code} environment which highlights strings
-% and comments. Several unicode characters are hacked to replace
-% the grabbed characters, since we can't escape them in the
-% verbatim environment.
+%% Create a verbatim {code} environment which highlights strings
+%% and comments. Several unicode characters are hacked to replace
+%% the grabbed characters, since we can't escape them in the
+%% verbatim environment.
 \colorlet{comment}{gray}
 \colorlet{string}{red!100!black!90}
 \let\‘=‘
@@ -67,17 +99,66 @@
 \catcode`‘=\active
 \def“¶1”{{\color{string}\“¶1”}}%
 \def‘¶1’{{\color{string}\‘¶1’}}%
+\def\comment{\itshape\color{comment}\let“=\“\let‘=\‘\#}
+\def\docodes{\catcode`\#=\active\catcode`“=\active\catcode`‘=\active\catcode`\☺=0}
+\def\dodefineactive{
+ \let#=\comment
+ }
 \DefineVerbatimEnvironment{code}{Verbatim}{xleftmargin=2em,gobble=2,%
- codes={\catcode`\#=\active\catcode`\:=\active\catcode`“=\active\catcode`‘=\active},%
- defineactive={%
- \def#{\itshape\color{comment}\let“=\“\let‘=\‘\#}%
- }}
+ codes={\docodes},%
+ defineactive={\dodefineactive}}
 \catcode`\#=6
 \catcode`“=12
 \catcode`‘=12
 
-% Convenience defs for the various wmii commands, and a few
-% others.
+%% Save code fragments for piecing together later
+\begingroup
+ \catcode`\@=0
+ @catcode`\\=12
+ @gdef_AT_bcode{@detokenize{\begin{code}^^J}}
+ @gdef_AT_ecode{@detokenize{\end{code}^^J}}
+ @catcode`@ =12_AT_gdef@sp{ }
+@endgroup
+
+% Ripped from fancyverb
+% I'm currently rather unfond of it.
+\def\Fragment{\FV_AT_Environment{}{Fragment}}
+\def\FVB_AT_Fragment#1{%
+ \@bsphack
+ \begingroup
+ \FV_AT_UseKeyValues
+ \gdef\Fragment_AT_Name{#1}%
+ \xdef\Fragment_AT_Prefix{\«*#1» \≔^^J}
+ \xdef\TheFragment{}
+ \def\FV_AT_ProcessLine##1{%
+ \edef\frag{\detokenize{##1^^J}}%
+ \xdef\TheFragment{\TheFragment\frag}}%
+ \FV_AT_Scan}
+\def\FVE_AT_Fragment{%
+ \EA\global\EA\let
+ \csname SV@\Fragment_AT_Name\endcsname\TheFragment%
+ \endgroup%
+ \EA\UseFragment\EA{\Fragment_AT_Prefix}\Fragment_AT_Name}
+\DefineVerbatimEnvironment{Fragment}{Fragment}{}
+
+\def\UseFragment#1#2{
+ \begingroup
+ % \message{UseFragment #2^^J}
+ \EA\let\EA\a\csname SV@#2\endcsname
+ \ifx\a\undefined\def\a{\ldots}\fi
+ \ifx\FV_AT_EnvironName\relax%
+ \edef\a{\bcode\detokenize{++#1}\a\ecode}\else%
+ \edef\a{\detokenize{#1}\a}\fi%
+ \newtoks\tokens
+ \EA\tokens\EA{\a}
+ \everyeof{\noexpand}%
+ % \EA\message\EA{\the\tokens}
+ \scantokens\EA{\the\tokens}
+ \endgroup
+}
+
+%% Convenience defs for the various wmii commands, and a few
+%% others.
 \def\wmii{\texttt{wmii}}
 \def\wiIXmenu{\texttt{wi9menu}}
 \def\wimenu{\texttt{wimenu}}
@@ -125,7 +206,6 @@
 \parindent=0pt
 \parskip=1em
 
-\catcode`\:=12
 Copyright © 2009 Kris Maglione <\href{mailto:maglione.k_AT_gmail.com}{maglione.k_AT_gmail.com}>
 
 Permission is hereby granted, free of charge, to any person obtaining a
@@ -635,8 +715,7 @@
 We'll start building our configuration with an event processing
 framework:
 
-\begin{code}
- «Event Loop» ::=
+\begin{Fragment}{Event Loop}
   # Broadcast a custom event
   wmiir xwrite /event Start wmiirc
 
@@ -657,13 +736,12 @@
       «Event Handlers»
       esac
   done
-\end{code}
+\end{Fragment}
 
 Now, we need to consider which types of events we'll need to
 handle:
 
-\begin{code}
- «Event Handlers» ::=
+\begin{Fragment}{Event Handlers}
   «View Button Events»
   «Urgency Events»
   «Unresponsive Clients»
@@ -671,37 +749,45 @@
   «Key Events»
   «Client Menu Events»
   «Tag Menu Events»
-\end{code}
+\end{Fragment}
 
 \section{Bar Items}
 
 The bar is described by the files in the two directories |/lbar/| and
 |/rbar/| for buttons on the left and right side of the bar,
-respectively. The format of the files is:
+respectively. The files act as control files (section
+\ref{sec:controlfiles}) with the contents:
 
 \begin{code}
- ‹Color Tuple› ‹Label›
+ color ‹Color Tuple›
+ label ‹Label›
 \end{code}
 
-although the color tuple may be elided in cases where the label
-doesn't match its format.
-
 A ‹Color Tuple› is defined as:
 
 \begin{code}
- ‹tuple› ::= ‹foreground color› ‹background color› ‹border color›
- ‹color› ::= #‹6 character RGB hex color code›
+ ‹Color Tuple› ≔ ‹foreground color› ‹background color› ‹border color›
+ ‹* Color› ≔ ‹RGB color› | ‹RGBA color›
+ ‹RGB color› ≔ #‹6 character RGB hex color code›
+ ‹RGBA color› ≔ rgba:‹red›/‹green›/‹blue›/‹alpha›
 \end{code}
 
+\noindent
+where all of the colors are represented as lowercase,
+hexidecimal values. In the case of RGBA colors, they may be 1--4
+characters long, though they will be standardized internally to
+2 characters.
+
+\medskip
+
 Let's define our basic theme information now:
 
-\begin{code}
- «Theme Definitions» ::=
+\begin{Fragment}{Theme Definitions}
   normcolors=‘#000000 #c1c48b #81654f’
   focuscolors=‘#000000 #81654f #000000’
   background=‘#333333’
   font=‘drift,-*-fixed-*-*-*-*-9-*-*-*-*-*-*-*’
-\end{code}
+\end{Fragment}
 
 \subsection{View Buttons}
 
@@ -712,8 +798,7 @@
 \index{events!DestroyTag}
 \index{events!FocusTag}
 \index{events!UnfocusTag}
-\begin{code}
- «View Button Events» ::=
+\begin{Fragment}{View Button Events}
   CreateTag) # CreateTag ‹Tag Name›
       echo $normcolors $1 | wmiir create /lbar/$1;;
   DestroyTag) # DestroyTag ‹Tag Name›
@@ -722,7 +807,7 @@
       wmiir xwrite /lbar/$1 $focuscolors $1;;
   UnfocusTag) # UnfocusTag ‹Tag Name›
       wmiir xwrite /lbar/$1 $normcolors $1;;
-\end{code}
+\end{Fragment}
 
 \subsection{Urgency}
 
@@ -732,13 +817,12 @@
 parlance, this is called urgency. When a window requests
 attention as such, or declares that it's been satisfied, \wmii\
 broadcasts an event for the client and an event for each view
-that it belongs to, and fills in the client's layout box. It's
-the job of a script to decide how to handle it above and beyond
-that. The standard scripts simply mark urgent views with an
-asterisk:
+that it belongs to. It also fills in the layout box of any
+client deemed urgent. It's the job of a script to decide how to
+handle urgency events above and beyond that basic measure. The
+standard scripts simply mark urgent views with an asterisk:
 
-\begin{code}
- «Urgency Events» ::=
+\begin{Fragment}{Urgency Events}
   # The urgency events are ‘Client’ events when the program
   # owning the window sets its urgency state. They're ‘Manager’
   # events when wmii or the wmii user sets the state.
@@ -746,7 +830,7 @@
       wmiir xwrite /lbar/$2 $2;;
   NotUrgentTag) # NotUrgentTag ‹‘Client’ or ‘Manager’› ‹Tag Name›
       wmiir xwrite /lbar/$2 $2;;
-\end{code}
+\end{Fragment}
 \index{events!UrgentTag|)}
 \index{events!NotUrgentTag|)}
 
@@ -756,18 +840,17 @@
 displaying status information. The events appear in the long bar
 between the left and right sides for five seconds.
 
-\begin{code}
- «Notice Events» ::=
+\begin{Fragment}{Notice Events}
   Notice)
       wmiir xwrite /rbar/!notice $line
       kill $xpid 2>/dev/null # Let's hope this isn't reused...
       { sleep 5; wmiir xwrite /rbar/!notice ‘ ’; } &
       xpid = $!;;
-\end{code}
+\end{Fragment}
 
 \section{Keys}
 
-\label{keybindings}
+\label{sec:keybindings}
 \index{key bindings}
 \index{filesystem!/!keys}
 \index{filesystem!/!event}
@@ -798,8 +881,7 @@
 
 Now, let's bind the keys we plan on using:
 
-\begin{code}
- «Bind Keys» ::=
+\begin{Fragment}{Bind Keys}
   {
   cat <<!
   Mod4-space
@@ -828,12 +910,11 @@
       echo Mod4-Shift-$i
   done
   } | wmiir write /keys
-\end{code}
+\end{Fragment}
 
 and lay a framework for processing their events:
 
-\begin{code}
- «Key Events» ::=
+\begin{Fragment}{Key Events}
   Key) # Key ‹Key Name›
       case $1 in
       «Motion Keys»
@@ -844,7 +925,7 @@
       «Tag Selection Keys»
       «Tagging Keys»
       esac;;
-\end{code}
+\end{Fragment}
 
 \section{Click Menus}
 
@@ -853,15 +934,16 @@
 mouse-driven, single-click menu. The default configuration uses
 it for client and tag menus.
 
-\begin{code}
- «Click Menu Initialization» ::=
+\begin{Fragment}{Click Menu Initialization}
   clickmenu() {
       if res=$(wmii9menu -- “$@”); then eval “$res”; fi
   }
-\end{code}
+\end{Fragment}
 
 \section{Control Files}
 
+\label{sec:controlfiles}
+
 Several directories including the root, have control files,
 named |ctl|. These files are used to control the object (e.g., a
 client or tag) represented by the directory. Each line of the
@@ -937,7 +1019,10 @@
       \item[pid] Read-only value of the PID of the program that
         owns the window, if the value is available and the
         process is on the same machine as wmii.
- \item[slay] When written, the client is killed peremptorily.
+ \item[slay] When written, the client is disconnected
+ peremptorily. If the client's PID is available and the
+ process is the same machine as wmii, its parent process
+ is killed
       \item[tags] The client's tags. The same as the tags file.
       \item[urgent] The client's urgency state. When |on|, the
         client's layout box will be highlighted. Possible values
@@ -953,19 +1038,21 @@
   \item[tags]
     \index{filesystem!/client/*/@\clientlabel!tags}
     The client's tags. Tag names are separated by |+|, |-|, or
- |^| signs. Tags beginning and ending with |/| are treated as
- regular expressions, which place the client on any extant
- matching tag\footnote{While a client with a regex tag will
- always appear in all matching views, it will not keep those
- views in existence. When the last client explicitly tagged
- with a view is removed, the view is deleted as soon as it
- becomes inactive.}. If the written value begins with a |+|,
- |-|, or |^|, the tags are updated rather than overwritten.
- Tag names which directly follow a |-| sign are removed
- rather than added, while those following a |^| are toggled.
- Regular expression tags which directly follow a minus sign
- are treated as exclusion expressions. For example, the tag
- string |+/foo/-/food/| will match the tag
+ |^| signs. Tag names which directly follow a |+| sign are
+ added, while whose following a |-| sign are removed and
+ those following a |^| are toggled. If the value written
+ begins with one of these characters, the value is appended
+ to the clients tags rather than replacing them.
+
+ Tags formatted as |/‹regex›/| are treated as regular
+ expressions, which place the client on any extant matching
+ tag\footnote{While a client with a regex tag will always
+ appear in all matching views, it will not keep those views
+ in existence. When the last client explicitly tagged with a
+ view is removed, the view is deleted as soon as it becomes
+ inactive.}. Regular expression tags which directly follow a
+ minus sign are treated as exclusion expressions. For
+ example, the tag string |+/foo/-/food/| will match the tag
     |foobar|, but not the tag |foodstand|.
 \end{description}
 
@@ -975,16 +1062,14 @@
 
 To control clients, we'll add the following key bindings:
 
-\begin{code}
- «Client Command Keys» ::=
+\begin{Fragment}{Client Command Keys}
   Mod4-Shift-c) wmiir xwrite /client/sel/ctl kill;;
   Mod4-f) wmiir xwrite /client/sel/ctl Fullscreen toggle;;
-\end{code}
+\end{Fragment}
 
 And to manage their tags, we'll need:
 
-\begin{code}
- «Tagging Keys» ::=
+\begin{Fragment}{Tagging Keys}
   Mod4-Shift-t)
     # Get the selected client's id
     c=$(wmiir read /client/sel/ctl | sed 1q)
@@ -994,19 +1079,18 @@
     wmiir xwrite /client/$c/tags $tag;;
   Mod4-Shift-[0-9])
     wmiir xwrite /client/sel/tags ${1##*-};;
-\end{code}
+\end{Fragment}
 
 \subsection{Click Menus}
 
 \index{events!ClientMouseDown}
-\begin{code}
- «Client Menu Events» ::=
+\begin{Fragment}{Client Menu Events}
   ClientMouseDown) # ClientMouseDown ‹Client ID› ‹Button›
     [ $2 = 3 ] && clickmenu \
       “Delete:wmiir xwrite /client/$1/ctl kill” \
       “Kill: wmiirxwrite /client/$1/ctl slay” \
       “Fullscreen:wmiir xwrite /client/$1/ctl fullscreen on”
-\end{code}
+\end{Fragment}
 
 \subsection{Unresponsive Clients}
 
@@ -1015,8 +1099,7 @@
 client to respond, and then lets its scripts decide what to do
 with it. The stock scripts prompt the user for input:
 
-\begin{code}
- «Unresponsive Clients» ::=
+\begin{Fragment}{Unresponsive Clients}
   UnresponsiveClient) # UnresponsiveClient ‹Client ID›
   {
       # Use wihack to make the xmessage a transient window of
@@ -1029,7 +1112,7 @@
              $(wmiir read /client/$1/label))
       [ $resp = Kill ] && wmiir xwrite /client/$1/ctl slay
   } &;;
-\end{code}
+\end{Fragment}
 \index{events!UnresponsiveClient|)}
 
 \section{Views}
@@ -1117,36 +1200,36 @@
 
 We'll use the following key bindings to interact with views:
 
-\begin{code}
- «Motion Keys» ::=
+\begin{Fragment}{Motion Keys}
   Mod4-h) wmiir xwrite /tag/sel/ctl select left;;
   Mod4-l) wmiir xwrite /tag/sel/ctl select right;;
   Mod4-k) wmiir xwrite /tag/sel/ctl select up;;
   Mod4-j) wmiir xwrite /tag/sel/ctl select down;;
   Mod4-space) wmiir xwrite /tag/sel/ctl select toggle;;
+\end{Fragment}
 
- «Client Movement Keys» ::=
+\begin{Fragment}{Client Movement Keys}
   Mod4-Shift-h) wmiir xwrite /tag/sel/ctl send sel left;;
   Mod4-Shift-l) wmiir xwrite /tag/sel/ctl send sel right;;
   Mod4-Shift-k) wmiir xwrite /tag/sel/ctl send sel up;;
   Mod4-Shift-j) wmiir xwrite /tag/sel/ctl send sel down;;
   Mod4-Shift-space) wmiir xwrite /tag/sel/ctl send sel toggle;;
+\end{Fragment}
 
- «Column Mode Keys» ::=
+\begin{Fragment}{Column Mode Keys}
   Mod4-d) wmiir xwrite /tag/sel/ctl colmode sel -stack-max;;
   Mod4-s) wmiir xwrite /tag/sel/ctl colmode sel stack-max;;
   Mod4-m) wmiir xwrite /tag/sel/ctl colmode sel stack+max;;
-\end{code}
+\end{Fragment}
 
 \subsection{Click Menus}
 
 \index{events!LeftBarMouseDown}
-\begin{code}
- «Tag Menu Events» ::=
+\begin{Fragment}{Tag Menu Events}
   LeftBarMouseDown) # LeftBarMouseDown ‹Button› ‹Bar Name›
     [ $1 = 3 ] && clickmenu \
       “Delete:delete_view $2”
-\end{code}
+\end{Fragment}
 
 \section{Command and Program Execution}
 
@@ -1160,28 +1243,26 @@
 We use |wmiir setsid| to launch programs with their own session
 IDs to prevent untoward effects when this script dies.
 
-\begin{code}
- «Command Execution Initialization» ::=
+\begin{Fragment}{Command Execution Initialization}
   terminal() { wmiir setsid xterm “$@” }
   proglist() {
       IFS=:
       wmiir proglist $1 | sort | uniq
       unset IFS
   }
-\end{code}
+\end{Fragment}
 
 \subsection{Key Bindings}
-\begin{code}
- «Command Execution Keys» ::=
+\begin{Fragment}{Command Execution Keys}
   Mod4-Return) terminal & ;;
- Mod4-p) eval exec wmiir setsid "$(proglist $PATH | wimenu)" &;;
+ Mod4-p) eval exec wmiir setsid “$(proglist $PATH | wimenu)” &;;
   Mod4-a) {
       set -- $(proglist $WMII_CONFPATH | wimenu)
       which=$(which which)
       prog=$(PATH=$WMII_CONFPATH $which $1); shift
       eval exec $prog “$@”
   } &;;
-\end{code}
+\end{Fragment}
 
 \section{The Root}
 
@@ -1243,9 +1324,9 @@
         searched for the executable. Otherwise, the whole
         argument is passed to the shell for evaluation.
     \end{description}
- \item[keys] The global keybindings. See section \ref{keybindings}.
+ \item[keys] The global keybindings. See section \ref{sec:keybindings}.
                \index{filesystem!/!keys|primary}
- \item[event] The global event feed. See section \ref{keybindings}.
+ \item[event] The global event feed. See section \ref{sec:keybindings}.
                \index{filesystem!/!event|primary}
   \item[colrules]
     \index{filesystem!/!colrules}
@@ -1260,7 +1341,7 @@
         Where,
 
         \begin{code}
- ‹width› := ‹percent of screen› | ‹pixels›px
+ ‹width› ≔ ‹percent of screen› | ‹pixels›px
         \end{code}
 
         When a new column, ‹n›, is created on a view whose name
@@ -1306,8 +1387,7 @@
 We'll need to let \wmii\ know about our previously defined theme
 information:
 
-\begin{code}
- «Configuration» ::=
+\begin{Fragment}{Configuration}
   «Theme Definitions»
 
   xsetroot -solid $background
@@ -1318,14 +1398,13 @@
   font $font
   grabmod Mod4
   !
-\end{code}
+\end{Fragment}
 
 \subsection{Key Bindings}
 
 And we need a few more key bindings to select our views:
 
-\begin{code}
- «Tag Selection Keys» ::=
+\begin{Fragment}{Tag Selection Keys}
   Mod4-t)
     # Prompt the user for a tag
     tags=$(wmiir ls /tag | sed ‘s,/,,; /^sel$/d’ | wimenu)
@@ -1333,7 +1412,7 @@
     wmiir xwrite /ctl view $tags;;
   Mod4-[0-9])
     wmiir xwrite /ctl view ${1##*-};;
-\end{code}
+\end{Fragment}
 
 \section{Tieing it All Together}
 
@@ -1501,7 +1580,7 @@
 
           # «Command Execution Keys»
           Mod4-Return) terminal & ;;
- Mod4-p) eval exec wmiir setsid "$(proglist $PATH | wimenu)" &;;
+ Mod4-p) eval exec wmiir setsid “$(proglist $PATH | wimenu)” &;;
           Mod4-a) {
               set -- $(proglist $WMII_CONFPATH | wimenu)
               prog=$(PATH=$WMII_CONFPATH which $1); shift
diff -r b69ff38fcfd3 -r 9d31d13386b8 include/stuff/base.h
--- a/include/stuff/base.h Thu Jun 24 11:03:52 2010 -0400
+++ b/include/stuff/base.h Fri Jun 25 17:21:12 2010 -0400
@@ -17,8 +17,10 @@
 #ifndef offsetof
 # define offsetof(type, member) ((size_t)&((type*)0)->member)
 #endif
+#define structptr(ptr, type, offset) \
+ ((type*)((char*)(ptr) + (offset)))
 #define structmember(ptr, type, offset) \
- (*(type*)((char*)(ptr) + (offset)))
+ (*structptr(ptr, type, offset))
 
 #undef uchar
 #undef ushort
diff -r b69ff38fcfd3 -r 9d31d13386b8 man/wmii.man1
--- a/man/wmii.man1 Thu Jun 24 11:03:52 2010 -0400
+++ b/man/wmii.man1 Fri Jun 25 17:21:12 2010 -0400
@@ -157,6 +157,8 @@
 | Mod-k | Move to a window _above_ the one currently focused
 | Mod-space | Toggle between the managed and floating layers
 | Mod-t <tag> | Move to the view of the given <tag>
+| Mod-n | Move to the next view
+| Mod-b | Move to the previous view
 | Mod-//[0-9]// | Move to the view with the given number
 
 === Moving Things Around ===
@@ -473,12 +475,9 @@
 occupying all extra available space. The items are sorted
 lexicographically.
 
-The files may be read to obtain the colors and text of the bars.
-The colors are at the beginning of the string, represented as a
-tuple of 3 hex color codes for the foreground, background, and
-border, respectively. When writing the bar files, the colors may
-be omitted if the text would not otherwise appear to contain
-them.
+The files may be read or written to obtain or alter the colors
+and text of the bars. The format is similar to the various _ctl_
+files and should be self explanitory.
 
 = FILES =
 
diff -r b69ff38fcfd3 -r 9d31d13386b8 rc/wmiirc.sh
--- a/rc/wmiirc.sh Thu Jun 24 11:03:52 2010 -0400
+++ b/rc/wmiirc.sh Fri Jun 25 17:21:12 2010 -0400
@@ -65,7 +65,7 @@
 
 # Status Bar Info
 status() {
- echo -n $(uptime | sed 's/.*://; s/,//g') '|' $(date)
+ echo -n label $(uptime | sed 's/.*://; s/,//g') '|' $(date)
 }
 
 # Generic overridable startup details
@@ -75,26 +75,26 @@
 wi_runconf -s wmiirc_local
 startup
 
-echo $WMII_NORMCOLORS | wmiir create $noticebar
+echo colors $WMII_NORMCOLORS | wmiir create $noticebar
 
 # Event processing
 events() {
         cat <<'!'
 # Events
 Event CreateTag
- echo "$WMII_NORMCOLORS" "$@" | wmiir create "/lbar/$@"
+ echo colors "$WMII_NORMCOLORS$wi_newline" label "$@" | wmiir create "/lbar/$@"
 Event DestroyTag
         wmiir remove "/lbar/$@"
 Event FocusTag
- wmiir xwrite "/lbar/$@" "$WMII_FOCUSCOLORS" "$@"
+ wmiir xwrite "/lbar/$@" colors "$WMII_FOCUSCOLORS"
 Event UnfocusTag
- wmiir xwrite "/lbar/$@" "$WMII_NORMCOLORS" "$@"
+ wmiir xwrite "/lbar/$@" colors "$WMII_NORMCOLORS"
 Event UrgentTag
         shift
- wmiir xwrite "/lbar/$@" "*$@"
+ wmiir xwrite "/lbar/$@" label "*$@"
 Event NotUrgentTag
         shift
- wmiir xwrite "/lbar/$@" "$@"
+ wmiir xwrite "/lbar/$@" label "$@"
 Event LeftBarClick LeftBarDND
         shift
         wmiir xwrite /ctl view "$@"
@@ -129,19 +129,12 @@
 Menu LBar-3-Delete
         tag=$1; clients=$(wmiir read "/tag/$tag/index" | awk '/[^#]/{print $2}')
         for c in $clients; do
- if [ "$tag" = "$(wmiir read /client/$c/tags)" ]; then
- wmiir xwrite /client/$c/ctl kill
- else
- wmiir xwrite /client/$c/tags -$tag
+ if [ "$tag" = "$(wmiir read /client/$c/tags)" ]
+ then wmiir xwrite /client/$c/ctl kill
+ else wmiir xwrite /client/$c/tags -$tag
                 fi
- if [ "$tag" = "$(wi_seltag)" ]; then
- newtag=$(wi_tags | awk -v't='$tag '
- $1 == t { if(!l) getline l
- print l
- exit }
- { l = $0 }')
- wmiir xwrite /ctl view $newtag
- fi
+ [ "$tag" = "$(wi_seltag)" ] &&
+ wmiir xwrite /ctl view $(wi_tags | wi_nexttag)
         done
 Event LeftBarMouseDown
         wi_fnmenu LBar "$@" &
@@ -160,7 +153,7 @@
         if wmiir remove /rbar/status 2>/dev/null; then
                 sleep 2
         fi
- echo "$WMII_NORMCOLORS" | wmiir create /rbar/status
+ echo colors "$WMII_NORMCOLORS" | wmiir create /rbar/status
         while status | wmiir write /rbar/status; do
                 sleep 1
         done
@@ -238,6 +231,10 @@
 Key $MODKEY-Shift-t # Retag the selected client
         # Assumes left-to-right order of evaluation
         wmiir xwrite /client/$(wi_selclient)/tags $(wi_tags | wimenu -h "${hist}.tags" -n 50) &
+Key $MODKEY-n # Move to the next tag
+ wmiir xwrite /ctl view $(wi_tags | wi_nexttag)
+Key $MODKEY-b # Move to the previous tag
+ wmiir xwrite /ctl view $(wi_tags | sort -r | wi_nexttag)
 !
         for i in 0 1 2 3 4 5 6 7 8 9; do
                 cat <<!
@@ -273,9 +270,11 @@
 wi_tags | while read tag
 do
         if [ "$tag" = "$seltag" ]; then
- echo "$WMII_FOCUSCOLORS" "$tag"
+ echo colors "$WMII_FOCUSCOLORS"
+ echo label $tag
         else
- echo "$WMII_NORMCOLORS" "$tag"
+ echo colors "$WMII_NORMCOLORS"
+ echo label $tag
         fi | wmiir create "/lbar/$tag"
 done
 
Received on Fri Jun 25 2010 - 21:22:23 UTC

This archive was generated by hypermail 2.2.0 : Fri Jun 25 2010 - 21:24:04 UTC