1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
{-# LANGUAGE CPP #-}
-----------------------------------------------------------------------------
-- |
-- Module : Plugins.Mail
-- Copyright : (c) Spencer Janssen
-- License : BSD-style (see LICENSE)
--
-- Maintainer : Spencer Janssen <sjanssen@cse.unl.edu>
-- Stability : unstable
-- Portability : unportable
--
-- A plugin for checking mail.
--
-----------------------------------------------------------------------------
module Xmobar.Plugins.Mail(Mail(..),MailX(..)) where
import Xmobar.Run.Exec
#ifdef INOTIFY
import Xmobar.Plugins.Monitors.Common (parseOptsWith)
import Xmobar.System.Utils (expandHome, changeLoop)
import Control.Monad
import Control.Concurrent.STM
import System.Directory
import System.FilePath
import System.INotify
import System.Console.GetOpt
import Data.List (isPrefixOf)
import Data.Set (Set)
import qualified Data.Set as S
#if MIN_VERSION_hinotify(0,3,10)
import qualified Data.ByteString.Char8 as BS (ByteString, pack, unpack)
unpack :: BS.ByteString -> String
unpack = BS.unpack
pack :: String -> BS.ByteString
pack = BS.pack
#else
unpack :: String -> String
unpack = id
pack :: String -> String
pack = id
#endif
#else
import System.IO
#endif
data MOptions = MOptions
{ oDir :: FilePath
, oPrefix :: String
, oSuffix :: String
}
defaults :: MOptions
defaults = MOptions {oDir = "", oPrefix = "", oSuffix = ""}
options :: [OptDescr (MOptions -> MOptions)]
options =
[ Option "d" ["dir"] (ReqArg (\x o -> o { oDir = x }) "") ""
, Option "p" ["prefix"] (ReqArg (\x o -> o { oPrefix = x }) "") ""
, Option "s" ["suffix"] (ReqArg (\x o -> o { oSuffix = x }) "") ""
]
-- | A list of mail box names and paths to maildirs.
data Mail = Mail [(String, FilePath)] String
deriving (Read, Show)
-- | A list of mail box names, paths to maildirs and display colors.
data MailX = MailX [(String, FilePath, String)] [String] String
deriving (Read, Show)
instance Exec Mail where
alias (Mail _ a) = a
start (Mail ms a) = start (MailX (map (\(n,p) -> (n,p,"")) ms) [] a)
instance Exec MailX where
alias (MailX _ _ a) = a
#ifndef INOTIFY
start _ _ =
hPutStrLn stderr $ "Warning: xmobar is not compiled with -fwith_inotify,"
++ " but the Mail plugin requires it."
#else
start (MailX ms args _) cb = do
vs <- mapM (const $ newTVarIO S.empty) ms
opts <- parseOptsWith options defaults args
let prefix = oPrefix opts
suffix = oSuffix opts
dir = oDir opts
ps = map (\(_,p,_) -> if null dir then p else dir </> p) ms
rs = map (</> "new") ps
ev = [Move, MoveIn, MoveOut, Create, Delete]
ds <- mapM expandHome rs
i <- initINotify
zipWithM_ (\d v -> addWatch i ev d (handle v)) (map pack ds) vs
forM_ (zip ds vs) $ \(d, v) -> do
s <- fmap (S.fromList . filter (not . isPrefixOf "."))
$ getDirectoryContents d
atomically $ modifyTVar v (S.union s)
changeLoop (mapM (fmap S.size . readTVar) vs) $ \ns ->
let showmbx m n c = if c == ""
then m ++ show n
else "<fc=" ++ c ++ ">" ++ m ++ show n ++ "</fc>"
cnts = [showmbx m n c | ((m,_,c), n) <- zip ms ns , n /= 0 ]
in cb $ if null cnts then "" else prefix ++ unwords cnts ++ suffix
handle :: TVar (Set String) -> Event -> IO ()
handle v e = atomically $ modifyTVar v $ case e of
Created {} -> create
MovedIn {} -> create
Deleted {} -> delete
MovedOut {} -> delete
_ -> id
where
delete = S.delete ((unpack . filePath) e)
create = S.insert ((unpack . filePath) e)
#endif
|