1{-# LANGUAGE OverloadedStrings #-}
2module Reporting.Progress.Terminal
9import Control.Concurrent (forkIO)
10import Control.Concurrent.Chan (Chan, newChan, readChan)
11import Control.Concurrent.MVar (newEmptyMVar, putMVar)
12import qualified System.Info as Info
13import System.IO (hFlush, hPutStr, stdout)
14import qualified Elm.Package as Pkg
15import qualified Elm.Version as V
17import qualified Deps.Diff as Diff
18import Reporting.Doc ((<>), (<+>))
19import qualified Reporting.Doc as D
20import qualified Reporting.Exit as Exit
21import qualified Reporting.Exit.Help as Help
22import Reporting.Progress (Msg(..), Progress(..), Outcome(..), PublishPhase(..), BumpPhase(..))
23import qualified Reporting.Progress as Progress
24import qualified Reporting.Progress.Bar as Bar
31create :: IO Progress.Reporter
35 _ <- forkIO (loop chan (State 0 0 0) >>= putMVar mvar)
36 return (Progress.makeReporter chan mvar)
55loop :: Chan Msg -> State -> IO ()
57 do msg <- readChan chan
67 putMVar mvar =<< getApproval
71 loopHelp chan progress state
84 do putStr "Must type 'y' for yes or 'n' for no: "
88loopHelp :: Chan Msg -> Progress -> State -> IO ()
89loopHelp chan progress state@(State total good bad) =
96 do putStrLn "Dependencies loaded from local cache."
103 do putStrLn "Starting downloads...\n"
106 DownloadPkgStart _name _version ->
109 DownloadPkgEnd name version outcome ->
110 do Help.toStdout (makeBullet name version outcome)
124 BuildDepsStart size ->
125 do hPutStr stdout "Verifying dependencies..."
127 loop chan (State size 0 0)
131 let msg = "\rBuilding dependencies (" ++ show n ++ "/" ++ show total ++ ")"
134 loop chan (State total n 0)
137 do putStrLn "\rDependencies ready! "
138 loop chan (State 0 0 0)
144 loop chan (State size 0 0)
146 CompileFileStart _ ->
149 CompileFileEnd _ Good ->
150 do hPutStr stdout $ Bar.render (good + 1) bad total
152 loop chan (State total (good + 1) bad)
154 CompileFileEnd _ Bad ->
155 do hPutStr stdout $ Bar.render good (bad + 1) total
157 loop chan (State total good (bad + 1))
164 (0, 1) -> "Success! Compiled 1 module."
165 (0, n) -> "Success! Compiled " ++ show n ++ " modules."
166 (1, _) -> "Detected errors in 1 module."
167 (n, _) -> "Detected errors in " ++ show n ++ " modules."
169 do hPutStr stdout $ Bar.clear
171 loop chan (State 0 0 0)
176 PublishStart name version maybePublishedVersions ->
177 case maybePublishedVersions of
179 do putStrLn newPackageOverview
180 putStrLn "I will now verify that everything is in order..."
185 do putStrLn $ unwords [ "Verifying", Pkg.toChars name, V.toChars version, "..." ]
189 PublishCheckBump version bumpPhase ->
190 do Help.toStdout $ bumpPhaseToChecklistDoc version bumpPhase
194 PublishProgress phase status ->
195 do Help.toStdout $ toChecklistDoc status (toChecklistMessages phase)
200 do putStrLn "Success!"
206 UnableToLoadLatestPackages ->
208 Help.toStdout $ D.dullyellow "WARNING:" <+> "I normally check <https://package.elm-lang.org> for new packages\n"
209 putStrLn "here, but my request failed. Are you offline? I will try to continue anyway.\n"
217makeBullet :: Pkg.Name -> V.Version -> Outcome -> D.Doc
218makeBullet name version outcome =
220 nm = D.fromUtf8 (Pkg.toString name)
221 vsn = D.fromUtf8 (V.toString version)
228 D.indent 2 $ bullet <+> nm <+> vsn <> "\n"
234 if Info.os == "mingw32" then "+" else "●"
240 if Info.os == "mingw32" then "X" else "✗"
246 if Info.os == "mingw32" then "-" else "→"
250-- OVERVIEW OF VERSIONING
253newPackageOverview :: String
256 [ "This package has never been published before. Here's how things work:"
258 , " - Versions all have exactly three parts: MAJOR.MINOR.PATCH"
260 , " - All packages start with initial version " ++ V.toChars V.one
262 , " - Versions are incremented based on how the API changes:"
264 , " PATCH = the API is the same, no risk of breaking code"
265 , " MINOR = values have been added, existing values are unchanged"
266 , " MAJOR = existing values have been changed or removed"
268 , " - I will bump versions for you, automatically enforcing these rules"
277toChecklistDoc :: Maybe Outcome -> ChecklistMessages -> D.Doc
278toChecklistDoc status (ChecklistMessages waiting success failure) =
281 message ++ replicate (length waiting - length message) ' '
285 " " <> waitingMark <+> D.fromChars waiting
288 "\r " <> goodMark <+> D.fromChars (padded success ++ "\n")
291 "\r " <> badMark <+> D.fromChars (padded failure ++ "\n\n")
294data ChecklistMessages =
302toChecklistMessages :: PublishPhase -> ChecklistMessages
303toChecklistMessages phase =
307 "Looking for README.md"
309 "Problem with your README.md"
313 "Looking for LICENSE"
315 "Problem with your LICENSE"
319 ("Is version " ++ V.toChars version ++ " tagged on GitHub?")
320 ("Version " ++ V.toChars version ++ " is tagged on GitHub")
321 ("Version " ++ V.toChars version ++ " is not tagged on GitHub!")
325 "Downloading code from GitHub..."
326 "Code downloaded successfully from GitHub"
327 "Could not download code from GitHub!"
331 "Building downloaded code and generated docs..."
332 "Downloaded code compiles successfully / docs generated\n"
333 "Cannot compile downloaded code!"
337 "Checking for uncommitted changes..."
338 "No uncommitted changes in local code"
339 "Your local code is different than the code tagged on GitHub"
346bumpPhaseToChecklistDoc :: V.Version -> BumpPhase -> D.Doc
347bumpPhaseToChecklistDoc version bumpPhase =
351 ("Checking semantic versioning rules. Is " ++ V.toChars version ++ " correct?")
353 ("Version " ++ V.toChars version ++ " is not correct!")
358 toChecklistDoc Nothing $ mkMsgs ""
361 toChecklistDoc (Just Good) $ mkMsgs $
362 "All packages start at version " ++ V.toChars V.one
364 GoodBump old magnitude ->
365 toChecklistDoc (Just Good) $ mkMsgs $
366 toCheckVersionSuccessMessage old version magnitude
369 toChecklistDoc (Just Bad) $ mkMsgs ""
372toCheckVersionSuccessMessage :: V.Version -> V.Version -> Diff.Magnitude -> String
373toCheckVersionSuccessMessage oldVersion newVersion magnitude =
375 old = V.toChars oldVersion
376 new = V.toChars newVersion
377 mag = Diff.magnitudeToString magnitude
379 "Version number " ++ new ++ " verified (" ++ mag ++ " change, " ++ old ++ " => " ++ new ++ ")"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list