@@ -1,13 +1,13 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2−module Reporting.Render.Code
2+module Reporting.Render.Code (render) where
7−import Control.Applicative ((<|>))
4+import Data.Text (Text)
5+import qualified Data.Text as Text
6+import Text.PrettyPrint.ANSI.Leijen
8−import Text.PrettyPrint.ANSI.Leijen (Doc, (<>), hardline, dullred, empty, text)
7+ ( Doc, (<>), hardline, dullred, empty, text )
10import qualified Reporting.Region as R
9import qualified Reporting.Region as R
10+import qualified Reporting.Helpers as H
13(|>) :: a -> (a -> b) -> b
13(|>) :: a -> (a -> b) -> b
@@ -20,59 +20,62 @@ import qualified Reporting.Region as R
20 a <> hardline <> b
20 a <> hardline <> b
23−render :: Maybe R.Region -> R.Region -> String -> Doc
23+render :: Maybe R.Region -> R.Region -> Text -> Doc
24render maybeSubRegion region@(R.Region start end) source =
24render maybeSubRegion region@(R.Region start end) source =
26− (R.Position startLine startColumn) = start
26+ (R.Position startLine _) = start
27− (R.Position endLine endColumn) = end
27+ (R.Position endLine _) = end
29 relevantLines =
29 relevantLines =
30− lines source
30+ (Text.lines source ++ [Text.empty])
31− |> drop (startLine - 1)
32+ |> drop (startLine - 1)
32− |> take (endLine - startLine + 1)
33+ |> zip [startLine .. endLine + 1]
36+ length (show (fst (last relevantLines)))
39+ maybe region id maybeSubRegion
34− case relevantLines of
41+ case makeUnderline width endLine smallerRegion of
36− empty
43+ drawLines True width smallerRegion relevantLines empty
38− [sourceLine] ->
45+ Just underline ->
39− singleLineRegion startLine sourceLine $
46+ drawLines False width smallerRegion relevantLines underline
40− case maybeSubRegion of
42− (0, startColumn, endColumn, length sourceLine)
44− Just (R.Region s e) ->
45− (startColumn, R.column s, R.column e, endColumn)
47− firstLine : rest ->
49+makeUnderline :: Int -> Int -> R.Region -> Maybe Doc
48− let
50+makeUnderline width realEndLine (R.Region (R.Position start c1) (R.Position end c2)) =
49− filteredFirstLine =
51+ if start /= end || end < realEndLine then
50− replicate (startColumn - 1) ' '
52+ Nothing
51− ++ drop (startColumn - 1) firstLine
53− filteredLastLine =
54+ else
54− take (endColumn) (last rest)
55+ let
56+ spaces = replicate (c1 + width + 1) ' '
57+ zigzag = replicate (max 1 (c2 - c1)) '^'
59+ Just (text spaces <> dullred (text zigzag))
56− focusedRelevantLines =
57− filteredFirstLine : init rest ++ [filteredLastLine]
59− lineNumbersWidth =
62+drawLines :: Bool -> Int -> R.Region -> [(Int, Text)] -> Doc -> Doc
60− length (show endLine)
63+drawLines addZigZag width (R.Region start end) sourceLines finalLine =
65+ (R.Position startLine _) = start
66+ (R.Position endLine _) = end
68+ foldr (<==>) finalLine $
69+ map (drawLine addZigZag width startLine endLine) sourceLines
63− maybeSubRegion <|> Just region
65− numberedLines =
72+drawLine :: Bool -> Int -> Int -> Int -> (Int, Text) -> Doc
66− zipWith
73+drawLine addZigZag width startLine endLine (n, line) =
67− (addLineNumber subregion lineNumbersWidth)
74+ addLineNumber addZigZag width startLine endLine n (H.text line)
68− [startLine .. endLine]
71− foldr (<==>) empty numberedLines
74−addLineNumber :: Maybe R.Region -> Int -> Int -> String -> Doc
77+addLineNumber :: Bool -> Int -> Int -> Int -> Int -> Doc -> Doc
75−addLineNumber maybeSubRegion width n line =
78+addLineNumber addZigZag width start end n line =
78 if n < 0 then " " else show n
81 if n < 0 then " " else show n
@@ -80,34 +83,10 @@ addLineNumber maybeSubRegion width n line =
80 lineNumber =
83 lineNumber =
81 replicate (width - length number) ' ' ++ number ++ "|"
84 replicate (width - length number) ' ' ++ number ++ "|"
83− spacer (R.Region start end) =
86+ spacer =
84− if R.line start <= n && n <= R.line end then
87+ if addZigZag && start <= n && n <= end then
85− dullred (text ">")
88+ dullred (text ">")
90− <> maybe (text " ") spacer maybeSubRegion
94−singleLineRegion :: Int -> String -> (Int, Int, Int, Int) -> Doc
95−singleLineRegion lineNum sourceLine (start, innerStart, innerEnd, end) =
98− length (show lineNum)
101− text (replicate (innerStart + width + 1) ' ')
103− dullred (text (replicate (max 1 (innerEnd - innerStart)) '^'))
108− |> take (end - start + 1)
109− |> (++) (replicate (start - 1) ' ')
111− addLineNumber Nothing width lineNum trimmedSourceLine
92+ text lineNumber <> spacer <> line