packages feed

dr-cabal-0.2.0.0: src/DrCabal/Profile.hs

{- |
Module                  : DrCabal.Profile
Copyright               : (c) 2022 Dmitrii Kovanikov
SPDX-License-Identifier : MPL-2.0
Maintainer              : Dmitrii Kovanikov <kovanikov@gmail.com>
Stability               : Experimental
Portability             : Portable

@dr-cabal profile@ command.
-}

module DrCabal.Profile
    ( runProfile
    ) where

import DrCabal.Cli (FileMode (..), ProfileArgs (..))
import DrCabal.Json (readEntries, writeEntries)
import DrCabal.Model (Entry (..), Style (..))
import DrCabal.Profile.Stacked (createStackedChart)
import DrCabal.Terminal (getTerminalWidth, withAlternateBuffer)
import DrCabal.Watch (watchBuild)


runProfile :: ProfileArgs -> IO ()
runProfile ProfileArgs{..} = case profileArgsFileMode of
     None ->
         profileInteractive profileArgsStyle
     Output outputFile ->
         profileWithOutput profileArgsStyle outputFile
     Input inputFile ->
         profileFromInput profileArgsStyle inputFile

profileInteractive :: Style -> IO ()
profileInteractive chartStyle = do
    -- draw profiling chart interactively and get all the entries after that
    entries <- withInteractiveProfiling chartStyle

    -- draw the chart in the normal terminal screen buffer now
    drawChart <- getChartDrawer chartStyle
    putTextLn $ drawChart entries

    putText $ unlines
        [ "✨  Done!"
        , "🆙  Scroll up to view full profiling chart."
        , "💾  To save the results in a file (to view later without recompilation), run:"
        , ""
        , "    cabal build ... | dr-cabal profile --output=my_file.json"
        ]

profileWithOutput :: Style -> FilePath -> IO ()
profileWithOutput chartStyle outputFile = do
    -- draw profiling chart interactively and get all the entries after that
    entries <- withInteractiveProfiling chartStyle
    writeEntries outputFile entries

    putText $ unlines
        [ "✨  Done!"
        , "💾  Profiling entries are saved in the file: " <> toText outputFile
        , "👀  To view the results from the saved file, run:"
        , ""
        , "    dr-cabal profile --input=" <> toText outputFile
        ]

profileFromInput :: Style -> FilePath -> IO ()
profileFromInput chartStyle inputFile = do
    terminalWidth <- getTerminalWidth
    entries <- readEntries inputFile
    let chart = createChart chartStyle terminalWidth entries
    putTextLn chart

-------------
-- HELPERS --
-------------

withInteractiveProfiling :: Style -> IO [Entry]
withInteractiveProfiling chartStyle = withAlternateBuffer $ do
    hSetBuffering stdout (BlockBuffering Nothing)
    drawChart <- getChartDrawer chartStyle
    watchBuild drawChart

getChartDrawer :: Style -> IO ([Entry] -> Text)
getChartDrawer chartStyle = do
    terminalWidth <- getTerminalWidth
    pure $ createChart chartStyle terminalWidth

createChart
    :: Style
    -- ^ Chart type
    -> Int
    -- ^ Terminal width
    -> [Entry]
    -- ^ Time entries
    -> Text
createChart = \case
    Stacked -> createStackedChart