fs-utils-0.1: FileSystem utils
Safe HaskellNone
LanguageGHC2021

FileSystem.OsPath

Description

Provides utilities for working with OsPath.

Since: 0.1

Synopsis

Types

type OsPath = OsString #

Type representing filenames/pathnames.

This type doesn't add any guarantees over OsString.

Encoding

Total

encode :: FilePath -> Either EncodingException OsPath Source #

Encodes a FilePath to an OsPath. This is a pure version of filepath's encodeUtf that returns the EncodingException in the event of an error.

Since: 0.1

encodeLenient :: FilePath -> OsPath Source #

Total conversion from FilePath to OsPath, replacing encode failures with the closest visual match.

Since: 0.1

Partial

unsafeEncode :: HasCallStack => FilePath -> OsPath Source #

Unsafely converts a FilePath to OsPath falling back to error.

WARNING: Partial

Since: 0.1

Encoding + Validation

Total

osp :: QuasiQuoter #

QuasiQuote an OsPath. This accepts Unicode characters and encodes as UTF-8 on unix and UTF-16LE on windows. Runs isValid on the input. If used as a pattern, requires turning on the ViewPatterns extension.

ospPathSep :: QuasiQuoter Source #

Like osp, except it runs paths through a "replace function" first. On unix, replaces \ with /. On windows, does the opposite.

This is convenient for writing paths in a platform-agnostic way i.e. we are expecting a path

  "path/to/foo" -- unix
  "path\to\foo" -- windows

The normal way to handle this would be to use the combine function (</>) i.e.

  [osp|path|] </> [osp|to|] </> [osp|foo|]

This can be quite cumbersome for long paths, so we provide this alternative, allowing:

  [ospPathSep|path/to/foo]

Which will automatically convert slashes.

encodeValid :: FilePath -> Either EncodingException OsPath Source #

encode that also checks isValid i.e. encode only succeeds if the FilePath can be encoded and passes expected invariants.

Since: 0.1

encodeValidLenient :: FilePath -> OsPath Source #

Total conversion from FilePath to OsPath, replacing encode failures with the closest visual match. If the result is not valid, makes it valid.

Since: 0.1

Partial

unsafeEncodeValid :: HasCallStack => FilePath -> OsPath Source #

Unsafely converts a FilePath to OsPath falling back to error.

WARNING: Partial

Since: 0.1

Decoding

Total

decode :: OsPath -> Either EncodingException FilePath Source #

Decodes an OsPath to a FilePath. This is a pure version of filepath's decodeUtf.

Since: 0.1

decodeLenient :: OsPath -> FilePath Source #

Total conversion from OsPath to FilePath, replacing decode failures with the closest visual match.

Since: 0.1

decodeDisplayEx :: OsPath -> String Source #

Total conversion from OsPath to String. If decoding fails, displays the exception.

Since: 0.1

decodeShow :: OsPath -> String Source #

Total conversion from OsPath to String. If decoding fails, falls back to its Show instance.

Since: 0.1

Partial

unsafeDecode :: HasCallStack => OsPath -> FilePath Source #

Unsafely converts an OsPath to a FilePath falling back to error.

WARNING: Partial

Since: 0.1

OsString

toOsString :: OsPath -> OsString Source #

Convert an OsPath to OsString. This is currently the identity function.

Since: 0.1

fromOsString :: OsString -> Either EncodingException OsPath Source #

Convert an OsString to OsPath. Currently this merely checks isValid.

Since: 0.1

unsafeFromOsString :: HasCallStack => OsString -> OsPath Source #

Unsafely checks an OsString for validity, dying with error on failure.

Since: 0.1

reallyUnsafeFromOsString :: OsString -> OsPath Source #

Converts from OsString to OsPath without checking any invariants. Used for when we know an operator cannot have

Since: 0.1

Functions

(</>) :: OsPath -> OsPath -> OsPath #

Combine two paths with a path separator. If the second path starts with a path separator or a drive letter, then it returns the second. The intention is that readFile (dir </> file) will access the same file as setCurrentDirectory dir; readFile file.

Posix:   "/directory" </> "file.ext" == "/directory/file.ext"
Windows: "/directory" </> "file.ext" == "/directory\\file.ext"
         "directory" </> "/file.ext" == "/file.ext"
Valid x => (takeDirectory x </> takeFileName x) `equalFilePath` x

Combined:

Posix:   "/" </> "test" == "/test"
Posix:   "home" </> "bob" == "home/bob"
Posix:   "x:" </> "foo" == "x:/foo"
Windows: "C:\\foo" </> "bar" == "C:\\foo\\bar"
Windows: "home" </> "bob" == "home\\bob"

Not combined:

Posix:   "home" </> "/bob" == "/bob"
Windows: "home" </> "C:\\bob" == "C:\\bob"

Not combined (tricky):

On Windows, if a filepath starts with a single slash, it is relative to the root of the current drive. In [1], this is (confusingly) referred to as an absolute path. The current behavior of </> is to never combine these forms.

Windows: "home" </> "/bob" == "/bob"
Windows: "home" </> "\\bob" == "\\bob"
Windows: "C:\\home" </> "\\bob" == "\\bob"

On Windows, from [1]: "If a file name begins with only a disk designator but not the backslash after the colon, it is interpreted as a relative path to the current directory on the drive with the specified letter." The current behavior of </> is to never combine these forms.

Windows: "D:\\foo" </> "C:bar" == "C:bar"
Windows: "C:\\foo" </> "C:bar" == "C:bar"

(<.>) :: OsPath -> OsString -> OsPath #

Add an extension, even if there is already one there, equivalent to addExtension.

"/directory/path" <.> "ext" == "/directory/path.ext"
"/directory/path" <.> ".ext" == "/directory/path.ext"

(-<.>) :: OsPath -> OsString -> OsPath #

Remove the current extension and add another, equivalent to replaceExtension.

"/directory/path.txt" -<.> "ext" == "/directory/path.ext"
"/directory/path.txt" -<.> ".ext" == "/directory/path.ext"
"foo.o" -<.> "c" == "foo.c"

Legacy

(</>!) :: HasCallStack => OsPath -> FilePath -> OsPath infixl 9 Source #

Unsafely combines an OsPath and a FilePath via (/) with unsafeEncode.

WARNING: Partial

Since: 0.1

(!</>) :: HasCallStack => FilePath -> OsPath -> OsPath infixl 9 Source #

Unsafely combines a FilePath and an OsPath via (/) with unsafeEncode.

WARNING: Partial

Since: 0.1

combineFilePaths :: FilePath -> FilePath -> FilePath Source #

Legacy alias for FilePaths' / operator. Exists because the / exported here is (</>) :: OsPath -> OsPath -> OsPath.

Since: 0.1

Errors

data EncodingException #

Constructors

EncodingError String (Maybe Word8)

Could not decode a byte sequence because it was invalid under the given encoding, or ran out of input in mid-decode.

Tildes

toTildePrefixState :: OsPath -> TildePrefixState Source #

Retrieves the path's "tilde state". Strips consecutive "tilde prefixes" if they exist. If the string contains no prefixes, returns it unchanged.

Since: 0.1

data TildePrefixState Source #

Represents the "tilde state" for a given path.

Constructors

TildePrefixStateNone OsPath

The path contained no tilde prefix.

TildePrefixStateStripped OsPathOrEmpty

The path contained "tilde prefix(es)" e.g. ~/ or ~\ (windows only), which have been stripped. The result can be empty, however.

Instances

Instances details
NFData TildePrefixState Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

Methods

rnf :: TildePrefixState -> () #

Generic TildePrefixState Source # 
Instance details

Defined in FileSystem.OsPath

Associated Types

type Rep TildePrefixState

Since: fs-utils-0.1

Instance details

Defined in FileSystem.OsPath

type Rep TildePrefixState = D1 ('MetaData "TildePrefixState" "FileSystem.OsPath" "fs-utils-0.1-inplace" 'False) (C1 ('MetaCons "TildePrefixStateNone" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 OsPath)) :+: C1 ('MetaCons "TildePrefixStateStripped" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 OsPathOrEmpty)))
Show TildePrefixState Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

Eq TildePrefixState Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

type Rep TildePrefixState Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

type Rep TildePrefixState = D1 ('MetaData "TildePrefixState" "FileSystem.OsPath" "fs-utils-0.1-inplace" 'False) (C1 ('MetaCons "TildePrefixStateNone" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 OsPath)) :+: C1 ('MetaCons "TildePrefixStateStripped" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 OsPathOrEmpty)))

data OsPathOrEmpty Source #

Sum type representing a possible empty OsPath. The OsPath type _can_ be empty, hence OsPathNonEmpty should only be used when the OsPath has been verified first. This type really exists to make it clear when the empty distinction matters.

Since: 0.1

Constructors

OsPathEmpty

OsPath is empty.

Since: 0.1

OsPathNonEmpty OsPath

OsPath is non-empty.

Since: 0.1

Instances

Instances details
NFData OsPathOrEmpty Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

Methods

rnf :: OsPathOrEmpty -> () #

Generic OsPathOrEmpty Source # 
Instance details

Defined in FileSystem.OsPath

Associated Types

type Rep OsPathOrEmpty

Since: fs-utils-0.1

Instance details

Defined in FileSystem.OsPath

type Rep OsPathOrEmpty = D1 ('MetaData "OsPathOrEmpty" "FileSystem.OsPath" "fs-utils-0.1-inplace" 'False) (C1 ('MetaCons "OsPathEmpty" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "OsPathNonEmpty" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 OsPath)))
Show OsPathOrEmpty Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

Eq OsPathOrEmpty Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

type Rep OsPathOrEmpty Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

type Rep OsPathOrEmpty = D1 ('MetaData "OsPathOrEmpty" "FileSystem.OsPath" "fs-utils-0.1-inplace" 'False) (C1 ('MetaCons "OsPathEmpty" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "OsPathNonEmpty" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 OsPath)))

newtype TildeException Source #

Exception for a path containing a tilde.

Constructors

MkTildeException OsPath 

Instances

Instances details
NFData TildeException Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

Methods

rnf :: TildeException -> () #

Exception TildeException Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

Generic TildeException Source # 
Instance details

Defined in FileSystem.OsPath

Associated Types

type Rep TildeException

Since: fs-utils-0.1

Instance details

Defined in FileSystem.OsPath

type Rep TildeException = D1 ('MetaData "TildeException" "FileSystem.OsPath" "fs-utils-0.1-inplace" 'True) (C1 ('MetaCons "MkTildeException" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 OsPath)))
Show TildeException Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

Eq TildeException Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

type Rep TildeException Source #

Since: 0.1

Instance details

Defined in FileSystem.OsPath

type Rep TildeException = D1 ('MetaData "TildeException" "FileSystem.OsPath" "fs-utils-0.1-inplace" 'True) (C1 ('MetaCons "MkTildeException" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 OsPath)))

containsTildePrefix :: OsPath -> Bool Source #

Returns true iff the string has a tilde prefix.

Since: 0.1

Functions

length :: OsPath -> Int Source #

The length of an OsPath. Counts word8 (posix) or word16 (windows) boundaries.

Since: 0.1

Normalization

normalize :: OsPath -> OsPath Source #

Performs canonical unicode decompositioncomposition. Converts tofrom Text via lenient encodings.

Since: 0.1

glyphLength :: OsPath -> Int Source #

Returns the number of "visual characters" i.e. glyphs. This is done by performing unicode normalization then taking the Text length. Note that this is not the same as length.

Since: 0.1