]> git.xolatile.top Git - emil-bake.git/commitdiff
expunge, color
authorEmil Williams <emilemilemil@cock.li>
Sat, 28 Sep 2024 21:35:50 +0000 (21:35 +0000)
committerEmil Williams <emilemilemil@cock.li>
Sat, 28 Sep 2024 21:35:50 +0000 (21:35 +0000)
bake.l

diff --git a/bake.l b/bake.l
index 069336f1f2c408f3089a44b4625886c7fb65df45..fa0b1f54f44d41e551ea7e566f338f3c13adb6ce 100644 (file)
--- a/bake.l
+++ b/bake.l
@@ -1,63 +1,84 @@
 /* cbake.l @BAKE flex @FILE && cc -Wall -Wextra -std=c99 -D_GNU_SOURCE -o @SHORT lex.yy.c @ARGS -lfl @STOP */
-/* TODO: implement expunge, color */
+/* expunge @BAKE flex @FILE && cc -Wall -Wextra -std=c99 -D_GNU_SOURCE -o @{@SHORT} lex.yy.c @ARGS -lfl @STOP */
+/* expunge @BAKE @STOP */
+
 %{
 #include <ctype.h>
 
+#define CHAR(c)          do { if (stdout) { fputc(c, stdout);             } if (g_pipe) { fputc(c, g_pipe);             } } while (0)
+#define STRING(s)        do { if (stdout) { fputs(s, stdout);             } if (g_pipe) { fputs(s, g_pipe);             } } while (0)
+#define FORMAT(...)      do { if (stdout) { fprintf(stdout, __VA_ARGS__); } if (g_pipe) { fprintf(g_pipe, __VA_ARGS__); } } while (0)
+#define FWRITE(str, len) do { if (stdout) { fwrite(str, 1, len, stdout);  } if (g_pipe) { fwrite(str, 1, len, g_pipe);  } } while (0)
+
 #undef ECHO
-#define ECHO             do { fprintf(stdout, yytext);      if (g_pipe) { fprintf(g_pipe, yytext); }      } while (0)
-#define CHAR(c)          do { fputc(c, stdout);             if (g_pipe) { fputc(c, g_pipe); }             } while (0)
-#define STRING(s)        do { fputs(s, stdout);             if (g_pipe) { fputs(s, g_pipe); }             } while (0)
-#define FORMAT(...)      do { fprintf(stdout, __VA_ARGS__); if (g_pipe) { fprintf(g_pipe, __VA_ARGS__); } } while (0)
-#define FWRITE(str, len) do { fwrite(str, 1, len, stdout);  if (g_pipe) { fwrite(str, 1, len, g_pipe); }  } while (0)
+#define ECHO STRING(yytext)
 
 /* input from main to lexer */
-FILE * g_pipe;
-char * g_filename;
-int g_ac;
-char ** g_av;
-int g_select = 1;
+FILE  * g_pipe = NULL, * g_restore, * g_expunge;
+int     g_ac, g_select = 1, g_color = 1, g_rm = 0;
+char ** g_av, * g_filename, * av0;
 /* for the lexers eyes only */
-int line = 1, nth = 0, expunge_depth = 0, first_nl, tmpline;
+int line = 1, expunge_depth, first_nl, tmpline;
 
 extern void root(char * filename);
 extern void args(int n);
 extern void shorten(char * filename, int n);
+extern void pipeopen(char * filename, char * mode);
 %}
 
 SPACE [ \t\r\v\f]
 MACROS (@BAKE|@FILENAME|@FILE|@NAME|@SHORT|@ARGS|@LINE|@STOP|$@|$*|$+)
 
-%x FOUND PADDING STOP
+%x FOUND PADDING STOP EXPAND
 %option nodefault noinput nounput noyywrap
 %%
 
+\n { ++line; }
+.  { ; }
+
 @BAKE[[:space:]] { bake:
+  static int nth = 0;
   first_nl = 1;
-
-  if (yytext[yyleng-1] == '\n') { ++line; }
-  if (!g_select) { ; }
-  else if (g_select < 0) { BEGIN FOUND; printf("\n%s:%d:s%d: ", g_filename, line, ++nth); }
-  else if (!--g_select)  { BEGIN FOUND;                                                   }
+  if (yytext[yyleng-1] == '\n') { ++line;                                                        }
+  if (!g_select)                {                                                              ; }
+  else if (g_select < 0)        { BEGIN FOUND; printf("\n%s:%d:s%d: ", g_filename, line, ++nth); }
+  else if (!--g_select)         { BEGIN FOUND;                                                   }
 }
 
-\n { ++line; }
-.  {;}
-
 <FOUND>{
- @BAKE[[:space:]]|@STOP   { BEGIN INITIAL; yyless(0); if (first_nl) { CHAR('\n'); } if (!g_select) { return 0; }    }
- @FILENAME|@FILE|@NAME|$@ { STRING(g_filename);                                                                   }
- @SHORT:[[:digit:]]+      { shorten(g_filename, atoi(strrchr(yytext, ':')+1));                                      }
- @SHORT|$\*               { shorten(g_filename, 1);                                                                 }
- @ARGS:[[:digit:]]+       { args(atoi(strrchr(yytext, ':')+1));                                                     }
- @ARGS|$\+                { args(-1);                                                                               }
- @LINE                    { FORMAT("%d", line);                                                                     }
- @\{                      { ++expunge_depth;                                                                        }
- \}                       { if (!expunge_depth--) { ECHO; }                                                         }
- \\\n                     { BEGIN PADDING; ++line; CHAR(' ');                                                       }
- \\{MACROS}               { STRING(yytext + 1);                                                                     }
- \n                       { CHAR('\n'); ++line; if (first_nl) { BEGIN STOP; first_nl = 0; tmpline = 0; }            }
- {SPACE}                  { BEGIN PADDING; CHAR(' ');                                                               }
- .                        { ECHO;                                                                                   }
+ @\{ {
+   expunge_depth = 1;
+   if (g_select < 0) { ECHO; }
+   else if (g_rm && !g_pipe) {
+     stdout = g_restore;
+     g_pipe = g_expunge; STRING("rm '");
+   }
+ }
+
+ \} {
+   if (g_select < 0 || !expunge_depth) { ECHO; break; }
+   if (g_rm)           { STRING("'"); return 0; }
+   expunge_depth = 0;
+ }
+
+ '                        { if (g_rm) { STRING("\\'"); } else { ECHO; }                                          }
+ @BAKE[[:space:]]|@STOP   { BEGIN INITIAL; yyless(0); if (first_nl) { CHAR('\n'); } if (!g_select) { return 0; } }
+ \\\n                     { BEGIN PADDING; ++line; CHAR(' ');                                                    }
+ {MACROS}                 { BEGIN EXPAND; yyless(0);                                                             }
+ \\{MACROS}               { STRING(yytext + 1);                                                                  }
+ {SPACE}                  { BEGIN PADDING; CHAR(' ');                                                            }
+ \n                       { CHAR('\n'); ++line; if (first_nl) { BEGIN STOP; first_nl = 0; tmpline = 0; }         }
+ .|\\'                    { ECHO;                                                                                }
+}
+
+<EXPAND>{
+ @FILENAME|@FILE|@NAME|$@ { BEGIN FOUND; STRING(g_filename);                                }
+ @SHORT:[[:digit:]]+      { BEGIN FOUND; shorten(g_filename, atoi(strrchr(yytext, ':')+1)); }
+ @SHORT|$\*               { BEGIN FOUND; shorten(g_filename, 1);                            }
+ @ARGS:[[:digit:]]+       { BEGIN FOUND; args(atoi(strrchr(yytext, ':')+1));                }
+ @ARGS|$\+                { BEGIN FOUND; args(-1);                                          }
+ @LINE                    { BEGIN FOUND; FORMAT("%d", line);                                }
+ .|\n                     { BEGIN FOUND; yyless(0); }
 }
 
 <PADDING>{
@@ -74,6 +95,13 @@ MACROS (@BAKE|@FILENAME|@FILE|@NAME|@SHORT|@ARGS|@LINE|@STOP|$@|$*|$+)
 
 %%
 
+# define    RED "\033[91m"
+# define  GREEN "\033[92m"
+# define YELLOW "\033[93m"
+# define    DIM "\033[2m"
+# define   BOLD "\033[1m"
+# define  RESET "\033[0m"
+
 void root(char * filename) {
   char * path, * terminator;
   if (!(path = realpath(filename, NULL))) { return; }
@@ -101,13 +129,17 @@ void shorten(char * filename, int n) {
   FWRITE(filename, end - filename);
 }
 
-void help(void) { fputs("see bake(1) - \"Buy high. Sell low.\"\n", stderr); }
+void help(void) { fprintf(stderr, g_color ? BOLD "%s" RESET : "%s", "see bake(1) - \"Buy high. Sell low.\"\n"); }
+
+void pipeopen(char * filename, char * mode) {
+  g_pipe = popen(filename, mode);
+  if (!g_pipe) { fprintf(stderr, "%s: <g_pipe> %s\n", av0, strerror(errno)); exit(1); }
+}
 
 int main (int ac, char ** av) {
   int run = 1;
-  char * av0 = av[0];
+  av0 = av[0];
   FILE * fp;
-
   /* supports long/short, -allinone, (-X ... -X=... -X<NUM>) */
   while (++av, --ac) {
     size_t i;
@@ -116,7 +148,7 @@ int main (int ac, char ** av) {
       if (av[0][2] == '\0')            { ++av, --ac;                       goto start;       }
       if (!strcmp(av[0]+2, "dry-run")) { i = strlen(av[0]);                goto opt_dry_run; }
       if (!strcmp(av[0]+2, "color"))   { i = strlen(av[0]);                goto opt_color;   }
-      if (!strcmp(av[0]+2, "expunge"))   { i = strlen(av[0]);              goto opt_expunge; }
+      if (!strcmp(av[0]+2, "expunge")) { i = strlen(av[0]);                goto opt_expunge; }
       if (!strcmp(av[0]+2, "select" )) { if (!ac-1 || isdigit(av[1][0])) { goto opt_arg;     }
                                          ++av, --ac; i = strlen(av[0]);    goto opt_select;  }
       if (!strcmp(av[0]+2, "list"   )) { i = strlen(av[0]);                goto opt_list;    }
@@ -128,16 +160,18 @@ int main (int ac, char ** av) {
         opt_dry_run: case 'n': run = 0; break;
           case 's':
           /* Covers cases -<LAST>s<NUM> -<LAST>s <NUM> */
-               if (isdigit(av[0][i+1]))         { g_select = atoi(av[0]+i+1); }
-          else if (ac > 1 && isdigit(av[1][0])) { ++av, --ac; opt_select: g_select = atoi(av[0]); }
-          else                                  { g_select = 0; }
-               if (!g_select)                   { fprintf(stderr, "%s: Invalid argument for -s\n", av0); return 1; }
+          if (g_select != -1) {
+                 if (isdigit(av[0][i+1]))         { g_select = atoi(av[0]+i+1); }
+            else if (ac > 1 && isdigit(av[1][0])) { ++av, --ac; opt_select: g_select = atoi(av[0]); }
+            else                                  { g_select = 0; }
+                 if (!g_select)                   { fprintf(stderr, "%s: Invalid argument for -s\n", av0); return 1; }
+          }
           i = strlen(av[0]);
           break;
         opt_list:    case 'l': run = 0; g_select = -1; break;
         opt_help:    case 'h': help(); return 0;
-        opt_color:   case 'c': break;
-        opt_expunge: case 'x': break;
+        opt_color:   case 'c': g_color = 0; break;
+        opt_expunge: case 'x': if (g_select > 0) { g_rm = 1; } break;
         opt_default:  default: fprintf(stderr, "%s: Unknown option '%s'\n", av0, av[0]); return 1;
         opt_arg:               fprintf(stderr, "%s: Argument missing for '%s'\n", av0, av[0]); return 1;
       }
@@ -157,25 +191,39 @@ int main (int ac, char ** av) {
 
   /* open and prepare ac, av */
   if (!(yyin = fp = fopen(g_filename, "rb")))
-  { fprintf(stderr, "%s: '%s' %s\n", av0, g_filename, strerror(errno)); return 1; }
+  { fprintf(stderr, g_color ? RED "%s" RESET ": '" BOLD "%s" RESET "' %s\n" : "%s: '%s' %s\n", av0, g_filename, strerror(errno)); return 1; }
   g_ac = --ac, g_av = ++av;
 
-  /* Prepares our UNIX pipe for input */
+  /* setup pipe and output */
   if (run) {
-    g_pipe = popen("/bin/sh -e", "w");
-    if (!g_pipe) { fprintf(stderr, "%s: <g_pipe> %s\n", av0, strerror(errno)); return 1; }
+    pipeopen("/bin/sh -e /dev/stdin", "w");
   }
+  if (g_rm) {
+    g_restore = stdout;
+    g_expunge = g_pipe;
+    stdout = NULL;
+    g_pipe = NULL;
+  }
+  if (g_select > 0) { fprintf(stderr, g_color ? GREEN "%s" RESET ": " : "%s: ", av0); fflush(stderr); }
 
-  if (g_select > 0) { fprintf(stderr, "%s: ", av0); fflush(stderr); }
   yylex(); fflush(stdout);
+
+  if (g_rm) {
+    fputs("\n", g_restore);
+    stdout = g_restore;
+    g_pipe = g_expunge;
+  }
   fclose(fp);
+
   if (g_select > 0) { pclose(g_pipe); goto out_of_range; }
 
   if (!run) { return 0; }
-  fprintf(stderr, "output: "); fflush(stderr);
+
+  if (!g_rm) { fprintf(stderr, g_color ? GREEN "output" RESET ": " : "output: "); fflush(stderr); }
+
   run = pclose(g_pipe); /* repurposed run */
-  putchar('\n');
-  if (run) { printf("%s: Exit code %d\n", av0, run); }
+  if (!g_rm) { putchar('\n'); }
+  if (run) { fprintf(stderr, "%s: Exit code %d\n", av0, run); }
   return run;
   out_of_range: fprintf(stderr, "%s: <%d> Out of range\n", av0, g_select); return 1;
 }