repl-toolkit-1.0.1.0: Toolkit for quickly whipping up config files and command-line interfaces.

Description

Asking the user for input on the console.

The main type is Asker, which takes care of parsing and verifying user input.

Synopsis

# Types

type PromptMsg = Text Source #

A prompt.

An error message indicating that a value wasn't able to be parsed.

An error message indicating that a value failed a predicate.

type Predicate m a b = a -> m (Either PredicateError b) Source #

A predicate which a value has to fulfil.

type Predicate' m a = Predicate m a a Source #

A predicate which does not change the type of its input.

type Parser a = Text -> Either TypeError a Source #

A parser which either returns a parsed value or an error message.

data Asker m a b Source #

The description of an 'ask for user input'-action. The type parameters are the used monad (typically IO or ExceptT), the type of the read value and the type of the error that is thrown in case of failures.

The components are a prompt, a parser, and a predicate that the parsed value must fulfil. The predicate

Constructors

 Asker FieldsaskerPrompt :: TextThe prompt to be displayed to the user.askerParser :: Parser aThe parser for the input value.askerPredicate :: Predicate m a bThe predicate which the input, once read, must fulfill. The Left side is an error message.

An Asker which does not convert its argument into a different type after parsing.

## Exceptions

Root of the exception hierarchy.

Constructors

 Exception e => SomeREPLError e

Instances

 Source # MethodsshowList :: [SomeREPLError] -> ShowS # Source # Methods

Generic error related to Askers. Either the input was incorrect in some way, or the process was aborted by the user.

Constructors

Instances

 Source # MethodsshowList :: [SomeAskerError] -> ShowS # Source # Methods

The input could not be parsed.

Constructors

Instances

 Source # MethodsshowList :: [AskerTypeError] -> ShowS # Source # Methods

The parsed value failed a predicate.

Constructors

Instances

 Source # Methods Source # Methods

A generic type failure for use with Askers.

Constructors

 GenericTypeError Text

Instances

 Source # Methods Source # MethodsshowList :: [GenericTypeError] -> ShowS # Source # Methods

A generic predicate failure for use with Askers.

Constructors

 GenericPredicateError Text

Instances

 Source # Methods Source # Methods Source #

Constructor for GenericTypeError which wraps the value into a SomeException.

Constructor for GenericTypeError which wraps the value into a SomeException.

These are all just convenience functions. You can also create Askers directly via the constructor.

For errors, you can supply a custom exception or use GenericTypeError, GenericPredicateError.

typeAskerP :: Applicative m => PromptMsg -> Parser a -> Asker' m a Source #

Creates an Asker which only cares about the type of the input.

maybeAskerP :: Applicative m => PromptMsg -> Parser a -> Predicate m a b -> Asker m (Maybe a) (Maybe b) Source #

An asker which asks for an optional value. If only whitespace is entered (according to isSpace), it returns Nothing without further parsing or checking; otherwise, it behaves identically to asker.

## Creating askers via Read

These askers use readMaybe as their parser.

It is possible to ask for Strings, but then quotes will be required around them (per their Read-instance). To get the user's input as-is, use the Verbatim type or predAsker.

newtype Verbatim Source #

A verbatim Text whose Read instance simply returns the read string, as-is. This is useful for askers which ask for strings without quotes.

Constructors

 Verbatim FieldsfromVerbatim :: Text

Instances

 Source # Read-instance for Verbatim. Wraps the given value into quotes and reads it a a Text. Methods

readParser :: Read a => (Text -> TypeError) -> Parser a Source #

A parser based on readMaybe. This suffices for the parsing of most data types.

asker :: (Functor m, Read a) => PromptMsg -> (Text -> TypeError) -> Predicate' m a -> Asker' m a Source #

Creates a general Asker with readMaybe as its parser. Using readMaybe is perfectly fine for most values, keep in mind that the input Text has to be unpacked into a string. This can be costly on very large inputs.

NOTE: Instances of String/Text have to be surrounded with quotes ("). You practically never want this when asking for input. If you want to get the user input as-is, restrict the return type to Asker m Verbatim or use 'predAsker'/'lineAsker'.

A wrapper around getLine. Prints no prompt and returns the user input as-is.

typeAsker :: (Applicative m, Read a) => PromptMsg -> (Text -> TypeError) -> Asker' m a Source #

Creates an Asker based on Read which just cares about the type of the input.

predAsker :: Functor m => PromptMsg -> Predicate m Text b -> Asker m Text b Source #

Creates an Asker which takes its input verbatim as Text. Quotes around the input are not required. The input thus only has to pass a predicate, not any parsing.

maybeAsker :: (Applicative m, Read a) => PromptMsg -> (Text -> TypeError) -> Predicate' m a -> Asker' m (Maybe a) Source #

Created askers can be run via these functions. Since the parsing depends on the Read-instance, the expected result type must be explicitly given. E.g.:

  intAsker :: Asker IO Int


  genericAsk :: Read a => Asker IO a
...
do (x :: Int) <- genericAsk
putStrLn \$ "The sum is: " ++ show (x+y)


Executes an Asker. A SomeAskerError is thrown if the inpout can't be parsing into a value of the correct type, if the input fails the Asker's predicate, or if the escape key is pressed.

See ask. Always reads the input from stdin.

ask' a = ask a Nothing


Executes an Asker. If the Text argument is Nothing, the user is asked to enter a line on stdin. If it is Just x, x is taken to be input.

Pressing the escape key returns a AskerInputAborterError (if supported).

untilValid :: forall m a. (MonadIO m, MonadCatch m, Read a) => m a -> m a Source #

Repeatedly executes an ask action until the user enters a valid value. Error messages are printed each time.

# Creating predicates

boolPredicate :: Functor m => (a -> m Bool) -> (a -> PredicateError) -> Predicate' m a Source #

Creates a predicate from a boolean function and an error message.

Indicates that no part of a path exists.

Constructors

 PathRootDoesNotExist FilePath

Instances

 Source # Methods Source # Methods Source # Methods

Indicates that the last existing portion of a path is not writable.

Constructors

 PathIsNotWritable FilePath

Instances

 Source # Methods Source # MethodsshowList :: [PathIsNotWritable] -> ShowS # Source # Methods

Indicates whether the target of a path exists and what form it has.

Constructors

 IsDirectory IsFile DoesNotExist

Instances

 Source # Methods Source # Methods Source # Methods Source # Methods Source # Methods Source # MethodsshowList :: [PathExistenceType] -> ShowS #

filepathAsker :: MonadIO m => PromptMsg -> (FilePath -> TypeError) -> Predicate m (PathExistenceType, FilePath) b -> Asker m FilePath b Source #

Asks the user for a file or a directory.

Parsing checks for basic validity via isValid. Invalid paths are rejected.

After that, the asker determines whether the target exists and what type it has. You can run a predicate on that information.

writableFilepathAsker :: MonadIO m => PromptMsg -> (FilePath -> TypeError) -> Predicate m (PathExistenceType, FilePath) b -> Asker m FilePath b Source #

See filepathAsker. This Asker also ensures that the given path is writeable in the following sense:

• at least some initial part of the path exists and
• the last existing part of the path is writeable.

PathRootDoesNotExist and PathIsNotWritable exceptions are thrown if the first or second of these conditions is violated.

For relative paths, we only check that the current directory is writable.

Handled exceptions:

• isPermissionError
• isDoesNotExistError