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 " "] .RB [ \-sf " "] .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 #include #include +#include #include #include #include @@ -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] [-nb ] [-nf ]\n" - " [-p ] [-sb ] [-sf ] [-v]\n"); + " [-p ] [-sb ] [-sf ] [-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#* }"