twitch: A high level file watcher DSL

[ library, mit, system ] [ Propose Tags ]

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.

import Twitch
import System.Process ( system )

main = defaultMain $ do
"*.md"   |> \filePath -> system $ "pandoc -t html " ++ filePath
"*.html" |> \_ -> system $ "osascript refreshSafari.AppleScript"

[Skip to Readme]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0, 0.1.1.0, 0.1.2.0, 0.1.2.1, 0.1.2.2, 0.1.3.0, 0.1.4.0, 0.1.5.0, 0.1.5.1, 0.1.6.1, 0.1.7.0, 0.1.7.1, 0.1.7.2
Dependencies base (>=4.5 && <5.0), data-default, directory, filepath, fsnotify, Glob, optparse-applicative, semigroups, time, transformers [details]
License MIT
Copyright (c) Jonathan Fischoff 2015
Author Jonathan Fischoff, Andreas Schacker
Maintainer jonathangfischoff@gmail.com
Category System
Home page https://github.com/jfischoff/twitch
Source repo head: git clone https://github.com/jfischoff/twitch.git
Uploaded by AndreasSchacker at 2018-12-12T16:16:39Z
Distributions
Reverse Dependencies 3 direct, 1 indirect [details]
Downloads 8709 total (34 in the last 30 days)
Rating 2.25 (votes: 2) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2018-12-12 [all 1 reports]

Readme for twitch-0.1.7.2

[back to package description]

Hackage travis build status

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 System.Process ( system )

main = defaultMain $ do
   "*.md"   |> \filePath -> system ("pandoc -t html " ++ 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

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.

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, which is the package of the same name.

Here is a slightly more complicated version the example from earlier, using the file-command-qq 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|]

For an alternative command line interface take a look at twitch-cli