diff --git a/CHANGELOG.md b/CHANGELOG.md index cc93ca45..3665b149 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. ## ??? - Unreleased +- Allow importing modules from custom directories more easily with the `@` prefix + to module paths. For example, if there is a dynamic binding :custom-modules that + is a file system path to a directory of modules, import from that directory with + `(import @custom-modules/mymod)`. - Fix error message bug in FFI library. ## 1.25.1 - 2022-10-29 diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 169be584..b326dcf6 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -2642,9 +2642,10 @@ [image] (unmarshal image load-image-dict)) +(defn- check-dyn-relative [x] (if (string/has-prefix? "@" x) x)) (defn- check-relative [x] (if (string/has-prefix? "." x) x)) (defn- check-not-relative [x] (if-not (string/has-prefix? "." x) x)) -(defn- check-is-dep [x] (unless (or (string/has-prefix? "/" x) (string/has-prefix? "." x)) x)) +(defn- check-is-dep [x] (unless (or (string/has-prefix? "/" x) (string/has-prefix? "@" x) (string/has-prefix? "." x)) x)) (defn- check-project-relative [x] (if (string/has-prefix? "/" x) x)) (def module/cache @@ -2678,6 +2679,8 @@ (defn- find-prefix [pre] (or (find-index |(and (string? ($ 0)) (string/has-prefix? pre ($ 0))) module/paths) 0)) + (def dyn-index (find-prefix ":@all:")) + (array/insert module/paths dyn-index [(string ":@all:" ext) loader check-dyn-relative]) (def all-index (find-prefix ".:all:")) (array/insert module/paths all-index [(string ".:all:" ext) loader check-project-relative]) (def sys-index (find-prefix ":sys:")) diff --git a/src/core/corelib.c b/src/core/corelib.c index ed474178..dc9ec1a4 100644 --- a/src/core/corelib.c +++ b/src/core/corelib.c @@ -111,7 +111,10 @@ JANET_CORE_FN(janet_core_expand_path, "This takes in a path (the argument to require) and a template string, " "to expand the path to a path that can be " "used for importing files. The replacements are as follows:\n\n" - "* :all: -- the value of path verbatim\n\n" + "* :all: -- the value of path verbatim.\n\n" + "* :@all: -- Same as :all:, bu if `path` starts with the @ character,\n" + " the first path segment is replaced with a dynamic binding\n" + " `(dyn )`.\n\n" "* :cur: -- the current file, or (dyn :current-file)\n\n" "* :dir: -- the directory containing the current file\n\n" "* :name: -- the name component of path, with extension if given\n\n" @@ -157,6 +160,21 @@ JANET_CORE_FN(janet_core_expand_path, if (strncmp(template + i, ":all:", 5) == 0) { janet_buffer_push_cstring(out, input); i += 4; + } else if (strncmp(template + i, ":@all:", 6) == 0) { + if (input[0] == '@') { + const char *p = input; + while (*p && !is_path_sep(*p)) p++; + size_t len = p - input - 1; + char *str = janet_smalloc(len + 1); + memcpy(str, input + 1, len); + str[len] = '\0'; + janet_formatb(out, "%V", janet_dyn(str)); + janet_sfree(str); + janet_buffer_push_cstring(out, p); + } else { + janet_buffer_push_cstring(out, input); + } + i += 5; } else if (strncmp(template + i, ":cur:", 5) == 0) { janet_buffer_push_bytes(out, (const uint8_t *)curdir, curlen); i += 4;