Re: [dwm] dmenu filename tab-completion patch

2009-01-28 Thread Jeremy Jay

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;
+

Re: [dwm] dmenu filename tab-completion patch

2009-01-28 Thread bill lam
On Wed, 28 Jan 2009, Jeremy Jay wrote:
 request granted =)  first tab will do longest
 completion, subsequent tabs will cycle through
 all choices.

Thank you for prompt action! 

If you could consider another request.  bash completion will list all
available choices for tabtab in one step.  Will it be possible to
do the same for dmenu.  There is another project dzen2 which can
display message text as dropdown from the status bar, it may be usable
for this tab completion.

-- 
regards,

GPG key 1024D/4434BAB3 2008-08-24
gpg --keyserver subkeys.pgp.net --recv-keys 4434BAB3
唐詩289 杜牧  將赴吳興登樂遊原
清時有味是無能  閒愛孤雲靜愛僧  欲把一麾江海去  樂遊原上望昭陵