# tecs.io.Path Immutable, platform-native filesystem paths. `Path` is an immutable platform-native UTF-8 filesystem path. Methods interpret roots, separators, drive prefixes, and UNC paths according to the operating system running Tecs. They return new paths rather than mutating their receiver: ```teal local root = tecs.io.Path.new("assets") local shader = root:join("shaders", "sprite.glsl") print(shader:fileName()) print(shader:withExtension("spv")) ``` `normalize` is lexical. It removes redundant separators and `.` components and resolves `..` without reading the filesystem. That is useful for output paths which do not exist yet, but it can change which object a path denotes when a traversed component is a symbolic link. `canonicalize` reads the filesystem, requires the path to exist, and follows symbolic links: use `resolve` for a normalized absolute spelling of a configured output and `canonicalize` only when an existing object's filesystem identity matters. Paths contain valid UTF-8 and no NUL byte, matching the string contract used by Tecs file and process APIs. Unix filenames containing invalid UTF-8 cannot be represented. A path object owns only its immutable Lua string and needs no `close`. ## Module contents ### Constructors | Constructor | Description | | --- | --- | | [`new`](/modules/io/Path/#tecs.io.Path.new) | Creates an immutable path from platform-native components. | ### Functions | Function | Kind | Description | | --- | --- | --- | | [`currentDirectory`](/modules/io/Path/#tecs.io.Path.currentDirectory) | Static | Returns the process's current working directory. | | [`separator`](/modules/io/Path/#tecs.io.Path.separator) | Static | Returns the platform's preferred path separator. | | [`absolute`](/modules/io/Path/#tecs.io.Path.absolute) | Instance | Returns an absolute spelling without requiring the path to exist. | | [`canonicalize`](/modules/io/Path/#tecs.io.Path.canonicalize) | Instance | Resolves filesystem identity and follows symbolic links. | | [`extension`](/modules/io/Path/#tecs.io.Path.extension) | Instance | Returns the final component's last extension without its dot. | | [`fileName`](/modules/io/Path/#tecs.io.Path.fileName) | Instance | Returns the final path component. | | [`isAbsolute`](/modules/io/Path/#tecs.io.Path.isAbsolute) | Instance | Returns whether this path carries a platform root. | | [`isRelative`](/modules/io/Path/#tecs.io.Path.isRelative) | Instance | Returns whether this path needs a base directory. | | [`join`](/modules/io/Path/#tecs.io.Path.join) | Instance | Appends path components and returns the result. | | [`normalize`](/modules/io/Path/#tecs.io.Path.normalize) | Instance | Returns a lexically normalized path without filesystem access. | | [`parent`](/modules/io/Path/#tecs.io.Path.parent) | Instance | Returns this path without its final component. | | [`relativeTo`](/modules/io/Path/#tecs.io.Path.relativeTo) | Instance | Expresses this path relative to a base path. | | [`resolve`](/modules/io/Path/#tecs.io.Path.resolve) | Instance | Returns a normalized absolute spelling without filesystem access. | | [`stem`](/modules/io/Path/#tecs.io.Path.stem) | Instance | Returns the final component without its last extension. | | [`toString`](/modules/io/Path/#tecs.io.Path.toString) | Instance | Returns this path's platform-native UTF-8 spelling. | | [`withExtension`](/modules/io/Path/#tecs.io.Path.withExtension) | Instance | Replaces or removes the final component's extension. | | [`withFileName`](/modules/io/Path/#tecs.io.Path.withFileName) | Instance | Replaces the final component. | ## Constructors ### tecs.io.Path.new Static Creates an immutable path from platform-native components. Construction joins the components lexically and does not require the path to exist. A later absolute component replaces the accumulated prefix according to the host platform's rules. ```teal function tecs.io.Path.new(first: string, ...: string): Path ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `first` | `string` | The caller supplies the first valid UTF-8 path component or complete path, without a NUL byte. | | `...` | `string` | The caller supplies additional path components in order. | #### Returns | Type | Description | | --- | --- | | [`Path`](/modules/io/Path/) | Returns a new immutable path. | #### Examples ```teal local shader = tecs.io.Path.new( "assets", "shaders", "sprite.glsl" ) assert(shader:fileName() == "sprite.glsl") ``` ## Functions ### tecs.io.Path.currentDirectory Static Returns the process's current working directory. ```teal function tecs.io.Path.currentDirectory(): Path, string ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | [`Path`](/modules/io/Path/) | Returns a new immutable normalized absolute path. | | `string` | Returns the platform reason when the first return is nil. | ### tecs.io.Path.separator Static Returns the platform's preferred path separator. Paths accept the forms supported by the host platform; this value is only for text that must display or emit a separator itself. ```teal function tecs.io.Path.separator(): string ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `string` | Returns `"\\"` on Windows and `"/"` elsewhere. | ### tecs.io.Path:absolute Instance Returns an absolute spelling without requiring the path to exist. A relative receiver is based on the process's current directory. Unlike `resolve`, this preserves platform-significant parent components where the native absolute operation preserves them. ```teal function tecs.io.Path.absolute(self): Path, string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The path to make absolute. | #### Returns | Type | Description | | --- | --- | | [`Path`](/modules/io/Path/) | Returns a new immutable absolute path. | | `string` | Returns the platform reason when the current directory cannot be determined. | ### tecs.io.Path:canonicalize Instance Resolves filesystem identity and follows symbolic links. The receiver must exist. The result is absolute and normalized by the operating system. ```teal function tecs.io.Path.canonicalize(self): Path, string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The existing path to canonicalize. | #### Returns | Type | Description | | --- | --- | | [`Path`](/modules/io/Path/) | Returns a new immutable canonical path. | | `string` | Returns the filesystem reason when the first return is nil. | #### Examples ```teal local executable, reason = tecs.io.Path.new("."):canonicalize() if executable == nil then error(reason) end print(executable) ``` ### tecs.io.Path:extension Instance Returns the final component's last extension without its dot. ```teal function tecs.io.Path.extension(self): string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The path to inspect without filesystem access. | #### Returns | Type | Description | | --- | --- | | `string` | Returns the extension, or nil when none exists. | ### tecs.io.Path:fileName Instance Returns the final path component. ```teal function tecs.io.Path.fileName(self): string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The path to inspect without filesystem access. | #### Returns | Type | Description | | --- | --- | | `string` | Returns the final component, or nil for a root or terminal parent component. | ### tecs.io.Path:isAbsolute Instance Returns whether this path carries a platform root. ```teal function tecs.io.Path.isAbsolute(self): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The path to inspect without filesystem access. | #### Returns | Type | Description | | --- | --- | | `boolean` | Returns true when the path is absolute on this platform. | ### tecs.io.Path:isRelative Instance Returns whether this path needs a base directory. ```teal function tecs.io.Path.isRelative(self): boolean ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The path to inspect without filesystem access. | #### Returns | Type | Description | | --- | --- | | `boolean` | Returns true when the path is relative on this platform. | ### tecs.io.Path:join Instance Appends path components and returns the result. A later absolute argument replaces everything accumulated before it, following the host platform's path rules. The result is not normalized and no component needs to exist. ```teal function tecs.io.Path.join(self, ...: string | Path): Path ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The base path left unchanged. | | `...` | string | [`Path`](/modules/io/Path/) | The caller supplies strings or paths to append in order. | #### Returns | Type | Description | | --- | --- | | [`Path`](/modules/io/Path/) | Returns a new immutable path. | #### Examples ```teal local assets = tecs.io.Path.new("assets") local shader = assets:join("shaders", "sprite.glsl") assert(tostring(assets) == "assets") assert( shader:toString() == tecs.io.Path.new( "assets", "shaders", "sprite.glsl" ):toString() ) ``` ### tecs.io.Path:normalize Instance Returns a lexically normalized path without filesystem access. Redundant separators and `.` are removed and `..` is resolved. A symbolic link can make that lexical result denote a different object. ```teal function tecs.io.Path.normalize(self): Path ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The path to normalize. | #### Returns | Type | Description | | --- | --- | | [`Path`](/modules/io/Path/) | Returns a new immutable path. | #### Examples ```teal local configured = tecs.io.Path.new( "assets", ".", "shaders", "..", "sprite.glsl" ) local normalized = configured:normalize() assert(normalized == tecs.io.Path.new("assets", "sprite.glsl")) ``` ### tecs.io.Path:parent Instance Returns this path without its final component. ```teal function tecs.io.Path.parent(self): Path ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The path to inspect without filesystem access. | #### Returns | Type | Description | | --- | --- | | [`Path`](/modules/io/Path/) | Returns a new immutable parent, or nil when the path has none. | ### tecs.io.Path:relativeTo Instance Expresses this path relative to a base path. Neither path is accessed. On Windows, paths on different drives or UNC roots have no relative spelling. ```teal function tecs.io.Path.relativeTo( self, base: string | Path ): Path, string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The destination path. | | `base` | string | [`Path`](/modules/io/Path/) | The caller supplies the directory from which to describe the destination. | #### Returns | Type | Description | | --- | --- | | [`Path`](/modules/io/Path/) | Returns a new immutable relative path. | | `string` | Returns a reason when the two paths cannot share a coordinate system. | #### Examples ```teal local root = tecs.io.Path.new("assets") local sprite = root:join("sprites", "hero.png") local relative, reason = sprite:relativeTo(root) if relative == nil then error(reason) end assert(relative == tecs.io.Path.new("sprites", "hero.png")) ``` ### tecs.io.Path:resolve Instance Returns a normalized absolute spelling without filesystem access. Arguments are joined first. The process's current directory supplies the base when the joined path remains relative. ```teal function tecs.io.Path.resolve( self, ...: string | Path ): Path, string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The first path in the resolution. | | `...` | string | [`Path`](/modules/io/Path/) | The caller supplies strings or paths to append in order. | #### Returns | Type | Description | | --- | --- | | [`Path`](/modules/io/Path/) | Returns a new immutable normalized absolute path. | | `string` | Returns the platform reason when the current directory cannot be determined. | #### Examples ```teal local output, reason = tecs.io.Path.new("build", "game.pack"):resolve() if output == nil then error(reason) end assert(output:isAbsolute()) ``` ### tecs.io.Path:stem Instance Returns the final component without its last extension. ```teal function tecs.io.Path.stem(self): string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The path to inspect without filesystem access. | #### Returns | Type | Description | | --- | --- | | `string` | Returns the stem, or nil when the path has no file name. | ### tecs.io.Path:toString Instance Returns this path's platform-native UTF-8 spelling. `tostring(path)` returns the same string. ```teal function tecs.io.Path.toString(self): string ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The immutable path to render. | #### Returns | Type | Description | | --- | --- | | `string` | Returns the complete path without accessing the filesystem. | ### tecs.io.Path:withExtension Instance Replaces or removes the final component's extension. ```teal function tecs.io.Path.withExtension(self, extension: string): Path ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The path whose final component changes. | | `extension` | `string` | The caller supplies one component without a leading dot, or an empty string to remove the extension. | #### Returns | Type | Description | | --- | --- | | [`Path`](/modules/io/Path/) | Returns a new immutable path. | #### Examples ```teal local source = tecs.io.Path.new("shaders", "sprite.glsl") local compiled = source:withExtension("spv") assert(source:extension() == "glsl") assert(compiled:fileName() == "sprite.spv") ``` ### tecs.io.Path:withFileName Instance Replaces the final component. ```teal function tecs.io.Path.withFileName(self, name: string): Path ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Path` | The path whose parent is retained. | | `name` | `string` | The caller supplies one non-empty platform path component. | #### Returns | Type | Description | | --- | --- | | [`Path`](/modules/io/Path/) | Returns a new immutable path. |