twitch 0.1.1.0 → 0.1.2.0
raw patch · 5 files changed
+130/−41 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Twitch: add' :: (FilePath -> IO a) -> Dep -> Dep
- Twitch: data Rule
- Twitch: delete' :: (FilePath -> IO a) -> Dep -> Dep
- Twitch: modify' :: (FilePath -> IO a) -> Dep -> Dep
- Twitch: type Name = Text
- Twitch: type PatternText = Text
- Twitch: type RuleAction = FilePath -> IO ()
+ Twitch: add :: (FilePath -> IO a) -> Dep -> Dep
+ Twitch: delete :: (FilePath -> IO a) -> Dep -> Dep
+ Twitch: modify :: (FilePath -> IO a) -> Dep -> Dep
+ Twitch: name :: Text -> Dep -> Dep
Files
- src/Twitch.hs +71/−9
- src/Twitch/Internal.hs +30/−19
- src/Twitch/Main.hs +3/−0
- src/Twitch/Rule.hs +6/−11
- twitch.cabal +20/−2
src/Twitch.hs view
@@ -1,21 +1,83 @@+-- | Twitch is monadic DSL and library for file watching. +-- It conveniently utilizes 'do' notation in the style of +-- <https://hackage.haskell.org/package/shake Shake> and +-- <https://hackage.haskell.org/package/clay clay> to expose the functionality of the+-- <http://hackage.haskell.org/package/fsnotify fsnotify> cross-platform file system +-- watcher.+-- +-- Here is an example that converts Markdown files to Html and reloads Safari+-- whenever the input files change.+-- +-- > {-# LANGUAGE OverloadedStrings #-}+-- > import Twitch +-- > import Filesystem.Path.CurrentOS+-- > +-- > main = defaultMain $ do+-- > "*.md" |> \filePath -> system $ "pandoc -t html " ++ encodeString filePath +-- > "*.html" |> \_ -> system $ "osascript refreshSafari.AppleScript"+-- +-- Rules are specified in the 'Dep' (for Dependency) monad. The library takes advantage +-- of the OverloadedStrings extension to create a Dep value from a glob pattern.+-- +-- After creating a 'Dep' value using a glob, event callbacks are added using prefix+-- or infix API.+-- +-- There are three types of events, \'add\', \'modify\' and \'delete\'. In many cases, +-- the add and modify responses are the same, so an \'add and modify\' API +-- is provided+-- +-- In the example above an \'add and modify\' callback was added to both the \"*.md\" +-- and \"*.html\" globs using the '|>' operator. +-- +-- All this is the common case, differing callbacks can be added with '|+' (or 'add')+-- and '|%' (or 'modify') functions. Finally, delete callbacks are added with +-- '|-' (of 'delete').+-- +-- Here is a more complex usage example, handling all three events seperately.+-- +-- > handleHaskellFiles :: Dep +-- > handleHaskellFiles = "src/**/*.hs" |+ addToCabalFile |% reloadFile |- removeFromCabalFile+-- +-- The glob above is also more complicated and incorporates a recursive wildcard. For+-- complete documentation on the glob syntax, consult the +-- <https://hackage.haskell.org/package/Glob-0.7.5/docs/System-FilePath-Glob.html#v:compile Glob>+-- library's documentation.+-- +-- Since a command pattern is calling system commands with a file path, a useful addition+-- to twitch is the <https://hackage.haskell.org/package/file-command-qq-0.1.0.4 file-command-qq> quasiquoter, +-- which is the package of the same name. +--+-- Here is a slightly more complicated version the example from earlier, using the +-- FileCommand quasiquoter.+-- +-- > {-# LANGUAGE OverloadedStrings #-}+-- > {-# LANGUAGE QuasiQuotes #-}+-- > import Twitch +-- > import FileCommand+-- >+-- > main = defaultMain $ do+-- > "*.md" |> [s|pandoc -t html -o$directory$basename-test.html $path|]+-- > "*.html" |> [s|osascript refreshSafari.AppleScript|]+-- module Twitch ( Dep- , DepM- , run , defaultMain+ -- * Infix API , (|+) , (|%) , (|-) , (|>) , (|#) - , add'- , modify'- , delete'+ -- * Prefix API+ , add+ , modify+ , delete , addModify- , Rule (..)- , RuleAction- , Name- , PatternText+ , name+ -- Running as a library+ , run+ -- * Extra+ , DepM ) where import Twitch.Internal import Twitch.Main
src/Twitch/Internal.hs view
@@ -27,6 +27,7 @@ import Data.Either import System.FSNotify (WatchManager) +-- | A polymorphic 'Dep'. Exported for completeness, ignore. newtype DepM a = DepM { unDepM :: State [Rule] a} deriving ( Functor , Applicative@@ -34,20 +35,20 @@ , MonadState [Rule] ) +-- | This is the key type of the package, it is where rules are accumulated.+type Dep = DepM ()++instance IsString Dep where+ fromString = addRule . fromString+ runDep :: Dep -> [Rule] runDep = runDepWithState mempty runDepWithState :: [Rule] -> Dep -> [Rule] runDepWithState xs = flip execState xs . unDepM -type Dep = DepM ()--instance IsString Dep where- fromString = addRule . fromString - addRule r = State.modify (r :) --- TODO this should probably issue a warning modHeadRule :: Dep -> (Rule -> Rule) -> Dep modHeadRule dep f = do let res = runDep dep@@ -55,24 +56,34 @@ x:xs -> put $ f x : xs r -> put r +-- Infix API ----------------------------------------------------------------- infixl 8 |+, |%, |-, |>, |# (|+), (|%), (|-), (|>) :: Dep -> (FilePath -> IO a) -> Dep--- | Set the 'add' field-x |+ f = modHeadRule x $ Rule.add' f--- | Set the modify field-x |% f = modHeadRule x $ Rule.modify' f--- | Set the delete field-x |- f = modHeadRule x $ Rule.delete' f--- | Set both the 'add' and 'modify' field to the same value+-- | Add a \'add\' callback+x |+ f = modHeadRule x $ Rule.addF f+-- | Add a \'modify\' callback+x |% f = modHeadRule x $ Rule.modifyF f+-- | Add a \'delete' callback+x |- f = modHeadRule x $ Rule.deleteF f+-- | Add the same callback for the \'add\' and the \'modify\' events. x |> f = x |+ f |% f --- | Set the name+-- | Set the name of a rule. Useful for debugging when logging is enabled.+-- Rules names default to the glob pattern. (|#) :: Dep -> Text -> Dep-r |# p = modHeadRule r $ Rule.name' p+r |# p = modHeadRule r $ Rule.nameF p -- Prefix API ------------------------------------------------------------------add', modify', delete', addModify :: (FilePath -> IO a) -> Dep -> Dep-add' = flip (|+)-modify' = flip (|%)-delete' = flip (|-)+add, modify, delete, addModify :: (FilePath -> IO a) -> Dep -> Dep+-- | Add a \'add\' callback+add = flip (|+)+-- | Add a \'modify\' callback+modify = flip (|%)+-- | Add a \'delete' callback+delete = flip (|-)+-- | Add the same callback for the \'add\' and the \'modify\' events. addModify = flip (|>)+-- | Set the name of a rule. Useful for debugging when logging is enabled.+-- Rules names default to the glob pattern.+name :: Text -> Dep -> Dep+name = flip (|#)
src/Twitch/Main.hs view
@@ -182,6 +182,9 @@ } return (currentDir', config, mhandle) +-- | Simplest way to create a file watcher app. Set your main equal to defaultMain +-- and you are good to go. See the module documentation for examples.+-- defaultMain :: Dep -> IO () defaultMain dep = do let opts = info (helper <*> pOptions)
src/Twitch/Rule.hs view
@@ -23,11 +23,6 @@ import Debug.Trace import System.FSNotify (WatchManager) --- It doesn't appear that the current directory is need in the monad--- The new way I am thinking about this--- This is a Rule type and what is currently called Rule is called --- InternalRule- type Name = Text type PatternText = Text @@ -84,12 +79,12 @@ r |# p = r { name = p } -- Prefix API ------------------------------------------------------------------add', modify', delete', addModify :: (FilePath -> IO a) -> Rule -> Rule-add' = flip (|+)-modify' = flip (|%)-delete' = flip (|-)-name' = flip (|#)-addModify = flip (|>)+addF, modifyF, deleteF, addModifyF :: (FilePath -> IO a) -> Rule -> Rule+addF = flip (|+)+modifyF = flip (|%)+deleteF = flip (|-)+nameF = flip (|#)+addModifyF = flip (|>) -- def & add foo & modify foo & delete foo & test tester -- def & add foo & modify foo & delete foo & pattern tester
twitch.cabal view
@@ -2,9 +2,27 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: twitch-version: 0.1.1.0+version: 0.1.2.0 synopsis: A high level file watcher DSL--- description: +description: + Twitch is monadic DSL and library for file watching. + It conveniently utilizes 'do' notation in the style of + Shake and clay to expose the functionality of the+ fsnotify cross-platform file system watcher.+ .+ Here is an example that converts Markdown files to Html and reloads Safari+ whenever the input files change.+ .+ @+ {-# LANGUAGE OverloadedStrings #-}+ import Twitch + import Filesystem.Path.CurrentOS+ . + main = defaultMain $ do+ "*.md" |> \\filePath -> system $ "pandoc -t html " ++ encodeString filePath + "*.html" |> \\_ -> system $ "osascript refreshSafari.AppleScript"+ @+ . homepage: https://github.com/jfischoff/twitch license: MIT license-file: LICENSE