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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
|
{-#LANGUAGE CPP #-}
{-#LANGUAGE RecordWildCards#-}
-----------------------------------------------------------------------------
-- |
-- Module : Plugins.Monitors.Cpu
-- Copyright : (c) 2011, 2017, 2022 Jose Antonio Ortega Ruiz
-- (c) 2007-2010 Andrea Rossato
-- License : BSD-style (see LICENSE)
--
-- Maintainer : Jose A. Ortega Ruiz <jao@gnu.org>
-- Stability : unstable
-- Portability : unportable
--
-- A cpu monitor for Xmobar
--
-----------------------------------------------------------------------------
module Xmobar.Plugins.Monitors.Cpu
( startCpu
, runCpu
, cpuConfig
, MC.CpuDataRef
, CpuOpts
, CpuArguments
, MC.parseCpu
, getArguments
) where
import Xmobar.Plugins.Monitors.Common
import Data.IORef (newIORef)
import System.Console.GetOpt
import Xmobar.Run.Timer (doEveryTenthSeconds)
import Control.Monad (void)
import Xmobar.Plugins.Monitors.Cpu.Common (CpuData(..))
#if defined(freebsd_HOST_OS)
import qualified Xmobar.Plugins.Monitors.Cpu.FreeBSD as MC
#else
import qualified Xmobar.Plugins.Monitors.Cpu.Linux as MC
#endif
newtype CpuOpts = CpuOpts
{ loadIconPattern :: Maybe IconPattern
}
defaultOpts :: CpuOpts
defaultOpts = CpuOpts
{ loadIconPattern = Nothing
}
options :: [OptDescr (CpuOpts -> CpuOpts)]
options =
[ Option "" ["load-icon-pattern"] (ReqArg (\x o ->
o { loadIconPattern = Just $ parseIconPattern x }) "") ""
]
barField :: String
barField = "bar"
vbarField :: String
vbarField = "vbar"
ipatField :: String
ipatField = "ipat"
totalField :: String
totalField = "total"
userField :: String
userField = "user"
niceField :: String
niceField = "nice"
systemField :: String
systemField = "system"
idleField :: String
idleField = "idle"
iowaitField :: String
iowaitField = "iowait"
cpuConfig :: IO MConfig
cpuConfig =
mkMConfig
"Cpu: <total>%"
[ barField
, vbarField
, ipatField
, totalField
, userField
, niceField
, systemField
, idleField
, iowaitField
]
data Field = Field {
fieldName :: !String,
fieldCompute :: !ShouldCompute
} deriving (Eq, Ord, Show)
data ShouldCompute = Compute | Skip deriving (Eq, Ord, Show)
formatField :: MonitorConfig -> CpuOpts -> CpuData -> Field -> IO String
formatField cpuParams cpuOpts cpuInfo@CpuData {..} Field {..}
| fieldName == barField =
if fieldCompute == Compute
then pShowPercentBar cpuParams (100 * cpuTotal) cpuTotal
else pure []
| fieldName == vbarField =
if fieldCompute == Compute
then pShowVerticalBar cpuParams (100 * cpuTotal) cpuTotal
else pure []
| fieldName == ipatField =
if fieldCompute == Compute
then pShowIconPattern (loadIconPattern cpuOpts) cpuTotal
else pure []
| otherwise =
if fieldCompute == Compute
then pShowPercentWithColors cpuParams (getFieldValue fieldName cpuInfo)
else pure []
getFieldValue :: String -> CpuData -> Float
getFieldValue field CpuData{..}
| field == barField = cpuTotal
| field == vbarField = cpuTotal
| field == ipatField = cpuTotal
| field == totalField = cpuTotal
| field == userField = cpuUser
| field == niceField = cpuNice
| field == systemField = cpuSystem
| field == idleField = cpuIdle
| otherwise = cpuIowait
computeFields :: [String] -> [String] -> [Field]
computeFields [] _ = []
computeFields (x:xs) inputFields =
if x `elem` inputFields
then (Field {fieldName = x, fieldCompute = Compute}) :
computeFields xs inputFields
else (Field {fieldName = x, fieldCompute = Skip}) :
computeFields xs inputFields
formatCpu :: CpuArguments -> CpuData -> IO [String]
formatCpu CpuArguments{..} cpuInfo = do
strs <- mapM (formatField cpuParams cpuOpts cpuInfo) cpuFields
pure $ filter (not . null) strs
getInputFields :: CpuArguments -> [String]
getInputFields CpuArguments{..} = map (\(_,f,_) -> f) cpuInputTemplate
optimizeAllTemplate :: CpuArguments -> CpuArguments
optimizeAllTemplate args@CpuArguments {..} =
let inputFields = getInputFields args
allTemplates =
filter (\(field, _) -> field `elem` inputFields) cpuAllTemplate
in args {cpuAllTemplate = allTemplates}
data CpuArguments =
CpuArguments
{ cpuDataRef :: !MC.CpuDataRef
, cpuParams :: !MonitorConfig
, cpuArgs :: ![String]
, cpuOpts :: !CpuOpts
, cpuInputTemplate :: ![(String, String, String)] -- [("Cpu: ","total","% "),("","user","%")]
, cpuAllTemplate :: ![(String, [(String, String, String)])] -- [("bar",[]),("vbar",[]),("ipat",[]),("total",[]),...]
, cpuFields :: ![Field]
}
getArguments :: [String] -> IO CpuArguments
getArguments cpuArgs = do
initCpuData <- MC.cpuData
cpuDataRef <- newIORef initCpuData
void $ MC.parseCpu cpuDataRef
cpuParams <- computeMonitorConfig cpuArgs cpuConfig
cpuInputTemplate <- runTemplateParser cpuParams
cpuAllTemplate <- runExportParser (pExport cpuParams)
nonOptions <-
case getOpt Permute pluginOptions cpuArgs of
(_, n, []) -> pure n
(_, _, errs) -> error $ "getArguments: " <> show errs
cpuOpts <-
case getOpt Permute options nonOptions of
(o, _, []) -> pure $ foldr id defaultOpts o
(_, _, errs) -> error $ "getArguments options: " <> show errs
let cpuFields =
computeFields
(map fst cpuAllTemplate)
(map (\(_, f, _) -> f) cpuInputTemplate)
pure $ optimizeAllTemplate CpuArguments {..}
runCpu :: CpuArguments -> IO String
runCpu args@CpuArguments {..} = do
cpuValue <- MC.parseCpu cpuDataRef
temMonitorValues <- formatCpu args cpuValue
let templateInput =
TemplateInput
{ temInputTemplate = cpuInputTemplate
, temAllTemplate = cpuAllTemplate
, ..
}
pureParseTemplate cpuParams templateInput
startCpu :: [String] -> Int -> (String -> IO ()) -> IO ()
startCpu args refreshRate cb = do
cpuArgs <- getArguments args
doEveryTenthSeconds refreshRate (runCpu cpuArgs >>= cb)
|