packages feed

shh 0.2.0.0 → 0.2.0.1

raw patch · 6 files changed

+50/−29 lines, 6 filesdep ~async

Dependency ranges changed: async

Files

README.md view
@@ -1,7 +1,7 @@ # Shh -[![Hackage](https://img.shields.io/hackage/v/shh.svg?colorB=%23999)](http://hackage.haskell.org/package/shh)-[![Build Status](https://travis-ci.org/luke-clifton/shh.svg?branch=master)](https://travis-ci.org/luke-clifton/shh)+[![](https://img.shields.io/hackage/v/shh.svg?colorB=%23999)](http://hackage.haskell.org/package/shh)+[![](https://travis-ci.org/luke-clifton/shh.svg?branch=master)](https://travis-ci.org/luke-clifton/shh)  Shh is a library to enable convinient shell-like programming in Haskell. It works well in scripts, and from GHCi, allowing you to use GHCi as a shell.@@ -104,7 +104,7 @@ Enable Temlpate Haskell and load the environment      {-# LANGUAGE TemplateHaskell #-}-    $(loadEnv)+    $(loadEnv SearchPath)  You now have all your executables available as simple to read Haskell functions.
app/Example.hs view
@@ -8,14 +8,20 @@ import Data.Monoid import Data.Char import Data.List+import Control.Concurrent.Async -$(loadEnv)+-- Load everything...+-- $(loadEnv) --- We could also have been a little more explicit about it.--- load ["sleep", "echo", "cat"]+-- OR -- +-- We could also be a little more explicit about it.+$(load Absolute ["sleep", "echo", "cat", "xxd"])+ main :: IO () main = do     -- Crash the program if we are missing any executables.     [] <- missingExecutables-    (sleep 1 >> echo "Hello" >> sleep 2) |> cat+    concurrently_+        ((sleep 1 >> echo "Hello" >> sleep 2) |> cat)+        (echo "A" >> sleep 1 >> echo "b" |> xxd)
shh.cabal view
@@ -1,5 +1,5 @@ name:                shh-version:             0.2.0.0+version:             0.2.0.1 synopsis:            Simple shell scripting from Haskell description:         Provides a shell scripting environment for Haskell. It                      helps you all external binaries, and allows you to@@ -42,9 +42,14 @@   default-language: Haskell2010   build-depends:     base >=4.9,+    async,     shh   hs-source-dirs: app   main-is: Example.hs+  build-tools:+    coreutils,+    vault,+    vim     test-suite shh-tests@@ -56,6 +61,9 @@     tasty-quickcheck,     tasty-hunit,     shh+  build-tools:+    perl,+    vim   hs-source-dirs: test   main-is: Test.hs   type: exitcode-stdio-1.0
src/Shh.hs view
@@ -53,6 +53,7 @@     -- | == Constructing Arguments     , ExecArg(..)     -- | == Template Haskell helpers+    , ExecReference(..)     , load     , loadEnv     , loadAnnotated
src/Shh/Internal.hs view
@@ -399,28 +399,34 @@ exe s = toArgs [s]  -- | Create a function for the executable named-loadExe :: String -> Q [Dec]-loadExe s = loadExeAs s s+loadExe :: ExecReference -> String -> Q [Dec]+loadExe ref s = loadExeAs ref s s +-- | Specify how executables should be referenced.+data ExecReference+    = Absolute -- ^ Find executables on PATH, but store their absolute path+    | SearchPath -- ^ Always search on PATH+ -- | @$(loadExeAs fnName executable)@ defines a function called @fnName@ -- which executes the path in @executable@.-loadExeAs :: String -> String -> Q [Dec]-loadExeAs fnName executable =+loadExeAs :: ExecReference -> String -> String -> Q [Dec]+loadExeAs ref fnName executable =     -- TODO: Can we place haddock markup in TH generated functions.     -- TODO: Can we palce the man page for each function in there xD     -- https://ghc.haskell.org/trac/ghc/ticket/5467     let         name = mkName $ fnName-        impl = valD (varP name) (normalB [|-            exe executable+        impl executableRef = valD (varP name) (normalB [|+            exe executableRef             |]) []         typn = mkName "a"         typ = SigD name (ForallT [PlainTV typn] [AppT (ConT ''Unit) (VarT typn), AppT (ConT ''ExecArgs) (VarT typn)] (VarT typn))     in do-        isExe <- runIO $ checkExecutable executable-        when (not isExe) $ error $ "Attempted to load '" ++ executable ++ "', but it isn't executable"-        i <- impl-        return $ [typ,i]+        runIO (Dir.findExecutable executable) >>= \case+            Nothing -> error $ "Attempted to load '" ++ executable ++ "', but it is not executable"+            Just absExe -> do+                i <- impl (case ref of { Absolute -> absExe; SearchPath -> executable })+                return $ [typ,i]  -- | Checks if a String is a valid Haskell identifier. validIdentifier :: String -> Bool@@ -441,8 +447,8 @@ -- are ignored. It also creates the IO action @missingExecutables@ which will -- do a runtime check to ensure all the executables that were found at -- compile time still exist.-loadEnv :: Q [Dec]-loadEnv = loadAnnotatedEnv id+loadEnv :: ExecReference -> Q [Dec]+loadEnv ref = loadAnnotatedEnv ref id  -- | Test to see if an executable can be found either on the $PATH or absolute. checkExecutable :: FilePath -> IO Bool@@ -451,14 +457,14 @@ -- | Load the given executables into the program, checking their executability -- and creating a function @missingExecutables@ to do a runtime check for their -- availability.-load :: [String] -> Q [Dec]-load = loadAnnotated id+load :: ExecReference -> [String] -> Q [Dec]+load ref = loadAnnotated ref id  -- | Same as `load`, but allows you to modify the function names.-loadAnnotated :: (String -> String) -> [String] -> Q [Dec]-loadAnnotated f bins = do+loadAnnotated :: ExecReference -> (String -> String) -> [String] -> Q [Dec]+loadAnnotated ref f bins = do     let pairs = mapMaybe getAnnotation bins-    ds <- fmap join $ mapM (uncurry loadExeAs) pairs+    ds <- fmap join $ mapM (uncurry (loadExeAs ref)) pairs     d <- valD (varP (mkName "missingExecutables")) (normalB [|                 filterM (fmap not . checkExecutable) bins             |]) []@@ -473,10 +479,10 @@  -- | Like `loadEnv`, but allows you to modify the function name that would -- be generated.-loadAnnotatedEnv :: (String -> String) -> Q [Dec]-loadAnnotatedEnv f = do+loadAnnotatedEnv :: ExecReference -> (String -> String) -> Q [Dec]+loadAnnotatedEnv ref f = do     bins <- runIO pathBins-    loadAnnotated f bins+    loadAnnotated ref f bins  -- | Function that splits '\0' seperated list of strings. Useful in conjuction -- with @find . "-print0"@.
test/Test.hs view
@@ -7,7 +7,7 @@ import Test.Tasty.HUnit import Test.Tasty.QuickCheck -$(loadEnv)+$(loadEnv SearchPath)  main = do     putStrLn "################################################"