From 089bf7bba73d942a750de55a5be8569be9fd6710 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Thu, 7 Oct 2010 16:31:42 -0400 Subject: [PATCH] [wimenu] Add paste key binding. --- cmd/menu/Makefile | 2 +- cmd/menu/dat.h | 1 + cmd/menu/keys.c | 1 + cmd/menu/keys.txt | 76 ++++++++++++++++++----------------- cmd/menu/main.c | 5 +++ cmd/menu/menu.c | 10 +++++ include/stuff/x11.h | 1 + lib/libstuff/Makefile | 1 + lib/libstuff/x11/selection.c | 63 +++++++++++++++++++++++++++++ lib/libstuff/x11/xatom.c | 2 +- man/wimenu.1 | 78 ++++++++++++++++++++++++++++++++++++ man/wimenu.man1 | 57 ++++++++++++++++++++++++++ mk/common.mk | 2 +- mk/dir.mk | 3 ++ mk/hdr.mk | 2 +- 15 files changed, 263 insertions(+), 41 deletions(-) create mode 100644 lib/libstuff/x11/selection.c diff --git a/cmd/menu/Makefile b/cmd/menu/Makefile index 909d5255..d8524c8a 100644 --- a/cmd/menu/Makefile +++ b/cmd/menu/Makefile @@ -11,7 +11,7 @@ bindings.c: keys.txt Makefile TARG = wimenu HFILES= dat.h fns.h -TAGFILES= dat.h +TAGFILES= dat.h $(ROOT)/include/*.h $(ROOT)/include/stuff/*.h PACKAGES += $(X11PACKAGES) diff --git a/cmd/menu/dat.h b/cmd/menu/dat.h index c31270c3..a2386931 100644 --- a/cmd/menu/dat.h +++ b/cmd/menu/dat.h @@ -38,6 +38,7 @@ enum { LLITERAL, LNEXT, LNEXTPAGE, + LPASTE, LPREV, LPREVPAGE, LREJECT, diff --git a/cmd/menu/keys.c b/cmd/menu/keys.c index 12c0d919..6924a1db 100644 --- a/cmd/menu/keys.c +++ b/cmd/menu/keys.c @@ -84,6 +84,7 @@ char *symtab[] = { "literal", "next", "nextpage", + "paste", "prev", "prevpage", "reject", diff --git a/cmd/menu/keys.txt b/cmd/menu/keys.txt index d16a6c64..cd2ea1cb 100644 --- a/cmd/menu/keys.txt +++ b/cmd/menu/keys.txt @@ -1,49 +1,51 @@ -Control-j Accept -Control-m Accept -Return Accept -Control-Shift-j Accept literal -Control-Shift-m Accept literal -Shift-Return Accept literal +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-Bracketleft Reject -Left Backward char -Control-b Backward char -Right Forward char -Control-f Forward char +Left Backward char +Control-b Backward char +Right Forward char +Control-f Forward char -Mod1-b Backward word -Mod1-f Forward word +Mod1-b Backward word +Mod1-f Forward word -Control-a Backward line -Control-e Forward line +Control-a Backward line +Control-e Forward line -Control-p History backward -Up History backward -Control-n History forward -Down History forward +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 +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 +Tab Complete next +Control-i Complete next +Mod1-l Complete next -Shift-Tab Complete prev -Control-Shift-i Complete prev -Mod1-h Complete prev +Mod1-p Paste PRIMARY -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 +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 --git a/cmd/menu/main.c b/cmd/menu/main.c index b90d0169..605eda68 100644 --- a/cmd/menu/main.c +++ b/cmd/menu/main.c @@ -172,6 +172,11 @@ init_screens(void) { menu_show(); } +ErrorCode ignored_xerrors[] = { + { 0, BadWindow }, + { X_GetAtomName, BadAtom }, +}; + int main(int argc, char *argv[]) { static char *address; diff --git a/cmd/menu/menu.c b/cmd/menu/menu.c index be7d47f0..40243afc 100644 --- a/cmd/menu/menu.c +++ b/cmd/menu/menu.c @@ -213,6 +213,13 @@ selectitem(Item *i) { } } +static void +paste(void *aux, char *str) { + if(str) + caret_insert(str, false); + menu_draw(); +} + static bool kdown_event(Window *w, void *aux, XKeyEvent *e) { char **action, **p; @@ -321,6 +328,9 @@ kdown_event(Window *w, void *aux, XKeyEvent *e) { caret_move(FORWARD, amount); update_input(); break; + case LPASTE: + getselection(action[1] ? action[1] : "PRIMARY", paste, nil); + break; case LREJECT: srv.running = false; result = 1; diff --git a/include/stuff/x11.h b/include/stuff/x11.h index 0ec66d5f..e33e06bb 100644 --- a/include/stuff/x11.h +++ b/include/stuff/x11.h @@ -277,6 +277,7 @@ ulong getproperty(Window*, char *prop, char *type, Atom *actual, ulong offset, u Rectangle getwinrect(Window*); int grabkeyboard(Window*); int grabpointer(Window*, Window *confine, Cursor, int mask); +void getselection(char*, void (*)(void*, char*), void*); bool havexft(void); void initdisplay(void); KeyCode keycode(const char*); diff --git a/lib/libstuff/Makefile b/lib/libstuff/Makefile index 174bb0d8..492d3423 100644 --- a/lib/libstuff/Makefile +++ b/lib/libstuff/Makefile @@ -96,6 +96,7 @@ OBJ=\ x11/ignored_xerrors \ x11/freestringlist \ x11/initdisplay \ + x11/selection \ x11/sendevent \ x11/sendmessage \ x11/sync \ diff --git a/lib/libstuff/x11/selection.c b/lib/libstuff/x11/selection.c new file mode 100644 index 00000000..974f15e7 --- /dev/null +++ b/lib/libstuff/x11/selection.c @@ -0,0 +1,63 @@ +/* Copyright ©2010 Kris Maglione + * See LICENSE file for license details. + */ +#include "x11.h" + +static Handlers handlers; + +typedef struct Data Data; + +struct Data { + long selection; + void (*callback)(void*, char*); + void* aux; +}; + +static bool +_getselection(Window *w, long selection, char *type) { + XConvertSelection(display, selection, xatom(type), + selection, w->xid, CurrentTime); + return true; +} + +void +getselection(char *selection, void (*callback)(void*, char*), void *aux) { + Window *w; + Data *d; + + d = emallocz(sizeof *d); + d->selection = xatom(selection); + d->callback = callback; + d->aux = aux; + + w = createwindow(&scr.root, Rect(0, 0, 1, 1), 0, InputOnly, nil, 0); + w->aux = d; + sethandler(w, &handlers); + + _getselection(w, d->selection, "UTF8_STRING"); +} + +static bool +selection_event(Window *w, void *aux, XSelectionEvent *ev) { + Data *d; + char **ret; + + d = aux; + if(ev->property == None && ev->target != xatom("STRING")) + return _getselection(w, d->selection, "STRING"); + else if(ev->property == None) + d->callback(d->aux, nil); + else { + getprop_textlist(w, atomname(ev->property), &ret); + delproperty(w, atomname(ev->property)); + d->callback(d->aux, ret ? *ret : nil); + free(ret); + } + destroywindow(w); + return false; +} + +static Handlers handlers = { + .selection = selection_event, +}; + diff --git a/lib/libstuff/x11/xatom.c b/lib/libstuff/x11/xatom.c index 829cf90d..d27eec18 100644 --- a/lib/libstuff/x11/xatom.c +++ b/lib/libstuff/x11/xatom.c @@ -24,7 +24,7 @@ atomname(ulong atom) { e = map_get(&atomnamemap, atom, true); if(*e == nil) { *e = XGetAtomName(display, atom); - if(&e == nil) { + if(*e == nil) { map_rm(&atomnamemap, atom); return nil; } diff --git a/man/wimenu.1 b/man/wimenu.1 index 47d85451..323089d9 100644 --- a/man/wimenu.1 +++ b/man/wimenu.1 @@ -85,6 +85,84 @@ as a menu option, and the text to the right is displayed when a selection is made. .RE +.SH KEY BINDINGS +.P +\fBwimenu\fR's default key bindings are based largely on the +movement keys of vi and the standard UNIX shell input bindings. + +.TP +Return, C\-j, C\-m +Accept the input, and select the first matching +completion if the cursor is at the end of the input. +.TP +S\-Return, C\-S\-j, C\-S\-m +Accept the input literally. +.TP +Esc, C\-[ +Quit without returning any output, and exit with +non\-zero status. + +.TP +A\-p +Paste the PRIMARY selection. + +.TP +Left, C\-b +Move backward one character. +.TP +Right, C\-f +Move forward one character. + +.TP +A\-b +Move backward one word. +.TP +A\-f +Move forward one word. + +.TP +C\-a +Move to the begining of the line. +.TP +C\-e +Move to the end of the line. + +.TP +C\-p, up +Move backward through the input history. +.TP +C\-n, up +Move forward through the input history. + +.TP +Backspace, C\-h +Delete the previous character. +.TP +C\-Backspace, C\-w +Delete the previous word. +.TP +C\-u +Delete the previous portion of the line. + +.TP +Tab, C\-i¸ A\-l +Select the next completion. +.TP +S\-Tab, C\-S\-i, A\-h +Select the previous completion. +.TP +PageUp, A\-k +Select the previous completion page. +.TP +PageDown, A\-j +Select the next completion page. +.TP +Home, A\-g +Select the first completion page. +.TP +End, A\-S\-g +Select the last completion page. + .SH CUSTOM COMPLETION .P Custom, multipart completion data may be proveded by an diff --git a/man/wimenu.man1 b/man/wimenu.man1 index 16d6b1ef..9c0c6dff 100644 --- a/man/wimenu.man1 +++ b/man/wimenu.man1 @@ -76,6 +76,63 @@ following. More advanced options are documented below. as a menu option, and the text to the right is displayed when a selection is made. += KEY BINDINGS = + +`wimenu`'s default key bindings are based largely on the +movement keys of vi and the standard UNIX shell input bindings. + +: Return, C-j, C-m + Accept the input, and select the first matching + completion if the cursor is at the end of the input. +: S-Return, C-S-j, C-S-m + Accept the input literally. +: Esc, C-[ + Quit without returning any output, and exit with + non-zero status. + +: A-p + Paste the PRIMARY selection. + +: Left, C-b + Move backward one character. +: Right, C-f + Move forward one character. + +: A-b + Move backward one word. +: A-f + Move forward one word. + +: C-a + Move to the begining of the line. +: C-e + Move to the end of the line. + +: C-p, Up + Move backward through the input history. +: C-n, Down + Move forward through the input history. + +: Backspace, C-h + Delete the previous character. +: C-Backspace, C-w + Delete the previous word. +: C-u + Delete the previous portion of the line. + +: Tab, C-i¸ A-l + Select the next completion. +: S-Tab, C-S-i, A-h + Select the previous completion. +: PageUp, A-k + Select the previous completion page. +: PageDown, A-j + Select the next completion page. +: Home, A-g + Select the first completion page. +: End, A-S-g + Select the last completion page. +: = CUSTOM COMPLETION = Custom, multipart completion data may be proveded by an diff --git a/mk/common.mk b/mk/common.mk index 90618822..955a3cf1 100644 --- a/mk/common.mk +++ b/mk/common.mk @@ -42,7 +42,7 @@ tags: [ -f "$$f.c" ] && files="$$files $$f.c"; \ done; \ echo CTAGS $$files $(TAGFILES); \ - $(DEBUG) $(CTAGS) $$files $(TAGFILES) + if [ -n "$$files" ]; then $(DEBUG) $(CTAGS) $$files $(TAGFILES); fi .PHONY: all options clean dist install uninstall depend cleandep tags .PHONY: simpleuninstall simpleinstall diff --git a/mk/dir.mk b/mk/dir.mk index 28cb2c42..2dda8dd2 100644 --- a/mk/dir.mk +++ b/mk/dir.mk @@ -21,12 +21,15 @@ duninstall: +dirs="$(INSTDIRS)"; $(MKSUBDIR) ddepend: +dirs="$(DIRS)"; $(MKSUBDIR) +dtags: + +dirs="$(DIRS)"; $(MKSUBDIR) all: dall clean: dclean install: dinstall uninstall: duninstall depend: ddepend +tags: dtags INSTDIRS = $(DIRS) diff --git a/mk/hdr.mk b/mk/hdr.mk index 8f5bd205..c4fced83 100644 --- a/mk/hdr.mk +++ b/mk/hdr.mk @@ -34,7 +34,7 @@ CLEANNAME=$(SHELL) $(ROOT)/util/cleanname SOEXT=so TAGFILES= -CTAGS=ctags +CTAGS=ctags --fields=+S --c-kinds=+px PACKAGES =