W3cubDocs

/Nim

Module ospaths

Include file that implements 'osErrorMsg' and friends. Do not import it!Include file that implements 'getEnv' and friends. Do not import it!

Imports

strutils, winlean

Types

ReadEnvEffect = object of ReadIOEffect
effect that denotes a read from an environment variable
WriteEnvEffect = object of WriteIOEffect
effect that denotes a write to an environment variable
ReadDirEffect = object of ReadIOEffect
effect that denotes a read operation from the directory structure
WriteDirEffect = object of WriteIOEffect
effect that denotes a write operation to the directory structure
OSErrorCode = distinct int32
Specifies an OS Error Code.

Consts

doslikeFileSystem = true
CurDir = '.'

The constant string used by the operating system to refer to the current directory.

For example: '.' for POSIX or ':' for the classic Macintosh.

ParDir = ".."

The constant string used by the operating system to refer to the parent directory.

For example: ".." for POSIX or "::" for the classic Macintosh.

DirSep = '/'
The character used by the operating system to separate pathname components, for example, '/' for POSIX or ':' for the classic Macintosh.
AltSep = '/'
An alternative character used by the operating system to separate pathname components, or the same as DirSep if only one separator character exists. This is set to '/' on Windows systems where DirSep is a backslash.
PathSep = ':'
The character conventionally used by the operating system to separate search patch components (as in PATH), such as ':' for POSIX or ';' for Windows.
FileSystemCaseSensitive = true
true if the file system is case sensitive, false otherwise. Used by cmpPaths to compare filenames properly.
ExeExt = ""
The file extension of native executables. For example: "" for POSIX, "exe" on Windows.
ScriptExt = ""
The file extension of a script file. For example: "" for POSIX, "bat" on Windows.
DynlibFormat = "lib$1.so"
The format string to turn a filename into a DLL file (also called shared object on some operating systems).
ExtSep = '.'
The character which separates the base filename from the extension; for example, the '.' in os.nim.

Procs

proc joinPath(head, tail: string): string {.noSideEffect, gcsafe, extern: "nos$1",
                                       raises: [], tags: [].}

Joins two directory names to one.

For example on Unix:

joinPath("usr", "lib")

results in:

"usr/lib"

If head is the empty string, tail is returned. If tail is the empty string, head is returned with a trailing path separator. If tail starts with a path separator it will be removed when concatenated to head. Other path separators not located on boundaries won't be modified. More examples on Unix:

assert joinPath("usr", "") == "usr/"
assert joinPath("", "lib") == "lib"
assert joinPath("", "/lib") == "/lib"
assert joinPath("usr/", "/lib") == "usr/lib"
proc joinPath(parts: varargs[string]): string {.noSideEffect, gcsafe,
    extern: "nos$1OpenArray", raises: [], tags: [].}
The same as joinPath(head, tail), but works with any number of directory parts. You need to pass at least one element or the proc will assert in debug builds and crash on release builds.
proc `/`(head, tail: string): string {.noSideEffect, raises: [], tags: [].}

The same as joinPath(head, tail)

Here are some examples for Unix:

assert "usr" / "" == "usr/"
assert "" / "lib" == "lib"
assert "" / "/lib" == "/lib"
assert "usr/" / "/lib" == "usr/lib"
proc splitPath(path: string): tuple[head, tail: string] {.noSideEffect, gcsafe,
    extern: "nos$1", raises: [], tags: [].}

Splits a directory into (head, tail), so that head / tail == path (except for edge cases like "/usr").

Examples:

splitPath("usr/local/bin") -> ("usr/local", "bin")
splitPath("usr/local/bin/") -> ("usr/local/bin", "")
splitPath("bin") -> ("", "bin")
splitPath("/bin") -> ("", "bin")
splitPath("") -> ("", "")
proc parentDir(path: string): string {.noSideEffect, gcsafe, extern: "nos$1",
                                   raises: [], tags: [].}

Returns the parent directory of path.

This is often the same as the head result of splitPath. If there is no parent, "" is returned.

Example: parentDir("/usr/local/bin") == "/usr/local".
Example: parentDir("/usr/local/bin/") == "/usr/local".

proc tailDir(path: string): string {.noSideEffect, gcsafe, extern: "nos$1", raises: [],
                                 tags: [].}
Returns the tail part of path..

Example: tailDir("/usr/local/bin") == "local/bin".
Example: tailDir("usr/local/bin/") == "local/bin".
Example: tailDir("bin") == "".

proc isRootDir(path: string): bool {.noSideEffect, gcsafe, extern: "nos$1", raises: [],
                                 tags: [].}
Checks whether a given path is a root directory
proc `/../`(head, tail: string): string {.noSideEffect, raises: [], tags: [].}
The same as parentDir(head) / tail unless there is no parent directory. Then head / tail is performed instead.
proc searchExtPos(path: string): int {.raises: [], tags: [].}
Returns index of the '.' char in path if it signifies the beginning of extension. Returns -1 otherwise.
proc splitFile(path: string): tuple[dir, name, ext: string] {.noSideEffect, gcsafe,
    extern: "nos$1", raises: [], tags: [].}

Splits a filename into (dir, filename, extension). dir does not end in DirSep. extension includes the leading dot.

Example:

var (dir, name, ext) = splitFile("usr/local/nimc.html")
assert dir == "usr/local"
assert name == "nimc"
assert ext == ".html"

If path has no extension, ext is the empty string. If path has no directory component, dir is the empty string. If path has no filename component, name and ext are empty strings.

proc extractFilename(path: string): string {.noSideEffect, gcsafe, extern: "nos$1",
    raises: [], tags: [].}
Extracts the filename of a given path. This is the same as name & ext from splitFile(path).
proc changeFileExt(filename, ext: string): string {.noSideEffect, gcsafe,
    extern: "nos$1", raises: [], tags: [].}

Changes the file extension to ext.

If the filename has no extension, ext will be added. If ext == "" then any extension is removed. Ext should be given without the leading '.', because some filesystems may use a different character. (Although I know of none such beast.)

proc addFileExt(filename, ext: string): string {.noSideEffect, gcsafe, extern: "nos$1",
    raises: [], tags: [].}

Adds the file extension ext to filename, unless filename already has an extension.

Ext should be given without the leading '.', because some filesystems may use a different character. (Although I know of none such beast.)

proc cmpPaths(pathA, pathB: string): int {.noSideEffect, gcsafe, extern: "nos$1",
                                      raises: [], tags: [].}

Compares two paths.

On a case-sensitive filesystem this is done case-sensitively otherwise case-insensitively. Returns:

0 iff pathA == pathB
< 0 iff pathA < pathB
> 0 iff pathA > pathB

proc isAbsolute(path: string): bool {.gcsafe, noSideEffect, extern: "nos$1", raises: [],
                                  tags: [].}

Checks whether a given path is absolute.

On Windows, network paths are considered absolute too.

proc unixToNativePath(path: string; drive = ""): string {.noSideEffect, gcsafe,
    extern: "nos$1", raises: [], tags: [].}

Converts an UNIX-like path to a native one.

On an UNIX system this does nothing. Else it converts '/', '.', '..' to the appropriate things.

On systems with a concept of "drives", drive is used to determine which drive label to use during absolute path conversion. drive defaults to the drive of the current working directory, and is ignored on systems that do not have a concept of "drives".

proc osErrorMsg(): string {.gcsafe, extern: "nos$1", deprecated, raises: [], tags: [].}

Retrieves the operating system's error flag, errno. On Windows GetLastError is checked before errno. Returns "" if no error occurred.

Deprecated since version 0.9.4: use the other osErrorMsg proc.

proc raiseOSError(msg: string = "") {.noinline, gcsafe, extern: "nos$1", deprecated,
                                 raises: [OSError], tags: [].}

raises an OSError exception with the given message msg. If msg == "", the operating system's error flag (errno) is converted to a readable error message. On Windows GetLastError is checked before errno. If no error flag is set, the message unknown OS error is used.

Deprecated since version 0.9.4: use the other raiseOSError proc.

proc `==`(err1, err2: OSErrorCode): bool {.borrow.}
proc `$`(err: OSErrorCode): string {.borrow.}
proc osErrorMsg(errorCode: OSErrorCode): string {.raises: [], tags: [].}

Converts an OS error code into a human readable string.

The error code can be retrieved using the osLastError proc.

If conversion fails, or errorCode is 0 then "" will be returned.

On Windows, the -d:useWinAnsi compilation flag can be used to make this procedure use the non-unicode Win API calls to retrieve the message.

proc raiseOSError(errorCode: OSErrorCode; additionalInfo = "") {.noinline,
    raises: [OSError], tags: [].}

Raises an OSError exception. The errorCode will determine the message, osErrorMsg will be used to get this message.

The error code can be retrieved using the osLastError proc.

If the error code is 0 or an error message could not be retrieved, the message unknown OS error will be used.

proc osLastError(): OSErrorCode {.raises: [], tags: [].}

Retrieves the last operating system error code.

This procedure is useful in the event when an OS call fails. In that case this procedure will return the error code describing the reason why the OS call failed. The OSErrorMsg procedure can then be used to convert this code into a string.

Warning: The behaviour of this procedure varies between Windows and POSIX systems. On Windows some OS calls can reset the error code to 0 causing this procedure to return 0. It is therefore advised to call this procedure immediately after an OS call fails. On POSIX systems this is not a problem.

proc getEnv(key: string): TaintedString {.tags: [ReadEnvEffect], raises: [].}

Returns the value of the environment variable named key.

If the variable does not exist, "" is returned. To distinguish whether a variable exists or it's value is just "", call existsEnv(key).

proc existsEnv(key: string): bool {.tags: [ReadEnvEffect], raises: [].}
Checks whether the environment variable named key exists. Returns true if it exists, false otherwise.
proc putEnv(key, val: string) {.tags: [WriteEnvEffect], raises: [OSError].}
Sets the value of the environment variable named key to val. If an error occurs, EInvalidEnvVar is raised.
proc getHomeDir(): string {.gcsafe, extern: "nos$1",
                         tags: [ReadEnvEffect, ReadIOEffect], raises: [].}

Returns the home directory of the current user.

This proc is wrapped by the expandTilde proc for the convenience of processing paths coming from user configuration files.

proc getConfigDir(): string {.gcsafe, extern: "nos$1",
                           tags: [ReadEnvEffect, ReadIOEffect], raises: [].}

Returns the config directory of the current user for applications.

On non-Windows OSs, this proc conforms to the XDG Base Directory spec. Thus, this proc returns the value of the XDG_CONFIG_DIR environment variable if it is set, and returns the default configuration directory, "~/.config/", otherwise.

An OS-dependent trailing slash is always present at the end of the returned string; \ on Windows and / on all other OSs.

proc getTempDir(): string {.gcsafe, extern: "nos$1",
                         tags: [ReadEnvEffect, ReadIOEffect], raises: [].}

Returns the temporary directory of the current user for applications to save temporary files in.

Please do not use this: On Android, it currently returns getHomeDir(), and on other Unix based systems it can cause security problems too. That said, you can override this implementation by adding -d:tempDir=mytempname to your compiler invokation.

proc expandTilde(path: string): string {.tags: [ReadEnvEffect, ReadIOEffect],
                                     raises: [].}

Expands a path starting with ~/ to a full path.

If path starts with the tilde character and is followed by / or \ this proc will return the reminder of the path appended to the result of the getHomeDir() proc, otherwise the input path will be returned without modification.

The behaviour of this proc is the same on the Windows platform despite not having this convention. Example:

let configFile = expandTilde("~" / "appname.cfg")
echo configFile
# --> C:\Users\amber\appname.cfg

Iterators

iterator parentDirs(path: string; fromRoot = false; inclusive = true): string {.
    raises: [], tags: [].}

Walks over all parent directories of a given path

If fromRoot is set, the traversal will start from the file system root diretory. If inclusive is set, the original argument will be included in the traversal.

Relative paths won't be expanded by this proc. Instead, it will traverse only the directories appearing in the relative path.

iterator envPairs(): tuple[key, value: TaintedString] {.tags: [ReadEnvEffect],
    raises: [].}
Iterate over all environments variables. In the first component of the tuple is the name of the current variable stored, in the second its value.

© 2006–2017 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/ospaths.html