Safe Haskell | None |
---|---|
Language | Haskell2010 |
Twitch is a 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"
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.
Although 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 separately.
handleHaskellFiles :: Dep handleHaskellFiles = "src/**/*.hs" |+ addToCabalFile |% reloadFile |- removeFromCabalFile
Here is another complex example, using the named addModify
and delete
callbacks
to the same function, which build a pdf and a Word document using pandoc, and
refreshes a mupdf window.
```haskell buildPDFandWordandRefreshWindow _ = do pdfLatexCode <- system "pdflatex --interaction errorstopmode -file-line-error -halt-on-error document.tex" (pandocCode,pandocOut,pandocErr) <- readProcessWithExitCode "pandoc" [ "--from=latex" , "--to=docx" , "document.tex" , "-o" , "document.docx" ] "" (xwininfoCode,xwininfoOut,xwininfoErr) <- readProcessWithExitCode "xwininfo" ["-root", "-int", "-all"] "" let windowId = head . words . head . filter (isInfixOf "document") $ lines xwininfoOut (xDoToolCode,xDoToolOut,xDoToolErr) <- readProcessWithExitCode "xdotool" ["key", "--window", windowId, "r"] "" return ()
main :: IO () main = defaultMain $ do addModify buildPDFandWordandRefreshWindow "src***.tex" delete buildPDFandWordandRefreshWindow "src***.tex" ```
The globs in the above two examples are also more complicated and incorporate recursive wildcards. For complete documentation on the glob syntax, consult the Glob library's documentation.
Since a command pattern is calling system commands with a file path, a useful addition to twitch is the file-command-qq quasiquoter.
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|]
Synopsis
- type Dep = DepM ()
- defaultMain :: Dep -> IO ()
- (|+) :: Dep -> (FilePath -> IO a) -> Dep
- (|%) :: Dep -> (FilePath -> IO a) -> Dep
- (|-) :: Dep -> (FilePath -> IO a) -> Dep
- (|>) :: Dep -> (FilePath -> IO a) -> Dep
- (|#) :: Dep -> String -> Dep
- add :: (FilePath -> IO a) -> Dep -> Dep
- modify :: (FilePath -> IO a) -> Dep -> Dep
- delete :: (FilePath -> IO a) -> Dep -> Dep
- addModify :: (FilePath -> IO a) -> Dep -> Dep
- name :: String -> Dep -> Dep
- data DebounceType
- data LoggerType
- data Options = Options {}
- defaultMainWithOptions :: Options -> Dep -> IO ()
- data Issue
- data InternalRule
- data Rule
- data RuleIssue
- data Config = Config {
- logger :: Issue -> IO ()
- dirs :: [FilePath]
- watchConfig :: WatchConfig
- run :: Dep -> IO WatchManager
- runWithConfig :: FilePath -> Config -> Dep -> IO WatchManager
- data DepM a
Documentation
defaultMain :: Dep -> IO () Source #
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.
The command line is parsed to make Options
value. For more information on
the arguments that can be passed see the doc for Options
and the run the
executable made with defaultMain with the --help argument.
Infix API
(|+) :: Dep -> (FilePath -> IO a) -> Dep infixl 8 Source #
Add a 'add' callback ex.
"*.png" |+ addToManifest
(|%) :: Dep -> (FilePath -> IO a) -> Dep infixl 8 Source #
Add a 'modify' callback ex.
"*.c" |% [s|gcc -o$directory$basename.o $path|]
(|-) :: Dep -> (FilePath -> IO a) -> Dep infixl 8 Source #
Add a 'delete' callback ex.
"*.c" |- [s|gcc -o$directory$basename.o $path|]
(|#) :: Dep -> String -> Dep infixl 8 Source #
Set the name of a rule. Useful for debugging when logging is enabled. Rules names default to the glob pattern. ex.
"*.md" |> [s|pandoc -t html $path|] |# "markdown to html"
Prefix API
modify :: (FilePath -> IO a) -> Dep -> Dep Source #
Add a 'modify' callback ex.
mod [s|gcc -o$directory$basename.o $path|] "*.c"
delete :: (FilePath -> IO a) -> Dep -> Dep Source #
Add a 'delete' callback ex.
delete [s|gcc -o$directory$basename.o $path|] "*.c"
addModify :: (FilePath -> IO a) -> Dep -> Dep Source #
Add the same callback for the 'add' and the 'modify' events. ex.
addModify [s|pandoc -t html $path|] "*.md"
name :: String -> Dep -> Dep Source #
Set the name of a rule. Useful for debugging when logging is enabled. Rules names default to the glob pattern. ex.
name "markdown to html" $ addModify [s|pandoc -t html $path|] "*.md"
Advanced Main
data DebounceType Source #
Instances
Eq DebounceType Source # | |
Defined in Twitch.Main (==) :: DebounceType -> DebounceType -> Bool # (/=) :: DebounceType -> DebounceType -> Bool # | |
Ord DebounceType Source # | |
Defined in Twitch.Main compare :: DebounceType -> DebounceType -> Ordering # (<) :: DebounceType -> DebounceType -> Bool # (<=) :: DebounceType -> DebounceType -> Bool # (>) :: DebounceType -> DebounceType -> Bool # (>=) :: DebounceType -> DebounceType -> Bool # max :: DebounceType -> DebounceType -> DebounceType # min :: DebounceType -> DebounceType -> DebounceType # | |
Read DebounceType Source # | |
Defined in Twitch.Main readsPrec :: Int -> ReadS DebounceType # readList :: ReadS [DebounceType] # | |
Show DebounceType Source # | |
Defined in Twitch.Main showsPrec :: Int -> DebounceType -> ShowS # show :: DebounceType -> String # showList :: [DebounceType] -> ShowS # |
data LoggerType Source #
Instances
Eq LoggerType Source # | |
Defined in Twitch.Main (==) :: LoggerType -> LoggerType -> Bool # (/=) :: LoggerType -> LoggerType -> Bool # | |
Ord LoggerType Source # | |
Defined in Twitch.Main compare :: LoggerType -> LoggerType -> Ordering # (<) :: LoggerType -> LoggerType -> Bool # (<=) :: LoggerType -> LoggerType -> Bool # (>) :: LoggerType -> LoggerType -> Bool # (>=) :: LoggerType -> LoggerType -> Bool # max :: LoggerType -> LoggerType -> LoggerType # min :: LoggerType -> LoggerType -> LoggerType # | |
Read LoggerType Source # | |
Defined in Twitch.Main readsPrec :: Int -> ReadS LoggerType # readList :: ReadS [LoggerType] # readPrec :: ReadPrec LoggerType # readListPrec :: ReadPrec [LoggerType] # | |
Show LoggerType Source # | |
Defined in Twitch.Main showsPrec :: Int -> LoggerType -> ShowS # show :: LoggerType -> String # showList :: [LoggerType] -> ShowS # |
Options | |
|
defaultMainWithOptions :: Options -> Dep -> IO () Source #
A main file that uses manually supplied options instead of parsing the passed in arguments.
Running as a library
A sum type for the various issues that can be logged
IEvent Event | logged every time an event is fired |
IRuleFired Event InternalRule | logged every time an rule is fired |
data InternalRule Source #
Instances
Show InternalRule Source # | |
Defined in Twitch.InternalRule showsPrec :: Int -> InternalRule -> ShowS # show :: InternalRule -> String # showList :: [InternalRule] -> ShowS # | |
Default InternalRule Source # | |
Defined in Twitch.InternalRule def :: InternalRule # |
The pattern entity holds a name and pattern that is compiled when the rules are evaluated
Configuration to run the file watcher
Config | |
|
runWithConfig :: FilePath -> Config -> Dep -> IO WatchManager Source #