[hackers] [wmii] Allow rebinding of keys in wimenu. || Kris Maglione

From: <hg_AT_suckless.org>
Date: Thu, 14 May 2009 03:30:20 +0000 (UTC)

changeset: 2446:2e61304eec5f
tag: tip
user: Kris Maglione <jg_AT_suckless.org>
date: Wed May 13 23:30:20 2009 -0400
files: .hgignore cmd/Makefile cmd/menu/Makefile cmd/menu/caret.c cmd/menu/dat.h cmd/menu/fns.h cmd/menu/keys.c cmd/menu/keys.txt cmd/menu/main.c cmd/menu/menu.c cmd/util.c cmd/wmii9menu.c include/util.h
description:
Allow rebinding of keys in wimenu.

diff -r 7f2809b8e1fd -r 2e61304eec5f .hgignore
--- a/.hgignore Wed May 13 12:57:22 2009 -0400
+++ b/.hgignore Wed May 13 23:30:20 2009 -0400
@@ -1,6 +1,8 @@
 syntax: regexp
-(^|/)\.((.*\.)?swp|depend|hgignore)$
+(^|/)\.((.*\.)?sw.|depend|hgignore)$
 (^|/)(tags|mkfile)$
-\.([oOa]|o_pic|so)$
-^config\.local\.mk$
-
+\.([oOa]|o_pic|so|orig|bak)$
+^cmd/(stfo|osd|wiwarp)(/|$)
+syntax: glob
+config.local.mk
+cmd/menu/bindings.c
diff -r 7f2809b8e1fd -r 2e61304eec5f cmd/Makefile
--- a/cmd/Makefile Wed May 13 12:57:22 2009 -0400
+++ b/cmd/Makefile Wed May 13 23:30:20 2009 -0400
@@ -35,7 +35,7 @@
 wmii/x11.o wmii/map.o: dall
         true
 
-O9MENU=wmii9menu.o wmii/x11.o wmii/map.o $(OFILES) $(LIBIXP)
+O9MENU=wmii9menu.o clientutil.o wmii/x11.o wmii/map.o $(OFILES) $(LIBIXP)
 wmii9menu.O: $(O9MENU)
         $(LINK) $@ $(O9MENU) $(LIBX11) -lXext -lbio
 
diff -r 7f2809b8e1fd -r 2e61304eec5f cmd/menu/Makefile
--- a/cmd/menu/Makefile Wed May 13 12:57:22 2009 -0400
+++ b/cmd/menu/Makefile Wed May 13 23:30:20 2009 -0400
@@ -3,6 +3,11 @@
 include $(ROOT)/mk/wmii.mk
 
 main.c: $(ROOT)/mk/wmii.mk
+
+bindings.c: keys.txt Makefile
+ ( echo "char binding_spec[] = "; \
+ sed 's/.*/ "&\\n"/' keys.txt; \
+ echo " ;" ) >bindings.c
 
 TARG = wimenu
 HFILES= dat.h fns.h
@@ -17,11 +22,14 @@
         history \
         event \
         menu \
+ keys \
+ bindings \
         ../wmii/geom \
         ../wmii/map \
         ../wmii/printevent \
         ../wmii/x11 \
         ../wmii/xext \
+ ../clientutil \
         ../util
 
 include $(ROOT)/mk/one.mk
diff -r 7f2809b8e1fd -r 2e61304eec5f cmd/menu/caret.c
--- a/cmd/menu/caret.c Wed May 13 12:57:22 2009 -0400
+++ b/cmd/menu/caret.c Wed May 13 23:30:20 2009 -0400
@@ -79,8 +79,7 @@
                         return end;
                 }
         }
- die("not reached");
- return nil; /* shut up ken */
+ return input.pos;
 }
 
 void
@@ -114,6 +113,8 @@
 caret_insert(char *s, bool clear) {
         int pos, end, len, size;
 
+ if(s == nil)
+ return;
         if(clear) {
                 input.pos = input.string;
                 input.end = input.string;
diff -r 7f2809b8e1fd -r 2e61304eec5f cmd/menu/dat.h
--- a/cmd/menu/dat.h Wed May 13 12:57:22 2009 -0400
+++ b/cmd/menu/dat.h Wed May 13 23:30:20 2009 -0400
@@ -26,6 +26,26 @@
         CARET_LAST,
 };
 
+enum {
+ LACCEPT,
+ LBACKWARD,
+ LCHAR,
+ LCOMPLETE,
+ LFIRST,
+ LFORWARD,
+ LHISTORY,
+ LKILL,
+ LLAST,
+ LLINE,
+ LLITERAL,
+ LNEXT,
+ LNEXTPAGE,
+ LPREV,
+ LPREVPAGE,
+ LREJECT,
+ LWORD,
+};
+
 typedef struct Item Item;
 
 struct Item {
@@ -45,6 +65,10 @@
         int len;
         int size;
 } input;
+
+extern char binding_spec[];
+
+EXTERN int numlock;
 
 EXTERN long xtime;
 EXTERN Image* ibuf;
diff -r 7f2809b8e1fd -r 2e61304eec5f cmd/menu/fns.h
--- a/cmd/menu/fns.h Wed May 13 12:57:22 2009 -0400
+++ b/cmd/menu/fns.h Wed May 13 23:30:20 2009 -0400
@@ -18,6 +18,11 @@
 void xtime_kludge(void);
 void update_filter(void);
 
+/* keys.c */
+void parse_keys(char*);
+char** find_key(char*, long);
+int getsym(char*);
+
 /* geom.c */
 Align get_sticky(Rectangle src, Rectangle dst);
 Cursor quad_cursor(Align);
diff -r 7f2809b8e1fd -r 2e61304eec5f cmd/menu/keys.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/menu/keys.c Wed May 13 23:30:20 2009 -0400
@@ -0,0 +1,143 @@
+#include "dat.h"
+#include <ctype.h>
+#include <strings.h>
+#include <unistd.h>
+#include "fns.h"
+
+typedef struct Key Key;
+typedef struct KMask KMask;
+
+struct Key {
+ Key* next;
+ long mask;
+ char* key;
+ char** action;
+};
+
+static Key* bindings;
+
+static struct KMask {
+ int mask;
+ const char* name;
+} masks[] = {
+ {ControlMask, "Control"},
+ {Mod1Mask, "Mod1"},
+ {Mod2Mask, "Mod2"},
+ {Mod3Mask, "Mod3"},
+ {Mod4Mask, "Mod4"},
+ {ShiftMask, "Shift"},
+ {0,}
+};
+
+/*
+ * To do: Find my red black tree implementation.
+ */
+void
+parse_keys(char *spec) {
+ static char *lines[1024];
+ static char *words[16];
+ static char *keys[16];
+ Key *k;
+ KMask *m;
+ char *p, *line;
+ long mask;
+ int i, j, nlines, nwords, nkeys;
+
+ nlines = tokenize(lines, nelem(lines), spec, '\n');
+ for(i=0; i < nlines; i++) {
+ line = lines[i];
+ p = strchr(line, '#');
+ if(p)
+ *p = '\0';
+ nwords = stokenize(words, nelem(words) - 1, line, " \t");
+ words[nwords] = nil;
+ if(!words[0])
+ continue;
+ mask = 0;
+ nkeys = tokenize(keys, nelem(keys), words[0], '-');
+ for(j=0; j < nkeys; j++) {
+ for(m=masks; m->mask; m++)
+ if(!strcasecmp(m->name, keys[j])) {
+ mask |= m->mask;
+ goto next;
+ }
+ break;
+ next: continue;
+ }
+ if(j == nkeys - 1) {
+ k = emallocz(sizeof *k);
+ k->key = keys[j];
+ k->mask = mask;
+ k->action = strlistdup(words + 1);
+ k->next = bindings;
+ bindings = k;
+ }
+ }
+}
+
+char**
+find_key(char *key, long mask) {
+ Key *k;
+
+ /* Horrible hack. */
+ if(!strcmp(key, "ISO_Left_Tab"))
+ key = "Tab";
+
+ mask &= ~(numlock | LockMask);
+ for(k=bindings; k; k=k->next)
+ if(!strcasecmp(k->key, key) && k->mask == mask)
+ return k->action;
+ return nil;
+}
+
+ /* sed 's/"([^"]+)"/L\1/g' | tr 'a-z' 'A-Z' */
+ /* awk '{$1=""; print}' keys.txt | perl -e '$_=lc join "", <>; print join "\n", m/(\w+)/g;' | sort -u | sed 's:.*: "&",:' */
+char *symtab[] = {
+ "accept",
+ "backward",
+ "char",
+ "complete",
+ "first",
+ "forward",
+ "history",
+ "kill",
+ "last",
+ "line",
+ "literal",
+ "next",
+ "nextpage",
+ "prev",
+ "prevpage",
+ "reject",
+ "word",
+};
+
+static int
+_bsearch(char *s, char **tab, int ntab) {
+ int i, n, m, cmp;
+
+ if(s == nil)
+ return -1;
+
+ n = ntab;
+ i = 0;
+ while(n) {
+ m = n/2;
+ cmp = strcasecmp(s, tab[i+m]);
+ if(cmp == 0)
+ return i+m;
+ if(cmp < 0 || m == 0)
+ n = m;
+ else {
+ i += m;
+ n = n-m;
+ }
+ }
+ return -1;
+}
+
+int
+getsym(char *s) {
+ return _bsearch(s, symtab, nelem(symtab));
+}
+
diff -r 7f2809b8e1fd -r 2e61304eec5f cmd/menu/keys.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd/menu/keys.txt Wed May 13 23:30:20 2009 -0400
@@ -0,0 +1,49 @@
+Control-j Accept
+Control-m Accept
+Return Accept
+Control-Shift-j Accept literal
+Control-Shift-m Accept literal
+Shift-Return Accept literal
+
+Escape Reject
+Control-[ Reject
+
+Left Backward char
+Control-b Backward char
+Right Forward char
+Control-f Forward char
+
+Mod1-b Backward word
+Mod1-f Forward word
+
+Control-a Backward line
+Control-e Forward line
+
+Control-p History backward
+Up History backward
+Control-n History forward
+Down History forward
+
+BackSpace Kill char
+Control-h Kill char
+Control-Backspace Kill word
+Control-w Kill word
+Control-u Kill line
+
+Tab Complete next
+Control-i Complete next
+Mod1-l Complete next
+
+Shift-Tab Complete prev
+Control-Shift-i Complete prev
+Mod1-h Complete prev
+
+Prior Complete prevpage
+Mod1-k Complete prevpage
+Next Complete nextpage
+Mod1-j Complete nextpage
+Home Complete first
+Mod1-g Complete first
+End Complete last
+Mod1-Shift-g Complete last
+
diff -r 7f2809b8e1fd -r 2e61304eec5f cmd/menu/main.c
--- a/cmd/menu/main.c Wed May 13 12:57:22 2009 -0400
+++ b/cmd/menu/main.c Wed May 13 23:30:20 2009 -0400
@@ -10,15 +10,13 @@
 #include <strings.h>
 #include <unistd.h>
 #include <bio.h>
+#include <clientutil.h>
 #include "fns.h"
 #define link _link
 
 static const char version[] = "wimenu-"VERSION", ©2009 Kris Maglione\n";
-static IxpClient* client;
-static IxpCFid* ctlfid;
 static Biobuf* inbuf;
-static char ctl[1024];
-static char* ectl;
+static bool alwaysprint;
 
 static void
 usage(void) {
@@ -49,27 +47,6 @@
         va_start(ap, fmt);
         vfprint(2, fmt, ap);
         va_end(ap);
-}
-
-static char*
-readctl(char *key) {
- char *s, *p;
- int nkey, n;
-
- nkey = strlen(key);
- p = ctl - 1;
- do {
- p++;
- if(!strncmp(p, key, nkey)) {
- p += nkey;
- s = strchr(p, '\n');
- n = (s ? s : ectl) - p;
- s = freelater(emalloc(n + 1));
- s[n] = '\0';
- return strncpy(s, p, n);
- }
- } while((p = strchr(p, '\n')));
- return "";
 }
 
 static void
@@ -149,6 +126,11 @@
          * has been truncated.
          */
         matchfirst = matchstart = matchidx = filter_list(items, input.string);
+ if(alwaysprint) {
+ write(1, input.string, input.pos - input.string);
+ write(1, "", 1);
+ write(1, input.pos, input.end - input.pos + 1);
+ }
 }
 
 /*
@@ -182,7 +164,7 @@
         check_x_event(nil);
 }
 
-#define SCREEN_WITH_POINTER -1
+enum { PointerScreen = -1 };
 
 void
 init_screens(int screen_hint) {
@@ -191,11 +173,10 @@
         int i, n;
 
         rects = xinerama_screens(&n);
- if (screen_hint >= 0 && screen_hint < n) {
- /* we were given a valid screen index, use that */
+ if (screen_hint >= 0 && screen_hint < n)
+ /* We were given a valid screen index, use that. */
                 i = screen_hint;
-
- } else {
+ else {
                 /* Pick the screen with the pointer, for now. Later,
                  * try for the screen with the focused window first.
                  */
@@ -215,6 +196,7 @@
         Item *item;
         char *address;
         char *histfile;
+ char *keyfile;
         int i;
         long ndump;
         int screen;
@@ -223,9 +205,8 @@
         fmtinstall('r', errfmt);
         address = getenv("WMII_ADDRESS");
         histfile = nil;
- prompt = nil;
- promptw = 0;
- screen = SCREEN_WITH_POINTER;
+ keyfile = nil;
+ screen = PointerScreen;
 
         find = strstr;
         compare = strncmp;
@@ -236,8 +217,14 @@
         case 'a':
                 address = EARGF(usage());
                 break;
+ case 'c':
+ alwaysprint = true;
+ break;
         case 'h':
                 histfile = EARGF(usage());
+ break;
+ case 'k':
+ keyfile = EARGF(usage());
                 break;
         case 'n':
                 ndump = strtol(EARGF(usage()), nil, 10);
@@ -267,16 +254,7 @@
         if(!isatty(0))
                 menu_init();
 
- if(address && *address)
- client = ixp_mount(address);
- else
- client = ixp_nsmount("wmii");
- if(client == nil)
- fatal("can't mount: %r\n");
-
- ctlfid = ixp_open(client, "ctl", OREAD);
- i = ixp_read(ctlfid, ctl, 1023);
- ectl = ctl + i;
+ client_init(address);
 
         srv.preselect = preselect;
         ixp_listen(&srv, ConnectionNumber(display), nil, check_x_event, end);
@@ -292,6 +270,13 @@
         items = populate_list(inbuf, false);
         caret_insert("", true);
         update_filter();
+
+ parse_keys(binding_spec);
+ if(keyfile) {
+ i = open(keyfile, O_RDONLY);
+ if(read(i, buffer, sizeof(buffer)) > 0)
+ parse_keys(buffer);
+ }
 
         Bterm(inbuf);
         histidx = &hist;
diff -r 7f2809b8e1fd -r 2e61304eec5f cmd/menu/menu.c
--- a/cmd/menu/menu.c Wed May 13 12:57:22 2009 -0400
+++ b/cmd/menu/menu.c Wed May 13 23:30:20 2009 -0400
@@ -7,7 +7,6 @@
 static Handlers handlers;
 
 static int ltwidth;
-static int numlock;
 
 static void menu_draw(void);
 
@@ -232,12 +231,15 @@
 
 static void
 kdown_event(Window *w, XKeyEvent *e) {
+ char **action, **p;
+ char *key;
         char buf[32];
         int num;
         KeySym ksym;
 
         buf[0] = 0;
         num = XLookupString(e, buf, sizeof buf, &ksym, 0);
+ key = XKeysymToString(ksym);
         if(IsKeypadKey(ksym))
                 if(ksym == XK_KP_Enter)
                         ksym = XK_Return;
@@ -251,145 +253,60 @@
         || IsPFKey(ksym))
                 return;
 
- if(e->state & ControlMask) {
- switch (ksym) {
- default:
- return;
- case XK_bracketleft: /* Esc */
- menu_cmd(REJECT, 0);
- return;
- case XK_j:
- case XK_J:
- case XK_m:
- case XK_M:
- menu_cmd(ACCEPT, e->state&ShiftMask);
- return;
- case XK_a:
- case XK_A:
- menu_cmd(BACKWARD, LINE);
- return;
- case XK_e:
- case XK_E:
- menu_cmd(FORWARD, LINE);
- return;
- case XK_b:
- case XK_B:
- menu_cmd(BACKWARD, CHAR);
- return;
- case XK_f:
- case XK_F:
- menu_cmd(FORWARD, CHAR);
- return;
- case XK_n:
- case XK_N:
- menu_cmd(HIST, FORWARD);
- return;
- case XK_p:
- case XK_P:
- menu_cmd(HIST, BACKWARD);
- return;
- case XK_h:
- case XK_H:
- menu_cmd(KILL, CHAR);
- return;
- case XK_BackSpace:
- case XK_w:
- case XK_W:
- menu_cmd(KILL, WORD);
- return;
- case XK_u:
- case XK_U:
- menu_cmd(KILL, LINE);
- return;
- case XK_i: /* Tab */
- case XK_I:
- if(e->state & ShiftMask)
- menu_cmd(CMPL_PREV, 0);
- else
- menu_cmd(CMPL_NEXT, 0);
- return;
- }
- }
- /* Alt-<Key> - Vim */
- if((e->state & ~(numlock | LockMask)) & Mod1Mask) {
- switch(ksym) {
- default:
- return;
- case XK_h:
- menu_cmd(CMPL_PREV, 0);
- return;
- case XK_l:
- menu_cmd(CMPL_NEXT, 0);
- return;
- case XK_k:
- menu_cmd(CMPL_PREV_PAGE, 0);
- return;
- case XK_j:
- menu_cmd(CMPL_NEXT_PAGE, 0);
- return;
- case XK_g:
- menu_cmd(CMPL_FIRST, 0);
- return;
- case XK_G:
- menu_cmd(CMPL_LAST, 0);
- return;
- case XK_b:
- case XK_B:
- menu_cmd(BACKWARD, WORD);
- return;
- case XK_f:
- case XK_F:
- menu_cmd(FORWARD, WORD);
- return;
- }
- }
- switch(ksym) {
- default:
+ action = find_key(key, e->state);
+ if(action == nil || action[0] == nil) {
                 if(num && !iscntrl(buf[0])) {
                         caret_insert(buf, false);
                         update_filter();
                         menu_draw();
                 }
- break;
- case XK_Tab:
- if(e->state & ShiftMask)
- menu_cmd(CMPL_PREV, 0);
- else
- menu_cmd(CMPL_NEXT, 0);
- return;
- case XK_Return:
- menu_cmd(ACCEPT, e->state & ShiftMask);
- return;
- case XK_Escape:
- menu_cmd(REJECT, 0);
- return;
- case XK_BackSpace:
- menu_cmd(KILL, CHAR);
- return;
- case XK_Left:
- menu_cmd(BACKWARD, CHAR);
- return;
- case XK_Right:
- menu_cmd(FORWARD, CHAR);
- return;
- case XK_Up:
- menu_cmd(HIST, BACKWARD);
- return;
- case XK_Down:
- menu_cmd(HIST, FORWARD);
- return;
- case XK_Home:
- menu_cmd(CMPL_FIRST, 0);
- return;
- case XK_End:
- menu_cmd(CMPL_LAST, 0);
- return;
- case XK_Prior:
- menu_cmd(CMPL_PREV_PAGE, 0);
- return;
- case XK_Next:
- menu_cmd(CMPL_NEXT_PAGE, 0);
- return;
+ }
+ else {
+ long mask = 0;
+# define have(val) !!(mask & (1 << val))
+ for(p=action+1; *p; p++)
+ mask |= 1 << getsym(*p);
+ int amount = (
+ have(LCHAR) ? CHAR :
+ have(LWORD) ? WORD :
+ have(LLINE) ? LINE :
+ -1);
+ switch(getsym(action[0])) {
+ case LACCEPT:
+ menu_cmd(ACCEPT, have(LLITERAL));
+ break;
+ case LBACKWARD:
+ menu_cmd(BACKWARD, amount);
+ break;
+ case LCOMPLETE:
+ amount = CMPL_NEXT;
+ if(have(LNEXT))
+ amount = CMPL_NEXT;
+ else if(have(LPREV))
+ amount = CMPL_PREV;
+ else if(have(LNEXTPAGE))
+ amount = CMPL_NEXT_PAGE;
+ else if(have(LPREVPAGE))
+ amount = CMPL_PREV_PAGE;
+ else if(have(LFIRST))
+ amount = CMPL_FIRST;
+ else if(have(LLAST))
+ amount = CMPL_LAST;
+ menu_cmd(amount, 0);
+ break;
+ case LFORWARD:
+ menu_cmd(FORWARD, amount);
+ break;
+ case LHISTORY:
+ menu_cmd(HIST, have(LBACKWARD) ? BACKWARD : FORWARD);
+ break;
+ case LKILL:
+ menu_cmd(KILL, amount);
+ break;
+ case LREJECT:
+ menu_cmd(REJECT, 0);
+ break;
+ }
         }
 }
 
diff -r 7f2809b8e1fd -r 2e61304eec5f cmd/util.c
--- a/cmd/util.c Wed May 13 12:57:22 2009 -0400
+++ b/cmd/util.c Wed May 13 23:30:20 2009 -0400
@@ -177,6 +177,24 @@
         return i;
 }
 
+uint
+stokenize(char *res[], uint reslen, char *str, char *delim) {
+ char *s;
+ uint i;
+
+ i = 0;
+ s = str;
+ while(i < reslen && *s) {
+ while(strchr(delim, *s))
+ *(s++) = '\0';
+ if(*s)
+ res[i++] = s;
+ while(*s && !strchr(delim, *s))
+ s++;
+ }
+ return i;
+}
+
 int
 max(int a, int b) {
         if(a > b)
diff -r 7f2809b8e1fd -r 2e61304eec5f cmd/wmii9menu.c
--- a/cmd/wmii9menu.c Wed May 13 12:57:22 2009 -0400
+++ b/cmd/wmii9menu.c Wed May 13 23:30:20 2009 -0400
@@ -44,6 +44,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <clientutil.h>
 #include <util.h>
 #include <x11.h>
 
@@ -55,36 +56,10 @@
 static CTuple csel;
 static Font* font;
 
-static IxpClient* client;
-static IxpCFid* ctlfid;
-static char ctl[1024];
-static char* ectl;
-
 static int wborder;
 
 char buffer[8092];
 char* _buffer;
-
-static char*
-readctl(char *key) {
- char *s, *p;
- int nkey, n;
-
- nkey = strlen(key);
- p = ctl - 1;
- do {
- p++;
- if(!strncmp(p, key, nkey)) {
- p += nkey;
- s = strchr(p, '\n');
- n = (s ? s : ectl) - p;
- s = freelater(emalloc(n + 1));
- s[n] = '\0';
- return strncpy(s, p, n);
- }
- } while((p = strchr(p, '\n')));
- return "";
-}
 
 /* for XSetWMProperties to use */
 int g_argc;
@@ -154,16 +129,7 @@
                         cur = i;
         }
 
- if(address && *address)
- client = ixp_mount(address);
- else
- client = ixp_nsmount("wmii");
- if(client == nil)
- fatal("can't mount: %r\n");
-
- ctlfid = ixp_open(client, "ctl", OREAD);
- i = ixp_read(ctlfid, ctl, 1023);
- ectl = ctl + i;
+ client_init(address);
 
         wborder = strtol(readctl("border "), nil, 10);
         loadcolor(&cnorm, readctl("normcolors "));
diff -r 7f2809b8e1fd -r 2e61304eec5f include/util.h
--- a/include/util.h Wed May 13 12:57:22 2009 -0400
+++ b/include/util.h Wed May 13 23:30:20 2009 -0400
@@ -46,7 +46,8 @@
 uint strlcat(char*, const char*, uint);
 char* strcasestr(const char*, const char*);
 char* sxprint(const char*, ...);
-uint tokenize(char **, uint, char*, char);
+uint tokenize(char**, uint, char*, char);
+uint stokenize(char**, uint, char*, char*);
 int utflcpy(char*, const char*, int);
 char* vsxprint(const char*, va_list);
 
Received on Thu May 14 2009 - 03:30:20 UTC

This archive was generated by hypermail 2.2.0 : Thu May 14 2009 - 03:36:02 UTC