packages feed

texbuilder-0.1.4.0: TexBuilder/CompileThread.hs

module TexBuilder.CompileThread
  ( compileThread )
where

import TexBuilder.Utils.BinSem
import TexBuilder.Utils.Hashing
import TexBuilder.Engine

import qualified Text.PrettyPrint.ANSI.Leijen as PP
import qualified Data.Map as M

import Control.Monad
import Control.Monad.Extra
import Control.Monad.State
import Control.Concurrent.MVar



data CompileLoopState = CompileLoopState
  { oldHashes :: M.Map FilePath (Digest MD5)
  , watchMVar :: MVar FilePath }


compileThread :: IO PP.Doc -- ^ The code compilation action
  -> BinSem
  -- ^ Signaling semaphore to communicate when the
  --   pdf view should be updated.
  -> MVar FilePath
  -- ^ Communication MVar for signaling file changes
  -> M.Map FilePath (Digest MD5)
  -- ^ Initial hashes
  -> IO ()
compileThread run viewSem wMVar hashes =
  evalStateT compileLoop $ CompileLoopState hashes wMVar
  where
    compileLoop = do
      path <- lift . takeMVar =<< gets watchMVar
      -- ^ Wait for watcher thread to signal potential changes
      newHash <- computeHash path
      table <- gets oldHashes
      case M.lookup path table of -- ^ lookup old hash
        Nothing -> go
        Just oldHash -> when (oldHash /= newHash) go
      -- ^ Compile when file was changed
      modify $ \st ->
        st { oldHashes = M.insert path newHash table }
      -- ^ Write new hash value
      compileLoop
    
    go = lift $ do
      run >>= PP.putDoc
      signal viewSem