packages feed

shell-monad 0.4.0 → 0.5.0

raw patch · 6 files changed

+92/−35 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Monad.Shell: instance Eq a => Eq (Quoted a)
- Control.Monad.Shell: instance Monoid a => Monoid (Quoted a)
- Control.Monad.Shell: instance Ord a => Ord (Quoted a)
- Control.Monad.Shell: instance Show a => Show (Quoted a)
+ Control.Monad.Shell: class Quotable t
+ Control.Monad.Shell.Quote: Q :: a -> Quoted a
+ Control.Monad.Shell.Quote: Val :: v -> Val v
+ Control.Monad.Shell.Quote: class Quotable t
+ Control.Monad.Shell.Quote: getQ :: Quoted a -> a
+ Control.Monad.Shell.Quote: instance [overlap ok] Eq a => Eq (Quoted a)
+ Control.Monad.Shell.Quote: instance [overlap ok] Monoid a => Monoid (Quoted a)
+ Control.Monad.Shell.Quote: instance [overlap ok] Ord a => Ord (Quoted a)
+ Control.Monad.Shell.Quote: instance [overlap ok] Quotable (Val String)
+ Control.Monad.Shell.Quote: instance [overlap ok] Quotable (Val Text)
+ Control.Monad.Shell.Quote: instance [overlap ok] Quotable String
+ Control.Monad.Shell.Quote: instance [overlap ok] Quotable Text
+ Control.Monad.Shell.Quote: instance [overlap ok] Show a => Show (Quoted a)
+ Control.Monad.Shell.Quote: instance [overlap ok] Show v => Quotable (Val v)
+ Control.Monad.Shell.Quote: newtype Quoted a
+ Control.Monad.Shell.Quote: newtype Val v
+ Control.Monad.Shell.Quote: quote :: Quotable t => t -> Quoted Text
- Control.Monad.Shell: lengthVar :: Var a -> Script (Var Int)
+ Control.Monad.Shell: lengthVar :: Var a -> Script (Var Integer)
- Control.Monad.Shell: newVarContaining :: NameHinted namehint => forall a. Text -> namehint -> Script (Var a)
+ Control.Monad.Shell: newVarContaining :: (NameHinted namehint, Quotable (Val t)) => t -> namehint -> Script (Var t)
- Control.Monad.Shell: quote :: Text -> Quoted Text
+ Control.Monad.Shell: quote :: Quotable t => t -> Quoted Text

Files

CHANGELOG view
@@ -1,3 +1,9 @@+shell-monad (0.5.0) unstable; urgency=medium++  * newVarContaining is generalized to work for all showable data types.++ -- Joey Hess <id@joeyh.name>  Sat, 27 Dec 2014 17:10:23 -0400+ shell-monad (0.4.0) unstable; urgency=medium    * Var now has a phantom type. This allows the haskell type checker
Control/Monad/Shell.hs view
@@ -4,8 +4,8 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE FlexibleContexts #-}  module Control.Monad.Shell ( 	-- * Core@@ -13,8 +13,9 @@ 	script, 	linearScript, 	Var,+	Val(..), 	Quoted,-	quote,+	Quotable(..), 	glob, 	-- * Running commands 	run,@@ -22,7 +23,6 @@ 	Param, 	CmdParams, 	Output(..),-	Val(..), 	-- * Shell variables 	NamedLike(..), 	NameHinted,@@ -79,6 +79,8 @@ import System.Posix.Types (Fd) import System.Posix.IO (stdInput, stdOutput, stdError) +import Control.Monad.Shell.Quote+ -- | A shell variable, with an associated phantom type. newtype Var a = Var UntypedVar @@ -102,22 +104,6 @@ 	, expandVar = \_ (VarName n) -> Q ("$" <> n) 	} --- | A value that is safely quoted.-newtype Quoted a = Q { getQ :: a }-	deriving (Eq, Ord, Show, Monoid)---- | Quotes the Text to allow it to be safely exposed to the shell.------ The method used is to replace ' with '"'"' and wrap the value inside--- single quotes. This works for POSIX shells, as well as other shells--- like csh.-quote :: L.Text -> Quoted L.Text-quote t-	| L.all (\c -> isAlphaNum c || c == '_') t = Q t-	| otherwise = Q $ q <> L.intercalate "'\"'\"'" (L.splitOn q t) <> q-  where-	q = "'"- -- | Treats the Text as a glob, which expands to one parameter per -- matching file. --@@ -341,13 +327,13 @@ -- | Any value that can be shown can be passed to 'cmd'; just wrap it -- inside a Val. instance (Show v) => Param (Val v) where-	toTextParam (Val v) = const $ L.pack (show v)+       toTextParam (Val v) = const $ L.pack (show v) --- | Var arguments cause the (quoted) value of a shell variable to be--- passed to the command. instance Param UntypedVar where 	toTextParam v = \env -> "\"" <> getQ (expandVar v env (varName v)) <> "\"" +-- | Var arguments cause the (quoted) value of a shell variable to be+-- passed to the command. instance Param (Var a) where 	toTextParam (Var v) = toTextParam v @@ -393,9 +379,6 @@ -- > cmd "echo" "root's pwent" (Output (cmd "cat" "/etc/passwd" -|- cmd "grep" "root")) newtype Output = Output (Script ()) --- | An arbitrary value.-newtype Val v = Val v- -- | Allows modifying the value of a variable before it is passed to a -- command. The function is passed a Quoted Text which will expand to the -- value of the variable, and can modify it, by using eg 'mappend'.@@ -439,15 +422,22 @@ -- The namehint can influence this name, but is modified to ensure -- uniqueness. newVar :: (NameHinted namehint) => forall a. namehint -> Script (Var a)-newVar = newVarContaining ""+newVar = newVarContaining' "" --- | Creates a new shell variable, with an initial value.-newVarContaining :: (NameHinted namehint) => forall a. L.Text -> namehint -> Script (Var a)-newVarContaining value = hinted $ \namehint -> do+newVarContaining' :: (NameHinted namehint) => L.Text -> namehint -> Script (Var t)+newVarContaining' value = hinted $ \namehint -> do 	v@(Var (V { varName = VarName name })) 		<- newVarUnsafe namehint-	Script $ \env -> ([Cmd (name <> "=" <> getQ (quote value))], env, v)+	Script $ \env -> ([Cmd (name <> "=" <> value)], env, v) +-- | Createa a new shell variable, with an initial value which can+-- be anything that can be shown.+--+-- > s <- newVarContaining "foo bar baz" (NamedLike "s")+-- > i <- newVarContaining (1 :: Int) (NamedLine "i")+newVarContaining :: (NameHinted namehint, Quotable (Val t)) => t -> namehint -> Script (Var t)+newVarContaining = newVarContaining' . getQ . quote . Val+ -- | Sets the Var to the value of the param.  setVar :: Param param => forall a. Var a -> param -> Script () setVar (Var (V { varName = VarName name })) p = Script $ \env -> @@ -545,7 +535,7 @@ -- -- Note that 'lengthVar positionalParameters' expands to the number -- of positional parameters.-lengthVar :: forall a. Var a -> Script (Var Int)+lengthVar :: forall a. Var a -> Script (Var Integer) -- Implementation note: ${#${foo:-bar}} is not legal shell code. -- So, to allow taking the length of Vars that expand to such things, -- a temporary Var is created, assigned to the expansion of the input Var.
+ Control/Monad/Shell/Quote.hs view
@@ -0,0 +1,55 @@+-- | Shell quoting++{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverlappingInstances #-}++module Control.Monad.Shell.Quote (+	Quoted(..),+	Quotable(..),+	Val(..),+) where++import qualified Data.Text.Lazy as L+import Data.Monoid+import Data.Char++-- | A value that is safely quoted so that it can be exposed to the shell.+--+-- While the constructor is exposed, you should avoid directly constucting+-- Quoted values. Instead, use 'quote'.+newtype Quoted a = Q { getQ :: a }+	deriving (Eq, Ord, Show, Monoid)++-- | Quotes a value to allow it to be safely exposed to the shell.+--+-- The method used is to replace ' with '"'"' and wrap the value inside+-- single quotes. This works for POSIX shells, as well as other shells+-- like csh.+class Quotable t where+	quote :: t -> Quoted L.Text++instance Quotable L.Text where+	quote t+		| L.all (\c -> isAlphaNum c || c == '_') t = Q t+		| otherwise = Q $ q <> L.intercalate "'\"'\"'" (L.splitOn q t) <> q+	  where+		q = "'"++instance Quotable String where+	quote = quote . L.pack++-- | Any Showable value can be quoted, just use 'quote (Val v)'+instance (Show v) => Quotable (Val v) where+	quote (Val v) = quote $ show v++-- To avoid double-quoting Text and String, override the above instance.+-- This needs OverlappingInstances+instance Quotable (Val L.Text) where+	quote (Val s) = quote s+instance Quotable (Val String) where+	quote (Val s) = quote s++-- | An arbitrary value.+newtype Val v = Val v
TODO view
@@ -1,1 +1,6 @@ * nicer interface for the `test` command (aka `[`)+* setVar allows `Var a` to be set to any value, the value+  is not constrained to be of type `a`. This seems necessary+  to allow, eg, `setVar v (Output (cmd "read"))`. On other+  hand, it's subptimal when using setVar with a Arith; in this+  case `a` should be some Integral.
examples/fib.hs view
@@ -3,7 +3,6 @@ import Control.Monad.Shell import qualified Data.Text.Lazy as T import qualified Data.Text.Lazy.IO as T-import Data.Monoid default (T.Text)  main :: IO ()@@ -19,4 +18,4 @@ 		setVar prev (AVar acc `AMinus` AVar prev) 	return acc   where-	new1 = newVarContaining "1" () :: Script (Var Integer)+	new1 = newVarContaining 1 ()
shell-monad.cabal view
@@ -1,5 +1,5 @@ Name: shell-monad-Version: 0.4.0+Version: 0.5.0 Cabal-Version: >= 1.8 License: BSD3 Maintainer: Joey Hess <id@joeyh.name>@@ -21,7 +21,9 @@  Library   GHC-Options: -Wall-  Exposed-Modules: Control.Monad.Shell+  Exposed-Modules:+    Control.Monad.Shell+    Control.Monad.Shell.Quote   Build-Depends: base (>= 4.5), base < 5, containers, text, unix  source-repository head