jm

Odin for scripts: small packages and a runner, on core: only
Log | Files | Refs | README

commit 72ed70346bbf6d2f3183971bd1c847f6d6b2dd73
parent f4d4f24b11ae3b81471ebba24353b6fce27ef10c
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date:   Thu, 24 Sep 2026 16:25:54 -0300

jm: rename the collection from jfm to jm

Every import, the odin-run build define, ols.json, the justfile flags and
the test fixture names move from jfm to jm. The baked-in define becomes
JM_COLLECTION so it shares vocabulary with the ODIN_RUN_COLLECTION
environment variable it falls back from.

cache_dir's test now asserts the returned path ends in the app name, so a
stub that ignored the argument could no longer pass it.

Diffstat:
MREADME.md | 10+++++-----
Mdebug/debug.odin | 2+-
Mexamples/hello.odin | 10+++++-----
Mhttp/http.odin | 2+-
Mjustfile | 6+++---
Mols.json | 2+-
Mpath/path_test.odin | 5+++--
Mprelude/prelude.odin | 4++--
Mprelude/prelude_test.odin | 2+-
Msh/sh_unix_test.odin | 4++--
Mtar/tar_test.odin | 6+++---
Mtools/odin-run/main.odin | 10+++++-----
12 files changed, 32 insertions(+), 31 deletions(-)

diff --git a/README.md b/README.md @@ -1,4 +1,4 @@ -# jfm — Odin for scripts +# jm — Odin for scripts A collection of small packages and one runner that make Odin comfortable for the scripts Python and bash usually get. Everything builds on `core:`; the @@ -9,9 +9,9 @@ only linked dependency is libcurl through `vendor:curl`. package main import "core:fmt" -import "jfm:prelude" -import "jfm:sh" -import "jfm:path" +import "jm:prelude" +import "jm:sh" +import "jm:path" must :: prelude.must die :: prelude.die @@ -84,5 +84,5 @@ just install odin-run -> ~/.local/bin (BINDIR overrides) just example run examples/hello.odin just clean ``` -`just install` bakes this checkout's path into the runner as the `jfm` +`just install` bakes this checkout's path into the runner as the `jm` collection root; `ODIN_RUN_COLLECTION` overrides it. diff --git a/debug/debug.odin b/debug/debug.odin @@ -44,7 +44,7 @@ and where it was freed, since ASan itself only knows the address is poisoned. Usage (debug builds only, compile with -debug so call chains symbolize): import "core:debug/trace" - import "jfm:debug" + import "jm:debug" main :: proc() { when ODIN_DEBUG { diff --git a/examples/hello.odin b/examples/hello.odin @@ -7,11 +7,11 @@ import "core:fmt" import "core:log" import "core:time" -import "jfm:http" -import "jfm:path" -import "jfm:prelude" -import "jfm:sh" -import "jfm:timefmt" +import "jm:http" +import "jm:path" +import "jm:prelude" +import "jm:sh" +import "jm:timefmt" must :: prelude.must die :: prelude.die diff --git a/http/http.odin b/http/http.odin @@ -64,7 +64,7 @@ Opts :: struct { on_error: proc(msg: string), } -DEFAULT_USER_AGENT :: "jfm-odin-http/1" +DEFAULT_USER_AGENT :: "jm-odin-http/1" // get performs a GET. get :: proc(url: string, opts := Opts{}, allocator := context.allocator) -> (Response, Error) { diff --git a/justfile b/justfile @@ -10,7 +10,7 @@ odin := env("ODIN", "odin") root := justfile_directory() -flags := "-vet -strict-style -collection:jfm=" + root +flags := "-vet -strict-style -collection:jm=" + root exe := if os() == "windows" { ".exe" } else { "" } bindir := env("BINDIR", home_directory() / ".local" / "bin") packages := "prelude sh http path timefmt debug flow tar" @@ -23,12 +23,12 @@ default: # Debug odin-run -> build/debug/odin-run build: mkdir -p build/debug - {{odin}} build tools/odin-run -debug {{flags}} -define:JFM_ROOT={{root}} -out:build/debug/odin-run{{exe}} + {{odin}} build tools/odin-run -debug {{flags}} -define:JM_COLLECTION={{root}} -out:build/debug/odin-run{{exe}} # Optimised odin-run -> build/release/odin-run release: mkdir -p build/release - {{odin}} build tools/odin-run -o:speed {{flags}} -define:JFM_ROOT={{root}} -out:build/release/odin-run{{exe}} + {{odin}} build tools/odin-run -o:speed {{flags}} -define:JM_COLLECTION={{root}} -out:build/release/odin-run{{exe}} # Run every package's tests test: diff --git a/ols.json b/ols.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json", "collections": [ - { "name": "jfm", "path": "." } + { "name": "jm", "path": "." } ], "enable_semantic_tokens": true, "enable_snippets": true diff --git a/path/path_test.odin b/path/path_test.odin @@ -16,7 +16,7 @@ expand_home :: proc(t: ^testing.T) { @(test) files_roundtrip :: proc(t: ^testing.T) { - root, err := temp_dir("jfm-path-test-", context.temp_allocator) + root, err := temp_dir("jm-path-test-", context.temp_allocator) testing.expect_value(t, err, nil) defer remove_all(root) @@ -75,8 +75,9 @@ same_paths :: proc(t: ^testing.T) { @(test) app_dirs_exist :: proc(t: ^testing.T) { - d, err := cache_dir("jfm-path-test", context.temp_allocator) + d, err := cache_dir("jm-path-test", context.temp_allocator) testing.expect_value(t, err, nil) testing.expect(t, is_dir(d)) + testing.expect(t, strings.has_suffix(d, "jm-path-test"), "cache_dir must use the app name") remove_all(d) } diff --git a/prelude/prelude.odin b/prelude/prelude.odin @@ -17,7 +17,7 @@ issues when the debug allocator is in use. Allocation policy: a growing virtual arena is context.allocator. Scripts never free; the process exit reclaims everything. Set Options.debug (or ODIN_DEBUG, or the environment variable ODIN_SCRIPT_DEBUG=1) to swap in the debug -allocator from jfm:debug, which reports overflow, double free, and write after +allocator from jm:debug, which reports overflow, double free, and write after free at exit. Logging: one logfmt line per record in <log_dir>/<name>/<name>.log, plus a @@ -45,7 +45,7 @@ import "core:path/filepath" import "core:strings" import "core:time" -import "jfm:debug" +import "jm:debug" Options :: struct { // Program name used in log paths and lines. Default: basename of os.args[0]. diff --git a/prelude/prelude_test.odin b/prelude/prelude_test.odin @@ -34,6 +34,6 @@ logfmt_quoting :: proc(t: ^testing.T) { @(test) env_default :: proc(t: ^testing.T) { - testing.expect_value(t, env("JFM_PRELUDE_UNSET_3F9A", "fallback", context.temp_allocator), "fallback") + testing.expect_value(t, env("JM_PRELUDE_UNSET_3F9A", "fallback", context.temp_allocator), "fallback") testing.expect_value(t, level_name(.Warning), "warning") } diff --git a/sh/sh_unix_test.odin b/sh/sh_unix_test.odin @@ -25,8 +25,8 @@ dir_and_env :: proc(t: ^testing.T) { testing.expect(t, ok) testing.expect_value(t, s, "/") s, ok = out( - "echo $JFM_TEST", - {env = {"JFM_TEST=set", "PATH=/usr/bin:/bin"}}, + "echo $JM_TEST", + {env = {"JM_TEST=set", "PATH=/usr/bin:/bin"}}, context.temp_allocator, ) testing.expect(t, ok) diff --git a/tar/tar_test.odin b/tar/tar_test.odin @@ -4,13 +4,13 @@ import "core:os" import "core:path/filepath" import "core:strings" import "core:testing" -import "jfm:sh" +import "jm:sh" @(test) git_archive_extracts_whole :: proc(t: ^testing.T) { context.allocator = context.temp_allocator temp := os.temp_directory(context.temp_allocator) or_else "" - root, err := os.make_directory_temp(temp, "jfm-tar-*", context.temp_allocator) + root, err := os.make_directory_temp(temp, "jm-tar-*", context.temp_allocator) testing.expect(t, err == nil) defer os.remove_all(root) git := proc(root: string, args: ..string) -> sh.Result { @@ -79,7 +79,7 @@ git_archive_extracts_whole :: proc(t: ^testing.T) { } testing.expect_value(t, len(names), 3) - dest, derr := os.make_directory_temp(temp, "jfm-tar-out-*", context.temp_allocator) + dest, derr := os.make_directory_temp(temp, "jm-tar-out-*", context.temp_allocator) testing.expect(t, derr == nil) defer os.remove_all(dest) count, xerr := extract(transmute([]byte)archive.stdout, dest) diff --git a/tools/odin-run/main.odin b/tools/odin-run/main.odin @@ -16,7 +16,7 @@ odin-run/<key>/. Environment: ODIN odin binary; default: "odin" on PATH - ODIN_RUN_COLLECTION root of the jfm collection; default: baked in at install + ODIN_RUN_COLLECTION root of the jm collection; default: baked in at install ODIN_RUN_FLAGS extra build flags, split on spaces, such as "-debug" ODIN_RUN_VERBOSE=1 print the build command and cache path to stderr (exactly "1") */ @@ -28,10 +28,10 @@ import "core:os" import "core:path/filepath" import "core:strings" -import "jfm:sh" +import "jm:sh" // The collection root baked in by `just install`; ODIN_RUN_COLLECTION wins. -JFM_ROOT :: #config(JFM_ROOT, "") +JM_COLLECTION :: #config(JM_COLLECTION, "") EXE :: ".exe" when ODIN_OS == .Windows else "" @@ -78,7 +78,7 @@ main :: proc() { argv := make([dynamic]string) append(&argv, odin, "build", abs_script, "-file") if collection != "" { - append(&argv, strings.concatenate({"-collection:jfm=", collection})) + append(&argv, strings.concatenate({"-collection:jm=", collection})) } append(&argv, strings.concatenate({"-out:", bin})) append(&argv, ..flags) @@ -156,7 +156,7 @@ collection_root :: proc() -> string { if v, found := os.lookup_env("ODIN_RUN_COLLECTION", context.allocator); found && v != "" { return v } - return JFM_ROOT + return JM_COLLECTION } odin_binary :: proc() -> string {