Hi all, I had a go at attempting to implement if-elsif-else-endif syntax for FVWM so I can do things like this in my .fvwm2rc file:
(Much more intuitive/maintainable than using PipeRead.) if xdpyinfo | /bin/grep -q XINERAMA Echo "dual head system!" Xinerama on XineramaPrimaryScreen 0 DeskTopSize 4x1 else Echo "NOT a dual head system." DeskTopSize 6x1 endif if [[ $(hostname) = "hamlet.denmark.org" ]] Echo "This is SCoTT's home system" elsif hostname | grep -q aao Echo "This is SCoTT's work system" endif if [ -f someSlackwareFile ] Echo "This is a Slackware system." elsif [ -f /etc/someDebianFile ] Echo "This is a Debian system." elsif [ -f /etc/redhat-release ] Echo "This is a RedHat system." else Echo "No idea what system this is." endif if [ $(cat /proc/meminfo | grep ^MemTotal | tr -s ' ' | cut -f2 -d' ') -gt 500000 ] Echo "You have more than 0.5GB of RAM" else Echo "You need to upgrade." endif Unfortunately I don't know of a way to make this work with FvwmConsole. Does anyone have any comments, suggestions, criticism, encouragement? SCoTT. :)
Index: fvwm/read.c =================================================================== RCS file: /home/cvs/fvwm/fvwm/fvwm/read.c,v retrieving revision 1.60 diff -u -r1.60 read.c --- fvwm/read.c 29 Jun 2003 19:53:23 -0000 1.60 +++ fvwm/read.c 29 Apr 2004 10:44:04 -0000 @@ -114,25 +114,16 @@ return curr_read_dir; } - -/* - * Read and execute each line from stream. - */ -void run_command_stream( - cond_rc_t *cond_rc, FILE *f, const exec_context_t *exc) +/* __run_command_stream() - utility function for run_command_stream(). */ +void __run_command_stream( + cond_rc_t *cond_rc, FILE *f, const exec_context_t *exc, + Bool bInIf, Bool bIfTrue) { - char *tline; + char *tline, *tmp, *func = "__run_command_stream", *cond; char line[1024]; + Bool bIgnoreSection = !bIfTrue; - /* Set close-on-exec flag */ - fcntl(fileno(f), F_SETFD, 1); - - /* Update window decorations in case we were called from a menu that - * has now popped down. */ - handle_all_expose(); - - tline = fgets(line, (sizeof line) - 1, f); - while (tline) + while (NULL != (tline = fgets(line, (sizeof line) - 1, f))) { int l; while (tline && (l = strlen(line)) < sizeof(line) && l >= 2 && @@ -150,6 +141,63 @@ { tline[l - 1] = '\0'; } + /* remove leading whitespace */ + tline = SkipSpaces(tline, NULL, 0); + /* ignore blank lines & comments. */ + if (tline == NULL || tline[0] == '\0' || tline[0] == '#') + continue; + + tmp = tline; + tmp = PeekToken(tmp, &cond); + if (strcasecmp(tmp, "if") == 0) + { + // fvwm_msg(DBG, func, "if-cmd=<%s>", cond); + bIfTrue = !system(cond); + // use recursion to allow nested if-statements. + __run_command_stream(cond_rc, f, exc, True, bIfTrue); + // at this point the complete if-statement has been handled. + // ie. we've parsed the file all the way through to the + // matching "endif". + continue; + } + else if (strcasecmp(tmp, "elsif") == 0) + { + if (!bInIf) + fvwm_msg(ERR, func, "\"elsif\" not within if-statement"); + if (bIfTrue) + bIgnoreSection = True; + else + { + // fvwm_msg(DBG, func, "elsif-cmd=<%s>", cond); + bIfTrue = !system(cond); + bIgnoreSection = !bIfTrue; + } + continue; + } + else if (strcasecmp(tmp, "else") == 0) + { + if (!bInIf) + fvwm_msg(ERR, func, "\"else\" not within if-statement"); + if (bIfTrue) + bIgnoreSection = True; + else + { + bIfTrue = True; + bIgnoreSection = False; + } + continue; + } + else if (strcasecmp(tmp, "endif") == 0) + { + if (!bInIf) + fvwm_msg(ERR, func, "\"endif\" not within if-statement"); + else + return; + } + + if (bInIf && bIgnoreSection) + continue; + if (debugging) { fvwm_msg( @@ -158,12 +206,26 @@ exc->m.modnum, tline); } execute_function(cond_rc, exc, tline, 0); - tline = fgets(line, (sizeof line) - 1, f); } return; } +/* + * Read and execute each line from stream. + */ +void run_command_stream( + cond_rc_t *cond_rc, FILE *f, const exec_context_t *exc) +{ + /* Set close-on-exec flag */ + fcntl(fileno(f), F_SETFD, 1); + + /* Update window decorations in case we were called from a menu that + * has now popped down. */ + handle_all_expose(); + + __run_command_stream(cond_rc, f, exc, False, False); +} /** * Parse the action string. We expect a filename, and optionally,