{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE CPP #-}

module Test.Sandwich.Formatters.TerminalUI.Draw where

import Brick
import Brick.Widgets.Border
import Brick.Widgets.Center
import qualified Brick.Widgets.List as L
import Control.Monad
import Control.Monad.Logger
import Control.Monad.Reader
import Data.Foldable
import qualified Data.List as L
import Data.Maybe
import qualified Data.Sequence as Seq
import Data.String.Interpolate
import qualified Data.Text.Encoding as E
import Data.Time.Clock
import GHC.Stack
import Lens.Micro
import Safe
import Test.Sandwich.Formatters.Common.Count
import Test.Sandwich.Formatters.Common.Util
import Test.Sandwich.Formatters.TerminalUI.AttrMap
import Test.Sandwich.Formatters.TerminalUI.Draw.ColorProgressBar
import Test.Sandwich.Formatters.TerminalUI.Draw.RunTimes
import Test.Sandwich.Formatters.TerminalUI.Draw.ToBrickWidget
import Test.Sandwich.Formatters.TerminalUI.Draw.TopBox
import Test.Sandwich.Formatters.TerminalUI.Draw.Util
import Test.Sandwich.Formatters.TerminalUI.Types
import Test.Sandwich.Types.RunTree
import Test.Sandwich.Types.Spec


drawUI :: AppState -> [Widget ClickableName]
drawUI :: AppState -> [Widget ClickableName]
drawUI AppState
app = [Widget ClickableName
ui]
  where
    ui :: Widget ClickableName
ui = [Widget ClickableName] -> Widget ClickableName
forall n. [Widget n] -> Widget n
vBox [
      AppState -> Widget ClickableName
forall {n}. AppState -> Widget n
topBox AppState
app
      , AppState -> Widget ClickableName
forall {n}. AppState -> Widget n
borderWithCounts AppState
app
      , AppState -> Widget ClickableName
mainList AppState
app
      , ClickableName -> Widget ClickableName -> Widget ClickableName
forall n. Ord n => n -> Widget n -> Widget n
clickable ClickableName
ColorBar (Widget ClickableName -> Widget ClickableName)
-> Widget ClickableName -> Widget ClickableName
forall a b. (a -> b) -> a -> b
$ AppState -> Widget ClickableName
forall {n}. AppState -> Widget n
bottomProgressBarColored AppState
app
      ]

mainList :: AppState -> Widget ClickableName
mainList AppState
app = Widget ClickableName -> Widget ClickableName
forall n. Widget n -> Widget n
hCenter (Widget ClickableName -> Widget ClickableName)
-> Widget ClickableName -> Widget ClickableName
forall a b. (a -> b) -> a -> b
$ Int -> Widget ClickableName -> Widget ClickableName
forall n. Int -> Widget n -> Widget n
padAll Int
1 (Widget ClickableName -> Widget ClickableName)
-> Widget ClickableName -> Widget ClickableName
forall a b. (a -> b) -> a -> b
$ (Int -> Bool -> MainListElem -> Widget ClickableName)
-> Bool
-> GenericList ClickableName Vector MainListElem
-> Widget ClickableName
forall (t :: * -> *) n e.
(Traversable t, Splittable t, Ord n, Show n) =>
(Int -> Bool -> e -> Widget n)
-> Bool -> GenericList n t e -> Widget n
L.renderListWithIndex Int -> Bool -> MainListElem -> Widget ClickableName
listDrawElement Bool
True (AppState
app AppState
-> Getting
     (GenericList ClickableName Vector MainListElem)
     AppState
     (GenericList ClickableName Vector MainListElem)
-> GenericList ClickableName Vector MainListElem
forall s a. s -> Getting a s a -> a
^. Getting
  (GenericList ClickableName Vector MainListElem)
  AppState
  (GenericList ClickableName Vector MainListElem)
Lens' AppState (GenericList ClickableName Vector MainListElem)
appMainList)
  where
    listDrawElement :: Int -> Bool -> MainListElem -> Widget ClickableName
listDrawElement Int
ix Bool
isSelected x :: MainListElem
x@(MainListElem {Bool
Int
String
Maybe String
Seq LogEntry
RunNodeCommon
Status
label :: String
depth :: Int
toggled :: Bool
open :: Bool
status :: Status
logs :: Seq LogEntry
visibilityLevel :: Int
folderPath :: Maybe String
node :: RunNodeCommon
ident :: Int
label :: MainListElem -> String
depth :: MainListElem -> Int
toggled :: MainListElem -> Bool
open :: MainListElem -> Bool
status :: MainListElem -> Status
logs :: MainListElem -> Seq LogEntry
visibilityLevel :: MainListElem -> Int
folderPath :: MainListElem -> Maybe String
node :: MainListElem -> RunNodeCommon
ident :: MainListElem -> Int
..}) = ClickableName -> Widget ClickableName -> Widget ClickableName
forall n. Ord n => n -> Widget n -> Widget n
clickable (Int -> ClickableName
ListRow Int
ix) (Widget ClickableName -> Widget ClickableName)
-> Widget ClickableName -> Widget ClickableName
forall a b. (a -> b) -> a -> b
$ Padding -> Widget ClickableName -> Widget ClickableName
forall n. Padding -> Widget n -> Widget n
padLeft (Int -> Padding
Pad (Int
4 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
depth)) (Widget ClickableName -> Widget ClickableName)
-> Widget ClickableName -> Widget ClickableName
forall a b. (a -> b) -> a -> b
$ (if Bool
isSelected then Widget ClickableName -> Widget ClickableName
forall n. Widget n -> Widget n
border else Widget ClickableName -> Widget ClickableName
forall a. a -> a
id) (Widget ClickableName -> Widget ClickableName)
-> Widget ClickableName -> Widget ClickableName
forall a b. (a -> b) -> a -> b
$ [Widget ClickableName] -> Widget ClickableName
forall n. [Widget n] -> Widget n
vBox ([Widget ClickableName] -> Widget ClickableName)
-> [Widget ClickableName] -> Widget ClickableName
forall a b. (a -> b) -> a -> b
$ [Maybe (Widget ClickableName)] -> [Widget ClickableName]
forall a. [Maybe a] -> [a]
catMaybes [
      Widget ClickableName -> Maybe (Widget ClickableName)
forall a. a -> Maybe a
Just (Widget ClickableName -> Maybe (Widget ClickableName))
-> Widget ClickableName -> Maybe (Widget ClickableName)
forall a b. (a -> b) -> a -> b
$ Bool -> MainListElem -> Widget ClickableName
forall {p} {n}. p -> MainListElem -> Widget n
renderLine Bool
isSelected MainListElem
x
      , do
          Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard Bool
toggled
          let infoWidgets :: [Widget n]
infoWidgets = MainListElem -> [Widget n]
forall {n}. MainListElem -> [Widget n]
getInfoWidgets MainListElem
x
          Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [Widget Any] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
L.null [Widget Any]
forall {n}. [Widget n]
infoWidgets)
          Widget ClickableName -> Maybe (Widget ClickableName)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (Widget ClickableName -> Maybe (Widget ClickableName))
-> Widget ClickableName -> Maybe (Widget ClickableName)
forall a b. (a -> b) -> a -> b
$ Padding -> Widget ClickableName -> Widget ClickableName
forall n. Padding -> Widget n -> Widget n
padLeft (Int -> Padding
Pad Int
4) (Widget ClickableName -> Widget ClickableName)
-> Widget ClickableName -> Widget ClickableName
forall a b. (a -> b) -> a -> b
$
            ClickableName
-> Int -> Widget ClickableName -> Widget ClickableName
forall n. (Ord n, Show n) => n -> Int -> Widget n -> Widget n
fixedHeightOrViewportPercent (Text -> ClickableName
InnerViewport [i|viewport_#{ident}|]) Int
33 (Widget ClickableName -> Widget ClickableName)
-> Widget ClickableName -> Widget ClickableName
forall a b. (a -> b) -> a -> b
$
              [Widget ClickableName] -> Widget ClickableName
forall n. [Widget n] -> Widget n
vBox [Widget ClickableName]
forall {n}. [Widget n]
infoWidgets
      ]

    renderLine :: p -> MainListElem -> Widget n
renderLine p
_isSelected (MainListElem {Bool
Int
String
Maybe String
Seq LogEntry
RunNodeCommon
Status
label :: MainListElem -> String
depth :: MainListElem -> Int
toggled :: MainListElem -> Bool
open :: MainListElem -> Bool
status :: MainListElem -> Status
logs :: MainListElem -> Seq LogEntry
visibilityLevel :: MainListElem -> Int
folderPath :: MainListElem -> Maybe String
node :: MainListElem -> RunNodeCommon
ident :: MainListElem -> Int
label :: String
depth :: Int
toggled :: Bool
open :: Bool
status :: Status
logs :: Seq LogEntry
visibilityLevel :: Int
folderPath :: Maybe String
node :: RunNodeCommon
ident :: Int
..}) = [Widget n] -> Widget n
forall n. [Widget n] -> Widget n
hBox ([Widget n] -> Widget n) -> [Widget n] -> Widget n
forall a b. (a -> b) -> a -> b
$ [Maybe (Widget n)] -> [Widget n]
forall a. [Maybe a] -> [a]
catMaybes [
      Widget n -> Maybe (Widget n)
forall a. a -> Maybe a
Just (Widget n -> Maybe (Widget n)) -> Widget n -> Maybe (Widget n)
forall a b. (a -> b) -> a -> b
$ AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
openMarkerAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (if Bool
open then String
"[-] " else String
"[+] ")
      , Widget n -> Maybe (Widget n)
forall a. a -> Maybe a
Just (Widget n -> Maybe (Widget n)) -> Widget n -> Maybe (Widget n)
forall a b. (a -> b) -> a -> b
$ AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr (Status -> AttrName
chooseAttr Status
status) (String -> Widget n
forall n. String -> Widget n
str String
label)
      , if Bool -> Bool
not (AppState
app AppState -> Getting Bool AppState Bool -> Bool
forall s a. s -> Getting a s a -> a
^. Getting Bool AppState Bool
Lens' AppState Bool
appShowFileLocations) then Maybe (Widget n)
forall a. Maybe a
Nothing else
          case RunNodeCommon -> Maybe SrcLoc
forall s l t. RunNodeCommonWithStatus s l t -> Maybe SrcLoc
runTreeLoc RunNodeCommon
node of
            Maybe SrcLoc
Nothing -> Maybe (Widget n)
forall a. Maybe a
Nothing
            Just SrcLoc
loc ->
              Widget n -> Maybe (Widget n)
forall a. a -> Maybe a
Just (Widget n -> Maybe (Widget n)) -> Widget n -> Maybe (Widget n)
forall a b. (a -> b) -> a -> b
$ [Widget n] -> Widget n
forall n. [Widget n] -> Widget n
hBox [String -> Widget n
forall n. String -> Widget n
str String
" ["
                          , AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
logFilenameAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (String -> Widget n) -> String -> Widget n
forall a b. (a -> b) -> a -> b
$ SrcLoc -> String
srcLocFile SrcLoc
loc
                          , String -> Widget n
forall n. String -> Widget n
str String
":"
                          , AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
logLineAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (String -> Widget n) -> String -> Widget n
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ SrcLoc -> Int
srcLocStartLine SrcLoc
loc
                          , String -> Widget n
forall n. String -> Widget n
str String
"]"]
      , if Bool -> Bool
not (AppState
app AppState -> Getting Bool AppState Bool -> Bool
forall s a. s -> Getting a s a -> a
^. Getting Bool AppState Bool
Lens' AppState Bool
appShowVisibilityThresholds) then Maybe (Widget n)
forall a. Maybe a
Nothing else
          Widget n -> Maybe (Widget n)
forall a. a -> Maybe a
Just (Widget n -> Maybe (Widget n)) -> Widget n -> Maybe (Widget n)
forall a b. (a -> b) -> a -> b
$ [Widget n] -> Widget n
forall n. [Widget n] -> Widget n
hBox [String -> Widget n
forall n. String -> Widget n
str String
" ["
                      , AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
visibilityThresholdIndicatorMutedAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str String
"V="
                      , AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
visibilityThresholdIndicatorAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (String -> Widget n) -> String -> Widget n
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
visibilityLevel
                      , String -> Widget n
forall n. String -> Widget n
str String
"]"]
      , Widget n -> Maybe (Widget n)
forall a. a -> Maybe a
Just (Widget n -> Maybe (Widget n)) -> Widget n -> Maybe (Widget n)
forall a b. (a -> b) -> a -> b
$ Padding -> Widget n -> Widget n
forall n. Padding -> Widget n -> Widget n
padRight Padding
Max (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
toggleMarkerAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (if Bool
toggled then String
" [-]" else String
" [+]")
      , if Bool -> Bool
not (AppState
app AppState -> Getting Bool AppState Bool -> Bool
forall s a. s -> Getting a s a -> a
^. Getting Bool AppState Bool
Lens' AppState Bool
appShowRunTimes) then Maybe (Widget n)
forall a. Maybe a
Nothing else case Status
status of
          Running {Maybe NominalDiffTime
UTCTime
Async Result
statusStartTime :: UTCTime
statusSetupTime :: Maybe NominalDiffTime
statusAsync :: Async Result
statusStartTime :: Status -> UTCTime
statusSetupTime :: Status -> Maybe NominalDiffTime
statusAsync :: Status -> Async Result
..} -> Widget n -> Maybe (Widget n)
forall a. a -> Maybe a
Just (Widget n -> Maybe (Widget n)) -> Widget n -> Maybe (Widget n)
forall a b. (a -> b) -> a -> b
$ AppState
-> UTCTime
-> UTCTime
-> Maybe NominalDiffTime
-> Maybe NominalDiffTime
-> Bool
-> Widget n
forall {n}.
AppState
-> UTCTime
-> UTCTime
-> Maybe NominalDiffTime
-> Maybe NominalDiffTime
-> Bool
-> Widget n
getRunTimes AppState
app UTCTime
statusStartTime (AppState
app AppState -> Getting UTCTime AppState UTCTime -> UTCTime
forall s a. s -> Getting a s a -> a
^. Getting UTCTime AppState UTCTime
Lens' AppState UTCTime
appCurrentTime) Maybe NominalDiffTime
statusSetupTime Maybe NominalDiffTime
forall a. Maybe a
Nothing Bool
True
          Done {Maybe NominalDiffTime
UTCTime
Result
statusStartTime :: Status -> UTCTime
statusSetupTime :: Status -> Maybe NominalDiffTime
statusStartTime :: UTCTime
statusEndTime :: UTCTime
statusSetupTime :: Maybe NominalDiffTime
statusTeardownTime :: Maybe NominalDiffTime
statusResult :: Result
statusEndTime :: Status -> UTCTime
statusTeardownTime :: Status -> Maybe NominalDiffTime
statusResult :: Status -> Result
..} -> Widget n -> Maybe (Widget n)
forall a. a -> Maybe a
Just (Widget n -> Maybe (Widget n)) -> Widget n -> Maybe (Widget n)
forall a b. (a -> b) -> a -> b
$ AppState
-> UTCTime
-> UTCTime
-> Maybe NominalDiffTime
-> Maybe NominalDiffTime
-> Bool
-> Widget n
forall {n}.
AppState
-> UTCTime
-> UTCTime
-> Maybe NominalDiffTime
-> Maybe NominalDiffTime
-> Bool
-> Widget n
getRunTimes AppState
app UTCTime
statusStartTime UTCTime
statusEndTime Maybe NominalDiffTime
statusSetupTime Maybe NominalDiffTime
statusTeardownTime Bool
False
          Status
_ -> Maybe (Widget n)
forall a. Maybe a
Nothing
      ]

    getInfoWidgets :: MainListElem -> [Widget n]
getInfoWidgets mle :: MainListElem
mle@(MainListElem {Bool
Int
String
Maybe String
Seq LogEntry
RunNodeCommon
Status
label :: MainListElem -> String
depth :: MainListElem -> Int
toggled :: MainListElem -> Bool
open :: MainListElem -> Bool
status :: MainListElem -> Status
logs :: MainListElem -> Seq LogEntry
visibilityLevel :: MainListElem -> Int
folderPath :: MainListElem -> Maybe String
node :: MainListElem -> RunNodeCommon
ident :: MainListElem -> Int
label :: String
depth :: Int
toggled :: Bool
open :: Bool
status :: Status
logs :: Seq LogEntry
visibilityLevel :: Int
folderPath :: Maybe String
node :: RunNodeCommon
ident :: Int
..}) = [Maybe (Widget n)] -> [Widget n]
forall a. [Maybe a] -> [a]
catMaybes [Widget n -> Maybe (Widget n)
forall a. a -> Maybe a
Just (Widget n -> Maybe (Widget n)) -> Widget n -> Maybe (Widget n)
forall a b. (a -> b) -> a -> b
$ Reader CustomExceptionFormatters (Widget n)
-> CustomExceptionFormatters -> Widget n
forall r a. Reader r a -> r -> a
runReader (Status -> Reader CustomExceptionFormatters (Widget n)
forall n. Status -> Reader CustomExceptionFormatters (Widget n)
forall a n.
ToBrickWidget a =>
a -> Reader CustomExceptionFormatters (Widget n)
toBrickWidget Status
status) (AppState
app AppState
-> Getting
     CustomExceptionFormatters AppState CustomExceptionFormatters
-> CustomExceptionFormatters
forall s a. s -> Getting a s a -> a
^. Getting
  CustomExceptionFormatters AppState CustomExceptionFormatters
Lens' AppState CustomExceptionFormatters
appCustomExceptionFormatters), MainListElem -> Maybe (Widget n)
forall {n}. MainListElem -> Maybe (Widget n)
callStackWidget MainListElem
mle, MainListElem -> Maybe (Widget n)
forall {m :: * -> *} {n}.
(Monad m, Alternative m) =>
MainListElem -> m (Widget n)
logWidget MainListElem
mle]

    callStackWidget :: MainListElem -> Maybe (Widget n)
callStackWidget (MainListElem {Bool
Int
String
Maybe String
Seq LogEntry
RunNodeCommon
Status
label :: MainListElem -> String
depth :: MainListElem -> Int
toggled :: MainListElem -> Bool
open :: MainListElem -> Bool
status :: MainListElem -> Status
logs :: MainListElem -> Seq LogEntry
visibilityLevel :: MainListElem -> Int
folderPath :: MainListElem -> Maybe String
node :: MainListElem -> RunNodeCommon
ident :: MainListElem -> Int
label :: String
depth :: Int
toggled :: Bool
open :: Bool
status :: Status
logs :: Seq LogEntry
visibilityLevel :: Int
folderPath :: Maybe String
node :: RunNodeCommon
ident :: Int
..}) = do
      CallStack
cs <- CustomExceptionFormatters -> Status -> Maybe CallStack
getCallStackFromStatus (AppState
app AppState
-> Getting
     CustomExceptionFormatters AppState CustomExceptionFormatters
-> CustomExceptionFormatters
forall s a. s -> Getting a s a -> a
^. Getting
  CustomExceptionFormatters AppState CustomExceptionFormatters
Lens' AppState CustomExceptionFormatters
appCustomExceptionFormatters) Status
status
      Widget n -> Maybe (Widget n)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (Widget n -> Maybe (Widget n)) -> Widget n -> Maybe (Widget n)
forall a b. (a -> b) -> a -> b
$ Widget n -> Widget n -> Widget n
forall n. Widget n -> Widget n -> Widget n
borderWithLabel (Int -> Widget n -> Widget n
forall n. Int -> Widget n -> Widget n
padLeftRight Int
1 (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str String
"Callstack") (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ Reader CustomExceptionFormatters (Widget n)
-> CustomExceptionFormatters -> Widget n
forall r a. Reader r a -> r -> a
runReader (CallStack -> Reader CustomExceptionFormatters (Widget n)
forall n. CallStack -> Reader CustomExceptionFormatters (Widget n)
forall a n.
ToBrickWidget a =>
a -> Reader CustomExceptionFormatters (Widget n)
toBrickWidget CallStack
cs) (AppState
app AppState
-> Getting
     CustomExceptionFormatters AppState CustomExceptionFormatters
-> CustomExceptionFormatters
forall s a. s -> Getting a s a -> a
^. Getting
  CustomExceptionFormatters AppState CustomExceptionFormatters
Lens' AppState CustomExceptionFormatters
appCustomExceptionFormatters)

    logWidget :: MainListElem -> m (Widget n)
logWidget (MainListElem {Bool
Int
String
Maybe String
Seq LogEntry
RunNodeCommon
Status
label :: MainListElem -> String
depth :: MainListElem -> Int
toggled :: MainListElem -> Bool
open :: MainListElem -> Bool
status :: MainListElem -> Status
logs :: MainListElem -> Seq LogEntry
visibilityLevel :: MainListElem -> Int
folderPath :: MainListElem -> Maybe String
node :: MainListElem -> RunNodeCommon
ident :: MainListElem -> Int
label :: String
depth :: Int
toggled :: Bool
open :: Bool
status :: Status
logs :: Seq LogEntry
visibilityLevel :: Int
folderPath :: Maybe String
node :: RunNodeCommon
ident :: Int
..}) = do
      let filteredLogs :: Seq LogEntry
filteredLogs = case AppState
app AppState
-> Getting (Maybe LogLevel) AppState (Maybe LogLevel)
-> Maybe LogLevel
forall s a. s -> Getting a s a -> a
^. Getting (Maybe LogLevel) AppState (Maybe LogLevel)
Lens' AppState (Maybe LogLevel)
appLogLevel of
            Maybe LogLevel
Nothing -> Seq LogEntry
forall a. Monoid a => a
mempty
            Just LogLevel
logLevel -> (LogEntry -> Bool) -> Seq LogEntry -> Seq LogEntry
forall a. (a -> Bool) -> Seq a -> Seq a
Seq.filter (\LogEntry
x -> LogEntry -> LogLevel
logEntryLevel LogEntry
x LogLevel -> LogLevel -> Bool
forall a. Ord a => a -> a -> Bool
>= LogLevel
logLevel) Seq LogEntry
logs
      Bool -> m ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Seq LogEntry -> Bool
forall a. Seq a -> Bool
Seq.null Seq LogEntry
filteredLogs)
      Widget n -> m (Widget n)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Widget n -> m (Widget n)) -> Widget n -> m (Widget n)
forall a b. (a -> b) -> a -> b
$ Widget n -> Widget n -> Widget n
forall n. Widget n -> Widget n -> Widget n
borderWithLabel (Int -> Widget n -> Widget n
forall n. Int -> Widget n -> Widget n
padLeftRight Int
1 (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str String
"Logs") (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ [Widget n] -> Widget n
forall n. [Widget n] -> Widget n
vBox ([Widget n] -> Widget n) -> [Widget n] -> Widget n
forall a b. (a -> b) -> a -> b
$
        Seq (Widget n) -> [Widget n]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Seq (Widget n) -> [Widget n]) -> Seq (Widget n) -> [Widget n]
forall a b. (a -> b) -> a -> b
$ (LogEntry -> Widget n) -> Seq LogEntry -> Seq (Widget n)
forall a b. (a -> b) -> Seq a -> Seq b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap LogEntry -> Widget n
forall {n}. LogEntry -> Widget n
logEntryWidget Seq LogEntry
filteredLogs

    logEntryWidget :: LogEntry -> Widget n
logEntryWidget (LogEntry {Text
UTCTime
LogStr
Loc
LogLevel
logEntryLevel :: LogEntry -> LogLevel
logEntryTime :: UTCTime
logEntryLoc :: Loc
logEntrySource :: Text
logEntryLevel :: LogLevel
logEntryStr :: LogStr
logEntryTime :: LogEntry -> UTCTime
logEntryLoc :: LogEntry -> Loc
logEntrySource :: LogEntry -> Text
logEntryStr :: LogEntry -> LogStr
..}) = [Widget n] -> Widget n
forall n. [Widget n] -> Widget n
hBox [
      AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
logTimestampAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (UTCTime -> String
forall a. Show a => a -> String
show UTCTime
logEntryTime)
      , String -> Widget n
forall n. String -> Widget n
str String
" "
      , LogLevel -> Widget n
forall {n}. LogLevel -> Widget n
logLevelWidget LogLevel
logEntryLevel
      , String -> Widget n
forall n. String -> Widget n
str String
" "
      , Loc -> Widget n
forall {n}. Loc -> Widget n
logLocWidget Loc
logEntryLoc
      , String -> Widget n
forall n. String -> Widget n
str String
" "
      , Text -> Widget n
forall n. Text -> Widget n
txtWrap (ByteString -> Text
E.decodeUtf8 (ByteString -> Text) -> ByteString -> Text
forall a b. (a -> b) -> a -> b
$ LogStr -> ByteString
fromLogStr LogStr
logEntryStr)
      ]

    logLocWidget :: Loc -> Widget n
logLocWidget (Loc {loc_start :: Loc -> CharPos
loc_start=(Int
line, Int
ch), String
CharPos
loc_filename :: String
loc_package :: String
loc_module :: String
loc_end :: CharPos
loc_filename :: Loc -> String
loc_package :: Loc -> String
loc_module :: Loc -> String
loc_end :: Loc -> CharPos
..}) = [Widget n] -> Widget n
forall n. [Widget n] -> Widget n
hBox [
      String -> Widget n
forall n. String -> Widget n
str String
"["
      , AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
logFilenameAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str String
loc_filename
      , String -> Widget n
forall n. String -> Widget n
str String
":"
      , AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
logLineAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (Int -> String
forall a. Show a => a -> String
show Int
line)
      , String -> Widget n
forall n. String -> Widget n
str String
":"
      , AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
logChAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (Int -> String
forall a. Show a => a -> String
show Int
ch)
      , String -> Widget n
forall n. String -> Widget n
str String
"]"
      ]

    logLevelWidget :: LogLevel -> Widget n
logLevelWidget LogLevel
LevelDebug = AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
debugAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str String
"(DEBUG)"
    logLevelWidget LogLevel
LevelInfo = AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
infoAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str String
"(INFO)"
    logLevelWidget LogLevel
LevelWarn = AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
infoAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str String
"(WARN)"
    logLevelWidget LogLevel
LevelError = AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
infoAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str String
"(ERROR)"
    logLevelWidget (LevelOther Text
x) = AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
infoAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str [i|#{x}|]


borderWithCounts :: AppState -> Widget n
borderWithCounts AppState
app = Widget n -> Widget n
forall n. Widget n -> Widget n
hBorderWithLabel (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ Int -> Widget n -> Widget n
forall n. Int -> Widget n -> Widget n
padLeftRight Int
1 (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ [Widget n] -> Widget n
forall n. [Widget n] -> Widget n
hBox ([Widget n] -> [[Widget n]] -> [Widget n]
forall a. [a] -> [[a]] -> [a]
L.intercalate [String -> Widget n
forall n. String -> Widget n
str String
", "] [[Widget n]]
forall {n}. [[Widget n]]
countWidgets [Widget n] -> [Widget n] -> [Widget n]
forall a. Semigroup a => a -> a -> a
<> [String -> Widget n
forall n. String -> Widget n
str [i| of |]
                                                                                                          , AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
totalAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (String -> Widget n) -> String -> Widget n
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
totalNumTests
                                                                                                          , String -> Widget n
forall n. String -> Widget n
str [i| in |]
                                                                                                          , AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
timeAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (String -> Widget n) -> String -> Widget n
forall a b. (a -> b) -> a -> b
$ NominalDiffTime -> String
formatNominalDiffTime (UTCTime -> UTCTime -> NominalDiffTime
diffUTCTime (AppState
app AppState -> Getting UTCTime AppState UTCTime -> UTCTime
forall s a. s -> Getting a s a -> a
^. Getting UTCTime AppState UTCTime
Lens' AppState UTCTime
appCurrentTime) (AppState
app AppState -> Getting UTCTime AppState UTCTime -> UTCTime
forall s a. s -> Getting a s a -> a
^. Getting UTCTime AppState UTCTime
Lens' AppState UTCTime
appStartTime))])
  where
    countWidgets :: [[Widget n]]
countWidgets =
      (if Int
totalSucceededTests Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then [[AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
successAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (String -> Widget n) -> String -> Widget n
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
totalSucceededTests, String -> Widget n
forall n. String -> Widget n
str String
" succeeded"]] else [[Widget n]]
forall a. Monoid a => a
mempty)
      [[Widget n]] -> [[Widget n]] -> [[Widget n]]
forall a. Semigroup a => a -> a -> a
<> (if Int
totalFailedTests Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then [[AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
failureAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (String -> Widget n) -> String -> Widget n
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
totalFailedTests, String -> Widget n
forall n. String -> Widget n
str String
" failed"]] else [[Widget n]]
forall a. Monoid a => a
mempty)
      [[Widget n]] -> [[Widget n]] -> [[Widget n]]
forall a. Semigroup a => a -> a -> a
<> (if Int
totalPendingTests Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then [[AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
pendingAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (String -> Widget n) -> String -> Widget n
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
totalPendingTests, String -> Widget n
forall n. String -> Widget n
str String
" pending"]] else [[Widget n]]
forall a. Monoid a => a
mempty)
      [[Widget n]] -> [[Widget n]] -> [[Widget n]]
forall a. Semigroup a => a -> a -> a
<> (if Int
totalRunningTests Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then [[AttrName -> Widget n -> Widget n
forall n. AttrName -> Widget n -> Widget n
withAttr AttrName
runningAttr (Widget n -> Widget n) -> Widget n -> Widget n
forall a b. (a -> b) -> a -> b
$ String -> Widget n
forall n. String -> Widget n
str (String -> Widget n) -> String -> Widget n
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
totalRunningTests, String -> Widget n
forall n. String -> Widget n
str String
" running"]] else [[Widget n]]
forall a. Monoid a => a
mempty)
      [[Widget n]] -> [[Widget n]] -> [[Widget n]]
forall a. Semigroup a => a -> a -> a
<> (if Int
totalNotStartedTests Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then [[String -> Widget n
forall n. String -> Widget n
str (String -> Widget n) -> String -> Widget n
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
totalNotStartedTests, String -> Widget n
forall n. String -> Widget n
str String
" not started"]] else [[Widget n]]
forall a. Monoid a => a
mempty)

    totalNumTests :: Int
totalNumTests = (forall context1.
 RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool)
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> Int
forall s l t context.
(forall context1. RunNodeWithStatus context1 s l t -> Bool)
-> [RunNodeWithStatus context s l t] -> Int
countWhere RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall context1.
RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall {context} {s} {l} {t}.
RunNodeWithStatus context s l t -> Bool
isItBlock (AppState
app AppState
-> Getting
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
     AppState
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
forall s a. s -> Getting a s a -> a
^. Getting
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
  AppState
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
Lens'
  AppState [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
appRunTree)
    totalSucceededTests :: Int
totalSucceededTests = (forall context1.
 RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool)
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> Int
forall s l t context.
(forall context1. RunNodeWithStatus context1 s l t -> Bool)
-> [RunNodeWithStatus context s l t] -> Int
countWhere RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall context1.
RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall {context} {l} {t}.
RunNodeWithStatus context Status l t -> Bool
isSuccessItBlock (AppState
app AppState
-> Getting
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
     AppState
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
forall s a. s -> Getting a s a -> a
^. Getting
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
  AppState
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
Lens'
  AppState [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
appRunTree)
    totalPendingTests :: Int
totalPendingTests = (forall context1.
 RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool)
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> Int
forall s l t context.
(forall context1. RunNodeWithStatus context1 s l t -> Bool)
-> [RunNodeWithStatus context s l t] -> Int
countWhere RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall context1.
RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall {context} {l} {t}.
RunNodeWithStatus context Status l t -> Bool
isPendingItBlock (AppState
app AppState
-> Getting
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
     AppState
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
forall s a. s -> Getting a s a -> a
^. Getting
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
  AppState
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
Lens'
  AppState [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
appRunTree)
    totalFailedTests :: Int
totalFailedTests = (forall context1.
 RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool)
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> Int
forall s l t context.
(forall context1. RunNodeWithStatus context1 s l t -> Bool)
-> [RunNodeWithStatus context s l t] -> Int
countWhere RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall context1.
RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall {context} {l} {t}.
RunNodeWithStatus context Status l t -> Bool
isFailedItBlock (AppState
app AppState
-> Getting
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
     AppState
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
forall s a. s -> Getting a s a -> a
^. Getting
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
  AppState
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
Lens'
  AppState [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
appRunTree)
    totalRunningTests :: Int
totalRunningTests = (forall context1.
 RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool)
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> Int
forall s l t context.
(forall context1. RunNodeWithStatus context1 s l t -> Bool)
-> [RunNodeWithStatus context s l t] -> Int
countWhere RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall context1.
RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall {context} {l} {t}.
RunNodeWithStatus context Status l t -> Bool
isRunningItBlock (AppState
app AppState
-> Getting
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
     AppState
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
forall s a. s -> Getting a s a -> a
^. Getting
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
  AppState
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
Lens'
  AppState [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
appRunTree)
    totalNotStartedTests :: Int
totalNotStartedTests = (forall context1.
 RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool)
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> Int
forall s l t context.
(forall context1. RunNodeWithStatus context1 s l t -> Bool)
-> [RunNodeWithStatus context s l t] -> Int
countWhere RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall context1.
RunNodeWithStatus context1 Status (Seq LogEntry) Bool -> Bool
forall {context} {l} {t}.
RunNodeWithStatus context Status l t -> Bool
isNotStartedItBlock (AppState
app AppState
-> Getting
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
     AppState
     [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
-> [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
forall s a. s -> Getting a s a -> a
^. Getting
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
  AppState
  [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
Lens'
  AppState [RunNodeWithStatus BaseContext Status (Seq LogEntry) Bool]
appRunTree)

getCallStackFromStatus :: CustomExceptionFormatters -> Status -> Maybe CallStack
getCallStackFromStatus :: CustomExceptionFormatters -> Status -> Maybe CallStack
getCallStackFromStatus CustomExceptionFormatters
cef (Done {statusResult :: Status -> Result
statusResult=(Failure reason :: FailureReason
reason@(GotException Maybe CallStack
_ Maybe String
_ (SomeExceptionWithEq SomeException
baseException)))}) =
  case [CustomTUIException] -> Maybe CustomTUIException
forall a. [a] -> Maybe a
headMay ([CustomTUIException] -> Maybe CustomTUIException)
-> [CustomTUIException] -> Maybe CustomTUIException
forall a b. (a -> b) -> a -> b
$ [Maybe CustomTUIException] -> [CustomTUIException]
forall a. [Maybe a] -> [a]
catMaybes [SomeException -> Maybe CustomTUIException
x SomeException
baseException | SomeException -> Maybe CustomTUIException
x <- CustomExceptionFormatters
cef] of
    Just (CustomTUIExceptionMessageAndCallStack Text
_ Maybe CallStack
maybeCs) -> Maybe CallStack
maybeCs
    Maybe CustomTUIException
_ -> FailureReason -> Maybe CallStack
failureCallStack FailureReason
reason
getCallStackFromStatus CustomExceptionFormatters
_ (Done {statusResult :: Status -> Result
statusResult=(Failure FailureReason
reason)}) = FailureReason -> Maybe CallStack
failureCallStack FailureReason
reason
getCallStackFromStatus CustomExceptionFormatters
_ Status
_ = Maybe CallStack
forall a. Maybe a
Nothing