{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

{- |
Module      : System.MemInfo.Print
Copyright   : (c) 2022 Tim Emiola
Maintainer  : Tim Emiola <adetokunbo@emio.la>
SPDX-License-Identifier: BSD3

This module provides functions that format the output of the __printmem__ command
-}
module System.MemInfo.Print (
  AsCmdName (asCmdName),
  fmtAsHeader,
  fmtOverall,
  fmtMemUsage,
  styleOutput,
) where

import Data.Proxy (Proxy (..))
import qualified Data.Text as Text
import Fmt (
  build,
  fixedF,
  padBothF,
  padLeftF,
  padRightF,
  (+|),
  (+||),
  (|+),
  (|++|),
  (||+),
 )
import System.MemInfo.Choices (Style (..))
import System.MemInfo.Prelude
import System.MemInfo.Proc (MemUsage (..))


-- | Generate the output for a given report using the specified style
styleOutput :: (AsCmdName a) => Bool -> Style -> Bool -> [(a, MemUsage)] -> [Text]
styleOutput :: forall a.
AsCmdName a =>
Bool -> Style -> Bool -> [(a, MemUsage)] -> [Text]
styleOutput Bool
showSwap Style
style Bool
isAccurate = Bool -> Printers a -> [(a, MemUsage)] -> [Text]
forall a.
AsCmdName a =>
Bool -> Printers a -> [(a, MemUsage)] -> [Text]
outputOf Bool
isAccurate (Style -> Bool -> Printers a
forall a. AsCmdName a => Style -> Bool -> Printers a
printStyle Style
style Bool
showSwap)


{- | Generates the text of a row displaying the metrics for a single command in
the memory report
-}
fmtMemUsage :: (AsCmdName a) => Bool -> a -> MemUsage -> Text
fmtMemUsage :: forall a. AsCmdName a => Bool -> a -> MemUsage -> Text
fmtMemUsage Bool
showSwap a
name MemUsage
ct =
  let
    padl :: Int -> Builder
padl = Int -> Char -> Text -> Builder
forall a. Buildable a => Int -> Char -> a -> Builder
padLeftF Int
columnWidth Char
' ' (Text -> Builder) -> (Int -> Text) -> Int -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text
fmtMem
    private :: Builder
private = Int -> Builder
padl (Int -> Builder) -> Int -> Builder
forall a b. (a -> b) -> a -> b
$ MemUsage -> Int
muPrivate MemUsage
ct Int -> Int -> Int
forall a. Num a => a -> a -> a
- MemUsage -> Int
muShared MemUsage
ct
    shared :: Builder
shared = Int -> Builder
padl (Int -> Builder) -> Int -> Builder
forall a b. (a -> b) -> a -> b
$ MemUsage -> Int
muShared MemUsage
ct
    all' :: Builder
all' = Int -> Builder
padl (Int -> Builder) -> Int -> Builder
forall a b. (a -> b) -> a -> b
$ MemUsage -> Int
muPrivate MemUsage
ct
    swap' :: Builder
swap' = Int -> Builder
padl (Int -> Builder) -> Int -> Builder
forall a b. (a -> b) -> a -> b
$ MemUsage -> Int
muSwap MemUsage
ct
    name' :: Text
name' = a -> Int -> Text
forall a. AsCmdName a => a -> Int -> Text
cmdWithCount a
name (Int -> Text) -> Int -> Text
forall a b. (a -> b) -> a -> b
$ MemUsage -> Int
muCount MemUsage
ct
    ram :: Builder
ram = Builder
private Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
" + " Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
shared Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
" = " Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
all'
    numbers :: Builder
numbers = if Bool
showSwap then Builder
ram Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
swap' else Builder
ram
   in
    Builder
numbers Builder -> Builder -> Text
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
"\t" Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Text
name' Text -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
""


fmtMemUsageCsv :: (AsCmdName a) => Bool -> a -> MemUsage -> Text
fmtMemUsageCsv :: forall a. AsCmdName a => Bool -> a -> MemUsage -> Text
fmtMemUsageCsv Bool
showSwap a
name MemUsage
ct =
  let
    private :: Builder
private = Int -> Builder
forall p. Buildable p => p -> Builder
build (Int -> Builder) -> Int -> Builder
forall a b. (a -> b) -> a -> b
$ MemUsage -> Int
muPrivate MemUsage
ct Int -> Int -> Int
forall a. Num a => a -> a -> a
- MemUsage -> Int
muShared MemUsage
ct
    shared :: Builder
shared = Int -> Builder
forall p. Buildable p => p -> Builder
build (Int -> Builder) -> Int -> Builder
forall a b. (a -> b) -> a -> b
$ MemUsage -> Int
muShared MemUsage
ct
    all' :: Builder
all' = Int -> Builder
forall p. Buildable p => p -> Builder
build (Int -> Builder) -> Int -> Builder
forall a b. (a -> b) -> a -> b
$ MemUsage -> Int
muPrivate MemUsage
ct
    swap' :: Builder
swap' = Int -> Builder
forall p. Buildable p => p -> Builder
build (Int -> Builder) -> Int -> Builder
forall a b. (a -> b) -> a -> b
$ MemUsage -> Int
muSwap MemUsage
ct
    name' :: Text
name' = a -> Int -> Text
forall a. AsCmdName a => a -> Int -> Text
cmdWithCount a
name (Int -> Text) -> Int -> Text
forall a b. (a -> b) -> a -> b
$ MemUsage -> Int
muCount MemUsage
ct
    ram :: Builder
ram = Builder
private Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
"," Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
shared Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
"," Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
all' Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
","
    numbers :: Builder
numbers = if Bool
showSwap then Builder
ram Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
swap' Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
"," else Builder
ram
   in
    Builder
numbers Builder -> Builder -> Text
forall b. FromBuilder b => Builder -> Builder -> b
+| Text
name' Text -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
""


-- | Generates the text showing the overall memory in the memory report
fmtOverall :: Bool -> (Int, Int) -> Text
fmtOverall :: Bool -> (Int, Int) -> Text
fmtOverall Bool
showSwap (Int
private, Int
swap) =
  let
    rimLength :: Int
rimLength = if Bool
showSwap then Int
46 else Int
36
    gapLength :: Int
gapLength = Int
26
    top :: Text
top = Int -> Text -> Text
Text.replicate Int
rimLength Text
"-"
    gap :: Text
gap = Int -> Text -> Text
Text.replicate Int
gapLength Text
" "
    bottom :: Text
bottom = Int -> Text -> Text
Text.replicate Int
rimLength Text
"="
    padl :: Int -> Builder
padl = Int -> Char -> Text -> Builder
forall a. Buildable a => Int -> Char -> a -> Builder
padLeftF Int
columnWidth Char
' ' (Text -> Builder) -> (Int -> Text) -> Int -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text
fmtMem
    withSwap :: Text
withSwap = Builder
"" Builder -> Builder -> Text
forall b. FromBuilder b => Builder -> Builder -> b
+| Text
gap Text -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|++| Int -> Builder
padl Int
private Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|++| Int -> Builder
padl Int
swap Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
""
    noSwap :: Text
noSwap = Builder
"" Builder -> Builder -> Text
forall b. FromBuilder b => Builder -> Builder -> b
+| Text
gap Text -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|++| Int -> Builder
padl Int
private Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
""
    out :: Text
out = if Bool
showSwap then Text
withSwap else Text
noSwap
   in
    [Text] -> Text
Text.unlines [Text
top, Text
out, Text
bottom]


data Power = Ki | Mi | Gi | Ti deriving (Power -> Power -> Bool
(Power -> Power -> Bool) -> (Power -> Power -> Bool) -> Eq Power
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Power -> Power -> Bool
== :: Power -> Power -> Bool
$c/= :: Power -> Power -> Bool
/= :: Power -> Power -> Bool
Eq, Int -> Power -> ShowS
[Power] -> ShowS
Power -> String
(Int -> Power -> ShowS)
-> (Power -> String) -> ([Power] -> ShowS) -> Show Power
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Power -> ShowS
showsPrec :: Int -> Power -> ShowS
$cshow :: Power -> String
show :: Power -> String
$cshowList :: [Power] -> ShowS
showList :: [Power] -> ShowS
Show, Eq Power
Eq Power =>
(Power -> Power -> Ordering)
-> (Power -> Power -> Bool)
-> (Power -> Power -> Bool)
-> (Power -> Power -> Bool)
-> (Power -> Power -> Bool)
-> (Power -> Power -> Power)
-> (Power -> Power -> Power)
-> Ord Power
Power -> Power -> Bool
Power -> Power -> Ordering
Power -> Power -> Power
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Power -> Power -> Ordering
compare :: Power -> Power -> Ordering
$c< :: Power -> Power -> Bool
< :: Power -> Power -> Bool
$c<= :: Power -> Power -> Bool
<= :: Power -> Power -> Bool
$c> :: Power -> Power -> Bool
> :: Power -> Power -> Bool
$c>= :: Power -> Power -> Bool
>= :: Power -> Power -> Bool
$cmax :: Power -> Power -> Power
max :: Power -> Power -> Power
$cmin :: Power -> Power -> Power
min :: Power -> Power -> Power
Ord, Int -> Power
Power -> Int
Power -> [Power]
Power -> Power
Power -> Power -> [Power]
Power -> Power -> Power -> [Power]
(Power -> Power)
-> (Power -> Power)
-> (Int -> Power)
-> (Power -> Int)
-> (Power -> [Power])
-> (Power -> Power -> [Power])
-> (Power -> Power -> [Power])
-> (Power -> Power -> Power -> [Power])
-> Enum Power
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Power -> Power
succ :: Power -> Power
$cpred :: Power -> Power
pred :: Power -> Power
$ctoEnum :: Int -> Power
toEnum :: Int -> Power
$cfromEnum :: Power -> Int
fromEnum :: Power -> Int
$cenumFrom :: Power -> [Power]
enumFrom :: Power -> [Power]
$cenumFromThen :: Power -> Power -> [Power]
enumFromThen :: Power -> Power -> [Power]
$cenumFromTo :: Power -> Power -> [Power]
enumFromTo :: Power -> Power -> [Power]
$cenumFromThenTo :: Power -> Power -> Power -> [Power]
enumFromThenTo :: Power -> Power -> Power -> [Power]
Enum, Power
Power -> Power -> Bounded Power
forall a. a -> a -> Bounded a
$cminBound :: Power
minBound :: Power
$cmaxBound :: Power
maxBound :: Power
Bounded)


fmtMem :: Int -> Text
fmtMem :: Int -> Text
fmtMem = Power -> Float -> Text
fmtMem' Power
Ki (Float -> Text) -> (Int -> Float) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Float
forall a b. (Integral a, Num b) => a -> b
fromIntegral


columnWidth :: Int
columnWidth :: Int
columnWidth = Int
10


fmtMem' :: Power -> Float -> Text
fmtMem' :: Power -> Float -> Text
fmtMem' =
  let doFmt :: a -> a -> b
doFmt a
p a
x = Builder
"" Builder -> Builder -> b
forall b. FromBuilder b => Builder -> Builder -> b
+| Int -> a -> Builder
forall a. Real a => Int -> a -> Builder
fixedF Int
1 a
x Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
" " Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+|| a
p a -> Builder -> Builder
forall a b. (Show a, FromBuilder b) => a -> Builder -> b
||+ Builder
"B"
      go :: Power -> Float -> Text
go Power
p Float
x | Power
p Power -> Power -> Bool
forall a. Eq a => a -> a -> Bool
== Power
forall a. Bounded a => a
maxBound = Power -> Float -> Text
forall {b} {a} {a}. (FromBuilder b, Real a, Show a) => a -> a -> b
doFmt Power
p Float
x
      go Power
p Float
x | Float
x Float -> Float -> Bool
forall a. Ord a => a -> a -> Bool
> Float
1000 = Power -> Float -> Text
fmtMem' (Power -> Power
forall a. Enum a => a -> a
succ Power
p) (Float
x Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
1024)
      go Power
p Float
x = Power -> Float -> Text
forall {b} {a} {a}. (FromBuilder b, Real a, Show a) => a -> a -> b
doFmt Power
p Float
x
   in Power -> Float -> Text
go


hdrPrivate, hdrShared, hdrRamUsed, hdrSwapUsed, hdrProgram, hdrCount, hdrPid :: Text
hdrPrivate :: Text
hdrPrivate = Text
"Private"
hdrShared :: Text
hdrShared = Text
"Shared"
hdrRamUsed :: Text
hdrRamUsed = Text
"RAM Used"
hdrSwapUsed :: Text
hdrSwapUsed = Text
"Swap Used"
hdrProgram :: Text
hdrProgram = Text
"Program"
hdrCount :: Text
hdrCount = Text
"(# processes)"
hdrPid :: Text
hdrPid = Text
"[pid]"


-- | Generates the text of the printed header of the memory report
fmtAsHeader :: Bool -> Bool -> Text
fmtAsHeader :: Bool -> Bool -> Text
fmtAsHeader Bool
hasPid Bool
showSwap =
  let
    padb :: Text -> Builder
padb = Int -> Char -> Text -> Builder
forall a. Buildable a => Int -> Char -> a -> Builder
padBothF Int
columnWidth Char
' '
    padr :: Text -> Builder
padr = Int -> Char -> Text -> Builder
forall a. Buildable a => Int -> Char -> a -> Builder
padRightF Int
columnWidth Char
' '
    padl :: Text -> Builder
padl = Int -> Char -> Text -> Builder
forall a. Buildable a => Int -> Char -> a -> Builder
padLeftF Int
columnWidth Char
' '
    private :: Builder
private = Text -> Builder
padb Text
hdrPrivate
    shared :: Builder
shared = Text -> Builder
padb Text
hdrShared
    all' :: Builder
all' = Text -> Builder
padl Text
hdrRamUsed
    nameExt :: Text
nameExt = if Bool
hasPid then Text
hdrPid else Text
hdrCount
    name' :: Builder
name' = Text -> Builder
padr (Text -> Builder) -> Text -> Builder
forall a b. (a -> b) -> a -> b
$ Text
hdrProgram Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
nameExt
    swap' :: Builder
swap' = Text -> Builder
padl Text
hdrSwapUsed
    ram :: Builder
ram = Builder
private Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
" + " Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
shared Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
" = " Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
all'
    numbers :: Builder
numbers = if Bool
showSwap then Builder
ram Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
swap' else Builder
ram
   in
    Builder
numbers Builder -> Builder -> Text
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
"\t" Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
name' Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
""


-- | Generates the text of the printed header of the memory report
fmtAsHeaderCsv :: Bool -> Bool -> Text
fmtAsHeaderCsv :: Bool -> Bool -> Text
fmtAsHeaderCsv Bool
hasPid Bool
showSwap =
  let
    private :: Builder
private = Text -> Builder
forall p. Buildable p => p -> Builder
build Text
hdrPrivate
    shared :: Builder
shared = Text -> Builder
forall p. Buildable p => p -> Builder
build Text
hdrShared
    all' :: Builder
all' = Text -> Builder
forall p. Buildable p => p -> Builder
build Text
hdrRamUsed
    nameExt :: Text
nameExt = if Bool
hasPid then Text
hdrPid else Text
hdrCount
    name' :: Builder
name' = Text -> Builder
forall p. Buildable p => p -> Builder
build (Text -> Builder) -> Text -> Builder
forall a b. (a -> b) -> a -> b
$ Text
hdrProgram Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
nameExt
    swap' :: Builder
swap' = Text -> Builder
forall p. Buildable p => p -> Builder
build Text
hdrSwapUsed
    ram :: Builder
ram = Builder
private Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
"," Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
shared Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
"," Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
all' Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
","
    numbers :: Builder
numbers = if Bool
showSwap then Builder
ram Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
swap' Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
"," else Builder
ram
   in
    Builder
numbers Builder -> Builder -> Text
forall b. FromBuilder b => Builder -> Builder -> b
+| Builder
name' Builder -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
""


{- | Identifies a type as a label to use to index programs in the report
output

The label is also used to group related processes under a single program
-}
class AsCmdName a where
  -- Convert the label to text to print in the report output
  asCmdName :: a -> Text


  -- Add a count of processes using that label to the label
  cmdWithCount :: a -> Int -> Text


  -- Indicate if pid or process count should shown in the hdr
  hdrHasPid :: Proxy a -> Bool


instance AsCmdName Text where
  asCmdName :: Text -> Text
asCmdName = Text -> Text
forall a. a -> a
id
  cmdWithCount :: Text -> Int -> Text
cmdWithCount Text
cmd Int
count = Builder
"" Builder -> Builder -> Text
forall b. FromBuilder b => Builder -> Builder -> b
+| Text -> Text
forall a. AsCmdName a => a -> Text
asCmdName Text
cmd Text -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
" (" Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| Int
count Int -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
")"
  hdrHasPid :: Proxy Text -> Bool
hdrHasPid Proxy Text
_ = Bool
False


instance AsCmdName (ProcessID, Text) where
  asCmdName :: (ProcessID, Text) -> Text
asCmdName (ProcessID
pid, Text
name) = Builder
"" Builder -> Builder -> Text
forall b. FromBuilder b => Builder -> Builder -> b
+| Text
name Text -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
" [" Builder -> Builder -> Builder
forall b. FromBuilder b => Builder -> Builder -> b
+| ProcessID -> Integer
forall a. Integral a => a -> Integer
toInteger ProcessID
pid Integer -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
"]"
  cmdWithCount :: (ProcessID, Text) -> Int -> Text
cmdWithCount (ProcessID, Text)
cmd Int
_count = Builder
"" Builder -> Builder -> Text
forall b. FromBuilder b => Builder -> Builder -> b
+| (ProcessID, Text) -> Text
forall a. AsCmdName a => a -> Text
asCmdName (ProcessID, Text)
cmd Text -> Builder -> Builder
forall a b. (Buildable a, FromBuilder b) => a -> Builder -> b
|+ Builder
""
  hdrHasPid :: Proxy (ProcessID, Text) -> Bool
hdrHasPid Proxy (ProcessID, Text)
_ = Bool
True


overallTotals :: [MemUsage] -> (Int, Int)
overallTotals :: [MemUsage] -> (Int, Int)
overallTotals [MemUsage]
cts =
  let step :: (Int, Int) -> MemUsage -> (Int, Int)
step (Int
private, Int
swap) MemUsage
ct = (Int
private Int -> Int -> Int
forall a. Num a => a -> a -> a
+ MemUsage -> Int
muPrivate MemUsage
ct, Int
swap Int -> Int -> Int
forall a. Num a => a -> a -> a
+ MemUsage -> Int
muSwap MemUsage
ct)
   in ((Int, Int) -> MemUsage -> (Int, Int))
-> (Int, Int) -> [MemUsage] -> (Int, Int)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (Int, Int) -> MemUsage -> (Int, Int)
step (Int
0, Int
0) [MemUsage]
cts


data Printers a = Printers
  { forall a. Printers a -> a -> MemUsage -> Text
psUsage :: a -> MemUsage -> Text
  , forall a. Printers a -> Text
psHeader :: Text
  , forall a. Printers a -> (Int, Int) -> Maybe Text
psOverall :: (Int, Int) -> Maybe Text
  }


printStyle :: forall a. (AsCmdName a) => Style -> Bool -> Printers a
printStyle :: forall a. AsCmdName a => Style -> Bool -> Printers a
printStyle Style
style Bool
showSwap =
  let usageFmt :: Style -> Bool -> a -> MemUsage -> Text
usageFmt Style
Normal = Bool -> a -> MemUsage -> Text
forall a. AsCmdName a => Bool -> a -> MemUsage -> Text
fmtMemUsage
      usageFmt Style
Csv = Bool -> a -> MemUsage -> Text
forall a. AsCmdName a => Bool -> a -> MemUsage -> Text
fmtMemUsageCsv
      headerFmt :: Style -> Bool -> Text
headerFmt Style
Normal = Bool -> Bool -> Text
fmtAsHeader (forall a. AsCmdName a => Proxy a -> Bool
hdrHasPid @a Proxy a
forall {k} (t :: k). Proxy t
Proxy)
      headerFmt Style
Csv = Bool -> Bool -> Text
fmtAsHeaderCsv (forall a. AsCmdName a => Proxy a -> Bool
hdrHasPid @a Proxy a
forall {k} (t :: k). Proxy t
Proxy)
      overallFmt :: Style -> (Int, Int) -> Maybe Text
overallFmt Style
Normal (Int, Int)
x = Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Bool -> (Int, Int) -> Text
fmtOverall Bool
showSwap (Int, Int)
x
      overallFmt Style
Csv (Int, Int)
_ = Maybe Text
forall a. Maybe a
Nothing
   in Printers
        { psUsage :: a -> MemUsage -> Text
psUsage = Style -> Bool -> a -> MemUsage -> Text
forall {a}. AsCmdName a => Style -> Bool -> a -> MemUsage -> Text
usageFmt Style
style Bool
showSwap
        , psOverall :: (Int, Int) -> Maybe Text
psOverall = Style -> (Int, Int) -> Maybe Text
overallFmt Style
style
        , psHeader :: Text
psHeader = Style -> Bool -> Text
headerFmt Style
style Bool
showSwap
        }


outputOf :: (AsCmdName a) => Bool -> Printers a -> [(a, MemUsage)] -> [Text]
outputOf :: forall a.
AsCmdName a =>
Bool -> Printers a -> [(a, MemUsage)] -> [Text]
outputOf Bool
isAccurate Printers a
style [(a, MemUsage)]
usages =
  let Printers {a -> MemUsage -> Text
psUsage :: forall a. Printers a -> a -> MemUsage -> Text
psUsage :: a -> MemUsage -> Text
psUsage, Text
psHeader :: forall a. Printers a -> Text
psHeader :: Text
psHeader, (Int, Int) -> Maybe Text
psOverall :: forall a. Printers a -> (Int, Int) -> Maybe Text
psOverall :: (Int, Int) -> Maybe Text
psOverall} = Printers a
style
      overall :: Maybe Text
overall = (Int, Int) -> Maybe Text
psOverall ((Int, Int) -> Maybe Text) -> (Int, Int) -> Maybe Text
forall a b. (a -> b) -> a -> b
$ [MemUsage] -> (Int, Int)
overallTotals ([MemUsage] -> (Int, Int)) -> [MemUsage] -> (Int, Int)
forall a b. (a -> b) -> a -> b
$ ((a, MemUsage) -> MemUsage) -> [(a, MemUsage)] -> [MemUsage]
forall a b. (a -> b) -> [a] -> [b]
map (a, MemUsage) -> MemUsage
forall a b. (a, b) -> b
snd [(a, MemUsage)]
usages
      headerAndRows :: [Text]
headerAndRows = [Text
psHeader] [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> ((a, MemUsage) -> Text) -> [(a, MemUsage)] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> MemUsage -> Text) -> (a, MemUsage) -> Text
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry a -> MemUsage -> Text
psUsage) [(a, MemUsage)]
usages
   in case Maybe Text
overall of
        Maybe Text
Nothing -> [Text]
headerAndRows
        Just Text
_ | Bool -> Bool
not Bool
isAccurate -> [Text]
headerAndRows
        Just Text
o -> [Text]
headerAndRows [Text] -> [Text] -> [Text]
forall a. Semigroup a => a -> a -> a
<> [Text
o]