aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorczjstmax <jstmaxlol@disroot.org>2026-05-14 16:08:04 +0200
committerczjstmax <jstmaxlol@disroot.org>2026-05-14 16:08:04 +0200
commit511f30b96d06041f528ec005e4d3edffc4047608 (patch)
treea93f707558255636e336cdac8dba0023f64a136a
parentd5be1b2375c4adcf4840ac379fe88aa2fae45771 (diff)
update 1.2.5
Signed-off-by: czjstmax <jstmaxlol@disroot.org>
-rw-r--r--Makefile22
-rw-r--r--README.md57
-rw-r--r--rf.c163
-rw-r--r--rfile28
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)
-
diff --git a/README.md b/README.md
index 958a059..db999fa 100644
--- a/README.md
+++ b/README.md
@@ -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]` :)
diff --git a/rf.c b/rf.c
index eced3e5..b78524a 100644
--- a/rf.c
+++ b/rf.c
@@ -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");
+}
diff --git a/rfile b/rfile
index 97ba695..f38ab34 100644
--- a/rfile
+++ b/rfile
@@ -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
}