diff options
author | Kierán Meinhardt <kieran.meinhardt@gmail.com> | 2020-09-23 17:44:40 +0200 |
---|---|---|
committer | Kierán Meinhardt <kieran.meinhardt@gmail.com> | 2020-09-23 17:44:40 +0200 |
commit | 8e92e6e11d2b3b0bfb5ac9d68f347219493e6380 (patch) | |
tree | 6484ca42d85ca89475e922f7b45039c116ebbf97 /Notmuch.hs | |
parent | 6a6ad3aecd53ffd89101a0dee2b4ea576d4964d4 (diff) |
split into library + executables
Diffstat (limited to 'Notmuch.hs')
-rw-r--r-- | Notmuch.hs | 200 |
1 files changed, 0 insertions, 200 deletions
diff --git a/Notmuch.hs b/Notmuch.hs deleted file mode 100644 index fc24d0e..0000000 --- a/Notmuch.hs +++ /dev/null @@ -1,200 +0,0 @@ -{-# LANGUAGE LambdaCase #-} -{-# LANGUAGE OverloadedStrings #-} -module Notmuch where - -import qualified Data.ByteString.Lazy as LBS -import qualified Data.ByteString.Lazy.Char8 as LBS8 -import qualified Data.Text.Lazy as LT -import qualified Data.Text.Lazy.Encoding as LT -import qualified Network.Mail.Mime as M -import Control.Concurrent -import Control.DeepSeq (rnf) -import Control.Exception -import Data.Aeson.Extends -import Data.Tree -import Notmuch.Class -import Notmuch.Message -import Notmuch.SearchResult -import ParseMail (readMail) -import System.Exit -import System.IO -import System.Process -import TagUtils - - --- | Fork a thread while doing something else, but kill it if there's an --- exception. --- --- This is important in the cases above because we want to kill the thread --- that is holding the Handle lock, because when we clean up the process we --- try to close that handle, which could otherwise deadlock. --- -withForkWait :: IO () -> (IO () -> IO a) -> IO a -withForkWait async body = do - waitVar <- newEmptyMVar :: IO (MVar (Either SomeException ())) - mask $ \restore -> do - tid <- forkIO $ try (restore async) >>= putMVar waitVar - let wait = takeMVar waitVar >>= either throwIO return - restore (body wait) `onException` killThread tid - - - - -notmuch :: [String] -> IO LBS.ByteString -notmuch args = do - (_, Just hout, _, ph) <- createProcess (proc "notmuch" args) - { std_out = CreatePipe } - output <- LBS.hGetContents hout - - - withForkWait (evaluate $ rnf output) $ \waitOut -> do - - ---- now write any input - --unless (null input) $ - -- ignoreSigPipe $ hPutStr inh input - -- hClose performs implicit hFlush, and thus may trigger a SIGPIPE - --ignoreSigPipe $ hClose inh - - -- wait on the output - waitOut - hClose hout - - -- wait on the process - _ex <- waitForProcess ph - --return (ex, output) - - --case ex of - -- ExitSuccess -> return output - -- ExitFailure r -> processFailedException "readProcess" cmd args r - - return output - - -notmuch' :: [String] -> IO (ExitCode, LBS.ByteString, LBS.ByteString) -notmuch' args = do - (_, Just hout, Just herr, ph) <- - createProcess (proc "notmuch" args) - { std_out = CreatePipe - , std_err = CreatePipe - } - out <- LBS.hGetContents hout - err <- LBS.hGetContents herr - - withForkWait (evaluate $ rnf out) $ \waitOut -> do - withForkWait (evaluate $ rnf err) $ \waitErr -> do - - ---- now write any input - --unless (null input) $ - -- ignoreSigPipe $ hPutStr inh input - -- hClose performs implicit hFlush, and thus may trigger a SIGPIPE - --ignoreSigPipe $ hClose inh - - -- wait on the output - waitOut - waitErr - hClose hout - hClose herr - - -- wait on the process - exitCode <- waitForProcess ph - - return (exitCode, out, err) - - -notmuchWithInput - :: [String] - -> LBS.ByteString - -> IO (ExitCode, LBS.ByteString, LBS.ByteString) -notmuchWithInput args input = do - (Just hin, Just hout, Just herr, ph) <- - createProcess (proc "notmuch" args) - { std_in = CreatePipe - , std_out = CreatePipe - , std_err = CreatePipe - } - LBS.hPut hin input - hClose hin - - out <- LBS.hGetContents hout - err <- LBS.hGetContents herr - - withForkWait (evaluate $ rnf out) $ \waitOut -> do - withForkWait (evaluate $ rnf err) $ \waitErr -> do - - ---- now write any input - --unless (null input) $ - -- ignoreSigPipe $ hPutStr inh input - -- hClose performs implicit hFlush, and thus may trigger a SIGPIPE - --ignoreSigPipe $ hClose inh - - -- wait on the output - waitOut - waitErr - hClose hout - hClose herr - - -- wait on the process - exitCode <- waitForProcess ph - - return (exitCode, out, err) - - -search :: [String] -> IO (Either String [SearchResult]) -search args = - eitherDecodeLenient' <$> - notmuch ("search" : "--format=json" : "--format-version=2" : args) - - -data ReplyTo = ToAll | ToSender -instance Show ReplyTo where - show ToAll = "all" - show ToSender = "sender" - ---notmuchReply :: String -> IO (Either String [SearchResult]) -notmuchReply :: ReplyTo -> String -> IO LBS.ByteString -notmuchReply replyTo term = - notmuch - [ "reply" - , "--reply-to=" ++ show replyTo - , term - ] - -- >>= return . eitherDecodeLenient' - - -notmuchShow :: String -> IO (Forest Message) -notmuchShow term = do - c' <- notmuch [ "show", "--format=json", "--format-version=2" - , term ] - -- TODO why head? - return $ threadForest $ head $ - either error id (eitherDecodeLenient' c') - - -notmuchShowPart :: String -> Int -> IO (Either String MessagePart) -notmuchShowPart term partId = do - -- TODO handle partId == 0 and partId > N - (exitCode, out, err) <- - notmuch' [ "show", "--format=json", "--format-version=2" - , "--part=" <> show partId - , term ] - return $ case exitCode of - ExitSuccess -> eitherDecodeLenient' out - _ -> Left $ show exitCode <> ": " <> LBS8.unpack err - - -notmuchShowMail :: String -> IO (Either String M.Mail) -notmuchShowMail term = - notmuch' [ "show", "--format=raw", "--format-version=2", term ] - >>= return . \case - (ExitSuccess, out, _) -> - case LT.decodeUtf8' out of - Right x -> Right (readMail $ LT.toStrict x) - Left ex -> Left $ "meh" ++ show ex - (exitCode, _, err) -> - Left $ "notmuch failed with exit code " ++ show exitCode ++ - ": " ++ LBS8.unpack err - - -notmuchTag :: HasNotmuchId a => [TagOp] -> a -> IO () -notmuchTag tagOps x = - notmuch ("tag" : tagOpsToArgs tagOps ++ [notmuchId x]) >> return () |