on ea5c662 help sign in
92 lines 2.4 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2module Reporting.Render.Code (render) where
4import Data.Text (Text)
5import qualified Data.Text as Text
6import Text.PrettyPrint.ANSI.Leijen
7 ( Doc, (<>), hardline, dullred, empty, text )
9import qualified Reporting.Region as R
10import qualified Reporting.Helpers as H
13(|>) :: a -> (a -> b) -> b
14(|>) a f =
15 f a
18(<==>) :: Doc -> Doc -> Doc
19(<==>) a b =
20 a <> hardline <> b
23render :: Maybe R.Region -> R.Region -> Text -> Doc
24render maybeSubRegion region@(R.Region start end) source =
25 let
26 (R.Position startLine _) = start
27 (R.Position endLine _) = end
29 relevantLines =
30 (Text.lines source ++ [Text.empty])
31 |> take endLine
32 |> drop (startLine - 1)
33 |> zip [startLine .. endLine + 1]
35 width =
36 length (show (fst (last relevantLines)))
38 smallerRegion =
39 maybe region id maybeSubRegion
40 in
41 case makeUnderline width endLine smallerRegion of
42 Nothing ->
43 drawLines True width smallerRegion relevantLines empty
45 Just underline ->
46 drawLines False width smallerRegion relevantLines underline
49makeUnderline :: Int -> Int -> R.Region -> Maybe Doc
50makeUnderline width realEndLine (R.Region (R.Position start c1) (R.Position end c2)) =
51 if start /= end || end < realEndLine then
52 Nothing
54 else
55 let
56 spaces = replicate (c1 + width + 1) ' '
57 zigzag = replicate (max 1 (c2 - c1)) '^'
58 in
59 Just (text spaces <> dullred (text zigzag))
62drawLines :: Bool -> Int -> R.Region -> [(Int, Text)] -> Doc -> Doc
63drawLines addZigZag width (R.Region start end) sourceLines finalLine =
64 let
65 (R.Position startLine _) = start
66 (R.Position endLine _) = end
67 in
68 foldr (<==>) finalLine $
69 map (drawLine addZigZag width startLine endLine) sourceLines
72drawLine :: Bool -> Int -> Int -> Int -> (Int, Text) -> Doc
73drawLine addZigZag width startLine endLine (n, line) =
74 addLineNumber addZigZag width startLine endLine n (H.text line)
77addLineNumber :: Bool -> Int -> Int -> Int -> Int -> Doc -> Doc
78addLineNumber addZigZag width start end n line =
79 let
80 number =
81 if n < 0 then " " else show n
83 lineNumber =
84 replicate (width - length number) ' ' ++ number ++ "|"
86 spacer =
87 if addZigZag && start <= n && n <= end then
88 dullred (text ">")
89 else
90 text " "
91 in
92 text lineNumber <> spacer <> line