iyi

Standard library, 0.18.0

std/path

File system paths, read lexically: nothing here touches the file system. A Path is a name and a kind, POSIX (/ separates) or Windows (\ and / both separate); Path.new takes the kind the program was built for, Path.posix and Path.windows name one.

import std/path to use it. Source: src/std/path.iyi at v0.18.0.

The anchor of a path is its drive and root: / on POSIX; on Windows a drive letter (C:, C:\), a UNC share (\\server\share, \\server\share\) or a bare root (\). A Windows path is absolute only with both a drive and a root, so C:foo (drive-relative) and \foo (rooted) are not. DOS device paths (\\.\, \\?\) are not recognised: they read as UNC shares named . and ?, except \\?\UNC\server\share, the long form of \\server\share, whose drive runs through the share as Python's reads it. Windows names compare case-insensitively: in every script on Windows, as its file systems fold them, and in ASCII letters alone where the program was built for another platform.

Lexical operations: basename, dirname, extension, stem, parent, parents, parts, join and /, normalize (. and .. folded, repeated separators collapsed, a trailing one dropped, a Windows anchor spelled with \: C:/a is C:\a), relative_to? and relative_to (nil, or a panic, when the paths have different anchors or the base climbs through .. — where that leads cannot be known without the file system), sibling, to_posix and to_windows (the kind changes and, for to_posix, \ becomes /; to_windows keeps the name, since Windows reads / as a separator).

expand(base, home:) makes the path absolute under base, which is Program.env("PWD") when not given, and the process's own directory when no shell set that; on Windows it is the process's own directory always, since nothing there keeps PWD true. With neither, expand panics rather than guess. home: true reads a leading ~ from HOME, or from USERPROFILE on Windows, which is where that platform keeps it.

Pathstruct

std/pathiyi doc src/std/path.iyi
pub struct Path
  enum Kind : UInt8
    POSIX = 0_u8
    WINDOWS = 1_u8
    def self.native : Kind
    # Returns `true` if this enum value equals `POSIX`
    def posix? : Bool
    # Returns `true` if this enum value equals `WINDOWS`
    def windows? : Bool
  end
  def /(part : String | Path) : Path
  def <=>(other : Path) : Int32
  def ==(other : Path) : Bool
  def self.[](first : String | Path, second : String | Path, third : String | Path) : Path
  def self.[](first : String | Path, second : String | Path) : Path
  def self.[](name : String = "") : Path
  def self.[](parts : Array(String)) : Path
  # A share is absolute without a separator after it: `\\server\share` is
  # the share's root, as Windows and Python read it. It was relative, so
  # after `Dir.cd` to a share every `expand` panicked "base is not
  # absolute".
  def absolute? : Bool
  def anchor : String | ::Nil
  # The last component; the anchor, or the empty name, is its own. A
  # *suffix* found at the end is left off.
  def basename(suffix : String | ::Nil = nil) : String
  def self.compare_strings(s1 : String, s2 : String) : Int32
  # As the two names' `windows_fold`s compare, read here without folding
  # either while both are ASCII.
  def self.compare_strings_ci(s1 : String, s2 : String) : Int32
  # Everything before the last component: `"."` for a bare name, the
  # anchor for a single component under it.
  def dirname : String
  def drive : String | ::Nil
  def each_parent(&block : (Path -> Nil)) : Nil
  def each_part(&block : (String -> Nil)) : Nil
  def empty? : Bool
  def ends_with_separator? : Bool
  # Absolute and normalized, under *base* when relative. *base* is
  # `Program.env("PWD")` when not given (on Windows, never), the
  # process's own directory when nothing set that, and a relative path
  # with neither is refused.
  # `home: true` reads a leading `~` from the home directory the
  # platform names (see `home_directory`).
  def expand(base : Path | String | Nil = nil, home : Bool = false) : Path
  # The last `.suffix` of the basename, with its dot; none for a name
  # that starts with its only dot (`.bashrc`) or ends with one (`foo.`).
  def extension : String
  def hash : Int32
  def initialize(name : String = "", kind : Kind = Kind.native)
  def inspect(io : IO) : Nil
  # A path of the kind this platform does not use names its constructor,
  # as the other library writes it: `Path.posix("/usr/bin")` on Windows
  # inspected as `Path["/usr/bin"]`, a Windows path, which `==` tells
  # apart from it.
  def inspect : String
  def join(first : String | Path, second : String | Path, third : String | Path) : Path
  def join(first : String | Path, second : String | Path) : Path
  # `self` with *part* under it; a *part* with an anchor of its own is
  # the answer by itself, and an empty one changes nothing. A Windows
  # anchor can be half of one, and then the other half is `self`'s, as
  # ntpath joins and Windows reads the name: a root with no drive is on
  # `self`'s drive, and a drive-relative *part* on `self`'s drive goes
  # under `self`. Answered by itself, `C:\a` joined with `\b` was `\b`,
  # a root on whatever drive is current, and with `C:b` it was `C:b`,
  # where `expand` read both on `C:\a`.
  def join(part : String) : Path
  def join(part : Path) : Path
  def join(parts : Array(String)) : Path
  def kind : Kind
  def name : String
  def native? : Bool
  def self.new(path : Path) : Path
  # `.` dropped, `..` folded into the component before it (kept at the
  # front of a relative path, dropped under a root), separators collapsed.
  def normalize : Path
  def parent : Path
  # Every ancestor, the outermost first: `"a/b/c"` has `"."`, `"a"`,
  # `"a/b"`; `"/a/b"` has `"/"`, `"/a"`. Each is a `parent` of the one
  # after it, so it keeps the spelling `parent` keeps: rebuilt from
  # `parts` and joined with `separator`, `Path.windows("C:/a/b/c")` had
  # `"C:/a\\b"` where its `parent` is `"C:/a/b"`.
  def parents : Array(Path)
  # The anchor, if any, then each non-empty component.
  def parts : Array(String)
  def self.posix(name : String = "") : Path
  def posix? : Bool
  def relative? : Bool
  def relative_to(base : Path | String) : Path
  # The path that reaches `self` from *base*, or nil where none can be
  # spelled: different anchors, or a *base* that climbs through `..`.
  def relative_to?(base : Path | String) : Path | ::Nil
  def root : String | ::Nil
  # The anchor with the root a share has whether written or not.
  protected def rooted_anchor : String
  def sibling(name : String | Path) : Path
  def stem : String
  def to_kind(kind : Kind) : Path
  def to_native : Path
  def to_posix : Path
  def to_s(io : IO) : Nil
  def to_s : String
  def to_windows : Path
  def self.windows(name : String = "") : Path
  def windows? : Bool
  # *s* as a Windows name compares: `/` written `\`, ASCII letters lower
  # case, and on Windows every other letter in the case its file systems
  # fold it to - LCMAP_UPPERCASE without linguistic casing, measured to
  # make the same classes as CompareStringOrdinal's on every BMP unit. A
  # surrogate pair stays as written, as both leave it. ASCII alone folded,
  # `C:\Ä` and `c:\ä` were two paths where NTFS has one file; built for
  # another platform there is no table to ask, and ASCII alone is folded.
  def self.windows_fold(s : String) : String
end

Std::Traits::Comparable for Pathimpl

std/pathiyi doc src/std/path.iyi
impl Std::Traits::Comparable for Path
  def <=>(other : self) : Int32
end