On Wed 28 Jan 2009 - 12:38PM, bill lam wrote:
It is very useful!
Can it be extended to handle tabtab ?
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
diff -r 13402291bc76 dmenu.1
--- a/dmenu.1 Fri Dec 12 19:58:52 2008 +
+++ 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 +
+++ 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; kexp.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;
+