1{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
3module Idris.Output where
6import Idris.Core.Evaluate (isDConName, isTConName, isFnName, normaliseAll)
10import Idris.Docstrings
14import Util.ScreenSize (getScreenWidth)
16import Control.Monad.Trans.Except (ExceptT (ExceptT), runExceptT)
18import System.Console.Haskeline.MonadException
19 (MonadException (controlIO), RunIO (RunIO))
20import System.IO (stdout, Handle, hPutStrLn)
22import Prelude hiding ((<$>))
24import Data.Char (isAlpha)
25import Data.List (nub, intersperse)
26import Data.Maybe (fromMaybe)
28instance MonadException m => MonadException (ExceptT Err m) where
29 controlIO f = ExceptT $ controlIO $ \(RunIO run) -> let
30 run' = RunIO (fmap ExceptT . run . runExceptT)
31 in fmap runExceptT $ f run'
33pshow :: IState -> Err -> String
34pshow ist err = displayDecorated (consoleDecorate ist) .
36 fmap (fancifyAnnots ist True) $ pprintErr ist err
38iWarn :: FC -> Doc OutputAnnotation -> Idris ()
41 case idris_outputmode i of
43 do err' <- iRender . fmap (fancifyAnnots i True) $
45 FC fn _ _ | fn /= "" -> text (show fc) <> colon <//> err
47 runIO . hPutStrLn h $ displayDecorated (consoleDecorate i) err'
49 do err' <- iRender . fmap (fancifyAnnots i True) $ err
50 let (str, spans) = displaySpans err'
52 convSExp "warning" (fc_fname fc, fc_start fc, fc_end fc, str, spans) n
54iRender :: Doc a -> Idris (SimpleDoc a)
55iRender d = do w <- getWidth
57 let ideMode = case idris_outputmode ist of
61 InfinitelyWide -> return $ renderPretty 1.0 1000000000 d
62 ColsWide n -> return $
64 then renderPretty 1.0 1000000000 d
65 else renderPretty 0.8 n d
66 AutomaticWidth | ideMode -> return $ renderPretty 1.0 80 d
67 | otherwise -> do width <- runIO getScreenWidth
68 return $ renderPretty 0.8 width d
70-- | Write a pretty-printed term to the console with semantic coloring
71consoleDisplayAnnotated :: Handle -> Doc OutputAnnotation -> Idris ()
72consoleDisplayAnnotated h output = do ist <- getIState
73 rendered <- iRender $ output
75 displayDecorated (consoleDecorate ist) $
78iPrintTermWithType :: Doc OutputAnnotation -> Doc OutputAnnotation -> Idris ()
79iPrintTermWithType tm ty = iRenderResult (tm <+> colon <+> align ty)
81-- | Pretty-print a collection of overloadings to REPL or IDEMode - corresponds to :t name
82iPrintFunTypes :: [(Name, Bool)] -> Name -> [(Name, Doc OutputAnnotation)] -> Idris ()
83iPrintFunTypes bnd n [] = iPrintError $ "No such variable " ++ show n
84iPrintFunTypes bnd n overloads = do ist <- getIState
85 let ppo = ppOptionIst ist
86 let infixes = idris_infixes ist
87 let output = vsep (map (uncurry (ppOverload ppo infixes)) overloads)
89 where fullName n = prettyName True True bnd n
90 ppOverload ppo infixes n tm =
91 fullName n <+> colon <+> align tm
93iRenderOutput :: Doc OutputAnnotation -> Idris ()
96 case idris_outputmode i of
97 RawOutput h -> do out <- iRender doc
98 runIO $ putStrLn (displayDecorated (consoleDecorate i) out)
100 do (str, spans) <- fmap displaySpans . iRender . fmap (fancifyAnnots i True) $ doc
101 let out = [toSExp str, toSExp spans]
102 runIO . hPutStrLn h $ convSExp "write-decorated" out n
104iRenderResult :: Doc OutputAnnotation -> Idris ()
105iRenderResult d = do ist <- getIState
106 case idris_outputmode ist of
107 RawOutput h -> consoleDisplayAnnotated h d
108 IdeMode n h -> ideModeReturnAnnotated n h d
110ideModeReturnWithStatus :: String -> Integer -> Handle -> Doc OutputAnnotation -> Idris ()
111ideModeReturnWithStatus status n h out = do
113 (str, spans) <- fmap displaySpans .
115 fmap (fancifyAnnots ist True) $
117 let good = [SymbolAtom status, toSExp str, toSExp spans]
118 runIO . hPutStrLn h $ convSExp "return" good n
121-- | Write pretty-printed output to IDEMode with semantic annotations
122ideModeReturnAnnotated :: Integer -> Handle -> Doc OutputAnnotation -> Idris ()
123ideModeReturnAnnotated = ideModeReturnWithStatus "ok"
125-- | Show an error with semantic highlighting
126iRenderError :: Doc OutputAnnotation -> Idris ()
127iRenderError e = do ist <- getIState
128 case idris_outputmode ist of
129 RawOutput h -> consoleDisplayAnnotated h e
130 IdeMode n h -> ideModeReturnWithStatus "error" n h e
132iPrintWithStatus :: String -> String -> Idris ()
133iPrintWithStatus status s = do
135 case idris_outputmode i of
136 RawOutput h -> case s of
138 s -> runIO $ hPutStrLn h s
140 let good = SexpList [SymbolAtom status, toSExp s] in
141 runIO $ hPutStrLn h $ convSExp "return" good n
144iPrintResult :: String -> Idris ()
145iPrintResult = iPrintWithStatus "ok"
147iPrintError :: String -> Idris ()
148iPrintError = iPrintWithStatus "error"
150iputStrLn :: String -> Idris ()
151iputStrLn s = do i <- getIState
152 case idris_outputmode i of
153 RawOutput h -> runIO $ hPutStrLn h s
154 IdeMode n h -> runIO . hPutStrLn h $ convSExp "write-string" s n
157idemodePutSExp :: SExpable a => String -> a -> Idris ()
158idemodePutSExp cmd info = do i <- getIState
159 case idris_outputmode i of
161 runIO . hPutStrLn h $
165-- TODO: send structured output similar to the metavariable list
166iputGoal :: SimpleDoc OutputAnnotation -> Idris ()
167iputGoal g = do i <- getIState
168 case idris_outputmode i of
169 RawOutput h -> runIO $ hPutStrLn h (displayDecorated (consoleDecorate i) g)
171 let (str, spans) = displaySpans . fmap (fancifyAnnots i True) $ g
172 goal = [toSExp str, toSExp spans]
173 in runIO . hPutStrLn h $ convSExp "write-goal" goal n
175-- | Warn about totality problems without failing to compile
176warnTotality :: Idris ()
177warnTotality = do ist <- getIState
178 mapM_ (warn ist) (nub (idris_totcheckfail ist))
179 where warn ist (fc, e) = iWarn fc (pprintErr ist (Msg e))
182printUndefinedNames :: [Name] -> Doc OutputAnnotation
183printUndefinedNames ns = text "Undefined " <> names <> text "."
184 where names = encloseSep empty empty (char ',') $ map ppName ns
185 ppName = prettyName True True []
188prettyDocumentedIst :: IState
189 -> (Name, PTerm, Maybe (Docstring DocTerm))
190 -> Doc OutputAnnotation
191prettyDocumentedIst ist (name, ty, docs) =
192 prettyName True True [] name <+> colon <+> align (prettyIst ist ty) <$>
193 fromMaybe empty (fmap (\d -> renderDocstring (renderDocTerm ppTm norm) d <> line) docs)
194 where ppTm = pprintDelab ist
195 norm = normaliseAll (tt_ctxt ist) []
197sendHighlighting :: [(FC, OutputAnnotation)] -> Idris ()
198sendHighlighting highlights =
200 case idris_outputmode ist of
201 RawOutput _ -> return ()
203 let fancier = [ toSExp (fc, fancifyAnnots ist False annot)
204 | (fc, annot) <- highlights, fullFC fc
208 _ -> runIO . hPutStrLn h $
211 (SymbolAtom "highlight-source", fancier)) n
213 where fullFC (FC _ _ _) = True
217renderExternal :: OutputFmt -> Int -> Doc OutputAnnotation -> Idris String
218renderExternal fmt width doc
219 | width < 1 = throwError . Msg $ "There must be at least one column for the pretty-printer."
223 displayDecorated (decorate fmt) .
224 renderPretty 1.0 width .
225 fmap (fancifyAnnots ist True) $
228 decorate _ (AnnFC _) = id
230 decorate HTMLOutput (AnnName _ (Just TypeOutput) d _) =
232 decorate HTMLOutput (AnnName _ (Just FunOutput) d _) =
233 tag "idris-function" d
234 decorate HTMLOutput (AnnName _ (Just DataOutput) d _) =
236 decorate HTMLOutput (AnnName _ (Just MetavarOutput) d _) =
237 tag "idris-metavar" d
238 decorate HTMLOutput (AnnName _ (Just PostulateOutput) d _) =
239 tag "idris-postulate" d
240 decorate HTMLOutput (AnnName _ _ _ _) = id
241 decorate HTMLOutput (AnnBoundName _ True) = tag "idris-bound idris-implicit" Nothing
242 decorate HTMLOutput (AnnBoundName _ False) = tag "idris-bound" Nothing
243 decorate HTMLOutput (AnnConst c) =
244 tag (if constIsType c then "idris-type" else "idris-data")
246 decorate HTMLOutput (AnnData _ _) = tag "idris-data" Nothing
247 decorate HTMLOutput (AnnType _ _) = tag "idris-type" Nothing
248 decorate HTMLOutput AnnKeyword = tag "idris-keyword" Nothing
249 decorate HTMLOutput (AnnTextFmt fmt) =
251 BoldText -> mkTag "strong"
252 ItalicText -> mkTag "em"
253 UnderlineText -> tag "idris-underlined" Nothing
254 where mkTag t x = "<"++t++">"++x++"</"++t++">"
255 decorate HTMLOutput (AnnTerm _ _) = id
256 decorate HTMLOutput (AnnSearchResult _) = id
257 decorate HTMLOutput (AnnErr _) = id
258 decorate HTMLOutput (AnnNamespace _ _) = id
260 decorate LaTeXOutput (AnnName _ (Just TypeOutput) _ _) =
262 decorate LaTeXOutput (AnnName _ (Just FunOutput) _ _) =
263 latex "IdrisFunction"
264 decorate LaTeXOutput (AnnName _ (Just DataOutput) _ _) =
266 decorate LaTeXOutput (AnnName _ (Just MetavarOutput) _ _) =
268 decorate LaTeXOutput (AnnName _ (Just PostulateOutput) _ _) =
269 latex "IdrisPostulate"
270 decorate LaTeXOutput (AnnName _ _ _ _) = id
271 decorate LaTeXOutput (AnnBoundName _ True) = latex "IdrisImplicit"
272 decorate LaTeXOutput (AnnBoundName _ False) = latex "IdrisBound"
273 decorate LaTeXOutput (AnnConst c) =
274 latex $ if constIsType c then "IdrisType" else "IdrisData"
275 decorate LaTeXOutput (AnnData _ _) = latex "IdrisData"
276 decorate LaTeXOutput (AnnType _ _) = latex "IdrisType"
277 decorate LaTeXOutput AnnKeyword = latex "IdrisKeyword"
278 decorate LaTeXOutput (AnnTextFmt fmt) =
280 BoldText -> latex "textbf"
281 ItalicText -> latex "emph"
282 UnderlineText -> latex "underline"
283 decorate LaTeXOutput (AnnTerm _ _) = id
284 decorate LaTeXOutput (AnnSearchResult _) = id
285 decorate LaTeXOutput (AnnErr _) = id
286 decorate LaTeXOutput (AnnNamespace _ _) = id
288 tag cls docs str = "<span class=\""++cls++"\""++title++">" ++ str ++ "</span>"
289 where title = maybe "" (\d->" title=\"" ++ d ++ "\"") docs
291 latex cmd str = "\\"++cmd++"{"++str++"}"
293 wrap HTMLOutput str =
294 "<!doctype html><html><head><style>" ++ css ++ "</style></head>" ++
295 "<body><!-- START CODE --><pre>" ++ str ++ "</pre><!-- END CODE --></body></html>"
296 where css = concat . intersperse "\n" $
297 [".idris-data { color: red; } ",
298 ".idris-type { color: blue; }",
299 ".idris-function {color: green; }",
300 ".idris-keyword { font-weight: bold; }",
301 ".idris-bound { color: purple; }",
302 ".idris-implicit { font-style: italic; }",
303 ".idris-underlined { text-decoration: underline; }"]
304 wrap LaTeXOutput str =
305 concat . intersperse "\n" $
306 ["\\documentclass{article}",
307 "\\usepackage{fancyvrb}",
308 "\\usepackage[usenames]{xcolor}"] ++
309 map (\(cmd, color) ->
310 "\\newcommand{\\"++ cmd ++
311 "}[1]{\\textcolor{"++ color ++"}{#1}}")
312 [("IdrisData", "red"), ("IdrisType", "blue"),
313 ("IdrisBound", "magenta"), ("IdrisFunction", "green")] ++
314 ["\\newcommand{\\IdrisKeyword}[1]{{\\underline{#1}}}",
315 "\\newcommand{\\IdrisImplicit}[1]{{\\itshape \\IdrisBound{#1}}}",
319 "\\begin{Verbatim}[commandchars=\\\\\\{\\}]",
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