hledger-lib-1.43.2: A library providing the core functionality of hledger
Safe HaskellNone
LanguageHaskell2010

Hledger.Utils.IO

Description

General and hledger-specific input/output-related helpers for pretty-printing haskell values, error reporting, time, files, command line parsing, terminals, pager output, ANSI colour/styles, etc.

Synopsis

Pretty showing/printing

pshow :: Show a => a -> String Source #

Pretty show. An easier alias for pretty-simple's pShow. This will probably show in colour if useColorOnStderrUnsafe is true.

pshow' :: Show a => a -> String Source #

Monochrome version of pshow. This will never show in colour.

pprint :: Show a => a -> IO () Source #

Pretty print a showable value. An easier alias for pretty-simple's pPrint. This will print in colour if useColorOnStderrUnsafe is true.

pprint' :: Show a => a -> IO () Source #

Monochrome version of pprint. This will never print in colour.

Errors

error' :: String -> a Source #

Call errorWithoutStackTrace, prepending a "Error:" label.

usageError :: String -> a Source #

Like error', but add a hint about using -h.

warn :: String -> a -> a Source #

Show a message, with "Warning:" label, on stderr before returning the given value. Also do some ANSI styling of the first line when allowed (using unsafe IO). Currently we use this very sparingly in hledger; we prefer to either quietly work, or loudly raise an error. (Varying output can make scripting harder.)

ansiFormatError :: String -> String Source #

Apply standard ANSI SGR formatting (red, bold) suitable for console error text.

ansiFormatWarning :: String -> String Source #

Apply standard ANSI SGR formatting (yellow, bold) suitable for console warning text.

printError :: String -> IO () Source #

Print an error message to stderr, with a consistent "programname: " prefix, and applying ANSI styling (bold bright red) to the first line if that is supported and allowed.

exitWithErrorMessage :: String -> IO () Source #

Print an error message with printError, then exit the program with a non-zero exit code.

handleExit :: IO () -> IO () Source #

This wraps a program's main routine so as to display more consistent, useful, and GHC-version-independent error output when the program exits because of certain common exceptions. It

  1. disables SIGPIPE errors, which are usually harmless, caused when our output is truncated in a piped command.
  2. catches these common exceptions:
  • UnicodeException, caused eg by text decoding errors in pure code
  • IOException, caused by IO errors, including text decoding errors during IO
  • ErrorCall - error / errorWithoutStackTrace calls
  1. compensates for GHC output bugs:
  • removes the trailing newlines added by some GHC 9.10.* versions
  • removes "uncaught exception" output added by some GHC 9.12.* versions
  • ensures a consistent "PROGNAME: " prefix
  1. applies bold bright red ANSI styling to the first line of error output, if that is supported and allowed
  2. for unicode exceptions and I/O exceptions which look like they were unicode-related, it adds a message (in english) explaining the problem and what to do.

Some exceptions this does not catch are ExitCode (exitSuccessexitFailureexitWith) and UserInterrupt (control-C).

Time

Files

getHomeSafe :: IO (Maybe FilePath) Source #

Like getHomeDirectory, but in case of IO error (home directory not found, not understood, etc.), returns "".

embedFileRelative :: FilePath -> Q Exp Source #

Like embedFile, but takes a path relative to the package directory.

expandHomePath :: FilePath -> IO FilePath Source #

Expand a tilde (representing home directory) at the start of a file path. ~username is not supported. Can raise an error.

expandPath :: FilePath -> FilePath -> IO FilePath Source #

Given a current directory, convert a possibly relative, possibly tilde-containing file path to an absolute one. ~username is not supported. Leaves "-" unchanged. Can raise an error.

expandGlob :: FilePath -> FilePath -> IO [FilePath] Source #

Like expandPath, but treats the expanded path as a glob, and returns zero or more matched absolute file paths, alphabetically sorted. Can raise an error.

sortByModTime :: [FilePath] -> IO [FilePath] Source #

Given a list of existing file paths, sort them by modification time, most recent first.

openFileOrStdin :: String -> IO Handle Source #

Open a file for reading, using the standard System.IO.openFile. This opens the handle in text mode, using the initial system locale's text encoding.

readFileOrStdinPortably :: String -> IO Text Source #

Like readFilePortably, but read from standard input if the path is "-".

readFileOrStdinPortably' :: Maybe DynEncoding -> String -> IO Text Source #

Like readFileOrStdinPortably, but take an optional converter.

readFileStrictly :: FilePath -> IO Text Source #

Like readFilePortably, but read all of the file before proceeding.

readFilePortably :: FilePath -> IO Text Source #

Read text from a file, converting any rn line endings to n,, using the system locale's text encoding, ignoring any utf8 BOM prefix (as seen in paypal's 2018 CSV, eg) if that encoding is utf8.

readHandlePortably' :: Maybe DynEncoding -> Handle -> IO Text Source #

Read text from a handle with a specified encoding, using the encoding package. Or if no encoding is specified, it uses the handle's current encoding, after first changing it to UTF-8BOM if it was UTF-8, to allow a Byte Order Mark at the start. Also it converts Windows line endings to newlines. If decoding fails, this throws an IOException (or possibly a UnicodeException or something else from the encoding package).

inputToHandle :: Text -> IO Handle Source #

Create a handle from which the given text can be read. Its encoding will be UTF-8BOM.

Command line parsing

progArgs :: [String] Source #

The program's command line arguments. Uses unsafePerformIO; tends to stick in GHCI until reloaded, and may or may not detect args provided by a hledger config file.

getOpt :: [String] -> IO (Maybe String) Source #

Given one or more long or short option names, read the rightmost value of this option from the command line arguments. If the value is missing raise an error. Concatenated short flags (-a -b written as -ab) are not supported.

parseYN :: String -> Either String Bool Source #

Parse yyesalways or nnonever to true or false, or return an error message.

parseYNA :: String -> Either String YNA Source #

Parse yyesalways or nnonever or a/auto to a YNA choice, or return an error message.

data YNA Source #

Constructors

Yes 
No 
Auto 

Instances

Instances details
Show YNA Source # 
Instance details

Defined in Hledger.Utils.IO

Methods

showsPrec :: Int -> YNA -> ShowS #

show :: YNA -> String #

showList :: [YNA] -> ShowS #

Eq YNA Source # 
Instance details

Defined in Hledger.Utils.IO

Methods

(==) :: YNA -> YNA -> Bool #

(/=) :: YNA -> YNA -> Bool #

Terminal size

getTerminalHeightWidth :: IO (Maybe (Int, Int)) Source #

An alternative to ansi-terminal's getTerminalSize, based on the more robust-looking terminal-size package.

Tries to get stdout's terminal's current height and width.

Pager output

findPager :: IO (Maybe String) Source #

Try to find a pager executable robustly, safely handling various error conditions like an unset PATH var or the specified pager not being found as an executable. The pager can be specified by a path or program name in the PAGER environment variable. If that is unset or has a problem, "less" is tried, then "more". If successful, the pager's path or program name is returned.

runPager :: String -> IO () Source #

Display the given text on the terminal, trying to use a pager ($PAGER, less, or more) when appropriate, otherwise printing to standard output. Uses maybePagerFor.

hledger's output may contain ANSI style/color codes (if the terminal supports them and they are not disabled by --color=no or NO_COLOR), so the pager should be configured to handle these. setupPager tries to configure that automatically when using the less pager.

ANSI colour/styles

hledger-specific

colorOption :: IO YNA Source #

Get the value of the rightmost --color or --colour option from the program's command line arguments. Throws an error if the option's value could not be parsed.

useColorOnStdout :: IO Bool Source #

Should ANSI color and styles be used for standard output ? Considers useColorOnHandle stdout and hasOutputFile.

useColorOnStderr :: IO Bool Source #

Should ANSI color and styles be used for standard error output ? Considers useColorOnHandle stderr; is not affected by an --output-file option.

useColorOnStdoutUnsafe :: Bool Source #

Like useColorOnStdout, but using unsafePerformIO. Useful eg for low-level debug code. Sticky in GHCI until reloaded, may not always be affected by --color in a hledger config file, etc.

useColorOnStderrUnsafe :: Bool Source #

Like useColorOnStdoutUnsafe, but for stderr.

bold' :: String -> String Source #

Set various ANSI styles/colours in a string, only if useColorOnStdoutUnsafe says we should.

Generic

color :: ColorIntensity -> Color -> String -> String Source #

Wrap a string in ANSI codes to set and reset foreground colour. ColorIntensity is Dull or Vivid (ie normal and bold). Color is one of Black, Red, Green, Yellow, Blue, Magenta, Cyan, White. Eg: color Dull Red "text".

bgColor :: ColorIntensity -> Color -> String -> String Source #

Wrap a string in ANSI codes to set and reset background colour.

colorB :: ColorIntensity -> Color -> WideBuilder -> WideBuilder Source #

Wrap a WideBuilder in ANSI codes to set and reset foreground colour.

bgColorB :: ColorIntensity -> Color -> WideBuilder -> WideBuilder Source #

Wrap a WideBuilder in ANSI codes to set and reset background colour.

terminalIsLight :: Maybe Bool Source #

Detect whether the terminal currently has a light background colour, if possible, using unsafePerformIO. If the terminal is transparent, its apparent light/darkness may be different.

terminalLightness :: Maybe Float Source #

Detect the terminal's current background lightness (0..1), if possible, using unsafePerformIO. If the terminal is transparent, its apparent lightness may be different.

terminalFgColor :: Maybe (RGB Float) Source #

Detect the terminal's current foreground colour, if possible, using unsafePerformIO.

terminalBgColor :: Maybe (RGB Float) Source #

Detect the terminal's current background colour, if possible, using unsafePerformIO.