On 18:25 Wed 28 Jan, Jeremy Jay wrote: > >On Wed 28 Jan 2009 - 12:38PM, bill lam wrote: >> It is very useful! >> Can it be extended to handle <tab><tab> ? > >request granted =) first tab will do longest >completion, subsequent tabs will cycle through >all choices. > >I dont know if others tried or not, but my >example didnt work... OpenOffice (and a few >other apps I noticed) doesn't like the escaped >spaces, so I tweaked the dmenu_run script so >it'll work now (assuming the filename is the >only argument... YMMV) > >This patch makes the functionality optional >through a "-c" command line argument, in the >interests of keeping dmenu generic and hoping >this will get committed to the main line. So >you'll want to add it to your dwm config.h or >whatever you call it through. I've also >added some info to the man page too. > >Jeremy
@Anselm I am curious, will you be committing this patch? -steve >diff -r 13402291bc76 dmenu.1 >--- a/dmenu.1 Fri Dec 12 19:58:52 2008 +0000 >+++ b/dmenu.1 Wed Jan 28 18:15:59 2009 -0500 >@@ -12,6 +12,7 @@ > .RB [ \-sb " <color>"] > .RB [ \-sf " <color>"] > .RB [ \-v ] >+.RB [ \-c ] > .SH DESCRIPTION > .SS Overview > dmenu is a generic menu for X, originally designed for >@@ -46,6 +47,9 @@ > .TP > .B \-v > prints version information to standard output, then exits. >+.TP >+.B \-c >+enables filename completion for text after a space (useful with the dmenu_run >script). > .SH USAGE > dmenu reads a list of newline-separated items from standard input and creates > a > menu. When the user selects an item or enters any text and presses Return, > his/her >@@ -67,7 +71,9 @@ > Select the first/last item. > .TP > .B Tab (Control\-i) >-Copy the selected item to the input field. >+Copy the selected item to the input field. Also, if the -c option is given >and there >+is a space in the input, will try to expand and complete text after the space >into a >+valid filename. (First Tab - Longest Completion, Multiple Tabs - cycle >through files) > .TP > .B Return (Control\-j) > Confirm selection and quit (print the selected item to standard output). > Returns >diff -r 13402291bc76 dmenu.c >--- a/dmenu.c Fri Dec 12 19:58:52 2008 +0000 >+++ b/dmenu.c Wed Jan 28 18:15:59 2009 -0500 >@@ -8,6 +8,7 @@ > #include <string.h> > #include <strings.h> > #include <unistd.h> >+#include <wordexp.h> > #include <X11/keysym.h> > #include <X11/Xlib.h> > #include <X11/Xutil.h> >@@ -59,6 +60,7 @@ > static void initfont(const char *fontstr); > static void kpress(XKeyEvent * e); > static void match(char *pattern); >+static void matchfile(char *filestart, Bool cycling); > static void readstdin(void); > static void run(void); > static void setup(Bool topbar); >@@ -77,7 +79,7 @@ > static int screen; > static unsigned int mw, mh; > static unsigned int numlockmask = 0; >-static Bool running = True; >+static Bool running = True, filecomplete = False; > static Display *dpy; > static DC dc; > static Item *allitems = NULL; /* first of all items */ >@@ -311,6 +313,7 @@ > > void > kpress(XKeyEvent * e) { >+ static KeySym lastkey=0; > char buf[32]; > int i, num; > unsigned int len; >@@ -396,7 +399,10 @@ > default: > if(num && !iscntrl((int) buf[0])) { > buf[num] = 0; >- strncpy(text + len, buf, sizeof text - len); >+ if(len > 0) >+ strncat(text, buf, sizeof text); >+ else >+ strncpy(text, buf, sizeof text); > match(text); > } > break; >@@ -467,12 +473,17 @@ > } > break; > case XK_Tab: >+ if( filecomplete && strchr(text, ' ')!=NULL ) { >+ matchfile( strchr(text, ' ')+1, lastkey==XK_Tab ); >+ break; >+ } > if(!sel) > return; > strncpy(text, sel->text, sizeof text); > match(text); > break; > } >+ lastkey=ksym; > drawmenu(); > } > >@@ -518,6 +529,44 @@ > } > > void >+matchfile(char *filestart, Bool cycling ) { >+ static int try=0, p=0; >+ wordexp_t exp; >+ int i, j, k; >+ >+ if( !cycling ) { >+ p = strlen(filestart); >+ try=0; >+ } >+ filestart[ p+1 ] = 0; >+ filestart[ p ] = '*'; >+ >+ wordexp(filestart, &exp, 0); >+ if( exp.we_wordc > 0 ) { >+ for(j=0,i=0; exp.we_wordv[try][i]!=0; i++,j++) { >+ if( exp.we_wordv[try][i]==' ' ) filestart[j++]='\\'; >+ filestart[j]=exp.we_wordv[try][i]; >+ } >+ filestart[j]=0; >+ >+ if( cycling ) >+ try = (try+1)%exp.we_wordc; >+ else >+ for(k=1; k<exp.we_wordc; k++) >+ for(j=0, i=0; exp.we_wordv[k][i]; i++,j++) { >+ if( filestart[j]=='\\' ) j++; >+ if( filestart[j]!=exp.we_wordv[k][i] ) { >+ filestart[j]=0; >+ break; >+ } >+ } >+ } else { >+ filestart[ p ] = 0; >+ } >+ wordfree(&exp); >+} >+ >+void > readstdin(void) { > char *p, buf[1024]; > unsigned int len = 0, max = 0; >@@ -677,6 +726,8 @@ > } > else if(!strcmp(argv[i], "-b")) > topbar = False; >+ else if(!strcmp(argv[i], "-c")) >+ filecomplete = True; > else if(!strcmp(argv[i], "-fn")) { > if(++i < argc) font = argv[i]; > } >@@ -699,7 +750,7 @@ > eprint("dmenu-"VERSION", © 2006-2008 dmenu engineers, > see LICENSE for details\n"); > else > eprint("usage: dmenu [-i] [-b] [-fn <font>] [-nb > <color>] [-nf <color>]\n" >- " [-p <prompt>] [-sb <color>] [-sf ><color>] [-v]\n"); >+ " [-p <prompt>] [-sb <color>] [-sf ><color>] [-v] [-c]\n"); > if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) > fprintf(stderr, "warning: no locale support\n"); > if(!(dpy = XOpenDisplay(0))) >diff -r 13402291bc76 dmenu_run >--- a/dmenu_run Fri Dec 12 19:58:52 2008 +0000 >+++ b/dmenu_run Wed Jan 28 18:15:59 2009 -0500 >@@ -1,2 +1,2 @@ >-#!/bin/sh >-exe=`dmenu_path | dmenu ${1+"$@"}` && exec $exe >+#!/bin/zsh >+exe=`dmenu_path | dmenu ${1+"$@"}` && exe2=${exe//\\ / } && exec ${exe2%% *} >"${exe2#* }"