{-# LANGUAGE ForeignFunctionInterface #-}
module Xmobar.Plugins.Monitors.Top.Linux (
timeMemEntries
, meminfos
, scale) where
import Xmobar.Plugins.Monitors.Common (parseFloat, parseInt)
import Xmobar.Plugins.Monitors.Top.Common (MemInfo, TimeEntry)
import Control.Exception (SomeException, handle)
import Data.List (foldl')
import System.Directory (getDirectoryContents)
import System.FilePath ((</>))
import System.IO (IOMode(ReadMode), hGetLine, withFile)
import System.Posix.Unistd (SysVar(ClockTick), getSysVar)
import Foreign.C.Types
foreign import ccall "unistd.h getpagesize"
c_getpagesize :: CInt
pageSize :: Float
pageSize :: Float
pageSize = forall a b. (Integral a, Num b) => a -> b
fromIntegral CInt
c_getpagesize forall a. Fractional a => a -> a -> a
/ Float
1024
processes :: IO [FilePath]
processes :: IO [String]
processes = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. (a -> Bool) -> [a] -> [a]
filter String -> Bool
isPid) (String -> IO [String]
getDirectoryContents String
"/proc")
where isPid :: String -> Bool
isPid = (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
'0'..Char
'9']) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> a
head
statWords :: [String] -> [String]
statWords :: [String] -> [String]
statWords line :: [String]
line@(String
x:String
pn:String
ppn:[String]
xs) =
if forall a. [a] -> a
last String
pn forall a. Eq a => a -> a -> Bool
== Char
')' then [String]
line else [String] -> [String]
statWords (String
xforall a. a -> [a] -> [a]
:(String
pn forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ String
ppn)forall a. a -> [a] -> [a]
:[String]
xs)
statWords [String]
_ = forall a. Int -> a -> [a]
replicate Int
52 String
"0"
getProcessData :: FilePath -> IO [String]
getProcessData :: String -> IO [String]
getProcessData String
pidf =
forall e a. Exception e => (e -> IO a) -> IO a -> IO a
handle SomeException -> IO [String]
ign forall a b. (a -> b) -> a -> b
$ forall r. String -> IOMode -> (Handle -> IO r) -> IO r
withFile (String
"/proc" String -> String -> String
</> String
pidf String -> String -> String
</> String
"stat") IOMode
ReadMode Handle -> IO [String]
readWords
where readWords :: Handle -> IO [String]
readWords = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([String] -> [String]
statWords forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Handle -> IO String
hGetLine
ign :: SomeException -> IO [String]
ign = forall a b. a -> b -> a
const (forall (m :: * -> *) a. Monad m => a -> m a
return []) :: SomeException -> IO [String]
memPages :: [String] -> String
memPages :: [String] -> String
memPages [String]
fs = [String]
fsforall a. [a] -> Int -> a
!!Int
23
ppid :: [String] -> String
ppid :: [String] -> String
ppid [String]
fs = [String]
fsforall a. [a] -> Int -> a
!!Int
3
skip :: [String] -> Bool
skip :: [String] -> Bool
skip [String]
fs = forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
fs forall a. Ord a => a -> a -> Bool
< Int
24 Bool -> Bool -> Bool
|| [String] -> String
memPages [String]
fs forall a. Eq a => a -> a -> Bool
== String
"0" Bool -> Bool -> Bool
|| [String] -> String
ppid [String]
fs forall a. Eq a => a -> a -> Bool
== String
"0"
handleProcesses :: ([String] -> a) -> IO [a]
handleProcesses :: forall a. ([String] -> a) -> IO [a]
handleProcesses [String] -> a
f =
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\[a]
a [String]
p -> if [String] -> Bool
skip [String]
p then [a]
a else [String] -> a
f [String]
p forall a. a -> [a] -> [a]
: [a]
a) [])
(IO [String]
processes forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM String -> IO [String]
getProcessData)
processName :: [String] -> String
processName :: [String] -> String
processName = forall a. Int -> [a] -> [a]
drop Int
1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
init forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. [a] -> Int -> a
!!Int
1)
meminfo :: [String] -> MemInfo
meminfo :: [String] -> MemInfo
meminfo [String]
fs = ([String] -> String
processName [String]
fs, Float
pageSize forall a. Num a => a -> a -> a
* String -> Float
parseFloat ([String]
fsforall a. [a] -> Int -> a
!!Int
23))
meminfos :: IO [MemInfo]
meminfos :: IO [MemInfo]
meminfos = forall a. ([String] -> a) -> IO [a]
handleProcesses [String] -> MemInfo
meminfo
timeMemEntry :: [String] -> (TimeEntry, MemInfo)
timeMemEntry :: [String] -> (TimeEntry, MemInfo)
timeMemEntry [String]
fs = ((Int
p, (String
n, Float
t)), (String
n, Float
r))
where p :: Int
p = String -> Int
parseInt (forall a. [a] -> a
head [String]
fs)
n :: String
n = [String] -> String
processName [String]
fs
t :: Float
t = String -> Float
parseFloat ([String]
fsforall a. [a] -> Int -> a
!!Int
13) forall a. Num a => a -> a -> a
+ String -> Float
parseFloat ([String]
fsforall a. [a] -> Int -> a
!!Int
14)
(String
_, Float
r) = [String] -> MemInfo
meminfo [String]
fs
timeMemEntries :: IO [(TimeEntry, MemInfo)]
timeMemEntries :: IO [(TimeEntry, MemInfo)]
timeMemEntries = forall a. ([String] -> a) -> IO [a]
handleProcesses [String] -> (TimeEntry, MemInfo)
timeMemEntry
scale :: IO Float
scale :: IO Float
scale = do
Integer
cr <- SysVar -> IO Integer
getSysVar SysVar
ClockTick
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
cr forall a. Fractional a => a -> a -> a
/ Float
100