nupp.io.path

nupp.io.path returns an immutable path value whose joining, normalizing and splitting follow the platform's own rules. Reach for it when a program builds a filesystem name or takes one apart, rather than when it reads the bytes behind one.

const path = nupp.io.path

local source = path.newPath("src", "app", "..", "main.nupp"):normalize()
assert(source:toString() == "src" .. path.separator() .. "main.nupp")
assert(source:fileName() == "main.nupp")

Every operation returns a new path, and two paths are equal when their native text is. tostring(path) and path:toString() return that same text.

Building a path#

path.newPath(first, parts...) joins its components using the current platform's rules. join appends more to a path already built, and both accept a string or another path. Path has no public constructor; creation goes through newPath, which interns recent paths in a bounded LRU cache.

const path = nupp.io.path

local native = path.newPath("out"):join("lib", "native")
assert(native:fileName() == "native")

currentDirectory and separator are functions on the module beside the record, because neither builds a path out of components:

const path = nupp.io.path

local current, reason = path.currentDirectory()
assert(current, reason)
local log = current:join("var", "app.log"):withExtension("jsonl")
assert(log:extension() == "jsonl")

Normalizing and resolving#

normalize removes lexical . and .. components without touching the filesystem, so it returns even for a path that does not exist:

const path = nupp.io.path

assert(path.newPath("src", "app", "..", "main.nupp"):normalize():stem() == "main")

The operations that consult the process or filesystem can fail, as can a relative path whose base uses a different coordinate system. Each returns nil with a reason when it does.

  • absolute() resolves the path against the process's working directory. A drive-relative Windows path fails when that directory uses another drive.
  • resolve(parts...) makes it absolute, appends the parts, and normalizes.
  • canonicalize() asks the filesystem for the real path, following every symbolic link, which requires the path to exist.
  • relativeTo(base) expresses the path against another one, when both share a coordinate system. A path expressed against itself returns ., the path that stays where the base already is.
const path = nupp.io.path

local real, reason = path.newPath("."):canonicalize()
assert(real, reason)
assert(real:isAbsolute())

Path components#

parent returns another path or nil. fileName, stem and extension return the final component, that component without its extension, and the extension without its dot:

const path = nupp.io.path

local source = path.newPath("src", "main.nupp")
assert(source:fileName() == "main.nupp")
assert(source:stem() == "main")
assert(source:extension() == "nupp")
assert(assert(source:parent()):toString() == "src")

withFileName and withExtension replace one component. Each takes one path component and raises when handed text that is not one, so a separator smuggled into a file name is reported where it was written rather than carried into the path it would have produced:

const path = nupp.io.path

local report = path.newPath("out", "report.tmp"):withExtension("json")
assert(report:fileName() == "report.json")

isAbsolute and isRelative classify a path without accessing the filesystem.

Submodules

ModuleDescription
nupp.io.path.spiImplementation interfaces consumed during ordinary module initialization.

Module contents

Types

TypeKindDescription
PathrecordA filesystem path.

Functions

FunctionKindDescription
currentDirectoryfunctionReads the process's current working directory.
newPathfunctionBuilds a path by joining one or more components using the platform's rules.
separatorfunctionReturns the current platform's primary path separator.

Types#

Pathrecord#

record Path ...

A filesystem path.

Members

NameKindDescription
toStringmethodReturns the native UTF-8 path text.
joinmethodAppends path components using the current platform's rules.
normalizemethodRemoves lexical .
absolutemethodResolves this path against the process's current working directory.
resolvemethodMakes this path absolute, appends components, and normalizes the result.
canonicalizemethodResolves every symbolic link and .., which requires the path to exist.
relativeTomethodExpresses this path relative to another.
parentmethodThe path without its final component.
fileNamemethodThe final component, extension included.
stemmethodThe final component without its extension.
extensionmethodThe final component's extension, without the dot.
withFileNamemethodThe path with its final component replaced.
withExtensionmethodThe path with its extension replaced.
isAbsolutemethodWhether the path is anchored at a root.
isRelativemethodWhether the path is interpreted against a working directory.
__tostringmetamethod
__eqmetamethod

toStringmethod#

toString: function toString(self): string

Returns the native UTF-8 path text.

Arguments
NameTypeDescription
selfany

this path

Returns
TypeDescription
string

the path text

joinmethod#

join: function join(self, ...: string | Path): Path

Appends path components using the current platform's rules.

Arguments
NameTypeDescription
selfany

this path

...string | Path

the components to append

Returns
TypeDescription
Path

the joined path

normalizemethod#

normalize: function normalize(self): Path

Removes lexical . and .. components without accessing the filesystem.

Arguments
NameTypeDescription
selfany

this path

Returns
TypeDescription
Path

the normalized path

absolutemethod#

absolute: function absolute(self): Path?, string?

Resolves this path against the process's current working directory.

A drive-relative Windows path can be resolved only when the current directory is on that drive.

Arguments
NameTypeDescription
selfany

this path

Returns
TypeDescription
Path?

the absolute path, or nil on failure

string?

a failure reason, when unsuccessful

resolvemethod#

resolve: function resolve(self, ...: string | Path): Path?, string?

Makes this path absolute, appends components, and normalizes the result.

Arguments
NameTypeDescription
selfany

this path

...string | Path

the components to append

Returns
TypeDescription
Path?

the resolved path, or nil on failure

string?

a failure reason, when unsuccessful

canonicalizemethod#

canonicalize: function canonicalize(self): Path?, string?

Resolves every symbolic link and .., which requires the path to exist.

This reads the filesystem, where normalize works on the text alone, so it fails on a path that is not there.

Arguments
NameTypeDescription
selfany

this path

Returns
TypeDescription
Path?

the canonical path, or nil on failure

string?

a failure reason, when unsuccessful

relativeTomethod#

relativeTo: function relativeTo(self, base: string | Path): Path?, string?

Expresses this path relative to another. A path expressed against itself returns ., the path that stays where the base already is.

Arguments
NameTypeDescription
selfany

this path

basestring | Path

the path to express this one against

Returns
TypeDescription
Path?

the relative path, or nil when there is no relative form

string?

a failure reason, when unsuccessful

parentmethod#

parent: function parent(self): Path?

The path without its final component.

Arguments
NameTypeDescription
selfany

this path

Returns
TypeDescription
Path?

the parent, or nil when there is none

fileNamemethod#

fileName: function fileName(self): string?

The final component, extension included.

Arguments
NameTypeDescription
selfany

this path

Returns
TypeDescription
string?

the file name, or nil when the path ends in a directory component

stemmethod#

stem: function stem(self): string?

The final component without its extension.

Arguments
NameTypeDescription
selfany

this path

Returns
TypeDescription
string?

the stem, or nil when there is no file name

extensionmethod#

extension: function extension(self): string?

The final component's extension, without the dot.

Arguments
NameTypeDescription
selfany

this path

Returns
TypeDescription
string?

the extension, or nil when there is none

withFileNamemethod#

withFileName: function withFileName(self, name: string): Path

The path with its final component replaced.

Arguments
NameTypeDescription
selfany

this path

namestring

the file name to use

Returns
TypeDescription
Path

the new path

Raises
TypeCondition
string

when name is not one component: empty, ., .., or holding a separator or NUL byte (or, on Windows, a colon)

withExtensionmethod#

withExtension: function withExtension(self, extension: string): Path

The path with its extension replaced.

Arguments
NameTypeDescription
selfany

this path

extensionstring

the extension to use, without the dot

Returns
TypeDescription
Path

the new path

Raises
TypeCondition
string

when extension holds a separator or NUL byte (or, on Windows, a colon)

isAbsolutemethod#

isAbsolute: function isAbsolute(self): boolean

Whether the path is anchored at a root.

Arguments
NameTypeDescription
selfany

this path

Returns
TypeDescription
boolean

whether the path is absolute

isRelativemethod#

isRelative: function isRelative(self): boolean

Whether the path is interpreted against a working directory.

Arguments
NameTypeDescription
selfany

this path

Returns
TypeDescription
boolean

whether the path is relative

__tostringmetamethod#

__tostring: function(self): string
Arguments
NameTypeDescription
?self
Returns
TypeDescription
string

__eqmetamethod#

__eq: function(self, any): boolean
Arguments
NameTypeDescription
?self
?any
Returns
TypeDescription
boolean

Functions#

currentDirectoryfunction#

function currentDirectory(): Path?, string?

Reads the process's current working directory.

Returns

TypeDescription
Path?

the current directory, or nil on failure

string?

a failure reason, when unsuccessful

newPathfunction#

function newPath(first: string | Path, ...: string | Path): Path

Builds a path by joining one or more components using the platform's rules.

Repeatedly building the same path reuses its immutable value from a bounded LRU.

Examples#
const path = nupp.io.path
local source = path.newPath("src", "main.nupp")

Arguments

NameTypeDescription
firststring | Path

the first path component

...string | Path

the remaining path components

Returns

TypeDescription
Path

the joined path

separatorfunction#

function separator(): string

Returns the current platform's primary path separator.

Returns

TypeDescription
string

the path separator