1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Helpers
7 , toSimpleNote, toSimpleHint, toFancyHint
8 , link, fancyLink, reflowLink, makeLink
10 , commaSep, capitalize, ordinalize, drawCycle
11 , findPotentialTypos, findTypoPairs, vetTypos
12 , nearbyNames, distance
14 , Doc, (<+>), (<>), black, blue, cat, dullyellow, fillSep, green, hang, hardline
15 , hcat, hsep, indent, magenta, parens, sep, text, underline, vcat
20import Data.Function (on)
21import qualified Data.Char as Char
22import qualified Data.List as List
23import qualified Data.Map as Map
24import qualified Data.Maybe as Maybe
25import qualified Data.Set as Set
26import Data.Monoid ((<>))
27import qualified Data.Text as Text
28import Data.Text (Text)
29import qualified Elm.Name as N
30import qualified Text.EditDistance as Dist
31import qualified Text.PrettyPrint.ANSI.Leijen as P
32import Text.PrettyPrint.ANSI.Leijen hiding ((<>))
34import qualified Elm.Compiler.Version as Compiler
35import qualified Elm.Package as Pkg
42textToDoc :: Text -> Doc
44 text (Text.unpack msg)
47nameToDoc :: N.Name -> Doc
49 text (N.toString name)
54 show n <> if n == 1 then " argument" else " arguments"
57moreArgs :: Int -> String
59 show n <> " more" <> if n == 1 then " argument" else " arguments"
66toSimpleNote :: String -> Doc
68 fillSep ((underline (text "Note") <> ":") : map text (words message))
71toSimpleHint :: String -> Doc
73 toFancyHint (map text (words message))
76toFancyHint :: [Doc] -> Doc
78 fillSep (underline (text "Hint") <> ":" : chunks)
81link :: Doc -> String -> String -> String -> Doc
82link word before fileName after =
84 (underline word <> ":")
85 : map text (words before)
86 ++ P.text (makeLink fileName)
87 : map text (words after)
90fancyLink :: Doc -> [Doc] -> String -> [Doc] -> Doc
91fancyLink word before fileName after =
93 (underline word <> ":") : before ++ P.text (makeLink fileName) : after
96makeLink :: String -> String
98 "<https://elm-lang.org/hints/" <> Pkg.versionToString Compiler.version <> "/" <> fileName <> ">"
101reflowLink :: String -> String -> String -> Doc
102reflowLink before fileName after =
104 map text (words before)
105 ++ P.text (makeLink fileName)
106 : map text (words after)
113 error "function `stack` requires a non-empty list of docs"
116 List.foldl' (\a b -> a <> hardline <> hardline <> b) doc docs
119reflow :: String -> Doc
121 fillSep (map text (words paragraph))
124commaSep :: Doc -> (Doc -> Doc) -> [Doc] -> [Doc]
125commaSep conjunction addStyle names =
131 [ addStyle name1, conjunction, addStyle name2 ]
134 map (\name -> addStyle name <> ",") (init names)
137 , addStyle (last names)
141capitalize :: Text -> Text
143 case Text.uncons txt of
148 Text.cons (Char.toUpper c) rest
151ordinalize :: Int -> String
161 | remainder100 `elem` [11..13] = "th"
162 | remainder10 == 1 = "st"
163 | remainder10 == 2 = "nd"
164 | remainder10 == 3 = "rd"
167 show number <> ending
171drawCycle :: [N.Name] -> Doc
175 nameLine name = "│ " <> dullyellow (nameToDoc name)
177 bottomLine = "└─────┘"
179 vcat (topLine : List.intersperse midLine (map nameLine names) ++ [ bottomLine ])
186findPotentialTypos :: [String] -> String -> [String]
187findPotentialTypos knownNames badName =
188 filter (\name -> distance badName name == 1) knownNames
191findTypoPairs :: [String] -> [String] -> [(String, String)]
192findTypoPairs leftOnly rightOnly =
195 map ((,) leftName) (findPotentialTypos rightOnly leftName)
197 concatMap veryNear leftOnly
200vetTypos :: [(String, String)] -> Maybe (Set.Set String, Set.Set String)
201vetTypos potentialTypos =
203 tallyNames (ln, rn) (lc, rc) =
204 ( Map.insertWith (+) ln 1 lc
205 , Map.insertWith (+) rn 1 rc
208 (leftCounts, rightCounts) =
209 foldr tallyNames (Map.empty, Map.empty) potentialTypos
211 acceptable :: Map.Map String Int -> Bool
213 not (Map.null counts)
215 Map.foldr (\n unique -> n < 2 && unique) True counts
217 if acceptable leftCounts && acceptable rightCounts then
218 Just (Map.keysSet leftCounts, Map.keysSet rightCounts)
228nearbyNames :: (a -> String) -> a -> [a] -> [a]
229nearbyNames toString value possibleValues =
235 if length name < 3 then 1 else 2
239 dist = abs (distance name (toString pValue))
241 if dist <= editDistance then Just (dist, pValue) else Nothing
244 List.sortBy (compare `on` fst) $
245 Maybe.mapMaybe getDistance possibleValues
248distance :: String -> String -> Int
250 Dist.restrictedDamerauLevenshteinDistance Dist.defaultEditCosts x y
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