diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Data/Tree/Extra.hs | 7 | ||||
-rw-r--r-- | src/Much/Action.hs | 8 | ||||
-rw-r--r-- | src/Much/Core.hs | 2 | ||||
-rw-r--r-- | src/Much/TreeView.hs | 22 | ||||
-rw-r--r-- | src/Notmuch.hs | 120 |
5 files changed, 36 insertions, 123 deletions
diff --git a/src/Data/Tree/Extra.hs b/src/Data/Tree/Extra.hs new file mode 100644 index 0000000..256af08 --- /dev/null +++ b/src/Data/Tree/Extra.hs @@ -0,0 +1,7 @@ +module Data.Tree.Extra where + +import Data.Tree (Forest, Tree(subForest)) + + +setSubForest :: Forest a -> Tree a -> Tree a +setSubForest sf t = t { subForest = sf } diff --git a/src/Much/Action.hs b/src/Much/Action.hs index 6613eb1..d76e503 100644 --- a/src/Much/Action.hs +++ b/src/Much/Action.hs @@ -3,15 +3,15 @@ {-# LANGUAGE RecordWildCards #-} module Much.Action where -import Blessings.String +import Blessings.String.WCWidth import Data.Maybe +import Data.Tree.Extra (setSubForest) import Scanner import Much.State import Much.TagUtils import Much.TreeSearch import Much.TreeView import Much.TreeZipperUtils -import qualified Data.Tree as Tree import qualified Data.Tree.Zipper as Z import qualified Notmuch import qualified Notmuch.Message as Notmuch @@ -216,7 +216,3 @@ topOverrun State{..} = botOverrun :: State -> Int botOverrun State{..} = max 0 (linearPos cursor - yoffset - (screenHeight - length headBuffer - 1)) - - -setSubForest :: Tree.Forest a -> Tree.Tree a -> Tree.Tree a -setSubForest sf t = t { Tree.subForest = sf } diff --git a/src/Much/Core.hs b/src/Much/Core.hs index 2ce5ad7..1c8daa7 100644 --- a/src/Much/Core.hs +++ b/src/Much/Core.hs @@ -4,7 +4,7 @@ {-# LANGUAGE RecordWildCards #-} module Much.Core where -import Blessings.String (Blessings(Plain,SGR),pp) +import Blessings.String.WCWidth (Blessings(Plain,SGR),pp) import Control.Concurrent import Control.Monad import Data.Aeson diff --git a/src/Much/TreeView.hs b/src/Much/TreeView.hs index e963497..9b309bc 100644 --- a/src/Much/TreeView.hs +++ b/src/Much/TreeView.hs @@ -25,6 +25,8 @@ import Notmuch import Notmuch.Message import Notmuch.SearchResult import Much.TreeView.Types as Export +import System.Exit (ExitCode(ExitSuccess)) +import System.Process.ByteString.Lazy (readProcessWithExitCode) getMessage :: TreeView -> Maybe Message @@ -144,8 +146,26 @@ loadSubForest = \case . findFirsts messageMatch <$> notmuchShow (termFromMessage m) + TVMessagePart m mp@MessagePart{partContentType="text/html"} -> + notmuchShowPartRaw (termFromMessage m) (partID mp) >>= \case + Left e -> return $ Left $ show e + Right html -> + readProcessWithExitCode + "lynx" + [ "-dump" + , "-nomargins" + , "-stdin" + ] + html + >>= \case + (ExitSuccess, out, _err) -> + return $ Right $ + zipWith (\i s -> Node (TVMessageLine m mp i s) []) [0..] (lines . LBS8.unpack $ out) + + (exitCode, _out, err) -> + return $ Left $ show exitCode <> ": " <> LBS8.unpack err + TVMessagePart m mp -> - -- TODO parse --format=raw notmuchShowPart (termFromMessage m) (partID mp) >>= return . \case Left e -> Left $ show e Right mp' -> diff --git a/src/Notmuch.hs b/src/Notmuch.hs index 080df1e..310657a 100644 --- a/src/Notmuch.hs +++ b/src/Notmuch.hs @@ -7,9 +7,6 @@ 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.Either.Combinators (mapRight) import Data.Functor ((<&>)) @@ -19,126 +16,19 @@ import Notmuch.Message import Notmuch.SearchResult import Much.ParseMail (readMail) import System.Exit -import System.IO -import System.Process +import System.Process.ByteString.Lazy (readProcessWithExitCode) import Much.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 + (_exitCode, out, _err) <- notmuch' args + return out 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) +notmuch' args = + readProcessWithExitCode "notmuch" args "" search :: [String] -> IO (Either String [SearchResult]) |