summaryrefslogtreecommitdiffhomepage
path: root/src/Plugins/Monitors/MultiCpu.hs
blob: b8c71ca3ae716ce41c4c7cac7dca0fc6e0363817 (plain)
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
-----------------------------------------------------------------------------
-- |
-- Module      :  Plugins.Monitors.MultiCpu
-- Copyright   :  (c) Jose A Ortega Ruiz
-- License     :  BSD-style (see LICENSE)
--
-- Maintainer  :  Jose A Ortega <jao@gnu.org>
-- Stability   :  unstable
-- Portability :  unportable
--
-- A multi-cpu monitor for Xmobar
--
-----------------------------------------------------------------------------

module Plugins.Monitors.MultiCpu(multiCpuConfig, runMultiCpu) where

import Plugins.Monitors.Common
import qualified Data.ByteString.Lazy.Char8 as B
import Data.List (isPrefixOf, transpose, unfoldr)

multiCpuConfig :: IO MConfig
multiCpuConfig =
  mkMConfig "Cpu: <total>%" $
            map ("auto" ++) monitors
            ++ [ k ++ n | n <- "" : map show [0 :: Int ..]
                        , k <- monitors]
    where monitors = ["bar","total","user","nice","system","idle"]


cpuData :: IO [[Float]]
cpuData = do s <- B.readFile "/proc/stat"
             return $ cpuParser s

cpuParser :: B.ByteString -> [[Float]]
cpuParser = map parseList . cpuLists
  where cpuLists = takeWhile isCpu . map B.words . B.lines
        isCpu (w:_) = "cpu" `isPrefixOf` B.unpack w
        isCpu _ = False
        parseList = map (read . B.unpack) . tail

parseCpuData :: IO [[Float]]
parseCpuData =
  do (as, bs) <- doActionTwiceWithDelay 950000 cpuData
     let p0 = zipWith percent bs as
     return p0

percent :: [Float] -> [Float] -> [Float]
percent b a = if tot > 0 then map (/ tot) $ take 4 dif else [0, 0, 0, 0]
  where dif = zipWith (-) b a
        tot = foldr (+) 0 dif

formatMultiCpus :: [[Float]] -> Monitor [String]
formatMultiCpus [] = return []
formatMultiCpus xs = fmap concat $ mapM formatCpu xs

formatCpu :: [Float] -> Monitor [String]
formatCpu xs
  | length xs < 4 = showPercentsWithColors $ replicate 6 0.0
  | otherwise = let t = foldr (+) 0 $ take 3 xs
                in do b <- showPercentBar (100 * t) t
                      ps <- showPercentsWithColors (t:xs)
                      return (b:ps)

splitEvery :: (Eq a) => Int -> [a] -> [[a]]
splitEvery n = unfoldr (\x -> if x == []
                              then Nothing
                              else Just $ splitAt n x)

groupData :: [String] -> [[String]]
groupData = transpose . tail . splitEvery 6

formatAutoCpus :: [String] -> Monitor [String]
formatAutoCpus [] = return $ replicate 6 ""
formatAutoCpus xs = return $ map unwords (groupData xs)

runMultiCpu :: [String] -> Monitor String
runMultiCpu _ =
  do c <- io parseCpuData
     l <- formatMultiCpus c
     a <- formatAutoCpus l
     parseTemplate (a ++ l)