seihou-cli-0.11.0.0: src/Seihou/CLI/Diff.hs
module Seihou.CLI.Diff
( handleDiff,
formatDiffOutput,
)
where
import Data.Generics.Labels ()
import Data.Map.Strict qualified as Map
import Data.Text qualified as T
import Data.Text.IO qualified as TIO
import Seihou.CLI.Shared (logIO)
import Seihou.CLI.Style (dim, red, useColor, yellow)
import Seihou.Core.Status (computeTrackedFileStatuses)
import Seihou.Core.Types
import Seihou.Effect.FilesystemInterp (runFilesystem)
import Seihou.Effect.Logger (logError)
import Seihou.Effect.ManifestStore (readManifest)
import Seihou.Effect.ManifestStoreInterp (runManifestStore)
import Seihou.Prelude
import System.Exit (exitFailure)
handleDiff :: IO ()
handleDiff = do
let manifestPath = ".seihou" </> "manifest.json"
result <- runEff $ runFilesystem $ runManifestStore manifestPath $ do
mResult <- readManifest
case mResult of
Left err -> pure (Left err)
Right Nothing -> pure (Right Nothing)
Right (Just manifest) -> do
tracked <- computeTrackedFileStatuses manifest
pure (Right (Just (tracked, Map.size (manifest ^. #seeds))))
colorEnabled <- useColor
case result of
Left err -> do
logIO LogNormal (logError $ "Error reading manifest: " <> err)
exitFailure
Right Nothing ->
TIO.putStrLn "No Seihou manifest found. Run 'seihou run <module>' to generate a project."
Right (Just (tracked, seedCount)) ->
TIO.putStr (formatDiffOutput colorEnabled tracked seedCount)
formatDiffOutput :: Bool -> [TrackedFile] -> Int -> Text
formatDiffOutput color tracked seedCount =
formatted <> if seedCount == 0 then "" else T.pack (show seedCount) <> " seed files not compared\n"
where
formatted = formatTrackedDiff color tracked
formatTrackedDiff :: Bool -> [TrackedFile] -> Text
formatTrackedDiff color tracked =
let modified = filter (\t -> t ^. #status == TfsModified) tracked
deleted = filter (\t -> t ^. #status == TfsDeleted) tracked
unchanged = filter (\t -> t ^. #status == TfsUnchanged) tracked
nMod = length modified
nDel = length deleted
nUnch = length unchanged
changed = modified ++ deleted
in if null changed
then "No changes since last generation.\n"
else
let maxPathLen = maximum (map (length . (^. #path)) changed)
header = "Seihou Diff:\n"
fileLines = map (formatLine color maxPathLen) changed
summary =
" "
<> T.pack (show nUnch)
<> " unchanged, "
<> T.pack (show nMod)
<> " modified, "
<> T.pack (show nDel)
<> " deleted\n"
in header <> "\n" <> T.unlines fileLines <> "\n" <> summary
formatLine :: Bool -> Int -> TrackedFile -> Text
formatLine color maxPathLen tf =
let (label, colorFn) = case tf ^. #status of
TfsModified -> ("modified", yellow)
TfsDeleted -> ("deleted ", red)
TfsUnchanged -> ("unchanged", dim)
path = T.pack (tf ^. #path)
modName = (tf ^. #moduleName . #unModuleName)
paddedLabel = if color then colorFn label else label
paddedPath = path <> T.replicate (maxPathLen - T.length path + 3) " "
modAttr = if color then dim ("(" <> modName <> ")") else "(" <> modName <> ")"
in " " <> paddedLabel <> " " <> paddedPath <> modAttr