Re: [dev] [hack] Having dmenu provide hints about current selected entry
Hey, On 29 November 2010 00:17, Christophe-Marie Duquesne wrote: > I rewrote my proposal with select(). Now readstdin() will return if it > cannot read data from stdin during more than 1 u_sec. It will set the > static flag 'eof' to 1 if it has read the end of file character. This > way while eof is 0, you know you should call readstdin() again. Great, it's a lot cleaner this way. One problem with this approach, though, is that if data is written to stdin it isn't displayed until the next X event. This is likely fine for your use case, and dmenu_run, but perhaps not for other cases. To fix that we'd have to select between stdin and XConnectionNumber(dc->dpy). I've also attached a slightly neater version of your patch, plus a bugfix. Thanks, cls diff -r a79e4a9cb167 dmenu.c --- a/dmenu.c Sat Nov 20 09:25:08 2010 + +++ b/dmenu.c Mon Nov 29 01:40:44 2010 + @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -54,11 +55,13 @@ static unsigned long normcol[ColLast]; static unsigned long selcol[ColLast]; static Atom utf8; +static Bool eof = False; static Bool topbar = True; static DC *dc; static Item *items = NULL; static Item *matches, *sel; static Item *prev, *curr, *next; +static Item **end = &items; static Window root, win; static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; @@ -102,7 +105,6 @@ dc = initdc(); initfont(dc, font); - readstdin(); setup(); run(); @@ -433,9 +435,20 @@ void readstdin(void) { char buf[sizeof text], *p; - Item *item, **end; + fd_set fds; + int n; + struct timeval tv; + Item *item; - for(end = &items; fgets(buf, sizeof buf, stdin); *end = item, end = &item->next) { + while(!eof) { + tv.tv_sec = 0; + tv.tv_usec = 1; + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + if((n = select(1, &fds, NULL, NULL, &tv)) < 0) + eprintf("cannot select stdin\n"); + if(n == 0 || (eof = !fgets(buf, sizeof buf, stdin))) + break; if((p = strchr(buf, '\n'))) *p = '\0'; if(!(item = malloc(sizeof *item))) @@ -444,6 +457,9 @@ eprintf("cannot strdup %u bytes\n", strlen(buf)+1); item->next = item->left = item->right = NULL; inputw = MAX(inputw, textw(dc, item->text)); + *end = item; + end = &item->next; + match(); } } @@ -451,7 +467,7 @@ run(void) { XEvent ev; - while(!XNextEvent(dc->dpy, &ev)) + while(!XNextEvent(dc->dpy, &ev)) { switch(ev.type) { case Expose: if(ev.xexpose.count == 0) @@ -469,6 +485,8 @@ XRaiseWindow(dc->dpy, win); break; } + readstdin(); + } } void @@ -531,7 +549,7 @@ promptw = prompt ? textw(dc, prompt) : 0; XMapRaised(dc->dpy, win); text[0] = '\0'; - match(); + drawmenu(); } void
Re: [dev] [hack] Having dmenu provide hints about current selected entry
Hi, I rewrote my proposal with select(). Now readstdin() will return if it cannot read data from stdin during more than 1 u_sec. It will set the static flag 'eof' to 1 if it has read the end of file character. This way while eof is 0, you know you should call readstdin() again. Attached is a patch that you can also pull from https://bitbucket.org/chmduquesne/dmenu diff -r a79e4a9cb167 dmenu.c --- a/dmenu.c Sat Nov 20 09:25:08 2010 + +++ b/dmenu.c Mon Nov 29 01:14:46 2010 +0100 @@ -10,6 +10,8 @@ #ifdef XINERAMA #include #endif +#include +#include #include "draw.h" #define INRECT(x,y,rx,ry,rw,rh) ((x) >= (rx) && (x) < (rx)+(rw) && (y) >= (ry) && (y) < (ry)+(rh)) @@ -44,6 +46,7 @@ static int lines = 0; static int monitor = -1; static int promptw; +static int eof = 0; static size_t cursor = 0; static const char *font = NULL; static const char *prompt = NULL; @@ -59,6 +62,7 @@ static Item *items = NULL; static Item *matches, *sel; static Item *prev, *curr, *next; +static Item **end = &items; static Window root, win; static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; @@ -432,26 +436,44 @@ void readstdin(void) { + fd_set rfds; + struct timeval tv; + int canread; char buf[sizeof text], *p; - Item *item, **end; + Item *item; - for(end = &items; fgets(buf, sizeof buf, stdin); *end = item, end = &item->next) { - if((p = strchr(buf, '\n'))) - *p = '\0'; - if(!(item = malloc(sizeof *item))) - eprintf("cannot malloc %u bytes\n", sizeof *item); - if(!(item->text = strdup(buf))) - eprintf("cannot strdup %u bytes\n", strlen(buf)+1); - item->next = item->left = item->right = NULL; - inputw = MAX(inputw, textw(dc, item->text)); - } + do { + tv.tv_sec = 0; + tv.tv_usec = 1; + FD_ZERO(&rfds); + FD_SET(0, &rfds); + canread = select(1, &rfds, NULL, NULL, &tv); + if(canread == -1) + perror("select()"); + if(canread) { + eof = (fgets(buf, sizeof buf, stdin) == NULL); + if(!eof) { +if((p = strchr(buf, '\n'))) + *p = '\0'; +if(!(item = malloc(sizeof *item))) + eprintf("cannot malloc %u bytes\n", sizeof *item); +if(!(item->text = strdup(buf))) + eprintf("cannot strdup %u bytes\n", strlen(buf)+1); +item->next = item->left = item->right = NULL; +inputw = MAX(inputw, textw(dc, item->text)); + +*end = item; +end = &item->next; + } + } + } while(canread && !eof); } void run(void) { XEvent ev; - while(!XNextEvent(dc->dpy, &ev)) + while(!XNextEvent(dc->dpy, &ev)) { switch(ev.type) { case Expose: if(ev.xexpose.count == 0) @@ -469,6 +491,9 @@ XRaiseWindow(dc->dpy, win); break; } + if (!eof) + readstdin(); + } } void
Re: [dev] [st] Fixed -e with support for spaces
On Sun, Nov 28, 2010 at 04:20:21PM -0500, Joseph Xu wrote: > > > On 11/28/2010 06:22 AM, Aur??lien Aptel wrote: > > On Sat, Nov 27, 2010 at 12:35 AM, Joseph Xu wrote: > >> came up with. It relies on the shell that executes st to parse the > >> arguments, so you can't run a command like st -e "touch arst", you have > >> to run st -e touch arst. This also means you can't have any st arguments > >> after the -e because they'll all be included in the command to run. > > > > This breaks argument parsing. Why would you want to do that? > > Josh's solution is better imo. I've pushed (a slight variation of) it to > > tip. > > Not sure what you mean by breaking argument parsing. I think it's the > simplest way to parse a command with complex quoted arguments correctly > without having to run an extra shell process. > Agree. I prefer this patch to mine. Mainly due to a bug(?) in dmenu_run where everything is escaped before being executed by the shell. So, for example, I can't run `st -e "tmux a"` from dmenu_run, since it parses it as st -e \"tmux a\" instead. The xterm-like -e behavior circumvents this issue.
Re: [dev] [st] Fixed -e with support for spaces
Excerpts from Joseph Xu's message of Sun Nov 28 22:20:21 +0100 2010: > On 11/28/2010 06:22 AM, Aurélien Aptel wrote: > > On Sat, Nov 27, 2010 at 12:35 AM, Joseph Xu wrote: > >> came up with. It relies on the shell that executes st to parse the > >> arguments, so you can't run a command like st -e "touch arst", you have > >> to run st -e touch arst. This also means you can't have any st arguments > >> after the -e because they'll all be included in the command to run. > > > > This breaks argument parsing. Why would you want to do that? > > Josh's solution is better imo. I've pushed (a slight variation of) it to > > tip. > > Not sure what you mean by breaking argument parsing. I think it's the > simplest way to parse a command with complex quoted arguments correctly > without having to run an extra shell process. I agree with you on that. Furthermore, both urxvt and xterm do it the same way. >From urxvt(1): -e command [arguments] Run the command with its command-line arguments in the urxvt window; also sets the window title and icon name to be the basename of the program being executed if neither -title (-T) nor -n are given on the command line. If this option is used, it must be the last on the command-line. If there is no -e option then the default is to run the program specified by the SHELL environment variable or, failing that, sh(1). Please note that you must specify a program with arguments. If you want to run shell commands, you have to specify the shell, like this: urxvt -e sh -c "shell commands" >From xterm(1): -e program [ arguments ... ] This option specifies the program (and its command line argu‐ ments) to be run in the xterm window. It also sets the window title and icon name to be the basename of the program being executed if neither -T nor -n are given on the command line. This must be the last option on the command line. I think it makes sense and people are used to it that way. Best regards, Moritz
Re: [dev] [st] Fixed -e with support for spaces
On 11/28/2010 06:22 AM, Aurélien Aptel wrote: > On Sat, Nov 27, 2010 at 12:35 AM, Joseph Xu wrote: >> came up with. It relies on the shell that executes st to parse the >> arguments, so you can't run a command like st -e "touch arst", you have >> to run st -e touch arst. This also means you can't have any st arguments >> after the -e because they'll all be included in the command to run. > > This breaks argument parsing. Why would you want to do that? > Josh's solution is better imo. I've pushed (a slight variation of) it to tip. Not sure what you mean by breaking argument parsing. I think it's the simplest way to parse a command with complex quoted arguments correctly without having to run an extra shell process.
Re: [dev] #wmii
qq On Nov 28, 2010 11:15 AM, "Kurt H Maier" wrote: > hey kris if you're going to set the #wmii topic to channel all these > stupid questions into #suckless can you at least show up in #suckless > > -- > # Kurt H Maier >
[dev] #wmii
hey kris if you're going to set the #wmii topic to channel all these stupid questions into #suckless can you at least show up in #suckless -- # Kurt H Maier
Re: [dev] [st] Fixed -e with support for spaces
On Sat, Nov 27, 2010 at 12:35 AM, Joseph Xu wrote: > came up with. It relies on the shell that executes st to parse the > arguments, so you can't run a command like st -e "touch arst", you have > to run st -e touch arst. This also means you can't have any st arguments > after the -e because they'll all be included in the command to run. This breaks argument parsing. Why would you want to do that? Josh's solution is better imo. I've pushed (a slight variation of) it to tip.