Safe Haskell | None |
---|---|
Language | Haskell2010 |
Shh provides a shell-like environment for Haskell.
Synopsis
- initInteractive :: IO ()
- exe :: (Unit a, ExecArgs a) => String -> a
- mkProc :: String -> [String] -> Proc ()
- mkProc' :: Bool -> String -> [String] -> Proc ()
- runProc :: Proc a -> IO a
- data Proc a
- pureProc :: PipeResult io => (String -> String) -> io ()
- writeOutput :: PipeResult io => String -> io ()
- writeError :: PipeResult io => String -> io ()
- prefixLines :: PipeResult io => String -> io ()
- capture :: PipeResult io => io String
- captureTrim :: PipeResult io => io String
- captureSplit :: PipeResult io => String -> io [String]
- captureSplit0 :: PipeResult io => io [String]
- captureLines :: PipeResult io => io [String]
- readInput :: (NFData a, PipeResult io) => (String -> IO a) -> io a
- readInputSplit :: (NFData a, PipeResult io) => String -> ([String] -> IO a) -> io a
- readInputSplit0 :: (NFData a, PipeResult io) => ([String] -> IO a) -> io a
- readInputLines :: (NFData a, PipeResult io) => ([String] -> IO a) -> io a
- readInputP :: (NFData a, PipeResult io) => (String -> Proc a) -> io a
- readInputSplitP :: (NFData a, PipeResult io) => String -> ([String] -> Proc a) -> io a
- readInputSplit0P :: (NFData a, PipeResult io) => ([String] -> Proc a) -> io a
- readInputLinesP :: (NFData a, PipeResult io) => ([String] -> Proc a) -> io a
- xargs1 :: (NFData a, Monoid a) => String -> (String -> Proc a) -> Proc a
- class PipeResult f where
- (<|) :: PipeResult f => Proc a -> Proc b -> f a
- data Stream
- devNull :: Stream
- withRead :: (PipeResult f, NFData b) => Proc a -> (String -> IO b) -> f b
- withReadSplit0 :: (NFData b, PipeResult io) => Proc a -> ([String] -> IO b) -> io b
- withReadLines :: (NFData b, PipeResult io) => Proc a -> ([String] -> IO b) -> io b
- withReadWords :: (NFData b, PipeResult io) => Proc a -> ([String] -> IO b) -> io b
- readProc :: PipeResult io => Proc a -> io String
- readTrim :: (Functor io, PipeResult io) => Proc a -> io String
- readSplit0 :: Proc () -> IO [String]
- readLines :: Proc () -> IO [String]
- readWords :: Proc () -> IO [String]
- readAuto :: Read a => Proc () -> IO a
- (<<<) :: PipeResult io => Proc a -> String -> io a
- (>>>) :: PipeResult io => String -> Proc a -> io a
- writeProc :: PipeResult io => Proc a -> String -> io a
- readWriteProc :: MonadIO io => Proc a -> String -> io String
- apply :: MonadIO io => Proc a -> String -> io String
- trim :: String -> String
- split0 :: String -> [String]
- data Failure = Failure {
- failureProg :: String
- failureArgs :: [String]
- failureCode :: Int
- ignoreFailure :: (Functor m, ProcFailure m) => Proc a -> m ()
- catchFailure :: ProcFailure m => Proc a -> m (Either Failure a)
- catchCode :: (Functor m, ProcFailure m) => Proc a -> m Int
- class ExecArg a where
- asArg :: a -> [String]
- asArgFromList :: [a] -> [String]
- class ExecArgs a
- class Unit a
- encodeIdentifier :: String -> String
- data ExecReference
- load :: ExecReference -> [String] -> Q [Dec]
- loadEnv :: ExecReference -> Q [Dec]
- loadFromDirs :: [FilePath] -> Q [Dec]
- loadFromBins :: [FilePath] -> Q [Dec]
- loadAnnotated :: ExecReference -> (String -> String) -> [String] -> Q [Dec]
- loadAnnotatedEnv :: ExecReference -> (String -> String) -> Q [Dec]
- loadAnnotatedFromDirs :: [FilePath] -> (String -> String) -> Q [Dec]
- loadExe :: ExecReference -> String -> Q [Dec]
- loadExeAs :: ExecReference -> String -> String -> Q [Dec]
- pathBins :: IO [FilePath]
- pathBinsAbs :: IO [FilePath]
- cd :: Cd a => a
Documentation
initInteractive :: IO () Source #
This function needs to be called in order to use the library successfully
from GHCi. If you use the formatPrompt
function from the shh-extras
package, this will be automatically called for you.
Constructing a Proc
| === External Processes
These allow for the construction of
s that call external
processes. You will often use the TemplateHaskell functions below
to create these.Proc
mkProc :: String -> [String] -> Proc () Source #
Create a Proc
from a command and a list of arguments. Does not delegate
control-c handling.
Type representing a series or pipeline (or both) of shell commands.
Proc
's can communicate to each other via stdin
, stdout
and stderr
and can communicate to Haskell via their parameterised return type, or by
throwing an exception.
Instances
Monad Proc Source # | |
Functor Proc Source # | |
Applicative Proc Source # | |
MonadIO Proc Source # | |
Defined in Shh.Internal | |
ProcFailure Proc Source # | |
Defined in Shh.Internal | |
PipeResult Proc Source # | |
Semigroup (Proc a) Source # | The |
a ~ () => Monoid (Proc a) Source # | |
ExecArgs (Proc ()) Source # | |
Native Processes
You can also create native Haskell
s which behave the same
way, but simply run Haskell functions instead of external processes.Proc
NB: The functions here that operate on String
s from stdin
read them
lazily, and can be used in a streaming fashion.
pureProc :: PipeResult io => (String -> String) -> io () Source #
Creates a pure
that simple transforms the Proc
stdin
and writes
it to stdout
. The input can be infinite.
>>>
yes |> pureProc (take 4) |> capture
"y\ny\n"
writeOutput :: PipeResult io => String -> io () Source #
writeError :: PipeResult io => String -> io () Source #
Simple
that writes a Proc
String
to it's stderr
.
See also
.
>>> writeError Hello &> devNull
HellowriteOutput
prefixLines :: PipeResult io => String -> io () Source #
Captures the stdout of a process and prefixes all the lines with the given string.
>>>
some_command |> prefixLines "stdout: " |!> prefixLines "stderr: " &> StdErr
stdout: this is stdout stderr: this is stderr
capture :: PipeResult io => io String Source #
captureTrim :: PipeResult io => io String Source #
captureSplit :: PipeResult io => String -> io [String] Source #
captureSplit0 :: PipeResult io => io [String] Source #
Same as
.captureSplit
"0"
captureLines :: PipeResult io => io [String] Source #
Same as
.captureSplit
"n"
readInputSplit :: (NFData a, PipeResult io) => String -> ([String] -> IO a) -> io a Source #
readInputSplit0 :: (NFData a, PipeResult io) => ([String] -> IO a) -> io a Source #
readInputLines :: (NFData a, PipeResult io) => ([String] -> IO a) -> io a Source #
readInputP :: (NFData a, PipeResult io) => (String -> Proc a) -> io a Source #
readInputSplitP :: (NFData a, PipeResult io) => String -> ([String] -> Proc a) -> io a Source #
Like
, but splits the input.readInputP
readInputSplit0P :: (NFData a, PipeResult io) => ([String] -> Proc a) -> io a Source #
Like
, but splits the input on 0 bytes.readInputP
readInputLinesP :: (NFData a, PipeResult io) => ([String] -> Proc a) -> io a Source #
Like
, but splits the input on new lines.readInputP
xargs1 :: (NFData a, Monoid a) => String -> (String -> Proc a) -> Proc a Source #
xargs1 n f
runs f
for each item in the input separated by n
. Similar
to the standard xargs
utility, but you get to choose the separator, and it
only does one argument per command. Compare the following two lines, which
do the same thing.
>>>
printf "a\\0b" |> xargs "--null" "-L1" "echo" |> cat
a b>>>
printf "a\\0b" |> xargs1 "\0" echo |> cat
a b
One benefit of this method over the standard xargs
is that we can run
Haskell functions as well.
>>>
yes |> head "-n" 5 |> xargs1 "\n" (const $ pure $ Sum 1)
Sum {getSum = 5}
Piping and Redirection
class PipeResult f where Source #
This class is used to allow most of the operators in Shh to be
polymorphic in their return value. This makes using them in an IO
context
easier (we can avoid having to prepend everything with a runProc
).
(|>) :: Proc b -> Proc a -> f a infixl 1 Source #
Use this to send the output of on process into the input of another. This is just like a shells `|` operator.
The result is polymorphic in it's output, and can result in either another `Proc a` or an `IO a` depending on the context in which it is used.
If any intermediate process throws an exception, the whole pipeline is canceled.
The result of the last process in the chain is the result returned by the pipeline.
>>>
echo "Hello" |> wc
1 1 6
(|!>) :: Proc b -> Proc a -> f a infixl 1 Source #
Similar to |!>
except that it connects stderr to stdin of the
next process in the chain.
NB: The next command to be |>
on will recapture the stdout of
both preceding processes, because they are both going to the same
handle!
See the &>
and &!>
operators for redirection.
>>>
echo "Ignored" |!> wc "-c"
Ignored 0
(&>) :: Proc a -> Stream -> f a infixl 9 Source #
Redirect stdout of this process to another location
>>>
echo "Ignore me" &> Append "/dev/null"
(&!>) :: Proc a -> Stream -> f a infixl 9 Source #
Redirect stderr of this process to another location
>>>
echo "Shh" &!> StdOut
Shh
nativeProc :: NFData a => (Handle -> Handle -> Handle -> IO a) -> f a Source #
Instances
PipeResult IO Source # | |
PipeResult Proc Source # | |
(<|) :: PipeResult f => Proc a -> Proc b -> f a infixr 1 Source #
Flipped version of |>
with lower precedence.
>>>
captureTrim <| (echo "Hello" |> wc "-c")
"6"
Lazy/Streaming reads
These reads are lazy. The process is run long enough to produce the amount of output that is actually used. It is therefor suitable for use with infinite output streams. The process is terminated as soon the function finishes. Note that the result is forced to normal form to prevent any accidental reading after the process has terminated.
NB: See readInput
and pureProc
for more flexible options to those
listed here.
withRead :: (PipeResult f, NFData b) => Proc a -> (String -> IO b) -> f b Source #
Run a process and capture it's output lazily. Once the continuation
is completed, the handles are closed. However, the process is run
until it naturally terminates in order to capture the correct exit
code. Most utilities behave correctly with this (e.g. cat
will
terminate if you close the handle).
Same as p |> readInput f
withReadSplit0 :: (NFData b, PipeResult io) => Proc a -> ([String] -> IO b) -> io b Source #
withReadLines :: (NFData b, PipeResult io) => Proc a -> ([String] -> IO b) -> io b Source #
Like
except it splits the string with withRead
first.lines
NB: Please consider using
where you can.withReadSplit0
withReadWords :: (NFData b, PipeResult io) => Proc a -> ([String] -> IO b) -> io b Source #
Strict reads
NB: See also capture
readTrim :: (Functor io, PipeResult io) => Proc a -> io String Source #
Like readProc
, but trim leading and tailing whitespace.
readSplit0 :: Proc () -> IO [String] Source #
A convenience function for reading in a "\NUL"
separated list of
strings. This is commonly used when dealing with paths.
readSplit0 $ find "-print0"
readLines :: Proc () -> IO [String] Source #
A convenience function for reading the output lines of a Proc
.
Note: Please consider using
instead if you can.readSplit0
Writing to stdin
NB: See also writeOutput
for an echo
-like option.
writeProc :: PipeResult io => Proc a -> String -> io a Source #
Provide the stdin of a Proc
from a String
Same as writeOutput
s |> p
readWriteProc :: MonadIO io => Proc a -> String -> io String Source #
Read and write to a Proc
. Same as
readProc proc <<< input
apply :: MonadIO io => Proc a -> String -> io String Source #
Some as readWriteProc
. Apply a Proc
to a String
.
> apply md5sum "Hello"
"8b1a9953c4611296a827abf8c47804d7 -n"
String manipulation
Utility functions for dealing with common string issues in shell scripting.
split0 :: String -> [String] Source #
Function that splits '\0' separated list of strings. Useful in conjunction
with find . "-print0"
.
Exceptions
If any exception is allowed to propagate out of a pipeline, all the
processes comprising the pipeline will be terminated. This is contrary
to how a shell normally works (even with -o pipefail
!).
When a process exits with a non-zero exit code
we throw this Failure
exception.
The only exception to this is when a process is terminated
by SIGPIPE
in a pipeline, in which case we ignore it.
Failure | |
|
Instances
Eq Failure Source # | |
Ord Failure Source # | |
Show Failure Source # | |
Exception Failure Source # | |
Defined in Shh.Internal toException :: Failure -> SomeException # fromException :: SomeException -> Maybe Failure # displayException :: Failure -> String # |
ignoreFailure :: (Functor m, ProcFailure m) => Proc a -> m () Source #
catchFailure :: ProcFailure m => Proc a -> m (Either Failure a) Source #
catchCode :: (Functor m, ProcFailure m) => Proc a -> m Int Source #
Run an Proc
action returning the return code if an
exception was thrown, and 0 if it wasn't.
Constructing Arguments
class ExecArg a where Source #
A class for things that can be converted to arguments on the command
line. The default implementation is to use show
.
Nothing
asArg :: a -> [String] Source #
asArg :: Show a => a -> [String] Source #
asArgFromList :: [a] -> [String] Source #
asArgFromList :: Show a => [a] -> [String] Source #
A class for building up a command
Force a `()` result.
Instances
a ~ () => Unit (m a) Source # | |
Defined in Shh.Internal | |
Unit b => Unit (a -> b) Source # | |
Defined in Shh.Internal |
Template Haskell helpers
encodeIdentifier :: String -> String Source #
Takes a string, and makes a Haskell identifier out of it. There
is some chance of overlap. If the string is a path, the filename portion
is used. The transformation replaces all non-alphanumeric characters
with '_'
. If the first character is uppercase it is forced into lowercase.
If it starts with a number, it is prefixed with `_`. If it overlaps with
a reserved word or a builtin, it is suffixed with an `_`.
data ExecReference Source #
Specify how executables should be referenced.
Absolute | Find executables on PATH, but store their absolute path |
SearchPath | Always search on PATH |
load :: ExecReference -> [String] -> Q [Dec] Source #
Load the given executables into the program, checking their executability
and creating a function missingExecutables
to do a runtime check for their
availability. Uses the
function to create function
names.encodeIdentifier
loadEnv :: ExecReference -> Q [Dec] Source #
Scans your '$PATH' environment variable and creates a function for each
executable found. Binaries that would not create valid Haskell identifiers
are encoded using the
function.encodeIdentifier
loadFromBins :: [FilePath] -> Q [Dec] Source #
Load executables from the given directories appended with "/bin"
.
Useful for use with Nix.
loadAnnotated :: ExecReference -> (String -> String) -> [String] -> Q [Dec] Source #
Same as load
, but allows you to modify the function names.
loadAnnotatedEnv :: ExecReference -> (String -> String) -> Q [Dec] Source #
Like loadEnv
, but allows you to modify the function name that would
be generated.
loadAnnotatedFromDirs :: [FilePath] -> (String -> String) -> Q [Dec] Source #
Load executables from the given dirs, applying the given transformation to the filenames.
loadExeAs :: ExecReference -> String -> String -> Q [Dec] Source #
$(loadExeAs ref fnName executable)
defines a function called fnName
which executes the path in executable
. If executable
is an absolute path
it is used directly. If it is just an executable name, then it is searched
for in the PATH environment variable. If ref
is SearchPath
, the short
name is retained, and your PATH will be searched at runtime. If ref
is Absolute
, a executable name will be turned into an absolute path, which
will be used at runtime.
pathBinsAbs :: IO [FilePath] Source #
Get all uniquely named executables on your `$PATH` as absolute file names. The uniqueness is determined by the filename, and not the whole path. First one found wins.