1{-# OPTIONS_GHC -Wall #-}
2module Reporting.Error.Helpers
4 , functionName, hintLink, stack, reflowParagraph
5 , commaSep, capitalize, ordinalize, drawCycle
6 , findPotentialTypos, vetTypos
7 , nearbyNames, distance, maybeYouWant
11import Data.Function (on)
12import qualified Data.Char as Char
13import qualified Data.List as List
14import qualified Data.Map as Map
15import qualified Data.Set as Set
16import qualified Text.EditDistance as Dist
17import Text.PrettyPrint.ANSI.Leijen
18 ( Doc, (<>), dullyellow, fillSep, hardline, text, vcat )
20import qualified AST.Helpers as Help
21import qualified Elm.Compiler.Version as Compiler
22import qualified Elm.Package as Pkg
29(|>) :: a -> (a -> b) -> b
41functionName :: String -> String
43 if Help.isOp opName then
50hintLink :: String -> String
52 "<https://github.com/elm-lang/elm-compiler/blob/"
53 ++ Pkg.versionToString Compiler.version
54 ++ "/hints/" ++ fileName ++ ".md>"
61 error "function `stack` requires a non-empty list of docs"
64 List.foldl' (\a b -> a <> hardline <> hardline <> b) doc docs
67reflowParagraph :: String -> Doc
68reflowParagraph paragraph =
69 fillSep (map text (words paragraph))
72commaSep :: [String] -> String
79 " " ++ token1 ++ " and " ++ token2
82 " " ++ List.intercalate ", " (init tokens) ++ ", and " ++ last tokens
85capitalize :: String -> String
93ordinalize :: Int -> String
103 | remainder100 `elem` [11..13] = "th"
104 | remainder10 == 1 = "st"
105 | remainder10 == 2 = "nd"
106 | remainder10 == 3 = "rd"
109 show number ++ ending
113drawCycle :: [String] -> Doc
120 text "│ " <> dullyellow (text str)
128 vcat (topLine : List.intersperse midLine (map line strings) ++ [ bottomLine ])
135findPotentialTypos :: [String] -> [String] -> [(String, String)]
136findPotentialTypos leftOnly rightOnly =
139 map ((,) leftName) (filter ((==1) . distance leftName) rightOnly)
141 concatMap veryNear leftOnly
144vetTypos :: [(String, String)] -> Maybe (Set.Set String, Set.Set String)
145vetTypos potentialTypos =
147 tallyNames (ln, rn) (lc, rc) =
148 ( Map.insertWith (+) ln 1 lc
149 , Map.insertWith (+) rn 1 rc
152 (leftCounts, rightCounts) =
153 foldr tallyNames (Map.empty, Map.empty) potentialTypos
155 acceptable :: Map.Map String Int -> Bool
157 not (Map.null counts)
159 Map.foldr (\n unique -> n < 2 && unique) True counts
161 if acceptable leftCounts && acceptable rightCounts then
162 Just (Map.keysSet leftCounts, Map.keysSet rightCounts)
172nearbyNames :: (a -> String) -> a -> [a] -> [a]
173nearbyNames format name names =
175 if length (format name) < 3 then 1 else 2
178 |> map (\x -> (distance (format name) (format x), x))
179 |> List.sortBy (compare `on` fst)
180 |> filter ( (<= editDistance) . abs . fst )
184distance :: String -> String -> Int
186 Dist.restrictedDamerauLevenshteinDistance Dist.defaultEditCosts x y
189maybeYouWant :: [String] -> String
190maybeYouWant suggestions =
196 "Maybe you want one of the following?\n"
197 ++ concatMap ("\n "++) (take 4 suggestions)
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