-----------------------------------------------------------------------------
-- |
-- Module      :  Plugins.Monitors.Disk
-- Copyright   :  (c) 2010, 2011, 2012, 2014, 2018, 2019 Jose A Ortega Ruiz
-- License     :  BSD-style (see LICENSE)
--
-- Maintainer  :  Jose A Ortega Ruiz <jao@gnu.org>
-- Stability   :  unstable
-- Portability :  unportable
--
--  Disk usage and throughput monitors for Xmobar
--
-----------------------------------------------------------------------------

module Xmobar.Plugins.Monitors.Disk (diskUConfig, runDiskU, startDiskIO) where

import Xmobar.Plugins.Monitors.Common
import Xmobar.System.StatFS

import Data.IORef (IORef, newIORef, readIORef, writeIORef)

import Control.Exception (SomeException, handle)
import Control.Monad (zipWithM)
import qualified Data.ByteString.Lazy.Char8 as B
import Data.List (isPrefixOf, find)
import Data.Maybe (catMaybes)
import System.Directory (canonicalizePath, doesFileExist)
import System.Console.GetOpt

data DiskIOOpts = DiskIOOpts
  { DiskIOOpts -> Maybe IconPattern
totalIconPattern :: Maybe IconPattern
  , DiskIOOpts -> Maybe IconPattern
writeIconPattern :: Maybe IconPattern
  , DiskIOOpts -> Maybe IconPattern
readIconPattern :: Maybe IconPattern
  , DiskIOOpts -> Bool
contiguous :: Bool
  }

dioDefaultOpts :: DiskIOOpts
dioDefaultOpts :: DiskIOOpts
dioDefaultOpts = DiskIOOpts :: Maybe IconPattern
-> Maybe IconPattern -> Maybe IconPattern -> Bool -> DiskIOOpts
DiskIOOpts
   { totalIconPattern :: Maybe IconPattern
totalIconPattern = Maybe IconPattern
forall a. Maybe a
Nothing
   , writeIconPattern :: Maybe IconPattern
writeIconPattern = Maybe IconPattern
forall a. Maybe a
Nothing
   , readIconPattern :: Maybe IconPattern
readIconPattern = Maybe IconPattern
forall a. Maybe a
Nothing
   , contiguous :: Bool
contiguous = Bool
False
   }

dioOptions :: [OptDescr (DiskIOOpts -> DiskIOOpts)]
dioOptions :: [OptDescr (DiskIOOpts -> DiskIOOpts)]
dioOptions =
   [ [Char]
-> [[Char]]
-> ArgDescr (DiskIOOpts -> DiskIOOpts)
-> [Char]
-> OptDescr (DiskIOOpts -> DiskIOOpts)
forall a. [Char] -> [[Char]] -> ArgDescr a -> [Char] -> OptDescr a
Option [Char]
"" [[Char]
"total-icon-pattern"] (([Char] -> DiskIOOpts -> DiskIOOpts)
-> [Char] -> ArgDescr (DiskIOOpts -> DiskIOOpts)
forall a. ([Char] -> a) -> [Char] -> ArgDescr a
ReqArg (\[Char]
x DiskIOOpts
o ->
      DiskIOOpts
o { totalIconPattern :: Maybe IconPattern
totalIconPattern = IconPattern -> Maybe IconPattern
forall a. a -> Maybe a
Just (IconPattern -> Maybe IconPattern)
-> IconPattern -> Maybe IconPattern
forall a b. (a -> b) -> a -> b
$ [Char] -> IconPattern
parseIconPattern [Char]
x}) [Char]
"") [Char]
""
   , [Char]
-> [[Char]]
-> ArgDescr (DiskIOOpts -> DiskIOOpts)
-> [Char]
-> OptDescr (DiskIOOpts -> DiskIOOpts)
forall a. [Char] -> [[Char]] -> ArgDescr a -> [Char] -> OptDescr a
Option [Char]
"" [[Char]
"write-icon-pattern"] (([Char] -> DiskIOOpts -> DiskIOOpts)
-> [Char] -> ArgDescr (DiskIOOpts -> DiskIOOpts)
forall a. ([Char] -> a) -> [Char] -> ArgDescr a
ReqArg (\[Char]
x DiskIOOpts
o ->
      DiskIOOpts
o { writeIconPattern :: Maybe IconPattern
writeIconPattern = IconPattern -> Maybe IconPattern
forall a. a -> Maybe a
Just (IconPattern -> Maybe IconPattern)
-> IconPattern -> Maybe IconPattern
forall a b. (a -> b) -> a -> b
$ [Char] -> IconPattern
parseIconPattern [Char]
x}) [Char]
"") [Char]
""
   , [Char]
-> [[Char]]
-> ArgDescr (DiskIOOpts -> DiskIOOpts)
-> [Char]
-> OptDescr (DiskIOOpts -> DiskIOOpts)
forall a. [Char] -> [[Char]] -> ArgDescr a -> [Char] -> OptDescr a
Option [Char]
"" [[Char]
"read-icon-pattern"] (([Char] -> DiskIOOpts -> DiskIOOpts)
-> [Char] -> ArgDescr (DiskIOOpts -> DiskIOOpts)
forall a. ([Char] -> a) -> [Char] -> ArgDescr a
ReqArg (\[Char]
x DiskIOOpts
o ->
      DiskIOOpts
o { readIconPattern :: Maybe IconPattern
readIconPattern = IconPattern -> Maybe IconPattern
forall a. a -> Maybe a
Just (IconPattern -> Maybe IconPattern)
-> IconPattern -> Maybe IconPattern
forall a b. (a -> b) -> a -> b
$ [Char] -> IconPattern
parseIconPattern [Char]
x}) [Char]
"") [Char]
""
   , [Char]
-> [[Char]]
-> ArgDescr (DiskIOOpts -> DiskIOOpts)
-> [Char]
-> OptDescr (DiskIOOpts -> DiskIOOpts)
forall a. [Char] -> [[Char]] -> ArgDescr a -> [Char] -> OptDescr a
Option [Char]
"c" [[Char]
"contiguous"] ((DiskIOOpts -> DiskIOOpts) -> ArgDescr (DiskIOOpts -> DiskIOOpts)
forall a. a -> ArgDescr a
NoArg (\DiskIOOpts
o -> DiskIOOpts
o {contiguous :: Bool
contiguous = Bool
True})) [Char]
""
   ]

diskIOConfig :: IO MConfig
diskIOConfig :: IO MConfig
diskIOConfig = [Char] -> [[Char]] -> IO MConfig
mkMConfig [Char]
"" [[Char]
"total", [Char]
"read", [Char]
"write"
                            ,[Char]
"totalb", [Char]
"readb", [Char]
"writeb"
                            ,[Char]
"totalbar", [Char]
"readbar", [Char]
"writebar"
                            ,[Char]
"totalbbar", [Char]
"readbbar", [Char]
"writebbar"
                            ,[Char]
"totalvbar", [Char]
"readvbar", [Char]
"writevbar"
                            ,[Char]
"totalbvbar", [Char]
"readbvbar", [Char]
"writebvbar"
                            ,[Char]
"totalipat", [Char]
"readipat", [Char]
"writeipat"
                            ,[Char]
"totalbipat", [Char]
"readbipat", [Char]
"writebipat"
                            ]

data DiskUOpts = DiskUOpts
  { DiskUOpts -> Maybe IconPattern
freeIconPattern :: Maybe IconPattern
  , DiskUOpts -> Maybe IconPattern
usedIconPattern :: Maybe IconPattern
  , DiskUOpts -> Bool
contiguousU :: Bool
  }

duDefaultOpts :: DiskUOpts
duDefaultOpts :: DiskUOpts
duDefaultOpts = DiskUOpts :: Maybe IconPattern -> Maybe IconPattern -> Bool -> DiskUOpts
DiskUOpts
   { freeIconPattern :: Maybe IconPattern
freeIconPattern = Maybe IconPattern
forall a. Maybe a
Nothing
   , usedIconPattern :: Maybe IconPattern
usedIconPattern = Maybe IconPattern
forall a. Maybe a
Nothing
   , contiguousU :: Bool
contiguousU = Bool
False
   }

duOptions :: [OptDescr (DiskUOpts -> DiskUOpts)]
duOptions :: [OptDescr (DiskUOpts -> DiskUOpts)]
duOptions =
   [ [Char]
-> [[Char]]
-> ArgDescr (DiskUOpts -> DiskUOpts)
-> [Char]
-> OptDescr (DiskUOpts -> DiskUOpts)
forall a. [Char] -> [[Char]] -> ArgDescr a -> [Char] -> OptDescr a
Option [Char]
"" [[Char]
"free-icon-pattern"] (([Char] -> DiskUOpts -> DiskUOpts)
-> [Char] -> ArgDescr (DiskUOpts -> DiskUOpts)
forall a. ([Char] -> a) -> [Char] -> ArgDescr a
ReqArg (\[Char]
x DiskUOpts
o ->
      DiskUOpts
o { freeIconPattern :: Maybe IconPattern
freeIconPattern = IconPattern -> Maybe IconPattern
forall a. a -> Maybe a
Just (IconPattern -> Maybe IconPattern)
-> IconPattern -> Maybe IconPattern
forall a b. (a -> b) -> a -> b
$ [Char] -> IconPattern
parseIconPattern [Char]
x}) [Char]
"") [Char]
""
   , [Char]
-> [[Char]]
-> ArgDescr (DiskUOpts -> DiskUOpts)
-> [Char]
-> OptDescr (DiskUOpts -> DiskUOpts)
forall a. [Char] -> [[Char]] -> ArgDescr a -> [Char] -> OptDescr a
Option [Char]
"" [[Char]
"used-icon-pattern"] (([Char] -> DiskUOpts -> DiskUOpts)
-> [Char] -> ArgDescr (DiskUOpts -> DiskUOpts)
forall a. ([Char] -> a) -> [Char] -> ArgDescr a
ReqArg (\[Char]
x DiskUOpts
o ->
      DiskUOpts
o { usedIconPattern :: Maybe IconPattern
usedIconPattern = IconPattern -> Maybe IconPattern
forall a. a -> Maybe a
Just (IconPattern -> Maybe IconPattern)
-> IconPattern -> Maybe IconPattern
forall a b. (a -> b) -> a -> b
$ [Char] -> IconPattern
parseIconPattern [Char]
x}) [Char]
"") [Char]
""
   , [Char]
-> [[Char]]
-> ArgDescr (DiskUOpts -> DiskUOpts)
-> [Char]
-> OptDescr (DiskUOpts -> DiskUOpts)
forall a. [Char] -> [[Char]] -> ArgDescr a -> [Char] -> OptDescr a
Option [Char]
"c" [[Char]
"contiguous"] ((DiskUOpts -> DiskUOpts) -> ArgDescr (DiskUOpts -> DiskUOpts)
forall a. a -> ArgDescr a
NoArg (\DiskUOpts
o -> DiskUOpts
o {contiguousU :: Bool
contiguousU = Bool
True})) [Char]
""
   ]

diskUConfig :: IO MConfig
diskUConfig :: IO MConfig
diskUConfig = [Char] -> [[Char]] -> IO MConfig
mkMConfig [Char]
""
              [ [Char]
"size", [Char]
"free", [Char]
"used", [Char]
"freep", [Char]
"usedp"
              , [Char]
"freebar", [Char]
"freevbar", [Char]
"freeipat"
              , [Char]
"usedbar", [Char]
"usedvbar", [Char]
"usedipat"
              ]

type DevName = String
type Path = String
type DevDataRef = IORef [(DevName, [Float])]

mountedDevices :: [String] -> IO [(DevName, Path)]
mountedDevices :: [[Char]] -> IO [([Char], [Char])]
mountedDevices [[Char]]
req = do
  ByteString
s <- [Char] -> IO ByteString
B.readFile [Char]
"/etc/mtab"
  [Maybe ([Char], [Char])] -> [([Char], [Char])]
parse ([Maybe ([Char], [Char])] -> [([Char], [Char])])
-> IO [Maybe ([Char], [Char])] -> IO [([Char], [Char])]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` (([Char], [Char]) -> IO (Maybe ([Char], [Char])))
-> [([Char], [Char])] -> IO [Maybe ([Char], [Char])]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ([Char], [Char]) -> IO (Maybe ([Char], [Char]))
forall b. ([Char], b) -> IO (Maybe ([Char], b))
mbcanon (ByteString -> [([Char], [Char])]
devs ByteString
s)
  where
    mbcanon :: ([Char], b) -> IO (Maybe ([Char], b))
mbcanon ([Char]
d, b
p) = [Char] -> IO Bool
doesFileExist [Char]
d IO Bool
-> (Bool -> IO (Maybe ([Char], b))) -> IO (Maybe ([Char], b))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Bool
e ->
                     if Bool
e
                        then ([Char], b) -> Maybe ([Char], b)
forall a. a -> Maybe a
Just (([Char], b) -> Maybe ([Char], b))
-> IO ([Char], b) -> IO (Maybe ([Char], b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` ([Char], b) -> IO ([Char], b)
forall b. ([Char], b) -> IO ([Char], b)
canon ([Char]
d,b
p)
                        else Maybe ([Char], b) -> IO (Maybe ([Char], b))
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ([Char], b)
forall a. Maybe a
Nothing
    canon :: ([Char], b) -> IO ([Char], b)
canon ([Char]
d, b
p) = do {[Char]
d' <- [Char] -> IO [Char]
canonicalizePath [Char]
d; ([Char], b) -> IO ([Char], b)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char]
d', b
p)}
    devs :: ByteString -> [([Char], [Char])]
devs = (([Char], [Char]) -> Bool)
-> [([Char], [Char])] -> [([Char], [Char])]
forall a. (a -> Bool) -> [a] -> [a]
filter ([Char], [Char]) -> Bool
forall b. ([Char], b) -> Bool
isDev ([([Char], [Char])] -> [([Char], [Char])])
-> (ByteString -> [([Char], [Char])])
-> ByteString
-> [([Char], [Char])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> ([Char], [Char]))
-> [ByteString] -> [([Char], [Char])]
forall a b. (a -> b) -> [a] -> [b]
map ([ByteString] -> ([Char], [Char])
firstTwo ([ByteString] -> ([Char], [Char]))
-> (ByteString -> [ByteString]) -> ByteString -> ([Char], [Char])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
B.words) ([ByteString] -> [([Char], [Char])])
-> (ByteString -> [ByteString]) -> ByteString -> [([Char], [Char])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
B.lines
    parse :: [Maybe ([Char], [Char])] -> [([Char], [Char])]
parse = (([Char], [Char]) -> ([Char], [Char]))
-> [([Char], [Char])] -> [([Char], [Char])]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], [Char]) -> ([Char], [Char])
forall a b. ([a], b) -> ([a], b)
undev ([([Char], [Char])] -> [([Char], [Char])])
-> ([Maybe ([Char], [Char])] -> [([Char], [Char])])
-> [Maybe ([Char], [Char])]
-> [([Char], [Char])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Char], [Char]) -> Bool)
-> [([Char], [Char])] -> [([Char], [Char])]
forall a. (a -> Bool) -> [a] -> [a]
filter ([Char], [Char]) -> Bool
isReq ([([Char], [Char])] -> [([Char], [Char])])
-> ([Maybe ([Char], [Char])] -> [([Char], [Char])])
-> [Maybe ([Char], [Char])]
-> [([Char], [Char])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe ([Char], [Char])] -> [([Char], [Char])]
forall a. [Maybe a] -> [a]
catMaybes
    firstTwo :: [ByteString] -> ([Char], [Char])
firstTwo (ByteString
a:ByteString
b:[ByteString]
_) = (ByteString -> [Char]
B.unpack ByteString
a, ByteString -> [Char]
B.unpack ByteString
b)
    firstTwo [ByteString]
_ = ([Char]
"", [Char]
"")
    isDev :: ([Char], b) -> Bool
isDev ([Char]
d, b
_) = [Char]
"/dev/" [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` [Char]
d
    isReq :: ([Char], [Char]) -> Bool
isReq ([Char]
d, [Char]
p) = [Char]
p [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]]
req Bool -> Bool -> Bool
|| Int -> [Char] -> [Char]
forall a. Int -> [a] -> [a]
drop Int
5 [Char]
d [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]]
req
    undev :: ([a], b) -> ([a], b)
undev ([a]
d, b
f) = (Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
5 [a]
d, b
f)

diskDevices :: [String] -> IO [(DevName, Path)]
diskDevices :: [[Char]] -> IO [([Char], [Char])]
diskDevices [[Char]]
req = do
  ByteString
s <- [Char] -> IO ByteString
B.readFile [Char]
"/proc/diskstats"
  [([Char], [Char])] -> [([Char], [Char])]
parse ([([Char], [Char])] -> [([Char], [Char])])
-> IO [([Char], [Char])] -> IO [([Char], [Char])]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` (([Char], [Char]) -> IO ([Char], [Char]))
-> [([Char], [Char])] -> IO [([Char], [Char])]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ([Char], [Char]) -> IO ([Char], [Char])
forall b. ([Char], b) -> IO ([Char], b)
canon (ByteString -> [([Char], [Char])]
devs ByteString
s)
  where
    canon :: ([Char], b) -> IO ([Char], b)
canon ([Char]
d, b
p) = do {[Char]
d' <- [Char] -> IO [Char]
canonicalizePath [Char]
d; ([Char], b) -> IO ([Char], b)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char]
d', b
p)}
    devs :: ByteString -> [([Char], [Char])]
devs = (ByteString -> ([Char], [Char]))
-> [ByteString] -> [([Char], [Char])]
forall a b. (a -> b) -> [a] -> [b]
map ([ByteString] -> ([Char], [Char])
third ([ByteString] -> ([Char], [Char]))
-> (ByteString -> [ByteString]) -> ByteString -> ([Char], [Char])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
B.words) ([ByteString] -> [([Char], [Char])])
-> (ByteString -> [ByteString]) -> ByteString -> [([Char], [Char])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
B.lines
    parse :: [([Char], [Char])] -> [([Char], [Char])]
parse = (([Char], [Char]) -> ([Char], [Char]))
-> [([Char], [Char])] -> [([Char], [Char])]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], [Char]) -> ([Char], [Char])
forall a b. ([a], b) -> ([a], b)
undev ([([Char], [Char])] -> [([Char], [Char])])
-> ([([Char], [Char])] -> [([Char], [Char])])
-> [([Char], [Char])]
-> [([Char], [Char])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (([Char], [Char]) -> Bool)
-> [([Char], [Char])] -> [([Char], [Char])]
forall a. (a -> Bool) -> [a] -> [a]
filter ([Char], [Char]) -> Bool
isReq
    third :: [ByteString] -> ([Char], [Char])
third (ByteString
_:ByteString
_:ByteString
c:[ByteString]
_) = ([Char]
"/dev/" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ ByteString -> [Char]
B.unpack ByteString
c, ByteString -> [Char]
B.unpack ByteString
c)
    third [ByteString]
_ = ([Char]
"", [Char]
"")
    isReq :: ([Char], [Char]) -> Bool
isReq ([Char]
d, [Char]
p) = [Char]
p [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]]
req Bool -> Bool -> Bool
|| Int -> [Char] -> [Char]
forall a. Int -> [a] -> [a]
drop Int
5 [Char]
d [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]]
req
    undev :: ([a], b) -> ([a], b)
undev ([a]
d, b
f) = (Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
5 [a]
d, b
f)

mountedOrDiskDevices :: [String] -> IO [(DevName, Path)]
mountedOrDiskDevices :: [[Char]] -> IO [([Char], [Char])]
mountedOrDiskDevices [[Char]]
req = do
  [([Char], [Char])]
mnt <- [[Char]] -> IO [([Char], [Char])]
mountedDevices [[Char]]
req
  case [([Char], [Char])]
mnt of
       []    -> [[Char]] -> IO [([Char], [Char])]
diskDevices [[Char]]
req
       [([Char], [Char])]
other -> [([Char], [Char])] -> IO [([Char], [Char])]
forall (m :: * -> *) a. Monad m => a -> m a
return [([Char], [Char])]
other

diskData :: IO [(DevName, [Float])]
diskData :: IO [([Char], [Float])]
diskData = do
  ByteString
s <- [Char] -> IO ByteString
B.readFile [Char]
"/proc/diskstats"
  let extract :: [[Char]] -> ([Char], [b])
extract [[Char]]
ws = ([[Char]] -> [Char]
forall a. [a] -> a
head [[Char]]
ws, ([Char] -> b) -> [[Char]] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map [Char] -> b
forall a. Read a => [Char] -> a
read ([[Char]] -> [[Char]]
forall a. [a] -> [a]
tail [[Char]]
ws))
  [([Char], [Float])] -> IO [([Char], [Float])]
forall (m :: * -> *) a. Monad m => a -> m a
return ([([Char], [Float])] -> IO [([Char], [Float])])
-> [([Char], [Float])] -> IO [([Char], [Float])]
forall a b. (a -> b) -> a -> b
$ (ByteString -> ([Char], [Float]))
-> [ByteString] -> [([Char], [Float])]
forall a b. (a -> b) -> [a] -> [b]
map ([[Char]] -> ([Char], [Float])
forall b. Read b => [[Char]] -> ([Char], [b])
extract ([[Char]] -> ([Char], [Float]))
-> (ByteString -> [[Char]]) -> ByteString -> ([Char], [Float])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> [Char]) -> [ByteString] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> [Char]
B.unpack ([ByteString] -> [[Char]])
-> (ByteString -> [ByteString]) -> ByteString -> [[Char]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [ByteString] -> [ByteString]
forall a. Int -> [a] -> [a]
drop Int
2 ([ByteString] -> [ByteString])
-> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
B.words) (ByteString -> [ByteString]
B.lines ByteString
s)

mountedData :: DevDataRef -> [DevName] -> IO [(DevName, [Float])]
mountedData :: DevDataRef -> [[Char]] -> IO [([Char], [Float])]
mountedData DevDataRef
dref [[Char]]
devs = do
  [([Char], [Float])]
dt <- DevDataRef -> IO [([Char], [Float])]
forall a. IORef a -> IO a
readIORef DevDataRef
dref
  [([Char], [Float])]
dt' <- IO [([Char], [Float])]
diskData
  DevDataRef -> [([Char], [Float])] -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef DevDataRef
dref [([Char], [Float])]
dt'
  [([Char], [Float])] -> IO [([Char], [Float])]
forall (m :: * -> *) a. Monad m => a -> m a
return ([([Char], [Float])] -> IO [([Char], [Float])])
-> [([Char], [Float])] -> IO [([Char], [Float])]
forall a b. (a -> b) -> a -> b
$ ([Char] -> ([Char], [Float])) -> [[Char]] -> [([Char], [Float])]
forall a b. (a -> b) -> [a] -> [b]
map ([([Char], [Float])] -> [Char] -> ([Char], [Float])
parseDev ((([Char], [Float]) -> ([Char], [Float]) -> ([Char], [Float]))
-> [([Char], [Float])]
-> [([Char], [Float])]
-> [([Char], [Float])]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith ([Char], [Float]) -> ([Char], [Float]) -> ([Char], [Float])
forall c a a. Num c => (a, [c]) -> (a, [c]) -> (a, [c])
diff [([Char], [Float])]
dt' [([Char], [Float])]
dt)) [[Char]]
devs
  where diff :: (a, [c]) -> (a, [c]) -> (a, [c])
diff (a
dev, [c]
xs) (a
_, [c]
ys) = (a
dev, (c -> c -> c) -> [c] -> [c] -> [c]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (-) [c]
xs [c]
ys)


parseDev :: [(DevName, [Float])] -> DevName -> (DevName, [Float])
parseDev :: [([Char], [Float])] -> [Char] -> ([Char], [Float])
parseDev [([Char], [Float])]
dat [Char]
dev =
  case (([Char], [Float]) -> Bool)
-> [([Char], [Float])] -> Maybe ([Char], [Float])
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (([Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
==[Char]
dev) ([Char] -> Bool)
-> (([Char], [Float]) -> [Char]) -> ([Char], [Float]) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char], [Float]) -> [Char]
forall a b. (a, b) -> a
fst) [([Char], [Float])]
dat of
    Maybe ([Char], [Float])
Nothing -> ([Char]
dev, [Float
0, Float
0, Float
0])
    Just ([Char]
_, [Float]
xs) ->
      let r :: Float
r = Float
4096 Float -> Float -> Float
forall a. Num a => a -> a -> a
* [Float]
xs [Float] -> Int -> Float
forall a. [a] -> Int -> a
!! Int
2
          w :: Float
w = Float
4096 Float -> Float -> Float
forall a. Num a => a -> a -> a
* [Float]
xs [Float] -> Int -> Float
forall a. [a] -> Int -> a
!! Int
6
          t :: Float
t = Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
w
          rSp :: Float
rSp = Float -> Float -> Float
forall p. (Eq p, Fractional p) => p -> p -> p
speed Float
r ([Float]
xs [Float] -> Int -> Float
forall a. [a] -> Int -> a
!! Int
3)
          wSp :: Float
wSp = Float -> Float -> Float
forall p. (Eq p, Fractional p) => p -> p -> p
speed Float
w ([Float]
xs [Float] -> Int -> Float
forall a. [a] -> Int -> a
!! Int
7)
          sp :: Float
sp =  Float -> Float -> Float
forall p. (Eq p, Fractional p) => p -> p -> p
speed Float
t ([Float]
xs [Float] -> Int -> Float
forall a. [a] -> Int -> a
!! Int
3 Float -> Float -> Float
forall a. Num a => a -> a -> a
+ [Float]
xs [Float] -> Int -> Float
forall a. [a] -> Int -> a
!! Int
7)
          speed :: p -> p -> p
speed p
x p
d = if p
d p -> p -> Bool
forall a. Eq a => a -> a -> Bool
== p
0 then p
0 else p
x p -> p -> p
forall a. Fractional a => a -> a -> a
/ p
d
          dat' :: [Float]
dat' = if [Float] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Float]
xs Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
6
                 then [Float
sp, Float
rSp, Float
wSp, Float
t, Float
r, Float
w]
                 else [Float
0, Float
0, Float
0, Float
0, Float
0, Float
0]
      in ([Char]
dev, [Float]
dat')

speedToStr :: Float -> String
speedToStr :: Float -> [Char]
speedToStr = Int -> Int -> Float -> [Char]
showWithUnits Int
2 Int
1 (Float -> [Char]) -> (Float -> Float) -> Float -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
1024)

sizeToStr :: Integer -> String
sizeToStr :: Integer -> [Char]
sizeToStr = Int -> Int -> Float -> [Char]
showWithUnits Int
3 Int
0 (Float -> [Char]) -> (Integer -> Float) -> Integer -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral

findTempl :: DevName -> Path -> [(String, String)] -> String
findTempl :: [Char] -> [Char] -> [([Char], [Char])] -> [Char]
findTempl [Char]
dev [Char]
path [([Char], [Char])]
disks =
  case (([Char], [Char]) -> Bool)
-> [([Char], [Char])] -> Maybe ([Char], [Char])
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ([Char], [Char]) -> Bool
forall b. ([Char], b) -> Bool
devOrPath [([Char], [Char])]
disks of
    Just ([Char]
_, [Char]
t) -> [Char]
t
    Maybe ([Char], [Char])
Nothing -> [Char]
""
  where devOrPath :: ([Char], b) -> Bool
devOrPath ([Char]
d, b
_) = [Char]
d [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
dev Bool -> Bool -> Bool
|| [Char]
d [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
path

devTemplates :: [(String, String)]
                -> [(DevName, Path)]
                -> [(DevName, [Float])]
                -> [(String, [Float])]
devTemplates :: [([Char], [Char])]
-> [([Char], [Char])] -> [([Char], [Float])] -> [([Char], [Float])]
devTemplates [([Char], [Char])]
disks [([Char], [Char])]
mounted [([Char], [Float])]
dat =
  (([Char], [Char]) -> ([Char], [Float]))
-> [([Char], [Char])] -> [([Char], [Float])]
forall a b. (a -> b) -> [a] -> [b]
map (\([Char]
d, [Char]
p) -> ([Char] -> [Char] -> [([Char], [Char])] -> [Char]
findTempl [Char]
d [Char]
p [([Char], [Char])]
disks, [Char] -> [Float]
findData [Char]
d)) [([Char], [Char])]
mounted
  where findData :: [Char] -> [Float]
findData [Char]
dev = case (([Char], [Float]) -> Bool)
-> [([Char], [Float])] -> Maybe ([Char], [Float])
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (([Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
==[Char]
dev) ([Char] -> Bool)
-> (([Char], [Float]) -> [Char]) -> ([Char], [Float]) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char], [Float]) -> [Char]
forall a b. (a, b) -> a
fst) [([Char], [Float])]
dat of
                         Maybe ([Char], [Float])
Nothing -> [Float
0, Float
0, Float
0]
                         Just ([Char]
_, [Float]
xs) -> [Float]
xs

runDiskIO' :: DiskIOOpts -> (String, [Float]) -> Monitor String
runDiskIO' :: DiskIOOpts -> ([Char], [Float]) -> Monitor [Char]
runDiskIO' DiskIOOpts
opts ([Char]
tmp, [Float]
xs) = do
  [[Char]]
s <- (Float -> Monitor [Char]) -> [Float] -> ReaderT MConfig IO [[Char]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ((Float -> [Char]) -> Float -> Monitor [Char]
forall a. (Num a, Ord a) => (a -> [Char]) -> a -> Monitor [Char]
showWithColors Float -> [Char]
speedToStr) [Float]
xs
  [[Char]]
b <- (Float -> Monitor [Char]) -> [Float] -> ReaderT MConfig IO [[Char]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Float -> Float -> Monitor [Char]
showLogBar Float
0.8) [Float]
xs
  [[Char]]
vb <- (Float -> Monitor [Char]) -> [Float] -> ReaderT MConfig IO [[Char]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Float -> Float -> Monitor [Char]
showLogVBar Float
0.8) [Float]
xs
  [[Char]]
ipat <- ((DiskIOOpts -> Maybe IconPattern, Float) -> Monitor [Char])
-> [(DiskIOOpts -> Maybe IconPattern, Float)]
-> ReaderT MConfig IO [[Char]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (\(DiskIOOpts -> Maybe IconPattern
f,Float
v) -> Maybe IconPattern -> Float -> Float -> Monitor [Char]
showLogIconPattern (DiskIOOpts -> Maybe IconPattern
f DiskIOOpts
opts) Float
0.8 Float
v)
        ([(DiskIOOpts -> Maybe IconPattern, Float)]
 -> ReaderT MConfig IO [[Char]])
-> [(DiskIOOpts -> Maybe IconPattern, Float)]
-> ReaderT MConfig IO [[Char]]
forall a b. (a -> b) -> a -> b
$ [DiskIOOpts -> Maybe IconPattern]
-> [Float] -> [(DiskIOOpts -> Maybe IconPattern, Float)]
forall a b. [a] -> [b] -> [(a, b)]
zip [DiskIOOpts -> Maybe IconPattern
totalIconPattern, DiskIOOpts -> Maybe IconPattern
readIconPattern, DiskIOOpts -> Maybe IconPattern
writeIconPattern
              , DiskIOOpts -> Maybe IconPattern
totalIconPattern, DiskIOOpts -> Maybe IconPattern
readIconPattern, DiskIOOpts -> Maybe IconPattern
writeIconPattern]
              [Float]
xs
  [Char] -> Selector [Char] -> Monitor ()
forall a. a -> Selector a -> Monitor ()
setConfigValue [Char]
tmp Selector [Char]
template
  [[Char]] -> Monitor [Char]
parseTemplate ([[Char]] -> Monitor [Char]) -> [[Char]] -> Monitor [Char]
forall a b. (a -> b) -> a -> b
$ [[Char]]
s [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
b [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
vb [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
ipat

runDiskIO :: DevDataRef -> [(String, String)] -> [String] -> Monitor String
runDiskIO :: DevDataRef -> [([Char], [Char])] -> [[Char]] -> Monitor [Char]
runDiskIO DevDataRef
dref [([Char], [Char])]
disks [[Char]]
argv = do
  DiskIOOpts
opts <- IO DiskIOOpts -> Monitor DiskIOOpts
forall a. IO a -> Monitor a
io (IO DiskIOOpts -> Monitor DiskIOOpts)
-> IO DiskIOOpts -> Monitor DiskIOOpts
forall a b. (a -> b) -> a -> b
$ [OptDescr (DiskIOOpts -> DiskIOOpts)]
-> DiskIOOpts -> [[Char]] -> IO DiskIOOpts
forall opts.
[OptDescr (opts -> opts)] -> opts -> [[Char]] -> IO opts
parseOptsWith [OptDescr (DiskIOOpts -> DiskIOOpts)]
dioOptions DiskIOOpts
dioDefaultOpts [[Char]]
argv
  [([Char], [Char])]
dev <- IO [([Char], [Char])] -> Monitor [([Char], [Char])]
forall a. IO a -> Monitor a
io (IO [([Char], [Char])] -> Monitor [([Char], [Char])])
-> IO [([Char], [Char])] -> Monitor [([Char], [Char])]
forall a b. (a -> b) -> a -> b
$ [[Char]] -> IO [([Char], [Char])]
mountedOrDiskDevices ((([Char], [Char]) -> [Char]) -> [([Char], [Char])] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], [Char]) -> [Char]
forall a b. (a, b) -> a
fst [([Char], [Char])]
disks)
  [([Char], [Float])]
dat <- IO [([Char], [Float])] -> Monitor [([Char], [Float])]
forall a. IO a -> Monitor a
io (IO [([Char], [Float])] -> Monitor [([Char], [Float])])
-> IO [([Char], [Float])] -> Monitor [([Char], [Float])]
forall a b. (a -> b) -> a -> b
$ DevDataRef -> [[Char]] -> IO [([Char], [Float])]
mountedData DevDataRef
dref ((([Char], [Char]) -> [Char]) -> [([Char], [Char])] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], [Char]) -> [Char]
forall a b. (a, b) -> a
fst [([Char], [Char])]
dev)
  [[Char]]
strs <- (([Char], [Float]) -> Monitor [Char])
-> [([Char], [Float])] -> ReaderT MConfig IO [[Char]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (DiskIOOpts -> ([Char], [Float]) -> Monitor [Char]
runDiskIO' DiskIOOpts
opts) ([([Char], [Float])] -> ReaderT MConfig IO [[Char]])
-> [([Char], [Float])] -> ReaderT MConfig IO [[Char]]
forall a b. (a -> b) -> a -> b
$ [([Char], [Char])]
-> [([Char], [Char])] -> [([Char], [Float])] -> [([Char], [Float])]
devTemplates [([Char], [Char])]
disks [([Char], [Char])]
dev [([Char], [Float])]
dat
  [Char] -> Monitor [Char]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> Monitor [Char]) -> [Char] -> Monitor [Char]
forall a b. (a -> b) -> a -> b
$ (if DiskIOOpts -> Bool
contiguous DiskIOOpts
opts then [[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat else [[Char]] -> [Char]
unwords) [[Char]]
strs

startDiskIO :: [(String, String)] ->
               [String] -> Int -> (String -> IO ()) -> IO ()
startDiskIO :: [([Char], [Char])] -> [[Char]] -> Int -> ([Char] -> IO ()) -> IO ()
startDiskIO [([Char], [Char])]
disks [[Char]]
args Int
rate [Char] -> IO ()
cb = do
  [([Char], [Char])]
dev <- [[Char]] -> IO [([Char], [Char])]
mountedOrDiskDevices ((([Char], [Char]) -> [Char]) -> [([Char], [Char])] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], [Char]) -> [Char]
forall a b. (a, b) -> a
fst [([Char], [Char])]
disks)
  DevDataRef
dref <- [([Char], [Float])] -> IO DevDataRef
forall a. a -> IO (IORef a)
newIORef ((([Char], [Char]) -> ([Char], [Float]))
-> [([Char], [Char])] -> [([Char], [Float])]
forall a b. (a -> b) -> [a] -> [b]
map (\([Char], [Char])
d -> (([Char], [Char]) -> [Char]
forall a b. (a, b) -> a
fst ([Char], [Char])
d, Float -> [Float]
forall a. a -> [a]
repeat Float
0)) [([Char], [Char])]
dev)
  [([Char], [Float])]
_ <- DevDataRef -> [[Char]] -> IO [([Char], [Float])]
mountedData DevDataRef
dref ((([Char], [Char]) -> [Char]) -> [([Char], [Char])] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], [Char]) -> [Char]
forall a b. (a, b) -> a
fst [([Char], [Char])]
dev)
  [[Char]]
-> IO MConfig
-> ([[Char]] -> Monitor [Char])
-> Int
-> ([Char] -> IO ())
-> IO ()
runM [[Char]]
args IO MConfig
diskIOConfig (DevDataRef -> [([Char], [Char])] -> [[Char]] -> Monitor [Char]
runDiskIO DevDataRef
dref [([Char], [Char])]
disks) Int
rate [Char] -> IO ()
cb

fsStats :: String -> IO [Integer]
fsStats :: [Char] -> IO [Integer]
fsStats [Char]
path = do
  Maybe FileSystemStats
stats <- [Char] -> IO (Maybe FileSystemStats)
getFileSystemStats [Char]
path
  case Maybe FileSystemStats
stats of
    Maybe FileSystemStats
Nothing -> [Integer] -> IO [Integer]
forall (m :: * -> *) a. Monad m => a -> m a
return [Integer
0, Integer
0, Integer
0]
    Just FileSystemStats
f -> let tot :: Integer
tot = FileSystemStats -> Integer
fsStatByteCount FileSystemStats
f
                  free :: Integer
free = FileSystemStats -> Integer
fsStatBytesAvailable FileSystemStats
f
                  used :: Integer
used = FileSystemStats -> Integer
fsStatBytesUsed FileSystemStats
f
              in [Integer] -> IO [Integer]
forall (m :: * -> *) a. Monad m => a -> m a
return [Integer
tot, Integer
free, Integer
used]

runDiskU' :: DiskUOpts -> String -> String -> Monitor String
runDiskU' :: DiskUOpts -> [Char] -> [Char] -> Monitor [Char]
runDiskU' DiskUOpts
opts [Char]
tmp [Char]
path = do
  [Char] -> Selector [Char] -> Monitor ()
forall a. a -> Selector a -> Monitor ()
setConfigValue [Char]
tmp Selector [Char]
template
  [Integer
total, Integer
free, Integer
diff] <-  IO [Integer] -> Monitor [Integer]
forall a. IO a -> Monitor a
io ((SomeException -> IO [Integer]) -> IO [Integer] -> IO [Integer]
forall e a. Exception e => (e -> IO a) -> IO a -> IO a
handle SomeException -> IO [Integer]
ign (IO [Integer] -> IO [Integer]) -> IO [Integer] -> IO [Integer]
forall a b. (a -> b) -> a -> b
$ [Char] -> IO [Integer]
fsStats [Char]
path)
  let strs :: [[Char]]
strs = (Integer -> [Char]) -> [Integer] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map Integer -> [Char]
sizeToStr [Integer
free, Integer
diff]
      freep :: Integer
freep = if Integer
total Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
0 then Integer
free Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
100 Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
total else Integer
0
      fr :: Float
fr = Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
freep Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
100
  [[Char]]
s <- ([Char] -> Integer -> Monitor [Char])
-> [[Char]] -> [Integer] -> ReaderT MConfig IO [[Char]]
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM [Char] -> Integer -> Monitor [Char]
forall a. (Num a, Ord a) => [Char] -> a -> Monitor [Char]
showWithColors' [[Char]]
strs [Integer
freep, Integer
100 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
freep]
  [[Char]]
sp <- [Float] -> ReaderT MConfig IO [[Char]]
showPercentsWithColors [Float
fr, Float
1 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
fr]
  [Char]
fb <- Float -> Float -> Monitor [Char]
showPercentBar (Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
freep) Float
fr
  [Char]
fvb <- Float -> Float -> Monitor [Char]
showVerticalBar (Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
freep) Float
fr
  [Char]
fipat <- Maybe IconPattern -> Float -> Monitor [Char]
showIconPattern (DiskUOpts -> Maybe IconPattern
freeIconPattern DiskUOpts
opts) Float
fr
  [Char]
ub <- Float -> Float -> Monitor [Char]
showPercentBar (Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Float) -> Integer -> Float
forall a b. (a -> b) -> a -> b
$ Integer
100 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
freep) (Float
1 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
fr)
  [Char]
uvb <- Float -> Float -> Monitor [Char]
showVerticalBar (Integer -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Float) -> Integer -> Float
forall a b. (a -> b) -> a -> b
$ Integer
100 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
freep) (Float
1 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
fr)
  [Char]
uipat <- Maybe IconPattern -> Float -> Monitor [Char]
showIconPattern (DiskUOpts -> Maybe IconPattern
usedIconPattern DiskUOpts
opts) (Float
1 Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
fr)
  [[Char]] -> Monitor [Char]
parseTemplate ([[Char]] -> Monitor [Char]) -> [[Char]] -> Monitor [Char]
forall a b. (a -> b) -> a -> b
$ [Integer -> [Char]
sizeToStr Integer
total] [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
s [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]]
sp [[Char]] -> [[Char]] -> [[Char]]
forall a. [a] -> [a] -> [a]
++ [[Char]
fb,[Char]
fvb,[Char]
fipat,[Char]
ub,[Char]
uvb,[Char]
uipat]
  where ign :: SomeException -> IO [Integer]
ign = IO [Integer] -> SomeException -> IO [Integer]
forall a b. a -> b -> a
const ([Integer] -> IO [Integer]
forall (m :: * -> *) a. Monad m => a -> m a
return [Integer
0, Integer
0, Integer
0]) :: SomeException -> IO [Integer]


runDiskU :: [(String, String)] -> [String] -> Monitor String
runDiskU :: [([Char], [Char])] -> [[Char]] -> Monitor [Char]
runDiskU [([Char], [Char])]
disks [[Char]]
argv = do
  [([Char], [Char])]
devs <- IO [([Char], [Char])] -> Monitor [([Char], [Char])]
forall a. IO a -> Monitor a
io (IO [([Char], [Char])] -> Monitor [([Char], [Char])])
-> IO [([Char], [Char])] -> Monitor [([Char], [Char])]
forall a b. (a -> b) -> a -> b
$ [[Char]] -> IO [([Char], [Char])]
mountedDevices ((([Char], [Char]) -> [Char]) -> [([Char], [Char])] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map ([Char], [Char]) -> [Char]
forall a b. (a, b) -> a
fst [([Char], [Char])]
disks)
  DiskUOpts
opts <- IO DiskUOpts -> Monitor DiskUOpts
forall a. IO a -> Monitor a
io (IO DiskUOpts -> Monitor DiskUOpts)
-> IO DiskUOpts -> Monitor DiskUOpts
forall a b. (a -> b) -> a -> b
$ [OptDescr (DiskUOpts -> DiskUOpts)]
-> DiskUOpts -> [[Char]] -> IO DiskUOpts
forall opts.
[OptDescr (opts -> opts)] -> opts -> [[Char]] -> IO opts
parseOptsWith [OptDescr (DiskUOpts -> DiskUOpts)]
duOptions DiskUOpts
duDefaultOpts [[Char]]
argv
  [[Char]]
strs <- (([Char], [Char]) -> Monitor [Char])
-> [([Char], [Char])] -> ReaderT MConfig IO [[Char]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (\([Char]
d, [Char]
p) -> DiskUOpts -> [Char] -> [Char] -> Monitor [Char]
runDiskU' DiskUOpts
opts ([Char] -> [Char] -> [([Char], [Char])] -> [Char]
findTempl [Char]
d [Char]
p [([Char], [Char])]
disks) [Char]
p) [([Char], [Char])]
devs
  [Char] -> Monitor [Char]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> Monitor [Char]) -> [Char] -> Monitor [Char]
forall a b. (a -> b) -> a -> b
$ (if DiskUOpts -> Bool
contiguousU DiskUOpts
opts then [[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat else [[Char]] -> [Char]
unwords) [[Char]]
strs