1+ #!/usr/bin/env cabal
2+ {- cabal:
3+ build-depends: base, haskeline >=0.8, directory >= 1.3, filepath >= 1.4
4+ -}
15module Main where
26
37import Control.Monad (forM , forM_ )
8+ import Control.Monad.IO.Class (liftIO )
49import Data.Char (isLower , isSpace , toLower , toUpper )
10+ import Data.Maybe (fromMaybe )
11+ import System.Console.Haskeline
512import System.Directory (createDirectory , createDirectoryIfMissing )
613import System.FilePath ((<.>) , (</>) )
714import System.IO (BufferMode (.. ), hSetBuffering , stdout )
815import Text.Read (readMaybe )
916
10- -------------------------------------------------------------------------------
11- -- Run this tool with `runghc` on the commandline:
12-
13- -- $ runghc create-message-template.hs
17+ type ToolM a = InputT IO a
1418
15- -------------------------------------------------------------------------------
19+ getInputLine' :: String -> ToolM String
20+ getInputLine' s = do
21+ ln <- getInputLine s
22+ pure (fromMaybe " " ln)
1623
1724-------------------------------------------------------------------------------
1825-- Querying the user about the diagnostic
@@ -29,15 +36,14 @@ normalize = fmap toLower . strip
2936
3037data Tool = GHC | GHCup | Stack | Cabal deriving (Show )
3138
32- readTool :: IO Tool
39+ readTool :: ToolM Tool
3340readTool = do
34- putStrLn " · Which tool's error code do you want to document?"
35- putStrLn " 1) GHC"
36- putStrLn " 2) GHCup"
37- putStrLn " 3) Stack"
38- putStrLn " 4) Cabal"
39- putStr " Input (Default = GHC): "
40- ln <- getLine
41+ outputStrLn " · Which tool's error code do you want to document?"
42+ outputStrLn " 1) GHC"
43+ outputStrLn " 2) GHCup"
44+ outputStrLn " 3) Stack"
45+ outputStrLn " 4) Cabal"
46+ ln <- getInputLine' " Input (Default = GHC): "
4147 case normalize ln of
4248 " 1" -> pure GHC
4349 " ghc" -> pure GHC
@@ -49,7 +55,7 @@ readTool = do
4955 " cabal" -> pure Cabal
5056 " " -> pure GHC
5157 _ -> do
52- putStrLn " Didn't understand input. Please type a tool name or a number."
58+ outputStrLn " Didn't understand input. Please type a tool name or a number."
5359 readTool
5460
5561-- Querying for the error code
@@ -58,80 +64,74 @@ readTool = do
5864-- to preserve leading 0's.
5965type ErrorCode = String
6066
61- readCode :: IO ErrorCode
67+ readCode :: ToolM ErrorCode
6268readCode = do
63- putStrLn " · What is the numeric code that you want to document?"
64- putStrLn " For example, enter \" 01234\" if you want to document GHC-01234."
65- putStr " Input: "
66- ln <- getLine
69+ outputStrLn " · What is the numeric code that you want to document?"
70+ outputStrLn " For example, enter \" 01234\" if you want to document GHC-01234."
71+ ln <- getInputLine' " Input: "
6772 case readMaybe ln :: Maybe Int of
6873 Nothing -> do
69- putStrLn " Could not parse the input as an integer. Only enter the numeric part of the error."
74+ outputStrLn " Could not parse the input as an integer. Only enter the numeric part of the error."
7075 readCode
7176 Just _ -> pure ln
7277
7378-- Title
7479type Title = String
7580
76- readTitle :: IO Title
81+ readTitle :: ToolM Title
7782readTitle = do
78- putStrLn " · What is the title of the error message?"
79- putStrLn " This is used as the title of the documentation page as well as in links to the page."
80- putStr " Input: "
81- getLine
83+ outputStrLn " · What is the title of the error message?"
84+ outputStrLn " This is used as the title of the documentation page as well as in links to the page."
85+ getInputLine' " Input: "
8286
8387-- Summary
8488type Summary = String
8589
86- readSummary :: IO Summary
90+ readSummary :: ToolM Summary
8791readSummary = do
88- putStrLn " · Give a short summary of the error message."
89- putStrLn " This appears on the overview page that lists all the documented errors and warnings."
90- putStr " Input: "
91- getLine
92+ outputStrLn " · Give a short summary of the error message."
93+ outputStrLn " This appears on the overview page that lists all the documented errors and warnings."
94+ getInputLine' " Input: "
9295
9396-- Severity
9497data Severity = Error | Warning deriving (Show )
9598
96- readSeverity :: IO Severity
99+ readSeverity :: ToolM Severity
97100readSeverity = do
98- putStrLn " · What is the severity of the diagnostic?"
99- putStrLn " 1) Error"
100- putStrLn " 2) Warning"
101- putStr " Input (Default = Error): "
102- ln <- getLine
101+ outputStrLn " · What is the severity of the diagnostic?"
102+ outputStrLn " 1) Error"
103+ outputStrLn " 2) Warning"
104+ ln <- getInputLine' " Input (Default = Error): "
103105 case normalize ln of
104106 " 1" -> pure Error
105107 " error" -> pure Error
106108 " 2" -> pure Warning
107109 " warning" -> pure Warning
108110 " " -> pure Error
109111 _ -> do
110- putStrLn " Please type \" error\" or \" warning\" or a number."
112+ outputStrLn " Please type \" error\" or \" warning\" or a number."
111113 readSeverity
112114
113115-- Warning flag
114116type WarningFlag = String
115117
116118-- | Only ask for a warning flag if Severity = Warning.
117- readWarningFlag :: Severity -> IO (Maybe WarningFlag )
119+ readWarningFlag :: Severity -> ToolM (Maybe WarningFlag )
118120readWarningFlag Warning = do
119- putStrLn " · What is the warning flag which enables this warning?"
120- putStrLn " For example, enter \" -Wtabs\" if you are documenting GHC's warning about tabs in your source file."
121- putStrLn " You can leave this blank if you're not sure."
122- putStr " Input: "
123- Just <$> getLine
121+ outputStrLn " · What is the warning flag which enables this warning?"
122+ outputStrLn " For example, enter \" -Wtabs\" if you are documenting GHC's warning about tabs in your source file."
123+ outputStrLn " You can leave this blank if you're not sure."
124+ Just <$> getInputLine' " Input: "
124125readWarningFlag _ = pure Nothing
125126
126127-- Version
127128type Version = String
128129
129- readVersion :: IO Version
130+ readVersion :: ToolM Version
130131readVersion = do
131- putStrLn " · Which version of the tool emitted the numeric code (not the message) for the first time?"
132- putStrLn " Note: For GHC this is most likely 9.6.1."
133- putStr " Input: "
134- getLine
132+ outputStrLn " · Which version of the tool emitted the numeric code (not the message) for the first time?"
133+ outputStrLn " Note: For GHC this is most likely 9.6.1."
134+ getInputLine' " Input: "
135135
136136-- Examples
137137type Examples = [String ]
@@ -141,23 +141,21 @@ validateExampleName "" = False
141141validateExampleName str@ (s : _) = not (any isSpace str) && isLower s
142142
143143-- | Only ask for examples if the system is GHC.
144- readExamples :: Tool -> IO Examples
144+ readExamples :: Tool -> ToolM Examples
145145readExamples GHC = do
146- putStrLn " · How many examples should be generated?"
147- putStr " Input: "
148- ln <- getLine
146+ outputStrLn " · How many examples should be generated?"
147+ ln <- getInputLine' " Input: "
149148 case readMaybe ln :: Maybe Int of
150149 Nothing -> pure []
151150 Just n -> forM [1 .. n] readExample
152151readExamples _ = pure []
153152
154- readExample :: Int -> IO String
153+ readExample :: Int -> ToolM String
155154readExample i = do
156- putStrLn " "
157- putStrLn (" · Give a name for example " <> show i)
158- putStrLn " The name should not contain spaces and begin with a lowercase letter."
159- putStr " Input: "
160- ln <- getLine
155+ outputStrLn " "
156+ outputStrLn (" · Give a name for example " <> show i)
157+ outputStrLn " The name should begin with a lowercase letter and should not contain any spaces."
158+ ln <- getInputLine' " Input: "
161159 if validateExampleName ln then pure ln else readExample i
162160
163161-- Template
@@ -173,25 +171,25 @@ data Template = MkTemplate
173171 }
174172 deriving (Show )
175173
176- readTemplate :: IO Template
174+ readTemplate :: ToolM Template
177175readTemplate = do
178- putStrLn " This tool helps you create the scaffolding for a new error message on the error-message-index."
179- putStrLn " You can leave any of the text fields blank and fill them in by hand later."
180- putStrLn " "
176+ outputStrLn " This tool helps you create the scaffolding for a new error message on the error-message-index."
177+ outputStrLn " You can leave any of the text fields blank and fill them in by hand later."
178+ outputStrLn " "
181179 sys <- readTool
182- putStrLn " "
180+ outputStrLn " "
183181 code <- readCode
184- putStrLn " "
182+ outputStrLn " "
185183 title <- readTitle
186- putStrLn " "
184+ outputStrLn " "
187185 summary <- readSummary
188- putStrLn " "
186+ outputStrLn " "
189187 severity <- readSeverity
190- putStrLn " "
188+ outputStrLn " "
191189 warningflag <- readWarningFlag severity
192- putStrLn " "
190+ outputStrLn " "
193191 version <- readVersion
194- putStrLn " "
192+ outputStrLn " "
195193 examples <- readExamples sys
196194 pure (MkTemplate sys code title summary severity warningflag version examples)
197195
@@ -200,7 +198,7 @@ readTemplate = do
200198-------------------------------------------------------------------------------
201199
202200createFiles :: Template -> IO ()
203- createFiles tmpl = do
201+ createFiles tmpl = liftIO $ do
204202 putStrLn " "
205203 putStrLn " · Creating scaffolding..."
206204
@@ -268,5 +266,5 @@ createFiles tmpl = do
268266main :: IO ()
269267main = do
270268 hSetBuffering stdout NoBuffering
271- tmpl <- readTemplate
269+ tmpl <- runInputT defaultSettings readTemplate
272270 createFiles tmpl
0 commit comments