steeloverseer 1.0.1.0 → 1.1.0.0
raw patch · 4 files changed
+14/−198 lines, 4 filesdep +system-filepathdep +textdep −ansi-terminaldep −filepathdep ~basedep ~fsnotify
Dependencies added: system-filepath, text
Dependencies removed: ansi-terminal, filepath
Dependency ranges changed: base, fsnotify
Files
- README.md +0/−66
- src/Main.hs +7/−3
- src/SOS.hs +0/−121
- steeloverseer.cabal +7/−8
− README.md
@@ -1,66 +0,0 @@-Steel Overseer-==============-> ->-> The world is already run by all manner of machines. One day, they'll remind us of that fact. -> -> -Sargis Haz, artificer --[](https://travis-ci.org/schell/steeloverseer)--It is-------A development tool that runs commands when certain files are updated, added or-deleted.--Steeloverseer watches files whose names match a regular expression and then -runs a series of commands when those files are updated. --Specifically--------------A filesystem event occurs when a file is added, deleted or updated. -If this event happens on a file that matches one of the patterns provided with -the `-p PATTERN` flag then steeloverseer will run the commands provided -with the `-c COMMAND` flag. These commands will be performed in serial until -one hangs, fails or all exit successfully.--You can provide multiple patterns and multiple commands, ie:-- sos -c "git status" -c "echo hi world" -p "hs" -p "md"--You can seperately specify the directory to run in with `-d DIRECTORY`. The -default is `.`.- -This will execute `git status` followed by `echo hi world` -whenever files matching "hs" or "md" are changed. `-d DIRECTORY` -is not provided above, so it's assumed to be `./`.--Also, since `-p PATTERN` are regular expressions we can do the same as above with:-- sos -c "git status" -c "echo hi world" -p "hs|md"- -Of course this would run whenever any match on "hs|md" is found, -for instance on the filepath `/Users/home/mdman/file.txt`.-For extensions it may make sense to use the endline matcher:-- sos -c "git status" -c "echo hi world" -p "hs$|md$"--Installation--------------Using cabal, `cabal install steeloverseer`.--Usage------- sos: Usage: sos [v] -c command -p pattern- -v --version show version info- -c COMMAND --command=COMMAND add command to run on file event- -p PATTERN --pattern=PATTERN add pattern to match on file path- -d DIRECTORY --directory=DIRECTORY set directory to watch for changes (default is ./)----Future--------Project `.sosrc` file for specifying multiple sos commands while working on a project (@see issue #4)--[Art above by Chris Rahn for Wizards of the Coast](http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=205036 "Steel Overseer")
src/Main.hs view
@@ -3,7 +3,11 @@ import System.Environment (getArgs) import System.Console.GetOpt+import Data.List import Control.Monad+import Filesystem.Path.CurrentOS hiding (concat, null)+import Data.Text as T hiding (foldl, concat, intercalate, null)+import Prelude hiding (FilePath) import SOS main :: IO ()@@ -24,7 +28,7 @@ defaultOptions = Options { optShowVersion = False , optCommands = [] , optPatterns = []- , optDirectory = "."+ , optDirectory = fromText $ T.pack "." } options :: [OptDescr (Options -> Options)]@@ -38,7 +42,7 @@ (ReqArg (\e opts -> opts { optPatterns = optPatterns opts ++ [e] }) "pattern") "Add pattern to match on file path." , Option "d" ["directory"]- (ReqArg (\d opts -> opts { optDirectory = d }) "directory")+ (ReqArg (\d opts -> opts { optDirectory = decodeString d }) "directory") "Set directory to watch for changes (default is ./)." ] @@ -46,7 +50,7 @@ header = "Usage: sos [vb] -c command -p pattern" version :: String-version = "\nSteel Overseer 1.1.0.4\n"+version = "\nSteel Overseer 1.1.0.0\n" startWithOpts :: Options -> IO () startWithOpts opts = do
− src/SOS.hs
@@ -1,121 +0,0 @@-module SOS where--import System.FSNotify-import System.Process-import System.Exit-import System.FilePath-import System.Console.ANSI-import Control.Monad-import Control.Concurrent-import Data.Maybe-import Text.Regex.TDFA-import Prelude hiding ( FilePath )---- | A structure to hold our changed file events,--- list of commands to run and possibly the currently running process,--- in case it's one that hasn't terminated.-data SOSState = SOSIdle- | SOSPending { accumulatedEvents :: [Event] }- | SOSRunning { runningProccess :: ProcessHandle- , pendingCommands :: [String]- }---- | Starts sos in a `dir` watching `ptns` to execute `cmds`.-steelOverseer :: FilePath -> [String] -> [String] -> IO ()-steelOverseer dir cmds ptns = do- putStrLn "Hit enter to quit.\n"- wm <- startManager- mvar <- newEmptyMVar-- let predicate = actionPredicateForRegexes ptns- action = performCommand mvar cmds- _ <- watchTree wm dir predicate action- _ <- getLine- cleanup wm mvar---- | Cleans up sos on close.-cleanup :: WatchManager -> MVar SOSState -> IO ()-cleanup wm mvar = do- putStrLn "Cleaning up."- mState <- tryTakeMVar mvar- case mState of- Just (SOSRunning pid _) -> terminatePID pid- _ -> return ()- stopManager wm--actionPredicateForRegexes :: [String] -> Event -> Bool-actionPredicateForRegexes ptns event =- or (fmap (eventPath event =~) ptns :: [Bool])--performCommand :: MVar SOSState -> [String] -> Event -> IO ()-performCommand mvar cmds event = do- cyanPrint event- mSosState <- tryTakeMVar mvar- sosState <- case mSosState of- Nothing -> do- -- This is the first file to change and there is no running process.- startWriteProcess mvar cmds 1000000- return $ SOSPending [event]-- Just (SOSRunning pid _) -> do- -- There is a hanging process.- mExCode <- getProcessExitCode pid- when (isNothing mExCode) $ terminatePID pid- startWriteProcess mvar cmds 1000000- return $ SOSPending [event]-- Just (SOSPending events) ->- -- SOS is waiting the 1sec delay for events before running the process.- return $ SOSPending $ event:events-- Just state -> return state-- putMVar mvar sosState--startWriteProcess :: MVar SOSState -> [String] -> Int -> IO ()-startWriteProcess mvar [] _ = do- _ <- tryTakeMVar mvar- return ()--startWriteProcess mvar (cmd:cmds) delay = void $ forkIO $ do- threadDelay delay-- setSGR [SetColor Foreground Dull Green]- putStr "\n> "- setSGR [Reset]- putStrLn cmd-- pId <- runCommand cmd- mEvProcCurrent <- tryTakeMVar mvar- case mEvProcCurrent of- -- This shouldn't ever happen.- Nothing -> putMVar mvar $ SOSRunning pId cmds-- Just _ -> void $ forkIO $ do- putMVar mvar $ SOSRunning pId cmds- exitCode <- waitForProcess pId- case exitCode of- ExitSuccess -> do- greenPrint exitCode- startWriteProcess mvar cmds 0- _ -> redPrint exitCode--terminatePID :: ProcessHandle -> IO ()-terminatePID pid = do- terminateProcess pid- putStrLnColor Red "Terminated hanging process."--cyanPrint :: Show a => a -> IO ()-cyanPrint = putStrLnColor Cyan . show--redPrint :: Show a => a -> IO ()-redPrint = putStrLnColor Red . show--greenPrint :: Show a => a -> IO ()-greenPrint = putStrLnColor Green . show--putStrLnColor :: Color -> String -> IO ()-putStrLnColor c s = do- setSGR [SetColor Foreground Dull c]- putStrLn s- setSGR [Reset]
steeloverseer.cabal view
@@ -2,9 +2,9 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: steeloverseer-version: 1.0.1.0+version: 1.1.0.0 synopsis: A file watcher.-description: A command line tool that responds to filesystem events. Allows the user to automatically execute commands after files are added or updated. Watches files using regular expressions.+description: A command line tool that responds to filesystem events. Allows the user to automatically execute commands after files are added or updated. Watches files using regular expressions. Can be invoked interactively or as a daemon. license: BSD3 license-file: LICENSE author: Schell Scivally@@ -15,7 +15,6 @@ category: Development build-type: Simple cabal-version: >=1.8-extra-source-files: README.md source-repository head type: git@@ -25,12 +24,12 @@ ghc-options: -Wall -threaded hs-source-dirs: src main-is: Main.hs- other-modules: SOS- build-depends: base >=4.5 && <4.9,- fsnotify >=0.2 && < 0.3,- filepath >= 1.4 && < 1.5,- ansi-terminal >= 0.6 && < 0.7,+ build-depends: base >=4.5 && <4.8,+ fsnotify >=0.0.11,+ system-filepath >=0.4.7, process >= 1.1.0.2,+ text >=0.11.2.3, time >=1.4, regex-tdfa >=1.1.8, unix >=2.6.0.1+