Commando 1.0.0.0 → 1.0.0.2
raw patch · 3 files changed
+38/−26 lines, 3 filesdep +data-defaultPVP: minor bump suggested
API additions: PVP suggests at least a minor version bump
Dependencies added: data-default
API changes (from Hackage documentation)
+ System.Commando: instance Default Options
Files
- Commando.cabal +7/−3
- Commando.hs +9/−9
- System/Commando.hs +22/−14
Commando.cabal view
@@ -1,5 +1,5 @@ name: Commando-version: 1.0.0.0+version: 1.0.0.2 synopsis: Watch some files; Rerun a command homepage: https://github.com/sordina/Commando license: MIT@@ -30,6 +30,8 @@ > import System.Commando . See the "System.Commando" module documentation for more details.+ .+ The Commando executable module is a good example of using Commando as a library. executable commando main-is: Commando.hs@@ -40,7 +42,8 @@ optparse-applicative >= 0.5 && < 0.6, system-fileio >= 0.3 && < 0.4, fsnotify >= 0.0.10 && < 0.1,- process >= 1.1 && < 1.2+ process >= 1.1 && < 1.2,+ data-default >= 0.5 && < 1.0 library exposed-modules: System.Commando@@ -51,4 +54,5 @@ optparse-applicative >= 0.5 && < 0.6, system-fileio >= 0.3 && < 0.4, fsnotify >= 0.0.10 && < 0.1,- process >= 1.1 && < 1.2+ process >= 1.1 && < 1.2,+ data-default >= 0.5 && < 1.0
Commando.hs view
@@ -2,17 +2,17 @@ module Main where -import System.Commando-import Control.Monad (when)-import Control.Applicative ((<*>)) import Data.Monoid (mempty)--import qualified Options.Applicative as O+import Control.Monad (when)+import System.Commando (commando, options, quiet)+import Options.Applicative (info, helper, execParser, (<*>))+import System.IO main :: IO () main = do- opts <- O.execParser (O.info (O.helper <*> options) mempty)-- when (not $ quiet opts) $ putStrLn "press return to stop"+ hSetBuffering stdout LineBuffering+ hSetBuffering stderr LineBuffering - commando opts >>= mapM_ putStrLn+ opts <- execParser (info (helper <*> options) mempty)+ when (not $ quiet opts) $ putStrLn "press return to quit"+ commando opts >>= mapM_ putStr
System/Commando.hs view
@@ -3,11 +3,11 @@ -- | A library providing an interface to generate a lazy stream of command -- results from events occurring in a directory. -module System.Commando (Options(..), options, commando) where+module System.Commando (module Data.Default, Options(..), options, commando) where import Prelude hiding (FilePath) import Control.Monad (void)-import System.Process (rawSystem, runCommand, runInteractiveCommand)+import System.Process (runInteractiveCommand) import System.FSNotify (startManager, watchTree, stopManager, Event(..)) import Filesystem.Path.CurrentOS (FilePath, fromText, toText) import Data.Text (pack, unpack)@@ -24,6 +24,8 @@ import qualified Options.Applicative.Builder.Internal as X import qualified Options.Applicative as O +import Data.Default+ type RunningProcess = (Handle, Handle, Handle, ProcessHandle) -- | Options used to configure the behavior of Commando@@ -44,11 +46,13 @@ , directory :: FilePath } +instance Default Options where def = Options "echo" True True False False (show . toFP) "."+ -- | The main listening loop. commando :: Options -> IO [String] commando o = do c <- newChan- start c o+ void $ forkIO $ start c o catMaybes . takeWhile isJust <$> getChanContents c -- | An optparse-applicative parser for command-line options.@@ -63,10 +67,10 @@ <*> (dir <$> defStr "." ( O.metavar "DIRECTORY" <> O.help "Directory to monitor" )) defStr :: String -> X.Mod X.ArgumentFields String -> O.Parser String-defStr a = def a . O.argument O.str+defStr a = xor a . O.argument O.str -def :: a -> O.Parser a -> O.Parser a-def a = fmap (fromMaybe a) . O.optional+xor :: a -> O.Parser a -> O.Parser a+xor a = fmap (fromMaybe a) . O.optional dir :: String -> FilePath dir = fromText . pack@@ -77,25 +81,29 @@ rc <- if persist o then Just <$> startPipe (command o) else return Nothing - void $ forkIO $ whenM rc $ \(_,so,_,_) -> hGetContents so >>= putChan c+ void $ forkIO $ whenM rc $ \(_,so,_,_) -> hGetContents so >>= mapM_ (putChan c) . lines let cmd = command o dsp = display o void $ watchTree man (directory o) (const True) $ case (consumer o, stdin o || persist o )- of (True , _ ) -> void . rawSystem cmd . return . dsp+ of (True , _ ) -> systemChan c cmd . return . dsp (_ , True ) -> void . pipe c rc cmd . dsp- (_ , _ ) -> const $ void $ runCommand cmd+ (_ , _ ) -> const $ systemChan c cmd [] void $ getLine- void $ stopManager man- whenM rc pipeClose- closeChan c +systemChan :: CH -> String -> [String] -> IO ()+systemChan c cmd as = do+ (i,o,e,_) <- runInteractiveCommand (cmd ++ " " ++ (as >>= show))+ hClose i+ hGetContents o >>= putChan c+ hGetContents e >>= putChan c+ whenM :: Monad m => Maybe a -> (a -> m ()) -> m () whenM m f = maybe (return ()) f m @@ -132,8 +140,8 @@ -- Chans type CH = Chan (Maybe String) -putChan :: Chan (Maybe a) -> a -> IO ()-putChan c = writeChan c . Just+putChan :: CH -> String -> IO ()+putChan c s = (writeChan c . Just) s closeChan :: Chan (Maybe a) -> IO () closeChan c = writeChan c Nothing