-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | A framework for creating shell envinronments
--   
--   Shellac is a framework for building read-eval-print style shells.
--   Shells are created by declaratively defining a set of shell commands
--   and an evaluation function. Shellac supports multiple shell backends,
--   including a <a>basic</a> backend which uses only Haskell IO primitives
--   and a full featured <a>readline</a> backend based on the the Haskell
--   readline bindings found in the standard libraries. This library
--   attempts to allow users to write shells at a high level and still
--   enjoy the advanced features that may be available from a powerful line
--   editing package like readline.
@package Shellac
@version 0.9.5.1


-- | This module defines the Shellac interface for shell backends. A shell
--   backend is required to provide sensible implementations for
--   <a>outputString</a>, <a>flushOutput</a>, <a>getSingleChar</a>,
--   <a>getInput</a>, and <a>getWordBreakChars</a>. All other operations
--   may be noops (however, they must not denote bottom!).
--   
--   This module is intended for use by backend implementers. It is not
--   intended to be used by regular clients of the library. The Shellac
--   package provides a basic backend
--   (<a>System.Console.Shell.Backend.Basic</a>). More advanced backends
--   are available in separate packages.
module System.Console.Shell.Backend

-- | The type of completion functions. The argument is a triple consisting
--   of (before,word,after), where 'word' is a string of non-word-break
--   characters which contains the cursor position. 'before' is all
--   characters on the line before 'word' and 'after' is all characters on
--   the line after word. The return value should be 'Nothing' if no
--   completions can be generated, or 'Just (newWord,completions)' if
--   completions can be generated. 'newWord' is a new string to replace
--   'word' on the command line and 'completions' is a list of all possible
--   completions of 'word'. To achieve the standard
--   "complete-as-far-as-possible" behavior, 'newWord' should be the
--   longest common prefix of all words in 'completions'.
type CompletionFunction = (String, String, String) -> IO (Maybe (String, [String]))

-- | A datatype representing ouput to be printed. The different categories
--   of output are distinguished to that shell backends can, for example,
--   apply different colors or send output to different places (stderr
--   versus stdout).
data BackendOutput

-- | The most regular way to produce output
RegularOutput :: String -> BackendOutput

-- | An informative output string, such as command help
InfoOutput :: String -> BackendOutput

-- | An string generated by an error
ErrorOutput :: String -> BackendOutput

-- | This record type contains all the functions that Shellac allows the
--   pluggable backend to provide. Most of these operations are optional
--   and relate to advanced features like command completion and history.
--   However, a shell backend is required to provide sensible
--   implementations for <a>outputString</a>, <a>flushOutput</a>,
--   <a>getSingleChar</a>, <a>getInput</a>, and <a>getWordBreakChars</a>.
data ShellBackend bst
ShBackend :: IO bst -> (bst -> IO ()) -> (bst -> BackendOutput -> IO ()) -> (bst -> IO ()) -> (bst -> String -> IO (Maybe Char)) -> (bst -> String -> IO (Maybe String)) -> (bst -> String -> IO ()) -> (bst -> String -> IO ()) -> (bst -> IO String) -> (bst -> IO ()) -> (bst -> CompletionFunction -> IO ()) -> (bst -> Maybe (String -> IO [String]) -> IO ()) -> (bst -> String -> IO [String]) -> (bst -> String -> IO [String]) -> (bst -> IO ()) -> (bst -> Int -> IO ()) -> (bst -> IO Int) -> (bst -> FilePath -> IO ()) -> (bst -> FilePath -> IO ()) -> ShellBackend bst

-- | Provides the backend a way to perform any necessary initialization
--   before the shell starts. This function is called once for each shell
--   instance. The generated value will be passed back in to each call of
--   the other methods in this record.
initBackend :: ShellBackend bst -> IO bst

-- | Called when the shell exits to allow the backend to perform any
--   necessary cleanup actions.
shutdownBackend :: ShellBackend bst -> bst -> IO ()

-- | Causes the string to be sent to the underlying console device.
outputString :: ShellBackend bst -> bst -> BackendOutput -> IO ()

-- | Perform any operations necessary to clear any output buffers. After
--   this operation, the user should be able to view any output sent to
--   this backend.
flushOutput :: ShellBackend bst -> bst -> IO ()

-- | Retrieve a single character from the user without waiting for carriage
--   return.
getSingleChar :: ShellBackend bst -> bst -> String -> IO (Maybe Char)

-- | Print the prompt and retrieve a line of input from the user.
getInput :: ShellBackend bst -> bst -> String -> IO (Maybe String)

-- | Add a string to the history list.
addHistory :: ShellBackend bst -> bst -> String -> IO ()

-- | Set the characters which define word boundaries. This is mostly used
--   for defining where completions occur.
setWordBreakChars :: ShellBackend bst -> bst -> String -> IO ()

-- | Get the current set of word break characters.
getWordBreakChars :: ShellBackend bst -> bst -> IO String

-- | A callback to run whenever evaluation or a command is canceled by the
--   keyboard signal
onCancel :: ShellBackend bst -> bst -> IO ()

-- | A completion function that is tried first.
setAttemptedCompletionFunction :: ShellBackend bst -> bst -> CompletionFunction -> IO ()

-- | An alternate function to generate completions. The function given
--   takes the word as an argument and generates all possible completions.
--   This function is called (if set) after the attemptedCompletionFunction
--   if it returns 'Nothing'.
setDefaultCompletionFunction :: ShellBackend bst -> bst -> Maybe (String -> IO [String]) -> IO ()

-- | A backend-provided method to complete filenames.
completeFilename :: ShellBackend bst -> bst -> String -> IO [String]

-- | A backend-provided method to complete usernames.
completeUsername :: ShellBackend bst -> bst -> String -> IO [String]

-- | An operation to clear the history buffer.
clearHistoryState :: ShellBackend bst -> bst -> IO ()

-- | Sets the maximum number of entries managed by the history buffer.
setMaxHistoryEntries :: ShellBackend bst -> bst -> Int -> IO ()

-- | Gets the maximum number of entries managed by the history buffer.
getMaxHistoryEntries :: ShellBackend bst -> bst -> IO Int

-- | Read the history buffer from a file. The file should be formatted as
--   plain-text, with each line in the file representing a single command
--   entered, most recent commands at the bottom. (This format is what
--   readline produces)
readHistory :: ShellBackend bst -> bst -> FilePath -> IO ()

-- | Write the history buffer to a file. The file should be formatted in
--   the same way as in the description for <a>readHistory</a>.
writeHistory :: ShellBackend bst -> bst -> FilePath -> IO ()

-- | Provides a sane default set of characters to use when breaking lines
--   into 'words'. If a backend does not have configurable word break
--   characters, then <tt>getWordBreakCharacters</tt> can just return this
--   default set.
defaultWordBreakChars :: [Char]

-- | This backend template is useful for defining custom backends. The idea
--   is that you will use <a>templateBackend</a> to generate a bare-bones
--   backend implemenation and only fill in the methods that you wish to
--   define using the record update syntax. The parameter to
--   <a>templateBackend</a> becomes the backend state associated with the
--   backend and is passed into to each of the operation methods.
templateBackend :: a -> ShellBackend a


-- | This module implements a simple Shellac backend that uses only the
--   primitives from "System.IO". It provides no history or command
--   completion capabilities. You get whatever line editing capabilities
--   <a>hGetLine</a> has and that's it.
module System.Console.Shell.Backend.Basic
basicBackend :: ShellBackend ()


-- | This module implements a monad for use in shell commands and in
--   evaluation functions. It is a state moand layered over <tt>IO</tt>.
--   <tt>liftIO</tt> may be used to execute arbitrary I/O actions. However,
--   the <tt>shellPut</tt>* commands are the preferred way to output text.
module System.Console.Shell.ShellMonad

-- | The type of shell commands. This monad is a state monad layered over
--   <tt>IO</tt>. The type parameter <tt>st</tt> allows the monad to carry
--   around a package of user-defined state.
data Sh st a

-- | Execute a shell action
runSh :: st -> OutputCommand -> Sh st () -> IO (CommandResult st)

-- | Output a tagged string to the console
shellPut :: BackendOutput -> Sh st ()

-- | Prints a regular output string
shellPutStr :: String -> Sh st ()

-- | Prints regular output with a line terminator
shellPutStrLn :: String -> Sh st ()

-- | Prints an informational output string
shellPutInfo :: String -> Sh st ()

-- | Prints an informational output string with a line terminator
shellPutInfoLn :: String -> Sh st ()

-- | Prints an error output string
shellPutErr :: String -> Sh st ()

-- | Prints and error output string with a line terminator
shellPutErrLn :: String -> Sh st ()

-- | Get the current shell state
getShellSt :: Sh st st

-- | Set the shell state
putShellSt :: st -> Sh st ()

-- | Apply the given funtion to the shell state
modifyShellSt :: (st -> st) -> Sh st ()

-- | Schedule a shell "special" action. Only the last call to this function
--   will affect the shell's behavior! It modifies a bit of state that is
--   overwritten on each call.
shellSpecial :: ShellSpecial st -> Sh st ()

-- | The total context held by the shell, with <tt><a>CommandResult</a>
--   st</tt> being mutable and <a>OutputCommand</a> immutable
type ShellContext st = (CommandResult st, OutputCommand)

-- | Extract the current shell context for future use, see
--   <a>runWithContext</a>
extractContext :: Sh st (ShellContext st)

-- | Run a shell with the supplied context, useful if you need to invoke a
--   shell within a new IO context, for example when using <a>timeout</a>
runWithContext :: ShellContext st -> Sh st a -> IO (a, CommandResult st)

-- | Update the mutable context of this shell
updateCommandResult :: CommandResult st -> Sh st ()
instance MonadState st (Sh st)


-- | This module implements a framework for creating read-eval-print style
--   command shells. Shells are created by declaratively defining
--   evaluation functions and "shell commands". Input is read using a
--   pluggable backend. The shell framework handles command history and
--   word completion if the backend supports it.
--   
--   The basic idea is for creating a shell is:
--   
--   <ol>
--   <li>Create a list of shell commands and an evaluation function</li>
--   <li>Create a shell description (using <a>mkShellDescription</a>)</li>
--   <li>Set up the initial shell state</li>
--   <li>Run the shell (using <a>runShell</a>)</li>
--   </ol>
--   
--   Shell commands and the evaluation function are written in a custom
--   monad. See <a>System.Console.Shell.ShellMonad</a> for details on using
--   this monad.
module System.Console.Shell

-- | A record type which describes the attributes of a shell.
data ShellDescription st
ShDesc :: [ShellCommand st] -> CommandStyle -> (String -> Sh st ()) -> Maybe String -> [Char] -> Sh st () -> (st -> IO String) -> Maybe (st -> IO String) -> (ShellacException -> Sh st ()) -> Maybe (st -> String -> IO [String]) -> Maybe FilePath -> Int -> Bool -> ShellDescription st

-- | Commands for this shell
shellCommands :: ShellDescription st -> [ShellCommand st]

-- | The style of shell commands
commandStyle :: ShellDescription st -> CommandStyle

-- | The evaluation function for this shell
evaluateFunc :: ShellDescription st -> String -> Sh st ()

-- | Text to print when the shell starts
greetingText :: ShellDescription st -> Maybe String

-- | The characters upon which the backend will break words
wordBreakChars :: ShellDescription st -> [Char]

-- | A shell action to run before each prompt is printed
beforePrompt :: ShellDescription st -> Sh st ()

-- | A command to generate the prompt to print
prompt :: ShellDescription st -> st -> IO String

-- | A command to generate the secondary prompt. The secondary prompt is
--   used for multi-line input. If not set, the regular prompt is used
--   instead.
secondaryPrompt :: ShellDescription st -> Maybe (st -> IO String)

-- | A set of handlers to call when an exception occurs
exceptionHandler :: ShellDescription st -> ShellacException -> Sh st ()

-- | If set, this function provides completions when NOT in the context of
--   a shell command
defaultCompletions :: ShellDescription st -> Maybe (st -> String -> IO [String])

-- | If set, this provides the path to a file to contain a history of
--   entered shell commands
historyFile :: ShellDescription st -> Maybe FilePath

-- | The maximum number of history entries to maintain
maxHistoryEntries :: ShellDescription st -> Int

-- | If true, the history mechanism of the backend (if any) will be used;
--   false will disable history features.
historyEnabled :: ShellDescription st -> Bool

-- | A basic shell description with sane initial values.
initialShellDescription :: ShellDescription st

-- | Creates a simple shell description from a list of shell commands and
--   an evaluation function.
mkShellDescription :: [ShellCommand st] -> (String -> Sh st ()) -> ShellDescription st

-- | The default shell exception handler. It simply prints the exception
--   and returns the shell state unchanged. (However, it specificaly
--   ignores the thread killed exception, because that is used to implement
--   execution canceling)
defaultExceptionHandler :: ShellacException -> Sh st ()

-- | Run a shell. Given a shell description, a shell backend to use and an
--   initial state this function runs the shell until it exits, and then
--   returns the final state.
runShell :: ShellDescription st -> ShellBackend bst -> st -> IO st

-- | Creates a shell command which will exit the shell.
exitCommand :: String -> ShellCommand st

-- | Creates a command which will print the shell help message.
helpCommand :: String -> ShellCommand st

-- | Creates a command to toggle a boolean value
toggle :: String -> String -> (st -> Bool) -> (Bool -> st -> st) -> ShellCommand st

-- | Creates a user defined shell commmand. This relies on the typeclass
--   machenery defined by <a>CommandFunction</a>.
cmd :: CommandFunction f st => String -> f -> String -> ShellCommand st

-- | This class is used in the <a>cmd</a> function to automaticly generate
--   the command parsers and command syntax strings for user defined
--   commands. The type of 'f' is restricted to have a restricted set of
--   monomorphic arguments (<a>Int</a>, <a>Integer</a>, <a>Float</a>,
--   <a>Double</a>, <a>String</a>, <a>File</a>, <a>Username</a>, and
--   <a>Completable</a>) and the head type must be <tt>Sh st ()</tt>
--   
--   <pre>
--   f :: Int -&gt; File -&gt; Sh MyShellState ()
--   g :: Double -&gt; Sh st ()
--   h :: Sh SomeShellState ()
--   </pre>
--   
--   are all legal types, whereas:
--   
--   <pre>
--   bad1 :: a -&gt; Sh (MyShellState a) ()
--   bad2 :: [Int] -&gt; Sh MyShellState ()
--   bad3 :: Bool -&gt; MyShellState
--   </pre>
--   
--   are not.
class CommandFunction f st | f -> st

-- | Represents a command argument which is a filename
newtype File
File :: String -> File

-- | Represents a command argument which is a username
newtype Username
Username :: String -> Username

-- | Represents a command argument which is an arbitrary completable item.
--   The type argument determines the instance of <a>Completion</a> which
--   is used to create completions for this command argument.
newtype Completable compl
Completable :: String -> Completable compl

-- | A typeclass representing user definable completion functions.
class Completion compl st | compl -> st
complete :: Completion compl st => compl -> (st -> String -> IO [String])
completableLabel :: Completion compl st => compl -> String

-- | The type of a shell command. The shell description is passed in, and
--   the tuple consists of (command name,command parser,command syntax
--   document,help message document)
type ShellCommand st = ShellDescription st -> (String, CommandParser st, Doc, Doc)

-- | The type of subshells. The tuple consists of:
--   
--   <ol>
--   <li>A function to generate the initial subshell state from the outer
--   shell state</li>
--   <li>A function to generate the outer shell state from the final
--   subshell state</li>
--   <li>A function to generate the shell description from the initial
--   subshell state</li>
--   </ol>
type Subshell st st' = (st -> IO st', st' -> IO st, st' -> IO (ShellDescription st'))

-- | Creates a simple subshell from a state mapping function and a shell
--   description.
simpleSubshell :: (st -> IO st') -> ShellDescription st' -> IO (Subshell st st')

-- | Prints the help message for this shell, which lists all avaliable
--   commands with their syntax and a short informative message about each.
showShellHelp :: ShellDescription st -> String

-- | Print the help message for a particular shell command
showCmdHelp :: ShellDescription st -> String -> String

-- | Datatype describing the style of shell commands. This determines how
--   shell input is parsed.
data CommandStyle

-- | Indicates that all input is to be interpreted as shell commands; input
--   is only passed to the evaluation fuction if it cannot be parsed as a
--   command.
OnlyCommands :: CommandStyle

-- | Indicates that commands are prefixed with a particular character.
--   Colon ':' is the default character (a la GHCi).
CharPrefixCommands :: Char -> CommandStyle

-- | Commands consist of a single character.
SingleCharCommands :: CommandStyle

-- | Special commands for the shell framework.
data ShellSpecial st

-- | Causes the shell to exit
ShellExit :: ShellSpecial st

-- | Causes the shell to print an informative message. If a command name is
--   specified, only information about that command will be displayed
ShellHelp :: (Maybe String) -> ShellSpecial st

-- | Instructs the shell to do nothing; redisplay the prompt and continue
ShellNothing :: ShellSpecial st

-- | Ask the shell to continue accepting input on another line, which
--   should be appended to the given string
ShellContinueLine :: String -> ShellSpecial st

-- | Causes the shell to execute a subshell
ExecSubshell :: (Subshell st st') -> ShellSpecial st

-- | The type of commands which produce output on the shell console.
type OutputCommand = BackendOutput -> IO ()

-- | The type of results from shell commands. They are a modified shell
--   state and possibly a shell "special" action to execute.
type CommandResult st = (st, Maybe (ShellSpecial st))

-- | Compatability layer. For base-3, this is 'Exception'. For base-4, this
--   is 'SomeException'.
type ShellacException = SomeException
