std/path
Filesystem path manipulation.
Paths are immutable string-backed values. Every operation returns a fresh
Path rather than mutating. POSIX-style / separator only in MVP: Windows
support deferred (will replace the constant with a runtime-determined value).
Types
Path :: string An immutable filesystem path: a nominal newtype over string. Zero-cost:
at runtime a Path is its UTF-8 string, with no wrapper box. Nominal at
typecheck so a Path never silently mixes with a raw string ; every
combinator returns a fresh Path rather than mutating in place.
Basename :: struct The two halves of a filename, as returned by basename.
RETAINED against its own redundancy: filename() / name() / extension()
cover every use, and this should have gone with them, but removing it makes
vader test lib/std/path panic in to_posix, a function it never touched
(no field replace_chars_where on Path). Bisected: ADDING the three views is
fine, REMOVING this is what breaks, so it is a materialisation bug the removal
merely exposes. tests/vader_e2e.test.ts runs that isolated mode per stdlib
module, so the panic is CI-visible. See TODO.md; delete this once fixed.
Fields
name: string The filename without its final extension: "archive.tar".
extension: string The final extension without the leading dot: "gz".
Functions
to_posix :: fn(s: string) -> string Rewrite OS-native path separators to the canonical /. The compiler keeps
/ as its single internal separator (module discovery, the module index,
and vader/front/resolver::join_path are all /-based) so a path entering from
an OS boundary that may carry \ (Windows CLI arguments, env vars) must be
funnelled through here first, otherwise parent / filename (which split
on SEP) silently return empty. POSIX paths pass through unchanged.
Takes and returns a raw string, not a Path: the compiler internals it
serves (vader/front/resolver::loader, vader/tools/lsp/protocol::uri) are string-based,
and the CLI-side Path conversion stops at their boundary. Nothing technical
forces this any more: a Path -> Path signature used to panic in midir on the
chained cast inside, which is fixed: it is scope.
Parameters
| s | string | a path string, possibly using \ separators. |
Returns
string the same path with every \ rewritten to /.name :: fn(self: Path) -> string The final segment without its extension.
One of three views on the last segment, none of them overlapping:
filename() gives toto.zip, name() gives toto, extension() gives
zip.
Parameters
| self | Path | the path receiver. |
Returns
string the filename with its extension and dot removed, or the filename unchanged when it has no extension: a dotfile keeps its full name (.gitignore → .gitignore), since its leading dot is not an extension separator.Example
"src/archive.tar.gz".to_path().name() // "archive.tar"
"dir/.gitignore".to_path().name() // ".gitignore"extension :: fn(self: Path) -> string The final segment's extension, without the dot.
One of three views on the last segment, none of them overlapping:
filename() gives toto.zip, name() gives toto, extension() gives
zip. Kept separate rather than returning both halves at once, so a caller
wanting one doesn't pay for the other being built.
Parameters
| self | Path | the path receiver. |
Returns
string the extension without its dot, or "" when the final segment has none: a dotfile and a trailing dot both count as none.Example
"src/archive.tar.gz".to_path().extension() // "gz"
"dir/.gitignore".to_path().extension() // ""join :: fn(self: Path, other: string) -> Path Append a sub-path. Adds a separator between segments unless one is
already present. If other is absolute (starts with /), it
REPLACES self (Java Path.resolve semantics).
Parameters
| self | Path | the base path. |
| other | string | the segment to append (may itself contain separators). |
Returns
Path a fresh Path.normalize :: fn(self: Path) -> Path Collapse . and .. segments. Purely lexical: does NOT touch the
filesystem (no symlink resolution, no existence check). Preserves an
absolute prefix when present.
Parameters
| self | Path | the path receiver. |
Returns
Path a fresh, lexically-normalised Path.Example
"a/./b".to_path().normalize() // "a/b"
"a/b/..".to_path().normalize() // "a"
"/a/../b".to_path().normalize() // "/b"
"../foo".to_path().normalize() // "../foo"Constants
SEP: char :: '/' Path separator codepoint. POSIX-only in MVP (/).
SEP_STR: string :: "/" Path separator as a string: useful for direct concatenation.