system-filepath-0.3: System/FilePath/Internal.hs
{-# LANGUAGE DeriveDataTypeable #-}
-- |
-- Module: System.FilePath.Internal
-- Copyright: 2010 John Millikin
-- License: MIT
--
-- Maintainer: jmillikin@gmail.com
-- Portability: portable
--
module System.FilePath.Internal where
import Prelude hiding (FilePath)
import Data.Data (Data)
import Data.List (intersperse)
import qualified Data.Text as T
import Data.Typeable (Typeable)
-------------------------------------------------------------------------------
-- File Paths
-------------------------------------------------------------------------------
data Chunk = Chunk
{ chunkText :: T.Text
, chunkGood :: Bool
}
deriving (Eq, Ord, Data, Typeable)
type Directory = Chunk
type Basename = Chunk
type Extension = Chunk
data Root
= RootPosix
| RootWindowsVolume Char
| RootWindowsCurrentVolume
deriving (Eq, Ord, Data, Typeable)
data FilePath = FilePath
{ pathRoot :: Maybe Root
, pathDirectories :: [Directory]
, pathBasename :: Maybe Basename
, pathExtensions :: [Extension]
}
deriving (Eq, Ord, Data, Typeable)
-- | A file path with no root, directory, or filename
empty :: FilePath
empty = FilePath Nothing [] Nothing []
dot :: Chunk
dot = Chunk (T.pack ".") True
dots :: Chunk
dots = Chunk (T.pack "..") True
filenameChunk :: FilePath -> Chunk
filenameChunk p = Chunk (T.concat texts) (and good) where
name = maybe (Chunk T.empty True) id (pathBasename p)
exts = case pathExtensions p of
[] -> []
exts' -> intersperse dot ((Chunk T.empty True):exts')
chunks = name:exts
texts = map chunkText chunks
good = map chunkGood chunks
-------------------------------------------------------------------------------
-- Rules
-------------------------------------------------------------------------------
data Rules platformFormat = Rules
{ rulesName :: T.Text
-- | Check if a 'FilePath' is valid; it must not contain any illegal
-- characters, and must have a root appropriate to the current
-- 'Rules'.
, valid :: FilePath -> Bool
-- | Split a search path, such as @$PATH@ or @$PYTHONPATH@, into
-- a list of 'FilePath's.
, splitSearchPath :: platformFormat -> [FilePath]
-- | Attempt to convert a 'FilePath' to human‐readable text.
--
-- If the path is decoded successfully, the result is a 'Right'
-- containing the decoded text. Successfully decoded text can be
-- converted back to the original path using 'fromText'.
--
-- If the path cannot be decoded, the result is a 'Left' containing an
-- approximation of the original path. If displayed to the user, this
-- value should be accompanied by some warning that the path has an
-- invalid encoding. Approximated text cannot be converted back to the
-- original path.
--
-- This function ignores the user’s locale, and assumes all
-- file paths are encoded in UTF8. If you need to display file paths
-- with an unusual or obscure encoding, use 'toBytes' and then decode
-- them manually.
--
-- Since: 0.2
, toText :: FilePath -> Either T.Text T.Text
-- | Convert human‐readable text into a 'FilePath'.
--
-- This function ignores the user’s locale, and assumes all
-- file paths are encoded in UTF8. If you need to create file paths
-- with an unusual or obscure encoding, encode them manually and then
-- use 'fromBytes'.
--
-- Since: 0.2
, fromText :: T.Text -> FilePath
-- | Convert a 'FilePath' to the platform’s underlying format.
--
-- Since: 0.3
, encode :: FilePath -> platformFormat
-- | Convert the platform’s underlying format to a 'FilePath'.
--
-- Since: 0.3
, decode :: platformFormat -> FilePath
}
instance Show (Rules a) where
showsPrec d r = showParen (d > 10)
(showString "Rules " . shows (rulesName r))