Re: [dwm] dmenu filename tab-completion patch

From: Steven Blatchford <dollarsignfoo_AT_gmail.com>
Date: Mon, 23 Mar 2009 13:22:24 -0400

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#* }"
Received on Mon Mar 23 2009 - 17:22:24 UTC

This archive was generated by hypermail 2.2.0 : Mon Mar 23 2009 - 17:24:04 UTC