# Path Support

Denys Duchier

module
  x-oz://system/os/Path.ozf

This module provides an object-oriented interface for path and OS operations on them

## Exports

The module exports not only the object-oriented API for path, but also a convenient functional API built on top of the later. It should be noted however that the functional API always needs to build path objects and thus is less efficient than the OO API, though possibly occasionally more convenient.

`{Path.make +VS ?P}`
  given a virtual string `VS`, returns a new path object `P`. If `VS` is already a path object, then it is simply returned.
`{Path.is +X ?B}`
  return true iff `X` is a path object
`Path.'class'`
  The class which implements path objects
`{Path.toString +X ?S}`
`{Path.toAtom +X ?A}`
`{Path.length +X ?N}`
`{Path.isAbsolute +X ?B}`
`{Path.isRelative +X ?B}`
`{Path.dirname +X ?S}`
`{Path.basename +X ?S}`
`{Path.exists +X ?B}`
`{Path.stat +X ?R}`
`{Path.isDir +X ?B}`
`{Path.isFile +X ?B}`
`{Path.size +X ?N}`
`{Path.mtime +X ?N}`
`{Path.resolve +X1 +X2 ?S}`
`{Path.getcwd ?S}`
`{Path.mkdir +X}`
`{Path.mkdirs +X}`
`{Path.isRoot +X ?B}`
`{Path.readdir +X ?L}`
`{Path.extension +X ?S}`
`{Path.dropExtension +X ?S}`
`{Path.addExtension +X +VS ?S}`
`{Path.maybeAddPlatform +X ?S}`
`{Path.rmdir +X}`
  for proper descriptions, see path methods below. Returned path objects are converted to strings where applicable

## Instance API

Each path object `P` has the following methods:

`{P init(+S windows:WIN<=ISWIN exact:EXACT<=false)}`
  initializes a path object from the string `S`. `WIN` indicates that it should be considered a Windows-style path: this usually defaults to false, except on Windows where it defaults to true. It is possible to indicate a directory by additing a terminal '/' or '\' (depending on OS). However, this slash/backslash is removed in the string output when `EXACT` is set to false, which is its default value.
`{P initFromRecord(+R)}`
  initializes the path object from its record-based representation
`{P newFromRecord(R $)}`
  This method is meant to be overriden when you subclass the `Path` class. It's default definition is `meth newFromRecord(R $) {New Path initFromRecord(R)} end`
`{P new(+S windows:WIN<=ISWIN exact:EXACT<=false)}`
  this method is also meant to be overriden to create derived instances from a string `S`
`{P toString($)}`
`{P toAtom($)}`
  return a string (resp. an atom) textual representation of the path
`{P length($)}`
  returns the length of the string that is the textual representation of the path
`{P isAbsolute($)}`
`{P isRelative($)}`
  returns true (resp. false) iff the path is absolute
`{P dirname($)}`
  returns a new path object representing the parent directory of `P`. If `P` contains only a single component (i.e. `P` is a plain file) then dirname returns`nil`.
`{P basename($)}`
  returns a new path object representing just the last component of path `P`
`{P dirnameString($)}`
  returns the string representation for the parent directory of `P`
`{P basenameString($)}`
  returns the string representation for the last component of `P`
`{P exists($)}`
  returns true iff path `P` exists
`{P stat($)}`
  returns a record representation of the stat information for path `P`
`{P isDir($)}`
`{P isFile($)}`
  returns true iff `P` is a directory (resp. a regular file). Note that these methods only work for an actually existing file which is either an absolute path or relative to the current path (the implementation calls`stat`)
`{P isDir2($)}`
`{P isFile2($)}`
  `isDir2` returns true if `P` ends in a slash or backslash (depending on OS), and `isFile2` returns true if `P` does not end in a slash or backslash. Note that this is not a foolproof technique for checking for directories, but it works also for non-existing pathes
`{P size($)}`
  returns the size of file `P` in bytes
`{P mtime($)}`
  returns the time of the last modification as an integer
`{P resolve(+P2 $)}`
  returns a new path object that results from resolving `P2` relative to `P` (if `P2` is not a path, it is made into one). In other words, `P2` is attached to the end of `P`. However, if `P2` is an absolute path, then it returns a path object only for `P2`. Note that resolve also 'appends' `P2` to `P` in case `P` is a regular file.
`{P getcwd($)}`
  returns a path object representing the current working directory
`{P mkdir}`
  creates directory `P`
`{P mkdirs}`
  creates directory `P` and its ancestor directories too if necessary
`{P rmdir}`
  removes directory `P`
`{P isRoot($)}`
  returns true iff `P` is a root path
`{P readdir($)}`
  returns a list of path objects representing the contents of directory `P`. Entries for `.` and `..` are omitted. All other entries are resolved relative to `P`
`{P extension($)}`
  returns the file extension for `P`, `unit` if none
`{P dropExtension($)}`
  returns a new path object with the extension of `P`, if any, omitted
`{P addExtension(+VS $)}`
  returns a new path object which is like `P` but with the extension `VS` added
`{P maybeAddPlatform($)}`
  is `P` has extension `so` then a new path object is returned with the appropriate (for native functors) platform-specific suffix added, else `P` itself is returned
`{P makeExecutable}`
  makes file `P` executable if this is meaningful on the current platform