diff options
| -rw-r--r-- | Makefile | 22 | ||||
| -rw-r--r-- | README.md | 57 | ||||
| -rw-r--r-- | rf.c | 163 | ||||
| -rw-r--r-- | rfile | 28 |
4 files changed, 203 insertions, 67 deletions
diff --git a/Makefile b/Makefile deleted file mode 100644 index 4d7f511..0000000 --- a/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -CC = gcc -OPTS = -Wall -Wextra -pedantic -std=c99 -FIN = rf.c -FOUT = rf -PREFIX ?= /usr -DESTDIR ?= - -.PHONY: all run install clean - -all: - $(CC) $(OPTS) $(FIN) -o $(FOUT) - -run: all - ./$(FOUT) - -install: all - sudo install -Dm755 $(FOUT) $(DESTDIR)$(PREFIX)/bin/$(FOUT) - $(MAKE) clean - -clean: - rm -v $(FOUT) - @@ -1,7 +1,58 @@ # runfile (`rfile`) -a **suckless**, **minimal**, **zero-dependancy**, **POSIX C99** alternative to `Makefile`/`justfile`s to *just run commands*. + +a **suckless** and **minimal**, **POSIX C99** alternative to `Makefile`/`justfile`! + +--- + +## `rfile` syntax & features + +- `#` -> ignore line (comment) + + +### variables + +the variable system in `rfile`s is very minimal: + +- every variable is a _string_ +- when accessed, `rf` text-substitutes the variable with its content + +example: +``` +@cc=gcc +@inp=rf.c +@out=rf +@opts=-Wall -Wextra -pedantic -std=c99 + +@cc @inp -o @out @opts +# becomes 'gcc rf.c -o rf -Wall -Wextra -pedantic -std=c99' +``` + + +### rfile command prefix (`@`) + +- `@: [msg]` -> print/log +- `@var=cmd` -> create variable `var` +- `@var` -> access variable `var` + + +### command sections + +example syntax: + +``` +section { + @: hello! +} +``` + +every other line is treated as a command and will run normally. + +> if no section is specified when calling `rf`, only commands in global scope will run. + +--- ## usage -1. create an `rfile` with commands divided by a `\n` -2. run `rf` in that directory. + +1. create an `rfile`. +2. run `rf [section name]` :) @@ -14,11 +14,22 @@ #define _POSIX_C_SOURCE 200809L -#define RUNFILE_VER_MAJ 1 /* anything that changes how rfile are written in the slightest */ -#define RUNFILE_VER_MIN 1 /* anything that varies the UX of the program (i.e. CLI flags) */ -#define RUNFILE_VER_FIX 20 /* optimizations, slight logic tweaks, anything that is not */ - /* noticeable by the user but impacts the dev experience enough */ -#include <stdio.h> /* to be important */ +#define RUNFILE_VER_MAJ 1 +#define RUNFILE_VER_MIN 2 +#define RUNFILE_VER_FIX 5 + +/* + *> rfile version system + * VER_MAX : anything that changes how rfile are written in the slightest + * between 0 and 999 + * VER_MIN : anything that varies the UX of the program (i.e. CLI flags) + * between 0 and 999 + * VER_FIX : optimizations, slight logic tweaks, anything that is not + * noticeable by the user but impacts the dev experience enough + * to be important. between 0 and 9999 + */ + +#include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <string.h> @@ -27,20 +38,25 @@ #include <wordexp.h> #include <sys/wait.h> +#define MAX_VARS 128 + +typedef struct { + char *key; + char *val; +} var_t; + +var_t vars[MAX_VARS]; +size_t var_count = 0; + void usage(); +void printBox(char *str); +char *expand_vars(char *input); int main(int argc, char **argv) { char *section = NULL; bool in_section = false; - bool should_run = false; - // check cli arguments - // if (argc < 2) { - // printf("<rf> not enough arguments.\n"); - // usage(); - // return 1; - // } if (argc >= 2) { for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { @@ -70,20 +86,9 @@ int main(int argc, char **argv) if (*cmd == '\0') continue; - else if (cmd[0] == '#') + else if (cmd[0] == '#') /* TODO: strchr() up to # and trim cmd to only skip + the commented-out part to allow in-line comments */ continue; - else if (strncmp(cmd, "@:", 2) == 0) { - for (size_t i = 0; i < strlen(cmd); i++) - printf("-"); - - printf("\n%s\n", cmd); - - for (size_t i = 0; i < strlen(cmd); i++) - printf("-"); - - printf("\n\n"); - continue; - } else if (strcmp(cmd, "}") == 0 || strcmp(line, "}") == 0) { in_section = false; @@ -92,6 +97,20 @@ int main(int argc, char **argv) continue; } + if (cmd[0] == '@' && strchr(cmd, '=')) { + char *eq = strchr(cmd, '='); + + *eq = '\0'; + + char *key = cmd + 1; //skip '@' + char *val = eq + 1; + + vars[var_count].key = strdup(key); + vars[var_count].val = strdup(val); + var_count++; + + continue; + } char *brace = strchr(cmd, '{'); if (brace) { @@ -110,24 +129,28 @@ int main(int argc, char **argv) continue; } - - should_run = false; - if (argc == 1) { - should_run = !in_section; + bool matches = + (argc == 1 && !in_section) + || (argc > 1 && section && strcmp(argv[1], section) == 0); + + if (!matches) + continue; + + if (strncmp(cmd, "@: ", 3) == 0) { + printf("\n%s\n", cmd); + continue; } - else { - should_run = in_section && - section && - strcmp(argv[1], section) == 0; + else if (strncmp(cmd, "@:! ", 4) == 0) { + printBox(cmd); + continue; } - if (!should_run) - continue; + char *expanded = expand_vars(cmd); - printf("$ %s\n", cmd); + printf("$ %s\n", expanded); - if (wordexp(cmd, &p, 0) != 0) { + if (wordexp(expanded, &p, 0) != 0) { fprintf(stderr, "wordexp failed\n"); continue; } @@ -160,3 +183,69 @@ void usage() ); } +char *expand_vars(char *input) +{ + static char buf[8192]; + size_t bi = 0; + + for (size_t i = 0; input[i] && bi < sizeof(buf) - 1; i++) { + + if (input[i] == '@') { + + char name[128] = {0}; + size_t ni = 0; + size_t j = i + 1; + + while (input[j] && + !isspace(input[j]) && + input[j] != '@' && + ni < sizeof(name) - 1) { + name[ni++] = input[j++]; + } + + name[ni] = '\0'; + + const char *replacement = NULL; + for (size_t v = 0; v < var_count; v++) { + if (strcmp(vars[v].key, name) == 0) { + replacement = vars[v].val; + break; + } + } + + if (replacement) { + size_t k = 0; + while (replacement[k] && bi < sizeof(buf) - 1) + buf[bi++] = replacement[k++]; + } + else { + buf[bi++] = '@'; + for (size_t k = 0; name[k]; k++) + buf[bi++] = name[k]; + } + + i = j - 1; + continue; + } + + buf[bi++] = input[i]; + } + + buf[bi] = '\0'; + return buf; +} + +void printBox(char *str) +{ + printf("┌"); + for (size_t i = 0; i < strlen(str) + 2; ++i) + printf("─"); + printf("┐\n"); + + printf("│ %s │\n", str); + + printf("└"); + for (size_t i = 0; i < strlen(str) + 2; ++i) + printf("─"); + printf("┘\n"); +} @@ -1,9 +1,27 @@ # rfile for rfile -@: hello from rfile -all { - cc -o rf rf.c -Wall -Wextra -pedantic - sudo install -Dm755 rf /usr/bin/rf - rm ./rf +# greet the polite visitor with a box! +@:! hello from rfile! + +# variables +@cc=gcc +@inp=rf.c +@out=rf +@opts=-Wall -Wextra -pedantic -std=c99 + +# build +@cc @inp -o @out @opts + +# install section +install { + rf + @: installing rf.. + sudo install -Dm755 @out /usr/bin/@out + rf clean +} + +# clean section +clean { + rm @out } |