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