Skip to main content

tancore/
path.rs

1use tan::{
2    context::Context,
3    error::Error,
4    expr::Expr,
5    util::{
6        fs::{get_dirname, get_full_extension},
7        module_util::require_module,
8    },
9};
10
11// #todo Consider removing from core.
12
13// #todo consider to associate most functions to the `Path` type.
14// #todo support (path :extension)
15// #todo support (path :full-extension)
16// #todo support (path :filename)
17// #todo support (path :directory)
18// #todo implement (get-parent ..)
19
20// #todo should it include the final `/`?
21/// Returns the directory part of a path.
22pub fn path_get_dirname(args: &[Expr]) -> Result<Expr, Error> {
23    let [path] = args else {
24        return Err(Error::invalid_arguments("requires a `path` argument", None));
25    };
26
27    // #todo in the future check for `Path`.
28    // #todo return Maybe::None if no directory found.
29
30    let Some(path) = path.as_string() else {
31        return Err(Error::invalid_arguments(
32            "`path` argument should be a String",
33            path.range(),
34        ));
35    };
36
37    // #todo should return a Maybe.
38    let dirname = get_dirname(path).unwrap_or("");
39
40    // #todo should return a `Path` value.
41
42    Ok(Expr::string(dirname))
43}
44
45/// Returns the 'full' extension of a path.
46pub fn path_get_extension(args: &[Expr]) -> Result<Expr, Error> {
47    let [path] = args else {
48        return Err(Error::invalid_arguments("requires a `path` argument", None));
49    };
50
51    // #todo in the future check for `Path`.
52    // #todo return Maybe::None if no extension found.
53
54    let Some(path) = path.as_string() else {
55        return Err(Error::invalid_arguments(
56            "`path` argument should be a String",
57            path.range(),
58        ));
59    };
60
61    // #todo should return a Maybe.
62    let extension = get_full_extension(path).unwrap_or("".to_string());
63
64    // #todo should return a `Path` value.
65
66    Ok(Expr::string(extension))
67}
68
69pub fn import_lib_path(context: &mut Context) {
70    // #todo Move under fs/?
71    // #insight not everything is fs-related.
72    let module = require_module("path", context);
73
74    // #todo think of a better name.
75    module.insert_invocable("get-dirname", Expr::foreign_func(&path_get_dirname));
76
77    // #todo think of a better name.
78    module.insert_invocable("get-extension", Expr::foreign_func(&path_get_extension));
79}