A Luau library to handle file paths based on the Rust path library.
The library can be configured to use unix or windows style separator using the global variable SYS_PATH_SEPARATOR
. The global should be defined to '/'
or '\'
.
When the global is not defined, it will default to '/'
. If a LUA_ENV
global variable is set to lune
, the path separator will be inferred from lune's process built-in library.
Add luau-path
in your dependencies:
yarn add luau-path
Or if you are using npm
:
npm install luau-path
This libary exports a Path
class and the AsPath
type.
local PathModule = require('@pkg/luau-path')
local Path = PathModule.Path
type Path = PathModule.Path
type AsPath = PathModule.AsPath
Constructors:
Static functions:
Path methods:
- ancestors
- clear
- components
- endsWith
- equal
- extension
- fileName
- filePrefix
- fileStem
- hasRoot
- isAbsolute
- isRelative
- join
- parent
- pop
- push
- setExtension
- setFileName
- startsWith
- stripPrefix
- toPathBuf
- toString
- withFileName
- withExtension
type AsPath = string | Path | Components
function Path.new(path: string): Path
Creates a new path from the given string
.
function Path.from(path: AsPath): Path
Creates a new path from a string
or a Components
iterator, or return the given Path object.
This function errors if the value does not satisfy the AsPath
type.
function Path.new(value: unknown): boolean
Returns true
if the given value is a Path.
function Path:toString(): string
Converts the path to a string representation.
function Path:toPathBuf(): Path
Creates a new Path
object that is a copy of the current path.
function Path:isAbsolute(): boolean
Returns true if the Path is absolute, i.e., if it is independent of the current directory.
- On Unix, a path is absolute if it starts with the root, so
isAbsolute
andhasRoot
are equivalent. - On Windows, a path is absolute if it has a prefix and starts with the root:
c:\windows
is absolute, whilec:temp
and\temp
are not.
function Path:isRelative(): boolean
Returns true
if the Path is relative, i.e., not absolute.
See isAbsolute's documentation for more details.
Examples
assert(Path.new("foo.txt"):isRelative())
function Path:hasRoot(): boolean
Returns true
if the Path has a root.
- On Unix, a path has a root if it begins with
/
. - On Windows, a path has a root if it:
- has no prefix and begins with a separator, e.g.,
\windows
- has a prefix followed by a separator, e.g.,
c:\windows
but notc:windows
- has any non-disk prefix, e.g.,
\\server\share
- has no prefix and begins with a separator, e.g.,
Examples
assert(Path.new("/etc/passwd"):hasRoot())
function Path:parent(): Path?
Returns the Path without its final component, if there is one.
This means it returns ""
for relative paths with one component.
Returns nil
if the path terminates in a root or prefix, or if it’s the empty string.
function Path:ancestors(): Ancestors
Produces an iterator over Path and its ancestors.
The iterator will yield the Path that is returned if the parent method is used zero or more times. That means, the iterator will yield self
, self:parent()
, self:parent():parent()
and so on. If the parent method returns nil
, the iterator will do likewise. The iterator will always yield at least one value, namely self
.
function Path:fileName(): string?
Returns the final component of the Path, if there is one.
If the path is a normal file, this is the file name. If it’s the path of a directory, this is the directory name.
Returns nil
if the path terminates in ..
.
function Path:stripPrefix(base: AsPath): Path?
Returns a path that, when joined onto base, yields self.
If base is not a prefix of self (i.e., startsWith returns false
), returns nil
.
function Path:startsWith(base: AsPath): boolean
Determines whether base
is a prefix of self
.
Only considers whole path components to match.
function Path:endsWith(child: AsPath): boolean
Determines whether child
is a suffix of self
.
Only considers whole path components to match.
function Path:fileStem(): string?
Extracts the stem (non-extension) portion of self:fileName()
.
The stem is:
nil
, if there is no file name;- The entire file name if there is no embedded
.
; - The entire file name if the file name begins with
.
and has no other.
s within; - Otherwise, the portion of the file name before the final
.
See Also
This method is similar to filePrefix
, which extracts the portion of the file name before the first .
function Path:filePrefix(): string?
Extracts the prefix of self:fileName()
.
The prefix is:
nil
, if there is no file name;- The entire file name if there is no embedded
.
; - The portion of the file name before the first non-beginning
.
; - The entire file name if the file name begins with
.
and has no other.
s within; - The portion of the file name before the second
.
if the file name begins with.
See Also
This method is similar to fileStem
, which extracts the portion of the file name before the last .
function Path:extension(): string?
Extracts the extension (without the leading dot) of self:fileName()
, if possible.
The extension is:
nil
, if there is no file name;nil
, if there is no embedded.
;nil
, if the file name begins with.
and has no other.
s within;- Otherwise, the portion of the file name after the final
.
function Path:join(path: AsPath): Path
Creates a new Path with path
adjoined to self.
If path is absolute, it replaces the current path.
See push
for more details on what it means to adjoin a path.
function Path:withFileName(fileName: string): Path
Creates a new Path like self
but with the given file name.
See setFileName
for more details.
function Path:withExtension(extension: string): Path
Creates a new Path like self
but with the given extension.
See setExtension
for more details.
function Path:components(): Components
Produces an iterator over the Components of the path.
When parsing the path, there is a small amount of normalization:
- Repeated separators are ignored, so a/b and a//b both have a and b as components.
- Occurrences of . are normalized away, except if they are at the beginning of the path. For example, a/./b, a/b/, a/b/. and a/b all have a and b as components, but ./a/b starts with an additional CurDir component.
- A trailing slash is normalized away, /a/b and /a/b/ are equivalent.
Note that no other normalization takes place; in particular, a/c
and a/b/../c
are distinct, to account for the possibility that b
is a symbolic link (so its parent isn't a
).
function Path:equal(other: Path): boolean
Returns true
if the current path is equal to the other path.
function Path:push(path: AsPath): ()
Extends self
with path
.
If path
is absolute, it replaces the current path.
On Windows:
- if
path
has a root but no prefix (e.g.,\windows
), it replaces everything except for the prefix (if any) of self. - if
path
has a prefix but no root, it replacesself
. - if
self
has a verbatim prefix (e.g.\\?\C:\windows
) andpath
is not empty, the new path is normalized: all references to.
and..
are removed.
Consider using join
if you need a new Path instead of using this function on a cloned Path.
function Path:pop(): boolean
Truncates self
to self:parent()
.
Returns false
and does nothing if self:parent()
is nil
. Otherwise, returns true
.
function Path:setFileName(fileName: string): ()
Updates self:fileName()
to fileName
.
If self:fileName()
was nil
, this is equivalent to pushing fileName
.
Otherwise it is equivalent to calling pop
and then pushing fileName
. The new path will be a sibling of the original path. (That is, it will have the same parent.)
function Path:setExtension(extension: string): boolean
Updates self:extension()
to extension
or to nil
if extension
is empty.
Returns false
and does nothing if self:fileName()
is nil
, returns true
and updates the extension otherwise.
If self:extension()
is nil
, the extension is added; otherwise it is replaced.
If extension is the empty string, self:extension()
will be None afterwards, not ""
.
Caveats
The new extension may contain dots and will be used in its entirety, but only the part after the final dot will be reflected in self:extension()
.
If the file stem contains internal dots and extension is empty, part of the old file stem will be considered the new self:extension()
.
function Path:clear(): ()
Clears the path, making it an empty path.
This project is available under the MIT license. See LICENSE.txt for details.
If you would like to use this library on a Lua environment, where it is currently incompatible, open an issue (or comment on an existing one) to request the appropriate modifications.
The library uses darklua to process its code.