/*---------------------------------------------------------------------------
  Copyright 2012-2021, Microsoft Research, Daan Leijen.

  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the LICENSE file at the root of this distribution.
---------------------------------------------------------------------------*/

/* File system paths.

The path functions are system independent: backward slashes (`'\\'`)
are treated as a forward slash to separate directories. Windows style
root names like ``c:\`` or ``//server`` are also recognized.

A list of paths can be separated with either a colon (``:``) or
semi-colon (``;``).

A `:path` is created using the `path` functions. Use `string` to convert
back to a normalized path string. A path consists of a _root_ name
(``/``, ``c:\``), the directory (``foo/bar``) and finally the _base_ name.
The base name itself consists of the _stem_ and the _extension_. The
extension is always the part that follows the last occurrence of a dot (`'.'`)
in the base name.

A `:path` is always normalized. For a sequence of directories, any
empty directory or ``.`` directory is ignored.
A directory followed by ``..`` is also ignored -- this is the [Plan 9](https://9p.io/sys/doc/lexnames.html)
interpretation of paths where ``..`` is considered lexically.
If parent directories should be resolved through symbolic links,
the `realpath` function should be used (which has the `:io` effect though).
*/
module std/os/pathstd/os/path

import std/text/parsestd/text/parse

extern import
  cs file "path-inline.cs"
  js file "path-inline.js"

// A `:path` represents a file system path.\
abstract value struct pathstd/os/path/path: V
  rootroot: string : stringstd/core/types/string: V = ""literal: string
count= 0
partsparts: list<string>: liststd/core/types/list: V -> V<stringstd/core/types/string: V> = [std/core/types/Nil: forall<a> list<a>
]std/core/types/Nil: forall<a> list<a> // directory parts in reverse order // Return the base name of a path (stem name + extension)\ // `"/foo/bar.txt".path.basename === "bar.txt"` \ // `"/foo".path.basename === "foo"` pub fun basenamestd/os/path/basename: (p : path) -> string( pp: path : pathstd/os/path/path: V )result: -> total string : stringstd/core/types/string: V pp: path.partsstd/os/path/path/parts: (path : path) -> list<string>.headstd/core/list/head: (xs : list<string>) -> maybe<string>.defaultstd/core/maybe/default: (m : maybe<string>, nothing : string) -> string(""literal: string
count= 0
) // Return the directory part of a path (including the rootname) // `"/foo/bar.txt".path.dirname === "/foo"` \ // `"/foo".path.dirname === "/"` pub fun dirnamestd/os/path/dirname: (p : path) -> string( pp: path : pathstd/os/path/path: V )result: -> total string : stringstd/core/types/string: V pp: path.rootstd/os/path/path/root: (path : path) -> string ++std/core/types/(++): (x : string, y : string) -> string pp: path.partsstd/os/path/path/parts: (path : path) -> list<string>.tailstd/core/list/tail: (xs : list<string>) -> list<string>.reversestd/core/list/reverse: (xs : list<string>) -> list<string>.joinstd/core/list/joinsep/join: (xs : list<string>, sep : string) -> string("/"literal: string
count= 1
) // Return the extension of path (without the preceding dot (`'.'`))\ // `"/foo/bar.svg.txt".path.extname === "txt"` pub fun extnamestd/os/path/extname: (p : path) -> string( pp: path : pathstd/os/path/path: V )result: -> total string : stringstd/core/types/string: V pp: path.basenamestd/os/path/basename: (p : path) -> string.split-basestd/os/path/split-base: (basename : string) -> (string, string).sndstd/core/types/tuple2/snd: (tuple2 : (string, string)) -> string // Return the stem name of path.\ // `"/foo/bar.svg.txt".path.extname === "foo.svg"` pub fun stemnamestd/os/path/stemname: (p : path) -> string( pp: path : pathstd/os/path/path: V )result: -> total string : stringstd/core/types/string: V pp: path.basenamestd/os/path/basename: (p : path) -> string.split-basestd/os/path/split-base: (basename : string) -> (string, string).fststd/core/types/tuple2/fst: (tuple2 : (string, string)) -> string // Return the root name of path. // `"c:\\foo".path.rootname === "c:/"`\ // `"/foo".path.rootname === "/"` pub fun rootnamestd/os/path/rootname: (p : path) -> string( pp: path : pathstd/os/path/path: V )result: -> total string : stringstd/core/types/string: V pp: path.rootstd/os/path/path/root: (path : path) -> string fun split-basestd/os/path/split-base: (basename : string) -> (string, string)( basenamebasename: string : stringstd/core/types/string: V )result: -> total (string, string) : (std/core/types/tuple2: (V, V) -> Vstringstd/core/types/string: V,stringstd/core/types/string: V) match(basenamebasename: string.find-laststd/core/sslice/find-last: (s : string, sub : string) -> maybe<sslice>("."literal: string
count= 1
)) Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(sliceslice: sslice) -> (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)sliceslice: sslice.beforestd/core/sslice/before: (slice : sslice) -> sslice.stringstd/core/sslice/string: (slice : sslice) -> string,sliceslice: sslice.afterstd/core/sslice/after: (slice : sslice) -> sslice.stringstd/core/sslice/string: (slice : sslice) -> string)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) Nothingstd/core/types/Nothing: forall<a> maybe<a> -> (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)basenamebasename: string,""literal: string
count= 0
)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) fun split-partsstd/os/path/split-parts: (parts : list<string>) -> (string, list<string>)( partsparts: list<string> : liststd/core/types/list: V -> V<stringstd/core/types/string: V> )result: -> total (string, list<string>) : (std/core/types/tuple2: (V, V) -> Vstringstd/core/types/string: V,liststd/core/types/list: V -> V<stringstd/core/types/string: V>) (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)partsparts: list<string>.headstd/core/list/head: (xs : list<string>) -> maybe<string>.defaultstd/core/maybe/default: (m : maybe<string>, nothing : string) -> string(""literal: string
count= 0
), partsparts: list<string>.tailstd/core/list/tail: (xs : list<string>) -> list<string>
)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) // Convert a `:path` to a normalized `:string` path.\ // If this results in an empty string, the current directory path `"."` is returned. // `"c:/foo/test.txt".path.string -> "c:/foo/test.txt"`\ // `"c:\\foo\\test.txt".path.string -> "c:/foo/test.txt"`\ // `"/foo//./bar/../test.txt".path.string -> "/foo/test.txt"` pub fun stringstd/os/path/string: (p : path) -> string( pp: path : pathstd/os/path/path: V )result: -> total string : stringstd/core/types/string: V val ss: string = pp: path.rootstd/os/path/path/root: (path : path) -> string ++std/core/types/(++): (x : string, y : string) -> string pp: path.partsstd/os/path/path/parts: (path : path) -> list<string>.reversestd/core/list/reverse: (xs : list<string>) -> list<string>.joinstd/core/list/joinsep/join: (xs : list<string>, sep : string) -> string("/"literal: string
count= 1
) if ss: string.is-emptystd/core/string/is-empty: (s : string) -> bool then "."literal: string
count= 1
else
ss: string // Show a path as a string. pub fun showstd/os/path/show: (p : path) -> string( pp: path : pathstd/os/path/path: V )result: -> total string : stringstd/core/types/string: V pp: path.stringstd/os/path/string: (p : path) -> string.showstd/core/show/string/show: (s : string) -> string // Is a path empty? pub fun is-emptystd/os/path/is-empty: (p : path) -> bool( pp: path : pathstd/os/path/path: V )result: -> total bool : boolstd/core/types/bool: V pp: path.rootstd/os/path/path/root: (path : path) -> string.is-emptystd/core/string/is-empty: (s : string) -> bool &&std/core/types/(&&): (x : bool, y : bool) -> bool pp: path.partsstd/os/path/path/parts: (path : path) -> list<string>.is-nilstd/core/types/is-nil: (list : list<string>) -> bool // Is a path relative? pub fun is-relativestd/os/path/is-relative: (p : path) -> bool( pp: path : pathstd/os/path/path: V )result: -> total bool : boolstd/core/types/bool: V pp: path.rootstd/os/path/path/root: (path : path) -> string.is-emptystd/core/string/is-empty: (s : string) -> bool // Is a path absolute? pub fun is-absolutestd/os/path/is-absolute: (p : path) -> bool( pp: path : pathstd/os/path/path: V )result: -> total bool : boolstd/core/types/bool: V !std/core/types/bool/(!): (b : bool) -> boolpp: path.is-relativestd/os/path/is-relative: (p : path) -> bool // Create a normalized `:path` from a path string. pub fun pathstd/os/path/path: (s : string) -> path( ss: string : stringstd/core/types/string: V )result: -> total path : pathstd/os/path/path: V if ss: string.is-emptystd/core/string/is-empty: (s : string) -> bool returnreturn: path Path(""literal: string
count= 0
,[std/core/types/Nil: forall<a> list<a>]std/core/types/Nil: forall<a> list<a>)std/core/types/Unit: () val tt: string = ss: string.replace-allstd/core/string/replace-all: (s : string, pattern : string, repl : string) -> string("\\"literal: string
count= 1
,"/"literal: string
count= 1
) match tt: string.starts-withstd/text/parse/starts-with: (s : string, p : () -> parse bool) -> maybe<(bool, sslice)>(prootstd/os/path/proot: () -> parse bool) Nothingstd/core/types/Nothing: forall<a> maybe<a> -> path-partsstd/os/path/path-parts: (root : string, s : string, dirs : ? (list<string>)) -> path(""literal: string
count= 0
,tt: string) Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>((std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)eofeof: bool,restrest: sslice)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)) -> path-partsstd/os/path/path-parts: (root : string, s : string, dirs : ? (list<string>)) -> path(restrest: sslice.beforestd/core/sslice/before: (slice : sslice) -> sslice.stringstd/core/sslice/string: (slice : sslice) -> string ++std/core/types/(++): (x : string, y : string) -> string (if eofeof: bool then "/"literal: string
count= 1
else ""literal: string
count= 0
),restrest: sslice.stringstd/core/sslice/string: (slice : sslice) -> string
) fun path-partsstd/os/path/path-parts: (root : string, s : string, dirs : ? (list<string>)) -> path( rootroot: string : stringstd/core/types/string: V, ss: string : stringstd/core/types/string: V, dirsdirs: ? (list<string>) : liststd/core/types/list: V -> V<stringstd/core/types/string: V> = [std/core/types/Nil: forall<a> list<a>]std/core/types/Nil: forall<a> list<a> )result: -> total path : pathstd/os/path/path: V val partsparts: list<string> = ss: string.splitstd/core/string/split: (s : string, sep : string) -> list<string>("/"literal: string
count= 1
).push-partsstd/os/path/push-parts: (parts : list<string>, dirs : list<string>) -> list<string>(dirsdirs: list<string>) Path(rootroot: string,partsparts: list<string>
) fun push-partsstd/os/path/push-parts: (parts : list<string>, dirs : list<string>) -> list<string>( partsparts: list<string> : liststd/core/types/list: V -> V<stringstd/core/types/string: V>, dirsdirs: list<string> : liststd/core/types/list: V -> V<stringstd/core/types/string: V> )result: -> total list<string> : liststd/core/types/list: V -> V<stringstd/core/types/string: V> match partsparts: list<string> Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(partpart: string,restrest: list<string>) -> push-partsstd/os/path/push-parts: (parts : list<string>, dirs : list<string>) -> list<string>(restrest: list<string>, push-partstd/os/path/push-part: (dir : string, dirs : list<string>) -> list<string>(partpart: string,dirsdirs: list<string>)) Nilstd/core/types/Nil: forall<a> list<a> -> dirsdirs: list<string> fun push-partstd/os/path/push-part: (dir : string, dirs : list<string>) -> list<string>( dirdir: string : stringstd/core/types/string: V, dirsdirs: list<string> : liststd/core/types/list: V -> V<stringstd/core/types/string: V> )result: -> total list<string> : liststd/core/types/list: V -> V<stringstd/core/types/string: V> if dirdir: string==std/core/string/(==): (string, string) -> bool"."literal: string
count= 1
||std/core/types/(||): (x : bool, y : bool) -> bool dirdir: string==std/core/string/(==): (string, string) -> bool""literal: string
count= 0
then dirsdirs: list<string> elif dirdir: string==std/core/string/(==): (string, string) -> bool".."literal: string
count= 2
&&std/core/types/(&&): (x : bool, y : bool) -> bool dirsdirs: list<string>.is-consstd/core/types/is-cons: (list : list<string>) -> bool then dirsdirs: list<string>.tailstd/core/list/tail: (xs : list<string>) -> list<string> else Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(dirdir: string,dirsdirs: list<string>
) fun prootstd/os/path/proot: () -> parse bool()result: -> parse bool : parsestd/text/parse/parse: (E, V) -> V boolstd/core/types/bool: V ({ alphastd/text/parse/alpha: () -> parse char(); charstd/text/parse/char: (c : char) -> parse char(':'literal: char
unicode= u003A
); (std/core/types/Unit: ())std/core/types/Unit: () }) ||std/text/parse/(||): (p1 : parser<total,()>, p2 : parser<total,()>) -> parse () ({charstd/text/parse/char: (c : char) -> parse char('/'literal: char
unicode= u002F
); many1std/text/parse/many1: (p : parser<total,char>) -> parse list<char>({none-ofstd/text/parse/none-of: (chars : string) -> parse char("/"literal: string
count= 1
)}); (std/core/types/Unit: ())std/core/types/Unit: () }) ({ charstd/text/parse/char: (c : char) -> parse char('/'literal: char
unicode= u002F
); Falsestd/core/types/False: bool }) ||std/text/parse/(||): (p1 : parser<total,bool>, p2 : parser<total,bool>) -> parse bool ({ eofstd/text/parse/eof: () -> parse ()(); Truestd/core/types/True: bool }
) // Parse a list of paths seperated by colon (`':'`) or semi-colon (`';'`) // // Colon separated paths can be ambiguous with Windows style root names (`c:\\`) // In particular, a single letter path followed by an absolute path, e.g. ``c:/foo:/bar`` is // parsed as ``c:/foo`` and ``/bar``. pub fun pathsstd/os/path/paths: (s : string) -> list<path>( ss: string : stringstd/core/types/string: V )result: -> total list<path> : liststd/core/types/list: V -> V<pathstd/os/path/path: V> ss: string.replace-allstd/core/string/replace-all: (s : string, pattern : string, repl : string) -> string(";"literal: string
count= 1
,":"literal: string
count= 1
).splitstd/core/string/split: (s : string, sep : string) -> list<string>(":"literal: string
count= 1
).paths-collectstd/os/path/paths-collect: (ps : list<string>) -> list<path>
fun paths-collectstd/os/path/paths-collect: (ps : list<string>) -> list<path>( psps: list<string> : liststd/core/types/list: V -> V<stringstd/core/types/string: V> )result: -> total list<path> : liststd/core/types/list: V -> V<pathstd/os/path/path: V> match psps: list<string> Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(rootroot: string,Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(partpart: string,restrest: list<string>)) // match on windows 'c:\' parts | rootroot: string.countstd/core/string/count: (s : string) -> int==std/core/int/(==): (x : int, y : int) -> bool1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
&&std/core/types/(&&): (x : bool, y : bool) -> bool rootroot: string.head-charstd/core/sslice/head-char: (s : string) -> maybe<char>.defaultstd/core/maybe/default: (m : maybe<char>, nothing : char) -> char(' 'literal: char
unicode= u0020
).is-alphastd/core/char/is-alpha: (c : char) -> bool &&std/core/types/(&&): (x : bool, y : bool) -> bool !std/core/types/bool/(!): (b : bool) -> boolpartpart: string.is-emptystd/core/string/is-empty: (s : string) -> bool &&std/core/types/(&&): (x : bool, y : bool) -> bool "/\\"literal: string
count= 2
.containsstd/core/string/contains: (s : string, sub : string) -> bool(partpart: string.headstd/core/sslice/head: (s : string) -> string) -> Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>( pathstd/os/path/path: (s : string) -> path(rootroot: string ++std/core/types/(++): (x : string, y : string) -> string ":"literal: string
count= 1
++std/core/types/(++): (x : string, y : string) -> string partpart: string), paths-collectstd/os/path/paths-collect: (ps : list<string>) -> list<path>(restrest: list<string>)) Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(partpart: string,restrest: list<string>) -> Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>( pathstd/os/path/path: (s : string) -> path(partpart: string), paths-collectstd/os/path/paths-collect: (ps : list<string>) -> list<path>(restrest: list<string>)) Nilstd/core/types/Nil: forall<a> list<a> -> Nilstd/core/types/Nil: forall<a> list<a>
// Add two paths together using left-associative operator `(/)`. \ // Keeps the root of `p1` and discards the root name of `p2`.\ // `"/a/" / "b/foo.txt" === "/a/b/foo.txt"`\ // `"/a/foo.txt" / "/b/bar.txt" === "/a/foo.txt/b/bar.txt"`\ // `"c:/foo" / "d:/bar" === "c:/foo/bar"` pub fun (/)std/os/path/(/): (p1 : path, p2 : path) -> path(p1p1: path : pathstd/os/path/path: V, p2p2: path: pathstd/os/path/path: V)result: -> total path : pathstd/os/path/path: V Path(p1p1: path.rootstd/os/path/path/root: (path : path) -> string,push-partsstd/os/path/push-parts: (parts : list<string>, dirs : list<string>) -> list<string>(p2p2: path.partsstd/os/path/path/parts: (path : path) -> list<string>.reversestd/core/list/reverse: (xs : list<string>) -> list<string>, p1p1: path.partsstd/os/path/path/parts: (path : path) -> list<string>)) // Convenience function that adds a string path. pub fun pathstring/(/)std/os/path/pathstring/(/): (p1 : path, p2 : string) -> path(p1p1: path : pathstd/os/path/path: V, p2p2: string: stringstd/core/types/string: V)result: -> total path : pathstd/os/path/path: V p1p1: path /std/os/path/(/): (p1 : path, p2 : path) -> path p2p2: string.pathstd/os/path/path: (s : string) -> path // Convenience function that adds two strings into a path. pub fun string/(/)std/os/path/string/(/): (p1 : string, p2 : string) -> path(p1p1: string : stringstd/core/types/string: V, p2p2: string: stringstd/core/types/string: V)result: -> total path : pathstd/os/path/path: V p1p1: string.pathstd/os/path/path: (s : string) -> path /std/os/path/(/): (p1 : path, p2 : path) -> path p2p2: string.pathstd/os/path/path: (s : string) -> path // Return the first path if it is not empty, otherwise return the second one. pub fun (||)std/os/path/(||): (p1 : path, p2 : path) -> path(p1p1: path : pathstd/os/path/path: V, p2p2: path: pathstd/os/path/path: V)result: -> total path : pathstd/os/path/path: V if p1p1: path.is-emptystd/os/path/is-empty: (p : path) -> bool then p2p2: path else p1p1: path // Combine multiple paths using `(/)`. pub fun combinestd/os/path/combine: (ps : list<path>) -> path( psps: list<path> : liststd/core/types/list: V -> V<pathstd/os/path/path: V> )result: -> total path : pathstd/os/path/path: V match psps: list<path> Nilstd/core/types/Nil: forall<a> list<a> -> Path() Consstd/core/types/Cons: forall<a> (head : a, tail : list<a>) -> list<a>(pp: path,pppp: list<path>) -> pppp: list<path>.foldlstd/core/list/foldl: (xs : list<path>, z : path, f : (path, path) -> path) -> path(pp: path,(/)std/os/path/(/): (p1 : path, p2 : path) -> path) // Remove the directory and root and only keep the base name (file name) portion of the path.\ // `nodir("foo/bar.ext".path) === "bar.ext"` pub fun nodirstd/os/path/nodir: (p : path) -> path( pp: path : pathstd/os/path/path: V )result: -> total path : pathstd/os/path/path: V pp: path(root=""literal: string
count= 0
,parts=pp: path.partsstd/os/path/path/parts: (path : path) -> list<string>.takestd/core/list/take: (xs : list<string>, n : int) -> list<string>(1literal: int
dec = 1
hex8 = 0x01
bit8 = 0b00000001
)
) // Remove the basename and only keep the root and directory name portion of the path.\ // `nobase("foo/bar.ext".path) == "foo")` pub fun nobasestd/os/path/nobase: (p : path) -> path( pp: path : pathstd/os/path/path: V )result: -> total path : pathstd/os/path/path: V pp: path( parts = pp: path.partsstd/os/path/path/parts: (path : path) -> list<string>.tailstd/core/list/tail: (xs : list<string>) -> list<string>) // Remove the extension from a path. pub fun noextstd/os/path/noext: (p : path) -> path( pp: path : pathstd/os/path/path: V )result: -> total path : pathstd/os/path/path: V pp: path.change-extstd/os/path/change-ext: (p : path, extname : string) -> path(""literal: string
count= 0
) // Change the extension of a path. // Only adds a dot if the extname does not already start with a dot. pub fun change-extstd/os/path/change-ext: (p : path, extname : string) -> path( pp: path : pathstd/os/path/path: V, extnameextname: string : stringstd/core/types/string: V )result: -> total path : pathstd/os/path/path: V val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)basenamebasename: string,dirsdirs: list<string>)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = pp: path.partsstd/os/path/path/parts: (path : path) -> list<string>.split-partsstd/os/path/split-parts: (parts : list<string>) -> (string, list<string>) val (std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b)stemnamestemname: string,_)std/core/types/Tuple2: forall<a,b> (fst : a, snd : b) -> (a, b) = basenamebasename: string.split-basestd/os/path/split-base: (basename : string) -> (string, string) val newextnewext: string = if (extnameextname: string.starts-withstd/core/sslice/starts-with: (s : string, pre : string) -> maybe<sslice>("."literal: string
count= 1
).is-juststd/core/types/is-just: (maybe : maybe<sslice>) -> bool) then extnameextname: string else "."literal: string
count= 1
++std/core/types/(++): (x : string, y : string) -> string extnameextname: string path-partsstd/os/path/path-parts: (root : string, s : string, dirs : ? (list<string>)) -> path(pp: path.rootstd/os/path/path/root: (path : path) -> string, stemnamestemname: string ++std/core/types/(++): (x : string, y : string) -> string newextnewext: string, dirsdirs: list<string>
) // If a path has no extension, set it to the provided one. pub fun default-extstd/os/path/default-ext: (p : path, newext : string) -> path( pp: path : pathstd/os/path/path: V, newextnewext: string : stringstd/core/types/string: V )result: -> total path : pathstd/os/path/path: V if pp: path.extnamestd/os/path/extname: (p : path) -> string.is-emptystd/core/string/is-empty: (s : string) -> bool then pp: path.change-extstd/os/path/change-ext: (p : path, extname : string) -> path(newextnewext: string) else pp: path // Change the stem name of a path pub fun change-stemstd/os/path/change-stem: (p : path, stemname : string) -> path( pp: path : pathstd/os/path/path: V, stemnamestemname: string : stringstd/core/types/string: V )result: -> total path : pathstd/os/path/path: V val extext: string = pp: path.extnamestd/os/path/extname: (p : path) -> string pp: path.change-basestd/os/path/change-base: (p : path, basename : string) -> path( stemnamestemname: string ++std/core/types/(++): (x : string, y : string) -> string (if extext: string.is-emptystd/core/string/is-empty: (s : string) -> bool then ""literal: string
count= 0
else "."literal: string
count= 1
++std/core/types/(++): (x : string, y : string) -> string extext: string)
) // Change the base name of a path pub fun change-basestd/os/path/change-base: (p : path, basename : string) -> path( pp: path : pathstd/os/path/path: V, basenamebasename: string : stringstd/core/types/string: V )result: -> total path : pathstd/os/path/path: V val qq: path = pp: path.nobasestd/os/path/nobase: (p : path) -> path path-partsstd/os/path/path-parts: (root : string, s : string, dirs : ? (list<string>)) -> path(qq: path.rootstd/os/path/path/root: (path : path) -> string, basenamebasename: string, qq: path.partsstd/os/path/path/parts: (path : path) -> list<string>) // Return a list of all directory components (excluding the root but including the basename).\ // `"/foo/bar/test.txt".path.dirparts === ["foo","bar","test.txt"]` pub fun dirpartsstd/os/path/dirparts: (p : path) -> list<string>(pp: path : pathstd/os/path/path: V)result: -> total list<string> : liststd/core/types/list: V -> V<stringstd/core/types/string: V> pp: path.partsstd/os/path/path/parts: (path : path) -> list<string>.reversestd/core/list/reverse: (xs : list<string>) -> list<string> // Return the last directory component name (or the empty string).\ // `"c:/foo/bar/tst.txt".path.parentname === "bar" pub fun parentnamestd/os/path/parentname: (p : path) -> string( pp: path : pathstd/os/path/path: V )result: -> total string : stringstd/core/types/string: V pp: path.partsstd/os/path/path/parts: (path : path) -> list<string>.tailstd/core/list/tail: (xs : list<string>) -> list<string>.headstd/core/list/head: (xs : list<string>) -> maybe<string>.defaultstd/core/maybe/default: (m : maybe<string>, nothing : string) -> string(""literal: string
count= 0
) // Convert a path to the absolute path on the file system. // The path is not required to exist on disk. However, if it // exists any permissions and symbolic links are resolved fully.\ // `".".realpath` (to get the current working directory)\ // `"/foo".realpath` (to resolve the full root, like `"c:/foo"` on windows) pub fun realpathstd/os/path/realpath: (p : path) -> io path( pp: path : pathstd/os/path/path: V )result: -> io path : iostd/core/io: E pathstd/os/path/path: V realpathstd/os/path/string/realpath: (s : string) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> path(pp: path.stringstd/os/path/string: (p : path) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> string) // Returns the current working directory.\ // Equal to `".".realpath`. pub fun cwdstd/os/path/cwd: () -> io path()result: -> io path "."literal: string
count= 1
.realpathstd/os/path/string/realpath: (s : string) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> path
// Convert a path to the absolute path on the file system.\ // The overload on a plain string is necessary as it allows // for unnormalized paths with `".."` parts. For example // `"/foo/symlink/../test.txt"` may resolve to `"/bar/test.txt"` if // ``symlink`` is a symbolic link to a sub directory of `"/bar"`. pub fun string/realpathstd/os/path/string/realpath: (s : string) -> io path( ss: string : stringstd/core/types/string: V )result: -> io path : iostd/core/io: E pathstd/os/path/path: V xrealpathstd/os/path/xrealpath: (p : string) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> string(ss: string).pathstd/os/path/path: (s : string) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> path extern xrealpathstd/os/path/xrealpath: (p : string) -> io string( pp: string : stringstd/core/types/string: V ) : iostd/core/io: E stringstd/core/types/string: V c "kk_os_realpath" cs "System.IO.Path.GetFullPath" js "_get_realpath" // Return the OS specific directory separator (`"/"` or `"\\"`) pub extern partsepstd/os/path/partsep: () -> ndet string() : ndetstd/core/types/ndet: X stringstd/core/types/string: V c "kk_os_dir_sep" cs "System.IO.Path.DirectorySeparatorChar.ToString" js "_get_partsep" // Return the OS specific path separator (`';'` or `':'`) pub extern pathsepstd/os/path/pathsep: () -> ndet string() : ndetstd/core/types/ndet: X stringstd/core/types/string: V c "kk_os_path_sep" cs "System.IO.Path.PathSeparator.ToString" js "_get_pathsep" // Return the path to the currently executing application. pub fun app-pathstd/os/path/app-path: () -> io path()result: -> io path : iostd/core/io: E pathstd/os/path/path: V xapp-pathstd/os/path/xapp-path: () -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> string().pathstd/os/path/path: (s : string) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> path extern xapp-pathstd/os/path/xapp-path: () -> io string() : iostd/core/io: E stringstd/core/types/string: V c "kk_os_app_path" cs inline "System.Reflection.Assembly.GetEntryAssembly().Location" js "_get_apppath" // Return the base directory that contains the currently running application. // First tries `app-path().nobase`; if that ends in the ``bin`` or ``exe`` directory it // returns the parent of that directory. pub fun appdirstd/os/path/appdir: () -> io path()result: -> io path : iostd/core/io: E pathstd/os/path/path: V val pp: path = app-pathstd/os/path/app-path: () -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> path().nobasestd/os/path/nobase: (p : path) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> path if pp: path.basenamestd/os/path/basename: (p : path) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> string==std/core/string/(==): (string, string) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> bool"bin"literal: string
count= 3
||std/core/types/(||): (x : bool, y : bool) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> bool pp: path.basenamestd/os/path/basename: (p : path) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> string==std/core/string/(==): (string, string) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> bool"exe"literal: string
count= 3
then pp: path.nobasestd/os/path/nobase: (p : path) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> path else
pp: path // Return the home directory of the current user. pub fun homedirstd/os/path/homedir: () -> io path()result: -> io path : iostd/core/io: E pathstd/os/path/path: V xhomedirstd/os/path/xhomedir: () -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> string().pathstd/os/path/path: (s : string) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> path extern xhomedirstd/os/path/xhomedir: () -> io string() : iostd/core/io: E stringstd/core/types/string: V c "kk_os_home_dir" cs "_Path.GetHomeDir" js "_get_homedir" // Return the temporary directory for the current user. pub fun tempdirstd/os/path/tempdir: () -> io path()result: -> io path : iostd/core/io: E pathstd/os/path/path: V xtempdirstd/os/path/xtempdir: () -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> string().pathstd/os/path/path: (s : string) -> <alloc<global>,console,div,exn,fsys,ndet,net,read<global>,ui,write<global>> path extern xtempdirstd/os/path/xtempdir: () -> io string() : iostd/core/io: E stringstd/core/types/string: V c "kk_os_temp_dir" cs "System.IO.Path.GetTempPath" js "_get_tempdir"