Hledger.Cli.Script

hledger-1.41: Command-line interface for the hledger accounting system

Safe Haskell | None
Language | Haskell2010

Hledger.Cli.Script

Description

A convenient module to import in hledger scripts, aiming to provide the most useful imports and reduce boilerplate. |

Synopsis

- module Control.Applicative
- module Control.Concurrent
- module Control.Monad
- module Data.Char
- module Data.Either
- module Data.List
- module Data.Maybe
- module Data.Ord
- module Data.Time
- module Hledger
- module Hledger.Cli.CliOptions
- module Hledger.Cli.Commands
- module Hledger.Cli.CompoundBalanceCommand
- module Hledger.Cli.DocFiles
- module Hledger.Cli.Utils
- module Hledger.Cli.Version
- module System.Console.CmdArgs.Explicit
- module System.Directory
- module System.Environment
- module System.Exit
- module System.IO
- module System.IO.Error
- module System.Process
- abort :: Partial => String -> a
- data Text
- ($>) :: Functor f => f a -> b -> f b
- formatRealFloat :: RealFloat a => a -> FieldFormatter
- (<&>) :: Functor f => f a -> (a -> b) -> f b
- type ModifierParser = String -> FormatParse
- type FieldFormatter = FieldFormat -> ShowS
- data FormatParse = FormatParse {
  - fpModifiers :: String
  - fpChar :: Char
  - fpRest :: String
  }
- data FieldFormat = FieldFormat {
  - fmtWidth :: Maybe Int
  - fmtPrecision :: Maybe Int
  - fmtAdjust :: Maybe FormatAdjustment
  - fmtSign :: Maybe FormatSign
  - fmtAlternate :: Bool
  - fmtModifiers :: String
  - fmtChar :: Char
  }
- data FormatSign
  - = SignPlus
  - | SignSpace
- data FormatAdjustment
  - = LeftAdjust
  - | ZeroPad
- class IsChar c where
  - toChar :: c -> Char
  - fromChar :: Char -> c
- class PrintfArg a where
  - formatArg :: a -> FieldFormatter
  - parseFormat :: a -> ModifierParser
- class HPrintfType t
- class PrintfType t
- printf :: PrintfType r => String -> r
- hPrintf :: HPrintfType r => Handle -> String -> r
- vFmt :: Char -> FieldFormat -> FieldFormat
- formatChar :: Char -> FieldFormatter
- formatInt :: (Integral a, Bounded a) => a -> FieldFormatter
- formatInteger :: Integer -> FieldFormatter
- perror :: String -> a
- errorBadFormat :: Char -> a
- errorShortFormat :: a
- errorMissingArgument :: a
- errorBadArgument :: a
- pack :: String -> Text
- unpack :: Text -> String
- searchPathSeparator :: Char
- normalise :: FilePath -> FilePath
- dropTrailingPathSeparator :: FilePath -> FilePath
- makeRelative :: FilePath -> FilePath -> FilePath
- (</>) :: FilePath -> FilePath -> FilePath
- headDef :: a -> [a] -> a
- lastDef :: a -> [a] -> a
- pathSeparator :: Char
- pathSeparators :: [Char]
- isPathSeparator :: Char -> Bool
- isSearchPathSeparator :: Char -> Bool
- extSeparator :: Char
- isExtSeparator :: Char -> Bool
- splitSearchPath :: String -> [FilePath]
- getSearchPath :: IO [FilePath]
- splitExtension :: FilePath -> (String, String)
- takeExtension :: FilePath -> String
- (-<.>) :: FilePath -> String -> FilePath
- replaceExtension :: FilePath -> String -> FilePath
- (<.>) :: FilePath -> String -> FilePath
- dropExtension :: FilePath -> FilePath
- addExtension :: FilePath -> String -> FilePath
- hasExtension :: FilePath -> Bool
- isExtensionOf :: String -> FilePath -> Bool
- stripExtension :: String -> FilePath -> Maybe FilePath
- splitExtensions :: FilePath -> (FilePath, String)
- dropExtensions :: FilePath -> FilePath
- takeExtensions :: FilePath -> String
- replaceExtensions :: FilePath -> String -> FilePath
- splitDrive :: FilePath -> (FilePath, FilePath)
- joinDrive :: FilePath -> FilePath -> FilePath
- takeDrive :: FilePath -> FilePath
- dropDrive :: FilePath -> FilePath
- hasDrive :: FilePath -> Bool
- isDrive :: FilePath -> Bool
- splitFileName :: FilePath -> (String, String)
- replaceFileName :: FilePath -> String -> FilePath
- dropFileName :: FilePath -> FilePath
- takeFileName :: FilePath -> FilePath
- takeBaseName :: FilePath -> String
- replaceBaseName :: FilePath -> String -> FilePath
- hasTrailingPathSeparator :: FilePath -> Bool
- addTrailingPathSeparator :: FilePath -> FilePath
- takeDirectory :: FilePath -> FilePath
- replaceDirectory :: FilePath -> String -> FilePath
- combine :: FilePath -> FilePath -> FilePath
- splitPath :: FilePath -> [FilePath]
- splitDirectories :: FilePath -> [FilePath]
- joinPath :: [FilePath] -> FilePath
- equalFilePath :: FilePath -> FilePath -> Bool
- isValid :: FilePath -> Bool
- makeValid :: FilePath -> FilePath
- isRelative :: FilePath -> Bool
- isAbsolute :: FilePath -> Bool
- foldl1May :: (a -> a -> a) -> [a] -> Maybe a
- foldr1May :: (a -> a -> a) -> [a] -> Maybe a
- foldl1Note :: Partial => String -> (a -> a -> a) -> [a] -> a
- foldr1Note :: Partial => String -> (a -> a -> a) -> [a] -> a
- minimumMay :: Ord a => [a] -> Maybe a
- maximumMay :: Ord a => [a] -> Maybe a
- minimumNote :: (Partial, Ord a) => String -> [a] -> a
- maximumNote :: (Partial, Ord a) => String -> [a] -> a
- minimumByMay :: (a -> a -> Ordering) -> [a] -> Maybe a
- maximumByMay :: (a -> a -> Ordering) -> [a] -> Maybe a
- minimumByNote :: Partial => String -> (a -> a -> Ordering) -> [a] -> a
- maximumByNote :: Partial => String -> (a -> a -> Ordering) -> [a] -> a
- maximumBoundBy :: a -> (a -> a -> Ordering) -> [a] -> a
- minimumBoundBy :: a -> (a -> a -> Ordering) -> [a] -> a
- maximumBound :: Ord a => a -> [a] -> a
- minimumBound :: Ord a => a -> [a] -> a
- maximumBounded :: (Ord a, Bounded a) => [a] -> a
- minimumBounded :: (Ord a, Bounded a) => [a] -> a
- findJust :: (a -> Bool) -> [a] -> a
- findJustDef :: a -> (a -> Bool) -> [a] -> a
- findJustNote :: Partial => String -> (a -> Bool) -> [a] -> a
- minimumDef :: Ord a => a -> [a] -> a
- maximumDef :: Ord a => a -> [a] -> a
- minimumByDef :: a -> (a -> a -> Ordering) -> [a] -> a
- maximumByDef :: a -> (a -> a -> Ordering) -> [a] -> a
- foldl1Def :: a -> (a -> a -> a) -> [a] -> a
- foldr1Def :: a -> (a -> a -> a) -> [a] -> a
- tailErr :: Partial => [a] -> [a]
- headErr :: Partial => [a] -> a
- tailMay :: [a] -> Maybe [a]
- tailDef :: [a] -> [a] -> [a]
- tailNote :: Partial => String -> [a] -> [a]
- tailSafe :: [a] -> [a]
- initMay :: [a] -> Maybe [a]
- initDef :: [a] -> [a] -> [a]
- initNote :: Partial => String -> [a] -> [a]
- initSafe :: [a] -> [a]
- headMay :: [a] -> Maybe a
- lastMay :: [a] -> Maybe a
- headNote :: Partial => String -> [a] -> a
- lastNote :: Partial => String -> [a] -> a
- foldl1May' :: (a -> a -> a) -> [a] -> Maybe a
- foldl1Note' :: Partial => String -> (a -> a -> a) -> [a] -> a
- scanr1May :: (a -> a -> a) -> [a] -> Maybe [a]
- scanl1May :: (a -> a -> a) -> [a] -> Maybe [a]
- scanr1Def :: [a] -> (a -> a -> a) -> [a] -> [a]
- scanl1Def :: [a] -> (a -> a -> a) -> [a] -> [a]
- scanr1Note :: Partial => String -> (a -> a -> a) -> [a] -> [a]
- scanl1Note :: Partial => String -> (a -> a -> a) -> [a] -> [a]
- cycleMay :: [a] -> Maybe [a]
- cycleDef :: [a] -> [a] -> [a]
- cycleNote :: Partial => String -> [a] -> [a]
- fromJustDef :: a -> Maybe a -> a
- fromJustNote :: Partial => String -> Maybe a -> a
- assertNote :: Partial => String -> Bool -> a -> a
- atMay :: [a] -> Int -> Maybe a
- atDef :: a -> [a] -> Int -> a
- atNote :: Partial => String -> [a] -> Int -> a
- readEitherSafe :: Read a => String -> Either String a
- readMay :: Read a => String -> Maybe a
- readDef :: Read a => a -> String -> a
- readNote :: (Partial, Read a) => String -> String -> a
- lookupJust :: (Eq a, Partial) => a -> [(a, b)] -> b
- lookupJustDef :: Eq a => b -> a -> [(a, b)] -> b
- lookupJustNote :: (Partial, Eq a) => String -> a -> [(a, b)] -> b
- elemIndexJust :: (Partial, Eq a) => a -> [a] -> Int
- elemIndexJustDef :: Eq a => Int -> a -> [a] -> Int
- elemIndexJustNote :: (Partial, Eq a) => String -> a -> [a] -> Int
- findIndexJust :: (a -> Bool) -> [a] -> Int
- findIndexJustDef :: Int -> (a -> Bool) -> [a] -> Int
- findIndexJustNote :: Partial => String -> (a -> Bool) -> [a] -> Int
- toEnumMay :: (Enum a, Bounded a) => Int -> Maybe a
- toEnumDef :: (Enum a, Bounded a) => a -> Int -> a
- toEnumNote :: (Partial, Enum a, Bounded a) => String -> Int -> a
- toEnumSafe :: (Enum a, Bounded a) => Int -> a
- succMay :: (Enum a, Eq a, Bounded a) => a -> Maybe a
- succDef :: (Enum a, Eq a, Bounded a) => a -> a -> a
- succNote :: (Partial, Enum a, Eq a, Bounded a) => String -> a -> a
- succSafe :: (Enum a, Eq a, Bounded a) => a -> a
- predMay :: (Enum a, Eq a, Bounded a) => a -> Maybe a
- predDef :: (Enum a, Eq a, Bounded a) => a -> a -> a
- predNote :: (Partial, Enum a, Eq a, Bounded a) => String -> a -> a
- predSafe :: (Enum a, Eq a, Bounded a) => a -> a
- indexMay :: Ix a => (a, a) -> a -> Maybe Int
- indexDef :: Ix a => Int -> (a, a) -> a -> Int
- indexNote :: (Partial, Ix a) => String -> (a, a) -> a -> Int
- foldl1Def' :: a -> (a -> a -> a) -> [a] -> a
- argsToCliOpts :: [String] -> [String] -> IO CliOpts

# Documentation

module Control.Applicative

module Control.Concurrent

module Control.Monad

module Data.Char

module Data.Either

module Data.List

module Data.Maybe

module Data.Ord

module Data.Time

module Hledger

module Hledger.Cli.CliOptions

module Hledger.Cli.Commands

module Hledger.Cli.CompoundBalanceCommand

module Hledger.Cli.DocFiles

module Hledger.Cli.Utils

module Hledger.Cli.Version

module System.Console.CmdArgs.Explicit

module System.Directory

module System.Environment

module System.Exit

module System.IO

module System.IO.Error

module System.Process

abort :: Partial => String -> a #

Synonym for `error`. Used for instances where the program has decided to exit because of invalid user input, or the user pressed quit etc. This function allows `error` to be reserved for programmer errors.

data Text #

A space efficient, packed, unboxed Unicode text type.

#### Instances

Instances details

ToJSON Text |
Instance details Defined in Data.Aeson.Types.ToJSON Methods toJSON :: Text -> Value # toEncoding :: Text -> Encoding # toJSONList :: [Text] -> Value # toEncodingList :: [Text] -> Encoding # omitField :: Text -> Bool #
ToJSONKey Text |
Instance details Defined in Data.Aeson.Types.ToJSON Methods toJSONKey :: ToJSONKeyFunction Text # toJSONKeyList :: ToJSONKeyFunction [Text] #
Chunk Text |
Instance details Defined in Data.Attoparsec.Internal.Types Associated Types
type ChunkElem Text |
Instance details Defined in Data.Attoparsec.Internal.Types type ChunkElem Text = Char
Methods nullChunk :: Text -> Bool # pappendChunk :: State Text -> Text -> State Text # atBufferEnd :: Text -> State Text -> Pos # bufferElemAt :: Text -> Pos -> State Text -> Maybe (ChunkElem Text, Int) # chunkElemToChar :: Text -> ChunkElem Text -> Char #
Show CsvRules |
Instance details Defined in Hledger.Read.RulesReader Methods showsPrec :: Int -> CsvRules -> ShowS # show :: CsvRules -> String # showList :: [CsvRules] -> ShowS #
Eq CsvRules |
Instance details Defined in Hledger.Read.RulesReader Methods (==) :: CsvRules -> CsvRules -> Bool # (/=) :: CsvRules -> CsvRules -> Bool #
Hashable Text |
Instance details Defined in Data.Hashable.Class Methods hashWithSalt :: Int -> Text -> Int # hash :: Text -> Int #
Anon Text # |
Instance details Defined in Hledger.Cli.Anon Methods anon :: Text -> Text #
ToHtml Text |
Instance details Defined in Lucid.Base Methods toHtml :: forall (m :: Type -> Type). Monad m => Text -> HtmlT m () # toHtmlRaw :: forall (m :: Type -> Type). Monad m => Text -> HtmlT m () #
Stream Text |
Instance details Defined in Text.Megaparsec.Stream Associated Types
type Token Text |
Instance details Defined in Text.Megaparsec.Stream type Token Text = Token (ShareInput Text)
type Tokens Text |
Instance details Defined in Text.Megaparsec.Stream type Tokens Text = Tokens (ShareInput Text)
Methods tokenToChunk :: Proxy Text -> Token Text -> Tokens Text # tokensToChunk :: Proxy Text -> [Token Text] -> Tokens Text # chunkToTokens :: Proxy Text -> Tokens Text -> [Token Text] # chunkLength :: Proxy Text -> Tokens Text -> Int # chunkEmpty :: Proxy Text -> Tokens Text -> Bool # take1_ :: Text -> Maybe (Token Text, Text) # takeN_ :: Int -> Text -> Maybe (Tokens Text, Text) # takeWhile_ :: (Token Text -> Bool) -> Text -> (Tokens Text, Text) #
TraversableStream Text |
Instance details Defined in Text.Megaparsec.Stream Methods reachOffset :: Int -> PosState Text -> (Maybe String, PosState Text) # reachOffsetNoLine :: Int -> PosState Text -> PosState Text #
VisualStream Text |
Instance details Defined in Text.Megaparsec.Stream Methods showTokens :: Proxy Text -> NonEmpty (Token Text) -> String # tokensLength :: Proxy Text -> NonEmpty (Token Text) -> Int #
Pretty Text | Automatically converts all newlines to ``line``.
    >>> pretty ("hello\nworld" :: Text)
    hello
    world
Note that ``line`` can be undone by ``group``:
    >>> group (pretty ("hello\nworld" :: Text))
    hello world
Manually use ``hardline`` if you definitely want newlines.
Instance details Defined in Prettyprinter.Internal Methods pretty :: Text -> Doc ann # prettyList :: [Text] -> Doc ann #
Extract Text | Since: regex-base-0.94.0.0
Instance details Defined in Text.Regex.Base.RegexLike Methods before :: Int -> Text -> Text # after :: Int -> Text -> Text # empty :: Text # extract :: (Int, Int) -> Text -> Text #
Uncons Text | Since: regex-tdfa-1.3.1
Instance details Defined in Text.Regex.TDFA.NewDFA.Uncons Methods uncons :: Text -> Maybe (Char, Text) #
ToHamletData Text |
Instance details Defined in Text.Hamlet.Runtime Methods toHamletData :: Text -> HamletData #
ToCss Text |
Instance details Defined in Text.Internal.Css Methods toCss :: Text -> Builder #
RawJS Text |
Instance details Defined in Text.Julius Methods rawJS :: Text -> RawJavascript #
ToJavascript Text |
Instance details Defined in Text.Julius Methods toJavascript :: Text -> Javascript #
ToMessage Text |
Instance details Defined in Text.Shakespeare.I18N Methods toMessage :: Text -> Text #
ToText Text |
Instance details Defined in Text.Shakespeare.Text Methods toText :: Text -> Builder #
Term Text Attribute | Some terms (like `style_`, `title_`) can be used for attributes as well as elements.
Instance details Defined in Lucid.Base Methods term :: Text -> Text -> Attribute # termWith :: Text -> [Attribute] -> Text -> Attribute #
TermRaw Text Attribute | Some termRaws (like `style_`, `title_`) can be used for attributes as well as elements.
Instance details Defined in Lucid.Base Methods termRaw :: Text -> Text -> Attribute # termRawWith :: Text -> [Attribute] -> Text -> Attribute #
RenderMessage master Text |
Instance details Defined in Text.Shakespeare.I18N Methods renderMessage :: master -> [Lang] -> Text -> Text #
(Monad m, a ~ ()) => TermRaw Text (HtmlT m a) | Given children immediately, just use that and expect no attributes.
Instance details Defined in Lucid.Base Methods termRaw :: Text -> Text -> HtmlT m a # termRawWith :: Text -> [Attribute] -> Text -> HtmlT m a #
Stream (NoShareInput Text) |
Instance details Defined in Text.Megaparsec.Stream Associated Types
type Token (NoShareInput Text) |
Instance details Defined in Text.Megaparsec.Stream type Token (NoShareInput Text) = Char
type Tokens (NoShareInput Text) |
Instance details Defined in Text.Megaparsec.Stream type Tokens (NoShareInput Text) = Text
Methods tokenToChunk :: Proxy (NoShareInput Text) -> Token (NoShareInput Text) -> Tokens (NoShareInput Text) # tokensToChunk :: Proxy (NoShareInput Text) -> [Token (NoShareInput Text)] -> Tokens (NoShareInput Text) # chunkToTokens :: Proxy (NoShareInput Text) -> Tokens (NoShareInput Text) -> [Token (NoShareInput Text)] # chunkLength :: Proxy (NoShareInput Text) -> Tokens (NoShareInput Text) -> Int # chunkEmpty :: Proxy (NoShareInput Text) -> Tokens (NoShareInput Text) -> Bool # take1_ :: NoShareInput Text -> Maybe (Token (NoShareInput Text), NoShareInput Text) # takeN_ :: Int -> NoShareInput Text -> Maybe (Tokens (NoShareInput Text), NoShareInput Text) # takeWhile_ :: (Token (NoShareInput Text) -> Bool) -> NoShareInput Text -> (Tokens (NoShareInput Text), NoShareInput Text) #
Stream (ShareInput Text) |
Instance details Defined in Text.Megaparsec.Stream Associated Types
type Token (ShareInput Text) |
Instance details Defined in Text.Megaparsec.Stream type Token (ShareInput Text) = Char
type Tokens (ShareInput Text) |
Instance details Defined in Text.Megaparsec.Stream type Tokens (ShareInput Text) = Text
Methods tokenToChunk :: Proxy (ShareInput Text) -> Token (ShareInput Text) -> Tokens (ShareInput Text) # tokensToChunk :: Proxy (ShareInput Text) -> [Token (ShareInput Text)] -> Tokens (ShareInput Text) # chunkToTokens :: Proxy (ShareInput Text) -> Tokens (ShareInput Text) -> [Token (ShareInput Text)] # chunkLength :: Proxy (ShareInput Text) -> Tokens (ShareInput Text) -> Int # chunkEmpty :: Proxy (ShareInput Text) -> Tokens (ShareInput Text) -> Bool # take1_ :: ShareInput Text -> Maybe (Token (ShareInput Text), ShareInput Text) # takeN_ :: Int -> ShareInput Text -> Maybe (Tokens (ShareInput Text), ShareInput Text) # takeWhile_ :: (Token (ShareInput Text) -> Bool) -> ShareInput Text -> (Tokens (ShareInput Text), ShareInput Text) #
ToAttributes [(Text, Text)] |
Instance details Defined in Text.Hamlet Methods toAttributes :: [(Text, Text)] -> [(Text, Text)] #
Ord (ParseError Text HledgerParseErrorData) |
Instance details Defined in Hledger.Utils.Parse Methods compare :: ParseError Text HledgerParseErrorData -> ParseError Text HledgerParseErrorData -> Ordering # (<) :: ParseError Text HledgerParseErrorData -> ParseError Text HledgerParseErrorData -> Bool # (<=) :: ParseError Text HledgerParseErrorData -> ParseError Text HledgerParseErrorData -> Bool # (>) :: ParseError Text HledgerParseErrorData -> ParseError Text HledgerParseErrorData -> Bool # (>=) :: ParseError Text HledgerParseErrorData -> ParseError Text HledgerParseErrorData -> Bool # max :: ParseError Text HledgerParseErrorData -> ParseError Text HledgerParseErrorData -> ParseError Text HledgerParseErrorData # min :: ParseError Text HledgerParseErrorData -> ParseError Text HledgerParseErrorData -> ParseError Text HledgerParseErrorData #
ToAttributes (Text, Text) |
Instance details Defined in Text.Hamlet Methods toAttributes :: (Text, Text) -> [(Text, Text)] #
HasAmounts b => HasAmounts (Text, PeriodicReport a b, Bool) |
Instance details Defined in Hledger.Reports.ReportTypes Methods styleAmounts :: Map CommoditySymbol AmountStyle -> (Text, PeriodicReport a b, Bool) -> (Text, PeriodicReport a b, Bool) #
type ChunkElem Text |
Instance details Defined in Data.Attoparsec.Internal.Types type ChunkElem Text = Char
type State Text |
Instance details Defined in Data.Attoparsec.Internal.Types type State Text = Buffer
type Item Text |
Instance details Defined in Data.Text type Item Text = Char
type Token Text |
Instance details Defined in Text.Megaparsec.Stream type Token Text = Token (ShareInput Text)
type Tokens Text |
Instance details Defined in Text.Megaparsec.Stream type Tokens Text = Tokens (ShareInput Text)
type Token (NoShareInput Text) |
Instance details Defined in Text.Megaparsec.Stream type Token (NoShareInput Text) = Char
type Token (ShareInput Text) |
Instance details Defined in Text.Megaparsec.Stream type Token (ShareInput Text) = Char
type Tokens (NoShareInput Text) |
Instance details Defined in Text.Megaparsec.Stream type Tokens (NoShareInput Text) = Text
type Tokens (ShareInput Text) |
Instance details Defined in Text.Megaparsec.Stream type Tokens (ShareInput Text) = Text

($>) :: Functor f => f a -> b -> f b infixl 4 #

Flipped version of `<$`.

@since base-4.7.0.0

#### Examples

Expand

Replace the contents of a ``Maybe` `Int`` with a constant `String`:

    >>> Nothing $> "foo"
    Nothing

    >>> Just 90210 $> "foo"
    Just "foo"

Replace the contents of an ``Either` `Int` `Int`` with a constant `String`, resulting in an ``Either` `Int` `String``:

    >>> Left 8675309 $> "foo"
    Left 8675309

    >>> Right 8675309 $> "foo"
    Right "foo"

Replace each element of a list with a constant `String`:

    >>> [1,2,3] $> "foo"
    ["foo","foo","foo"]

Replace the second element of a pair with a constant `String`:

    >>> (1,2) $> "foo"
    (1,"foo")

formatRealFloat :: RealFloat a => a -> FieldFormatter #

Formatter for `RealFloat` values.

Since: base-4.7.0.0

(<&>) :: Functor f => f a -> (a -> b) -> f b infixl 1 #

Flipped version of `<$>`.

    (<&>) = flip fmap

@since base-4.11.0.0

#### Examples

Expand

Apply `(+1)` to a list, a `Just` and a `Right`:

    >>> Just 2 <&> (+1)
    Just 3

    >>> [1,2,3] <&> (+1)
    [2,3,4]

    >>> Right 3 <&> (+1)
    Right 4

type ModifierParser = String -> FormatParse #

Type of a function that will parse modifier characters from the format string.

Since: base-4.7.0.0

type FieldFormatter = FieldFormat -> ShowS #

This is the type of a field formatter reified over its argument.

Since: base-4.7.0.0

data FormatParse #

The "format parser" walks over argument-type-specific modifier characters to find the primary format character. This is the type of its result.

Since: base-4.7.0.0

Constructors

FormatParse |
Fields fpModifiers :: String Any modifiers found. fpChar :: Char Primary format character. fpRest :: String Rest of the format string.

data FieldFormat #

Description of field formatting for `formatArg`. See UNIX `printf(3)` for a description of how field formatting works.

Since: base-4.7.0.0

Constructors

FieldFormat |
Fields fmtWidth :: Maybe Int Total width of the field. fmtPrecision :: Maybe Int Secondary field width specifier. fmtAdjust :: Maybe FormatAdjustment Kind of filling or padding to be done. fmtSign :: Maybe FormatSign Whether to insist on a plus sign for positive numbers. fmtAlternate :: Bool Indicates an "alternate format". See `printf(3)` for the details, which vary by argument spec. fmtModifiers :: String Characters that appeared immediately to the left of `fmtChar` in the format and were accepted by the type's `parseFormat`. Normally the empty string. fmtChar :: Char The format character `printf` was invoked with. `formatArg` should fail unless this character matches the type. It is normal to handle many different format characters for a single type.

data FormatSign #

How to handle the sign of a numeric field. These are mutually exclusive, with `SignPlus` taking precedence.

Since: base-4.7.0.0

Constructors

SignPlus |
SignSpace |

data FormatAdjustment #

Whether to left-adjust or zero-pad a field. These are mutually exclusive, with `LeftAdjust` taking precedence.

Since: base-4.7.0.0

Constructors

LeftAdjust |
ZeroPad |

class IsChar c where #

This class, with only the one instance, is used as a workaround for the fact that `String`, as a concrete type, is not allowable as a typeclass instance. `IsChar` is exported for backward-compatibility.

Methods

toChar :: c -> Char #

Since: base-4.7.0.0

fromChar :: Char -> c #

Since: base-4.7.0.0

#### Instances

Instances details

IsChar Char | Since: base-2.1
Instance details Defined in Text.Printf Methods toChar :: Char -> Char # fromChar :: Char -> Char #

class PrintfArg a where #

Typeclass of `printf`-formattable values. The `formatArg` method takes a value and a field format descriptor and either fails due to a bad descriptor or produces a `ShowS` as the result. The default `parseFormat` expects no modifiers: this is the normal case. Minimal instance: `formatArg`.

Minimal complete definition

formatArg

Methods

formatArg :: a -> FieldFormatter #

Since: base-4.7.0.0

parseFormat :: a -> ModifierParser #

Since: base-4.7.0.0

#### Instances

Instances details

PrintfArg Int16 | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Int16 -> FieldFormatter # parseFormat :: Int16 -> ModifierParser #
PrintfArg Int32 | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Int32 -> FieldFormatter # parseFormat :: Int32 -> ModifierParser #
PrintfArg Int64 | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Int64 -> FieldFormatter # parseFormat :: Int64 -> ModifierParser #
PrintfArg Int8 | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Int8 -> FieldFormatter # parseFormat :: Int8 -> ModifierParser #
PrintfArg Word16 | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Word16 -> FieldFormatter # parseFormat :: Word16 -> ModifierParser #
PrintfArg Word32 | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Word32 -> FieldFormatter # parseFormat :: Word32 -> ModifierParser #
PrintfArg Word64 | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Word64 -> FieldFormatter # parseFormat :: Word64 -> ModifierParser #
PrintfArg Word8 | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Word8 -> FieldFormatter # parseFormat :: Word8 -> ModifierParser #
PrintfArg ShortText | Since: text-short-0.1.2
Instance details Defined in Data.Text.Short.Internal Methods formatArg :: ShortText -> FieldFormatter # parseFormat :: ShortText -> ModifierParser #
PrintfArg Integer | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Integer -> FieldFormatter # parseFormat :: Integer -> ModifierParser #
PrintfArg Natural | Since: base-4.8.0.0
Instance details Defined in Text.Printf Methods formatArg :: Natural -> FieldFormatter # parseFormat :: Natural -> ModifierParser #
PrintfArg Char | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Char -> FieldFormatter # parseFormat :: Char -> ModifierParser #
PrintfArg Double | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Double -> FieldFormatter # parseFormat :: Double -> ModifierParser #
PrintfArg Float | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Float -> FieldFormatter # parseFormat :: Float -> ModifierParser #
PrintfArg Int | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Int -> FieldFormatter # parseFormat :: Int -> ModifierParser #
PrintfArg Word | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: Word -> FieldFormatter # parseFormat :: Word -> ModifierParser #
IsChar c => PrintfArg [c] | Since: base-2.1
Instance details Defined in Text.Printf Methods formatArg :: [c] -> FieldFormatter # parseFormat :: [c] -> ModifierParser #

class HPrintfType t #

The `HPrintfType` class provides the variable argument magic for `hPrintf`. Its implementation is intentionally not visible from this module.

Minimal complete definition

hspr

#### Instances

Instances details

a ~ () => HPrintfType (IO a) | Since: base-4.7.0.0
Instance details Defined in Text.Printf Methods hspr :: Handle -> String -> [UPrintf] -> IO a
(PrintfArg a, HPrintfType r) => HPrintfType (a -> r) | Since: base-2.1
Instance details Defined in Text.Printf Methods hspr :: Handle -> String -> [UPrintf] -> a -> r

class PrintfType t #

The `PrintfType` class provides the variable argument magic for `printf`. Its implementation is intentionally not visible from this module. If you attempt to pass an argument of a type which is not an instance of this class to `printf` or `hPrintf`, then the compiler will report it as a missing instance of `PrintfArg`.

Minimal complete definition

spr

#### Instances

Instances details

a ~ () => PrintfType (IO a) | Since: base-4.7.0.0
Instance details Defined in Text.Printf Methods spr :: String -> [UPrintf] -> IO a
IsChar c => PrintfType [c] | Since: base-2.1
Instance details Defined in Text.Printf Methods spr :: String -> [UPrintf] -> [c]
(PrintfArg a, PrintfType r) => PrintfType (a -> r) | Since: base-2.1
Instance details Defined in Text.Printf Methods spr :: String -> [UPrintf] -> a -> r

printf :: PrintfType r => String -> r #

Format a variable number of arguments with the C-style formatting string.

    >>> printf "%s, %d, %.4f" "hello" 123 pi
    hello, 123, 3.1416

The return value is either `String` or `(`IO` a)` (which should be `(`IO` ())`, but Haskell's type system makes this hard).

The format string consists of ordinary characters and conversion specifications, which specify how to format one of the arguments to `printf` in the output string. A format specification is introduced by the `%` character; this character can be self-escaped into the format string using `%%`. A format specification ends with a format character that provides the primary information about how to format the value. The rest of the conversion specification is optional. In order, one may have flag characters, a width specifier, a precision specifier, and type-specific modifier characters.

Unlike C `printf(3)`, the formatting of this `printf` is driven by the argument type; formatting is type specific. The types formatted by `printf` "out of the box" are:

- `Integral` types, including `Char`
- `String`
- `RealFloat` types

`printf` is also extensible to support other types: see below.

A conversion specification begins with the character `%`, followed by zero or more of the following flags:

    -      left adjust (default is right adjust)
    +      always use a sign (+ or -) for signed conversions
    space  leading space for positive numbers in signed conversions
    0      pad with zeros rather than spaces
    #      use an \"alternate form\": see below

When both flags are given, `-` overrides `0` and `+` overrides space. A negative width specifier in a `*` conversion is treated as positive but implies the left adjust flag.

The "alternate form" for unsigned radix conversions is as in C `printf(3)`:

    %o           prefix with a leading 0 if needed
    %x           prefix with a leading 0x if nonzero
    %X           prefix with a leading 0X if nonzero
    %b           prefix with a leading 0b if nonzero
    %[eEfFgG]    ensure that the number contains a decimal point

Any flags are followed optionally by a field width:

    num    field width
    *      as num, but taken from argument list

The field width is a minimum, not a maximum: it will be expanded as needed to avoid mutilating a value.

Any field width is followed optionally by a precision:

    .num   precision
    .      same as .0
    .*     as num, but taken from argument list

Negative precision is taken as 0. The meaning of the precision depends on the conversion type.

    Integral    minimum number of digits to show
    RealFloat   number of digits after the decimal point
    String      maximum number of characters

The precision for Integral types is accomplished by zero-padding. If both precision and zero-pad are given for an Integral field, the zero-pad is ignored.

Any precision is followed optionally for Integral types by a width modifier; the only use of this modifier being to set the implicit size of the operand for conversion of a negative operand to unsigned:

    hh     Int8
    h      Int16
    l      Int32
    ll     Int64
    L      Int64

The specification ends with a format character:

    c      character               Integral
    d      decimal                 Integral
    o      octal                   Integral
    x      hexadecimal             Integral
    X      hexadecimal             Integral
    b      binary                  Integral
    u      unsigned decimal        Integral
    f      floating point          RealFloat
    F      floating point          RealFloat
    g      general format float    RealFloat
    G      general format float    RealFloat
    e      exponent format float   RealFloat
    E      exponent format float   RealFloat
    s      string                  String
    v      default format          any type

The "%v" specifier is provided for all built-in types, and should be provided for user-defined type formatters as well. It picks a "best" representation for the given type. For the built-in types the "%v" specifier is converted as follows:

    c      Char
    u      other unsigned Integral
    d      other signed Integral
    g      RealFloat
    s      String

Mismatch between the argument types and the format string, as well as any other syntactic or semantic errors in the format string, will cause an exception to be thrown at runtime.

Note that the formatting for `RealFloat` types is currently a bit different from that of C `printf(3)`, conforming instead to `showEFloat`, `showFFloat` and `showGFloat` (and their alternate versions `showFFloatAlt` and `showGFloatAlt`). This is hard to fix: the fixed versions would format in a backward-incompatible way. In any case the Haskell behavior is generally more sensible than the C behavior. A brief summary of some key differences:

- Haskell `printf` never uses the default "6-digit" precision used by C printf.
- Haskell `printf` treats the "precision" specifier as indicating the number of digits after the decimal point.
- Haskell `printf` prints the exponent of e-format numbers without a gratuitous plus sign, and with the minimum possible number of digits.
- Haskell `printf` will place a zero after a decimal point when possible.

hPrintf :: HPrintfType r => Handle -> String -> r #

Similar to `printf`, except that output is via the specified `Handle`. The return type is restricted to `(`IO` a)`.

vFmt :: Char -> FieldFormat -> FieldFormat #

Substitute a 'v' format character with the given default format character in the `FieldFormat`. A convenience for user-implemented types, which should support "%v".

Since: base-4.7.0.0

formatChar :: Char -> FieldFormatter #

Formatter for `Char` values.

Since: base-4.7.0.0

formatInt :: (Integral a, Bounded a) => a -> FieldFormatter #

Formatter for `Int` values.

Since: base-4.7.0.0

formatInteger :: Integer -> FieldFormatter #

Formatter for `Integer` values.

Since: base-4.7.0.0

perror :: String -> a #

Raises an `error` with a printf-specific prefix on the message string.

Since: base-4.7.0.0

errorBadFormat :: Char -> a #

Calls `perror` to indicate an unknown format letter for a given type.

Since: base-4.7.0.0

errorShortFormat :: a #

Calls `perror` to indicate that the format string ended early.

Since: base-4.7.0.0

errorMissingArgument :: a #

Calls `perror` to indicate that there is a missing argument in the argument list.

Since: base-4.7.0.0

errorBadArgument :: a #

Calls `perror` to indicate that there is a type error or similar in the given argument.

Since: base-4.7.0.0

pack :: String -> Text #

O(n) Convert a `String` into a `Text`. Performs replacement on invalid scalar values, so ``unpack` . `pack`` is not `id`:

    >>> Data.Text.unpack (pack "\55555")
    "\65533"

unpack :: Text -> String #

O(n) Convert a `Text` into a `String`.

searchPathSeparator :: Char #

The character that is used to separate the entries in the $PATH environment variable.

    Windows: searchPathSeparator == ';'
    Posix:   searchPathSeparator == ':'

normalise :: FilePath -> FilePath #

Normalise a file

- // outside of the drive can be made blank
- / -> `pathSeparator`
- ./ -> ""

Does not remove `".."`, because of symlinks.

    Posix:   normalise "/file/\\test////" == "/file/\\test/"
    Posix:   normalise "/file/./test" == "/file/test"
    Posix:   normalise "/test/file/../bob/fred/" == "/test/file/../bob/fred/"
    Posix:   normalise "../bob/fred/" == "../bob/fred/"
    Posix:   normalise "/a/../c" == "/a/../c"
    Posix:   normalise "./bob/fred/" == "bob/fred/"
    Windows: normalise "c:\\file/bob\\" == "C:\\file\\bob\\"
    Windows: normalise "c:\\" == "C:\\"
    Windows: normalise "c:\\\\\\\\" == "C:\\"
    Windows: normalise "C:.\\" == "C:"
    Windows: normalise "\\\\server\\test" == "\\\\server\\test"
    Windows: normalise "//server/test" == "\\\\server\\test"
    Windows: normalise "c:/file" == "C:\\file"
    Windows: normalise "/file" == "\\file"
    Windows: normalise "\\" == "\\"
    Windows: normalise "/./" == "\\"
             normalise "." == "."
    Posix:   normalise "./" == "./"
    Posix:   normalise "./." == "./"
    Posix:   normalise "/./" == "/"
    Posix:   normalise "/" == "/"
    Posix:   normalise "bob/fred/." == "bob/fred/"
    Posix:   normalise "//home" == "/home"

dropTrailingPathSeparator :: FilePath -> FilePath #

Remove any trailing path separators

    dropTrailingPathSeparator "file/test/" == "file/test"
              dropTrailingPathSeparator "/" == "/"
    Windows:  dropTrailingPathSeparator "\\" == "\\"
    Posix:    not (hasTrailingPathSeparator (dropTrailingPathSeparator x)) || isDrive x

makeRelative :: FilePath -> FilePath -> FilePath #

Contract a filename, based on a relative path. Note that the resulting path will never introduce `..` paths, as the presence of symlinks means `../b` may not reach `a/b` if it starts from `a/c`. For a worked example see this blog post.

The corresponding `makeAbsolute` function can be found in `System.Directory`.

             makeRelative "/directory" "/directory/file.ext" == "file.ext"
             Valid x => makeRelative (takeDirectory x) x `equalFilePath` takeFileName x
             makeRelative x x == "."
             Valid x y => equalFilePath x y || (isRelative x && makeRelative y x == x) || equalFilePath (y </> makeRelative y x) x
    Windows: makeRelative "C:\\Home" "c:\\home\\bob" == "bob"
    Windows: makeRelative "C:\\Home" "c:/home/bob" == "bob"
    Windows: makeRelative "C:\\Home" "D:\\Home\\Bob" == "D:\\Home\\Bob"
    Windows: makeRelative "C:\\Home" "C:Home\\Bob" == "C:Home\\Bob"
    Windows: makeRelative "/Home" "/home/bob" == "bob"
    Windows: makeRelative "/" "//" == "//"
    Posix:   makeRelative "/Home" "/home/bob" == "/home/bob"
    Posix:   makeRelative "/home/" "/home/bob/foo/bar" == "bob/foo/bar"
    Posix:   makeRelative "/fred" "bob" == "bob"
    Posix:   makeRelative "/file/test" "/file/test/fred" == "fred"
    Posix:   makeRelative "/file/test" "/file/test/fred/" == "fred/"
    Posix:   makeRelative "some/path" "some/path/a/b/c" == "a/b/c"

(</>) :: FilePath -> FilePath -> FilePath infixr 5 #

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"

headDef :: a -> [a] -> a #

lastDef :: a -> [a] -> a #

pathSeparator :: Char #

The character that separates directories. In the case where more than one character is possible, `pathSeparator` is the 'ideal' one.

    Windows: pathSeparator == '\\'
    Posix:   pathSeparator ==  '/'
    isPathSeparator pathSeparator

pathSeparators :: [Char] #

The list of all possible separators.

    Windows: pathSeparators == ['\\', '/']
    Posix:   pathSeparators == ['/']
    pathSeparator `elem` pathSeparators

isPathSeparator :: Char -> Bool #

Rather than using `(== `pathSeparator`)`, use this. Test if something is a path separator.

    isPathSeparator a == (a `elem` pathSeparators)

isSearchPathSeparator :: Char -> Bool #

Is the character a file separator?

    isSearchPathSeparator a == (a == searchPathSeparator)

extSeparator :: Char #

File extension character

    extSeparator == '.'

isExtSeparator :: Char -> Bool #

Is the character an extension character?

    isExtSeparator a == (a == extSeparator)

splitSearchPath :: String -> [FilePath] #

Take a string, split it on the `searchPathSeparator` character. Blank items are ignored on Windows, and converted to `.` on Posix. On Windows path elements are stripped of quotes.

Follows the recommendations in http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html

    Posix:   splitSearchPath "File1:File2:File3"  == ["File1","File2","File3"]
    Posix:   splitSearchPath "File1::File2:File3" == ["File1",".","File2","File3"]
    Windows: splitSearchPath "File1;File2;File3"  == ["File1","File2","File3"]
    Windows: splitSearchPath "File1;;File2;File3" == ["File1","File2","File3"]
    Windows: splitSearchPath "File1;\"File2\";File3" == ["File1","File2","File3"]

getSearchPath :: IO [FilePath] #

Get a list of `FILEPATH`s in the $PATH variable.

splitExtension :: FilePath -> (String, String) #

Split on the extension. `addExtension` is the inverse.

    splitExtension "/directory/path.ext" == ("/directory/path",".ext")
    uncurry (<>) (splitExtension x) == x
    Valid x => uncurry addExtension (splitExtension x) == x
    splitExtension "file.txt" == ("file",".txt")
    splitExtension "file" == ("file","")
    splitExtension "file/file.txt" == ("file/file",".txt")
    splitExtension "file.txt/boris" == ("file.txt/boris","")
    splitExtension "file.txt/boris.ext" == ("file.txt/boris",".ext")
    splitExtension "file/path.txt.bob.fred" == ("file/path.txt.bob",".fred")
    splitExtension "file/path.txt/" == ("file/path.txt/","")

takeExtension :: FilePath -> String #

Get the extension of a file, returns `""` for no extension, `.ext` otherwise.

    takeExtension "/directory/path.ext" == ".ext"
    takeExtension x == snd (splitExtension x)
    Valid x => takeExtension (addExtension x "ext") == ".ext"
    Valid x => takeExtension (replaceExtension x "ext") == ".ext"

(-<.>) :: FilePath -> String -> FilePath infixr 7 #

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"

replaceExtension :: FilePath -> String -> FilePath #

Set the extension of a file, overwriting one if already present, equivalent to `-<.>`.

    replaceExtension "/directory/path.txt" "ext" == "/directory/path.ext"
    replaceExtension "/directory/path.txt" ".ext" == "/directory/path.ext"
    replaceExtension "file.txt" ".bob" == "file.bob"
    replaceExtension "file.txt" "bob" == "file.bob"
    replaceExtension "file" ".bob" == "file.bob"
    replaceExtension "file.txt" "" == "file"
    replaceExtension "file.fred.bob" "txt" == "file.fred.txt"
    replaceExtension x y == addExtension (dropExtension x) y

(<.>) :: FilePath -> String -> FilePath infixr 7 #

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"

dropExtension :: FilePath -> FilePath #

Remove last extension, and the "." preceding it.

    dropExtension "/directory/path.ext" == "/directory/path"
    dropExtension x == fst (splitExtension x)

addExtension :: FilePath -> String -> FilePath #

Add an extension, even if there is already one there, equivalent to `<.>`.

    addExtension "/directory/path" "ext" == "/directory/path.ext"
    addExtension "file.txt" "bib" == "file.txt.bib"
    addExtension "file." ".bib" == "file..bib"
    addExtension "file" ".bib" == "file.bib"
    addExtension "/" "x" == "/.x"
    addExtension x "" == x
    Valid x => takeFileName (addExtension (addTrailingPathSeparator x) "ext") == ".ext"
    Windows: addExtension "\\\\share" ".txt" == "\\\\share\\.txt"

hasExtension :: FilePath -> Bool #

Does the given filename have an extension?

    hasExtension "/directory/path.ext" == True
    hasExtension "/directory/path" == False
    null (takeExtension x) == not (hasExtension x)

isExtensionOf :: String -> FilePath -> Bool #

Does the given filename have the specified extension?

    "png" `isExtensionOf` "/directory/file.png" == True
    ".png" `isExtensionOf` "/directory/file.png" == True
    ".tar.gz" `isExtensionOf` "bar/foo.tar.gz" == True
    "ar.gz" `isExtensionOf` "bar/foo.tar.gz" == False
    "png" `isExtensionOf` "/directory/file.png.jpg" == False
    "csv/table.csv" `isExtensionOf` "/data/csv/table.csv" == False

stripExtension :: String -> FilePath -> Maybe FilePath #

Drop the given extension from a FilePath, and the `"."` preceding it. Returns `Nothing` if the FilePath does not have the given extension, or `Just` and the part before the extension if it does.

This function can be more predictable than `dropExtensions`, especially if the filename might itself contain `.` characters.

    stripExtension "hs.o" "foo.x.hs.o" == Just "foo.x"
    stripExtension "hi.o" "foo.x.hs.o" == Nothing
    dropExtension x == fromJust (stripExtension (takeExtension x) x)
    dropExtensions x == fromJust (stripExtension (takeExtensions x) x)
    stripExtension ".c.d" "a.b.c.d"  == Just "a.b"
    stripExtension ".c.d" "a.b..c.d" == Just "a.b."
    stripExtension "baz"  "foo.bar"  == Nothing
    stripExtension "bar"  "foobar"   == Nothing
    stripExtension ""     x          == Just x

splitExtensions :: FilePath -> (FilePath, String) #

Split on all extensions.

    splitExtensions "/directory/path.ext" == ("/directory/path",".ext")
    splitExtensions "file.tar.gz" == ("file",".tar.gz")
    uncurry (<>) (splitExtensions x) == x
    Valid x => uncurry addExtension (splitExtensions x) == x
    splitExtensions "file.tar.gz" == ("file",".tar.gz")

dropExtensions :: FilePath -> FilePath #

Drop all extensions.

    dropExtensions "/directory/path.ext" == "/directory/path"
    dropExtensions "file.tar.gz" == "file"
    not $ hasExtension $ dropExtensions x
    not $ any isExtSeparator $ takeFileName $ dropExtensions x

takeExtensions :: FilePath -> String #

Get all extensions.

    takeExtensions "/directory/path.ext" == ".ext"
    takeExtensions "file.tar.gz" == ".tar.gz"

replaceExtensions :: FilePath -> String -> FilePath #

Replace all extensions of a file with a new extension. Note that `replaceExtension` and `addExtension` both work for adding multiple extensions, so only required when you need to drop all extensions first.

    replaceExtensions "file.fred.bob" "txt" == "file.txt"
    replaceExtensions "file.fred.bob" "tar.gz" == "file.tar.gz"

splitDrive :: FilePath -> (FilePath, FilePath) #

Split a path into a drive and a path. On Posix, / is a Drive.

    uncurry (<>) (splitDrive x) == x
    Windows: splitDrive "file" == ("","file")
    Windows: splitDrive "c:/file" == ("c:/","file")
    Windows: splitDrive "c:\\file" == ("c:\\","file")
    Windows: splitDrive "\\\\shared\\test" == ("\\\\shared\\","test")
    Windows: splitDrive "\\\\shared" == ("\\\\shared","")
    Windows: splitDrive "\\\\?\\UNC\\shared\\file" == ("\\\\?\\UNC\\shared\\","file")
    Windows: splitDrive "\\\\?\\UNCshared\\file" == ("\\\\?\\","UNCshared\\file")
    Windows: splitDrive "\\\\?\\d:\\file" == ("\\\\?\\d:\\","file")
    Windows: splitDrive "/d" == ("","/d")
    Posix:   splitDrive "/test" == ("/","test")
    Posix:   splitDrive "//test" == ("//","test")
    Posix:   splitDrive "test/file" == ("","test/file")
    Posix:   splitDrive "file" == ("","file")

joinDrive :: FilePath -> FilePath -> FilePath #

Join a drive and the rest of the path.

    Valid x => uncurry joinDrive (splitDrive x) == x
    Windows: joinDrive "C:" "foo" == "C:foo"
    Windows: joinDrive "C:\\" "bar" == "C:\\bar"
    Windows: joinDrive "\\\\share" "foo" == "\\\\share\\foo"
    Windows: joinDrive "/:" "foo" == "/:\\foo"

takeDrive :: FilePath -> FilePath #

Get the drive from a filepath.

    takeDrive x == fst (splitDrive x)

dropDrive :: FilePath -> FilePath #

Delete the drive, if it exists.

    dropDrive x == snd (splitDrive x)

hasDrive :: FilePath -> Bool #

Does a path have a drive.

    not (hasDrive x) == null (takeDrive x)
    Posix:   hasDrive "/foo" == True
    Windows: hasDrive "C:\\foo" == True
    Windows: hasDrive "C:foo" == True
             hasDrive "foo" == False
             hasDrive "" == False

isDrive :: FilePath -> Bool #

Is an element a drive

    Posix:   isDrive "/" == True
    Posix:   isDrive "/foo" == False
    Windows: isDrive "C:\\" == True
    Windows: isDrive "C:\\foo" == False
             isDrive "" == False

splitFileName :: FilePath -> (String, String) #

Split a filename into directory and file. `</>` is the inverse. The first component will often end with a trailing slash.

    splitFileName "/directory/file.ext" == ("/directory/","file.ext")
    Valid x => uncurry (</>) (splitFileName x) == x || fst (splitFileName x) == "./"
    Valid x => isValid (fst (splitFileName x))
    splitFileName "file/bob.txt" == ("file/", "bob.txt")
    splitFileName "file/" == ("file/", "")
    splitFileName "bob" == ("./", "bob")
    Posix:   splitFileName "/" == ("/","")
    Windows: splitFileName "c:" == ("c:","")
    Windows: splitFileName "\\\\?\\A:\\fred" == ("\\\\?\\A:\\","fred")
    Windows: splitFileName "\\\\?\\A:" == ("\\\\?\\A:","")

replaceFileName :: FilePath -> String -> FilePath #

Set the filename.

    replaceFileName "/directory/other.txt" "file.ext" == "/directory/file.ext"
    Valid x => replaceFileName x (takeFileName x) == x

dropFileName :: FilePath -> FilePath #

Drop the filename. Unlike `takeDirectory`, this function will leave a trailing path separator on the directory.

    dropFileName "/directory/file.ext" == "/directory/"
    dropFileName x == fst (splitFileName x)
    isPrefixOf (takeDrive x) (dropFileName x)

takeFileName :: FilePath -> FilePath #

Get the file name.

    takeFileName "/directory/file.ext" == "file.ext"
    takeFileName "test/" == ""
    isSuffixOf (takeFileName x) x
    takeFileName x == snd (splitFileName x)
    Valid x => takeFileName (replaceFileName x "fred") == "fred"
    Valid x => takeFileName (x </> "fred") == "fred"
    Valid x => isRelative (takeFileName x)

takeBaseName :: FilePath -> String #

Get the base name, without an extension or path.

    takeBaseName "/directory/file.ext" == "file"
    takeBaseName "file/test.txt" == "test"
    takeBaseName "dave.ext" == "dave"
    takeBaseName "" == ""
    takeBaseName "test" == "test"
    takeBaseName (addTrailingPathSeparator x) == ""
    takeBaseName "file/file.tar.gz" == "file.tar"

replaceBaseName :: FilePath -> String -> FilePath #

Set the base name.

    replaceBaseName "/directory/other.ext" "file" == "/directory/file.ext"
    replaceBaseName "file/test.txt" "bob" == "file/bob.txt"
    replaceBaseName "fred" "bill" == "bill"
    replaceBaseName "/dave/fred/bob.gz.tar" "new" == "/dave/fred/new.tar"
    Valid x => replaceBaseName x (takeBaseName x) == x

hasTrailingPathSeparator :: FilePath -> Bool #

Is an item either a directory or the last character a path separator?

    hasTrailingPathSeparator "test" == False
    hasTrailingPathSeparator "test/" == True

addTrailingPathSeparator :: FilePath -> FilePath #

Add a trailing file path separator if one is not already present.

    hasTrailingPathSeparator (addTrailingPathSeparator x)
    hasTrailingPathSeparator x ==> addTrailingPathSeparator x == x
    Posix:    addTrailingPathSeparator "test/rest" == "test/rest/"

takeDirectory :: FilePath -> FilePath #

Get the directory name, move up one level.

              takeDirectory "/directory/other.ext" == "/directory"
              isPrefixOf (takeDirectory x) x || takeDirectory x == "."
              takeDirectory "foo" == "."
              takeDirectory "/" == "/"
              takeDirectory "/foo" == "/"
              takeDirectory "/foo/bar/baz" == "/foo/bar"
              takeDirectory "/foo/bar/baz/" == "/foo/bar/baz"
              takeDirectory "foo/bar/baz" == "foo/bar"
    Windows:  takeDirectory "foo\\bar" == "foo"
    Windows:  takeDirectory "foo\\bar\\\\" == "foo\\bar"
    Windows:  takeDirectory "C:\\" == "C:\\"

replaceDirectory :: FilePath -> String -> FilePath #

Set the directory, keeping the filename the same.

    replaceDirectory "root/file.ext" "/directory/" == "/directory/file.ext"
    Valid x => replaceDirectory x (takeDirectory x) `equalFilePath` x

combine :: FilePath -> FilePath -> FilePath #

An alias for `</>`.

splitPath :: FilePath -> [FilePath] #

Split a path by the directory separator.

    splitPath "/directory/file.ext" == ["/","directory/","file.ext"]
    concat (splitPath x) == x
    splitPath "test//item/" == ["test//","item/"]
    splitPath "test/item/file" == ["test/","item/","file"]
    splitPath "" == []
    Windows: splitPath "c:\\test\\path" == ["c:\\","test\\","path"]
    Posix:   splitPath "/file/test" == ["/","file/","test"]

splitDirectories :: FilePath -> [FilePath] #

Just as `splitPath`, but don't add the trailing slashes to each element.

             splitDirectories "/directory/file.ext" == ["/","directory","file.ext"]
             splitDirectories "test/file" == ["test","file"]
             splitDirectories "/test/file" == ["/","test","file"]
    Windows: splitDirectories "C:\\test\\file" == ["C:\\", "test", "file"]
             Valid x => joinPath (splitDirectories x) `equalFilePath` x
             splitDirectories "" == []
    Windows: splitDirectories "C:\\test\\\\\\file" == ["C:\\", "test", "file"]
             splitDirectories "/test///file" == ["/","test","file"]

joinPath :: [FilePath] -> FilePath #

Join path elements back together.

    joinPath z == foldr (</>) "" z
    joinPath ["/","directory/","file.ext"] == "/directory/file.ext"
    Valid x => joinPath (splitPath x) == x
    joinPath [] == ""
    Posix: joinPath ["test","file","path"] == "test/file/path"

equalFilePath :: FilePath -> FilePath -> Bool #

Equality of two `FILEPATH`s. If you call `System.Directory.canonicalizePath` first this has a much better chance of working. Note that this doesn't follow symlinks or DOSNAM~1s.

Similar to `normalise`, this does not expand `".."`, because of symlinks.

             x == y ==> equalFilePath x y
             normalise x == normalise y ==> equalFilePath x y
             equalFilePath "foo" "foo/"
             not (equalFilePath "/a/../c" "/c")
             not (equalFilePath "foo" "/foo")
    Posix:   not (equalFilePath "foo" "FOO")
    Windows: equalFilePath "foo" "FOO"
    Windows: not (equalFilePath "C:" "C:/")

isValid :: FilePath -> Bool #

Is a FilePath valid, i.e. could you create a file like it? This function checks for invalid names, and invalid characters, but does not check if length limits are exceeded, as these are typically filesystem dependent.

             isValid "" == False
             isValid "\0" == False
    Posix:   isValid "/random_ path:*" == True
    Posix:   isValid x == not (null x)
    Windows: isValid "c:\\test" == True
    Windows: isValid "c:\\test:of_test" == False
    Windows: isValid "test*" == False
    Windows: isValid "c:\\test\\nul" == False
    Windows: isValid "c:\\test\\prn.txt" == False
    Windows: isValid "c:\\nul\\file" == False
    Windows: isValid "\\\\" == False
    Windows: isValid "\\\\\\foo" == False
    Windows: isValid "\\\\?\\D:file" == False
    Windows: isValid "foo\tbar" == False
    Windows: isValid "nul .txt" == False
    Windows: isValid " nul.txt" == True

makeValid :: FilePath -> FilePath #

Take a FilePath and make it valid; does not change already valid FILEPATHs.

    isValid (makeValid x)
    isValid x ==> makeValid x == x
    makeValid "" == "_"
    makeValid "file\0name" == "file_name"
    Windows: makeValid "c:\\already\\/valid" == "c:\\already\\/valid"
    Windows: makeValid "c:\\test:of_test" == "c:\\test_of_test"
    Windows: makeValid "test*" == "test_"
    Windows: makeValid "c:\\test\\nul" == "c:\\test\\nul_"
    Windows: makeValid "c:\\test\\prn.txt" == "c:\\test\\prn_.txt"
    Windows: makeValid "c:\\test/prn.txt" == "c:\\test/prn_.txt"
    Windows: makeValid "c:\\nul\\file" == "c:\\nul_\\file"
    Windows: makeValid "\\\\\\foo" == "\\\\drive"
    Windows: makeValid "\\\\?\\D:file" == "\\\\?\\D:\\file"
    Windows: makeValid "nul .txt" == "nul _.txt"

isRelative :: FilePath -> Bool #

Is a path relative, or is it fixed to the root?

    Windows: isRelative "path\\test" == True
    Windows: isRelative "c:\\test" == False
    Windows: isRelative "c:test" == True
    Windows: isRelative "c:\\" == False
    Windows: isRelative "c:/" == False
    Windows: isRelative "c:" == True
    Windows: isRelative "\\\\foo" == False
    Windows: isRelative "\\\\?\\foo" == False
    Windows: isRelative "\\\\?\\UNC\\foo" == False
    Windows: isRelative "/foo" == True
    Windows: isRelative "\\foo" == True
    Posix:   isRelative "test/path" == True
    Posix:   isRelative "/test" == False
    Posix:   isRelative "/" == False

According to [1]:

- "A UNC name of any format [is never relative]."
- "You cannot use the "\?" prefix with a relative path."

isAbsolute :: FilePath -> Bool #

    not . isRelative

    isAbsolute x == not (isRelative x)

foldl1May :: (a -> a -> a) -> [a] -> Maybe a #

foldr1May :: (a -> a -> a) -> [a] -> Maybe a #

foldl1Note :: Partial => String -> (a -> a -> a) -> [a] -> a #

foldr1Note :: Partial => String -> (a -> a -> a) -> [a] -> a #

minimumMay :: Ord a => [a] -> Maybe a #

maximumMay :: Ord a => [a] -> Maybe a #

minimumNote :: (Partial, Ord a) => String -> [a] -> a #

maximumNote :: (Partial, Ord a) => String -> [a] -> a #

minimumByMay :: (a -> a -> Ordering) -> [a] -> Maybe a #

maximumByMay :: (a -> a -> Ordering) -> [a] -> Maybe a #

minimumByNote :: Partial => String -> (a -> a -> Ordering) -> [a] -> a #

maximumByNote :: Partial => String -> (a -> a -> Ordering) -> [a] -> a #

maximumBoundBy :: a -> (a -> a -> Ordering) -> [a] -> a #

The largest element of a list with respect to the given comparison function. The result is bounded by the value given as the first argument.

minimumBoundBy :: a -> (a -> a -> Ordering) -> [a] -> a #

The smallest element of a list with respect to the given comparison function. The result is bounded by the value given as the first argument.

maximumBound :: Ord a => a -> [a] -> a #

The largest element of a list. The result is bounded by the value given as the first argument.

minimumBound :: Ord a => a -> [a] -> a #

The smallest element of a list. The result is bounded by the value given as the first argument.

maximumBounded :: (Ord a, Bounded a) => [a] -> a #

The largest element of a list. The result is bounded by `minBound`.

minimumBounded :: (Ord a, Bounded a) => [a] -> a #

The largest element of a list. The result is bounded by `maxBound`.

findJust :: (a -> Bool) -> [a] -> a #

    findJust op = fromJust . find op

findJustDef :: a -> (a -> Bool) -> [a] -> a #

findJustNote :: Partial => String -> (a -> Bool) -> [a] -> a #

minimumDef :: Ord a => a -> [a] -> a #

New users are recommended to use `minimumBound` or `maximumBound` instead.

maximumDef :: Ord a => a -> [a] -> a #

New users are recommended to use `minimumBound` or `maximumBound` instead.

minimumByDef :: a -> (a -> a -> Ordering) -> [a] -> a #

New users are recommended to use `minimumBoundBy` or `maximumBoundBy` instead.

maximumByDef :: a -> (a -> a -> Ordering) -> [a] -> a #

New users are recommended to use `minimumBoundBy` or `maximumBoundBy` instead.

foldl1Def :: a -> (a -> a -> a) -> [a] -> a #

foldr1Def :: a -> (a -> a -> a) -> [a] -> a #

tailErr :: Partial => [a] -> [a] #

Identical to `tail`, namely that fails on an empty list. Useful to avoid the `x-partial` warning introduced in GHC 9.8.

    tailErr [] = error "Prelude.tail: empty list"
    tailErr [1,2,3] = [2,3]

headErr :: Partial => [a] -> a #

Identical to `head`, namely that fails on an empty list. Useful to avoid the `x-partial` warning introduced in GHC 9.8.

    headErr [] = error "Prelude.head: empty list"
    headErr [1,2,3] = 1

tailMay :: [a] -> Maybe [a] #

    tailMay [] = Nothing
    tailMay [1,3,4] = Just [3,4]

tailDef :: [a] -> [a] -> [a] #

    tailDef [12] [] = [12]
    tailDef [12] [1,3,4] = [3,4]

tailNote :: Partial => String -> [a] -> [a] #

    tailNote "help me" [] = error "Safe.tailNote [], help me"
    tailNote "help me" [1,3,4] = [3,4]

tailSafe :: [a] -> [a] #

    tailSafe [] = []
    tailSafe [1,3,4] = [3,4]

initMay :: [a] -> Maybe [a] #

initDef :: [a] -> [a] -> [a] #

initNote :: Partial => String -> [a] -> [a] #

initSafe :: [a] -> [a] #

headMay :: [a] -> Maybe a #

lastMay :: [a] -> Maybe a #

headNote :: Partial => String -> [a] -> a #

lastNote :: Partial => String -> [a] -> a #

foldl1May' :: (a -> a -> a) -> [a] -> Maybe a #

foldl1Note' :: Partial => String -> (a -> a -> a) -> [a] -> a #

scanr1May :: (a -> a -> a) -> [a] -> Maybe [a] #

scanl1May :: (a -> a -> a) -> [a] -> Maybe [a] #

scanr1Def :: [a] -> (a -> a -> a) -> [a] -> [a] #

scanl1Def :: [a] -> (a -> a -> a) -> [a] -> [a] #

scanr1Note :: Partial => String -> (a -> a -> a) -> [a] -> [a] #

scanl1Note :: Partial => String -> (a -> a -> a) -> [a] -> [a] #

cycleMay :: [a] -> Maybe [a] #

cycleDef :: [a] -> [a] -> [a] #

cycleNote :: Partial => String -> [a] -> [a] #

fromJustDef :: a -> Maybe a -> a #

An alternative name for `fromMaybe`, to fit the naming scheme of this package. Generally using `fromMaybe` directly would be considered better style.

fromJustNote :: Partial => String -> Maybe a -> a #

assertNote :: Partial => String -> Bool -> a -> a #

atMay :: [a] -> Int -> Maybe a #

atDef :: a -> [a] -> Int -> a #

atNote :: Partial => String -> [a] -> Int -> a #

readEitherSafe :: Read a => String -> Either String a #

This function provides a more precise error message than `readEither` from `base`.

readMay :: Read a => String -> Maybe a #

readDef :: Read a => a -> String -> a #

readNote :: (Partial, Read a) => String -> String -> a #

`readNote` uses `readEitherSafe` for the error message.

lookupJust :: (Eq a, Partial) => a -> [(a, b)] -> b #

    lookupJust key = fromJust . lookup key

lookupJustDef :: Eq a => b -> a -> [(a, b)] -> b #

lookupJustNote :: (Partial, Eq a) => String -> a -> [(a, b)] -> b #

elemIndexJust :: (Partial, Eq a) => a -> [a] -> Int #

    elemIndexJust op = fromJust . elemIndex op

elemIndexJustDef :: Eq a => Int -> a -> [a] -> Int #

elemIndexJustNote :: (Partial, Eq a) => String -> a -> [a] -> Int #

findIndexJust :: (a -> Bool) -> [a] -> Int #

    findIndexJust op = fromJust . findIndex op

findIndexJustDef :: Int -> (a -> Bool) -> [a] -> Int #

findIndexJustNote :: Partial => String -> (a -> Bool) -> [a] -> Int #

toEnumMay :: (Enum a, Bounded a) => Int -> Maybe a #

toEnumDef :: (Enum a, Bounded a) => a -> Int -> a #

toEnumNote :: (Partial, Enum a, Bounded a) => String -> Int -> a #

toEnumSafe :: (Enum a, Bounded a) => Int -> a #

succMay :: (Enum a, Eq a, Bounded a) => a -> Maybe a #

succDef :: (Enum a, Eq a, Bounded a) => a -> a -> a #

succNote :: (Partial, Enum a, Eq a, Bounded a) => String -> a -> a #

succSafe :: (Enum a, Eq a, Bounded a) => a -> a #

predMay :: (Enum a, Eq a, Bounded a) => a -> Maybe a #

predDef :: (Enum a, Eq a, Bounded a) => a -> a -> a #

predNote :: (Partial, Enum a, Eq a, Bounded a) => String -> a -> a #

predSafe :: (Enum a, Eq a, Bounded a) => a -> a #

indexMay :: Ix a => (a, a) -> a -> Maybe Int #

indexDef :: Ix a => Int -> (a, a) -> a -> Int #

indexNote :: (Partial, Ix a) => String -> (a, a) -> a -> Int #

foldl1Def' :: a -> (a -> a -> a) -> [a] -> a #

argsToCliOpts :: [String] -> [String] -> IO CliOpts #

A helper for addons/scripts: this parses hledger CliOpts from these command line arguments and add-on command names, roughly how hledger main does. If option parsing/validating fails, it exits the program with usageError. Unlike main, this does not read extra args from a config file or search for addons; to do those things, mimic the code in main for now.