1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Reporting.Helpers
6 , Doc, (<+>), (<>), cat, dullyellow, fillSep, hang
7 , hsep, indent, parens, sep, text, underline, vcat
10 , functionName, args, moreArgs
11 , toHint, hintLink, stack, reflowParagraph
12 , commaSep, capitalize, ordinalize, drawCycle
13 , findPotentialTypos, findTypoPairs, vetTypos
14 , nearbyNames, distance, maybeYouWant, maybeYouWant'
18import Data.Function (on)
19import qualified Data.Char as Char
20import qualified Data.List as List
21import qualified Data.Map as Map
22import Data.Monoid ((<>))
23import qualified Data.Set as Set
24import qualified Data.Text as Text
25import Data.Text (Text)
26import qualified Text.EditDistance as Dist
27import qualified Text.PrettyPrint.ANSI.Leijen as P
28import Text.PrettyPrint.ANSI.Leijen hiding ((<>), text)
30import qualified AST.Helpers as Help
31import qualified Elm.Compiler.Version as Compiler
32import qualified Elm.Package as Pkg
39(|>) :: a -> (a -> b) -> b
53 P.text (Text.unpack msg)
61functionName :: Text -> Text
63 if Help.isOp opName then
72 i2t n <> if n == 1 then " argument" else " arguments"
75moreArgs :: Int -> Text
77 i2t n <> " more" <> if n == 1 then " argument" else " arguments"
88 underline (text "Hint") <> ":"
90 fillSep (hint : map text (Text.words txt))
93hintLink :: Text -> Text
95 "<https://github.com/elm-lang/elm-compiler/blob/"
96 <> Text.pack (Pkg.versionToString Compiler.version)
97 <> "/hints/" <> fileName <> ".md>"
104 error "function `stack` requires a non-empty list of docs"
107 List.foldl' (\a b -> a <> hardline <> hardline <> b) doc docs
110reflowParagraph :: Text -> Doc
111reflowParagraph paragraph =
112 fillSep (map text (Text.words paragraph))
115commaSep :: [Text] -> Text
122 " " <> token1 <> " and " <> token2
125 " " <> Text.intercalate ", " (init tokens) <> ", and " <> last tokens
128capitalize :: Text -> Text
130 case Text.uncons txt of
135 Text.cons (Char.toUpper c) rest
138ordinalize :: Int -> Text
148 | remainder100 `elem` [11..13] = "th"
149 | remainder10 == 1 = "st"
150 | remainder10 == 2 = "nd"
151 | remainder10 == 3 = "rd"
158drawCycle :: [Text] -> Doc
165 text "│ " <> dullyellow (text name)
173 vcat (topLine : List.intersperse midLine (map nameLine names) ++ [ bottomLine ])
180findPotentialTypos :: [Text] -> Text -> [Text]
181findPotentialTypos knownNames badName =
182 filter ((==1) . distance badName) knownNames
185findTypoPairs :: [Text] -> [Text] -> [(Text, Text)]
186findTypoPairs leftOnly rightOnly =
189 map ((,) leftName) (findPotentialTypos rightOnly leftName)
191 concatMap veryNear leftOnly
194vetTypos :: [(Text, Text)] -> Maybe (Set.Set Text, Set.Set Text)
195vetTypos potentialTypos =
197 tallyNames (ln, rn) (lc, rc) =
198 ( Map.insertWith (+) ln 1 lc
199 , Map.insertWith (+) rn 1 rc
202 (leftCounts, rightCounts) =
203 foldr tallyNames (Map.empty, Map.empty) potentialTypos
205 acceptable :: Map.Map Text Int -> Bool
207 not (Map.null counts)
209 Map.foldr (\n unique -> n < 2 && unique) True counts
211 if acceptable leftCounts && acceptable rightCounts then
212 Just (Map.keysSet leftCounts, Map.keysSet rightCounts)
222nearbyNames :: (a -> Text) -> a -> [a] -> [a]
223nearbyNames format name names =
225 if Text.length (format name) < 3 then 1 else 2
228 |> map (\x -> (distance (format name) (format x), x))
229 |> List.sortBy (compare `on` fst)
230 |> filter ( (<= editDistance) . abs . fst )
234distance :: Text -> Text -> Int
236 Dist.restrictedDamerauLevenshteinDistance
237 Dist.defaultEditCosts
242maybeYouWant :: Maybe Doc -> [Text] -> Doc
243maybeYouWant maybeStarter suggestions =
244 maybe P.empty id (maybeYouWant' maybeStarter suggestions)
247maybeYouWant' :: Maybe Doc -> [Text] -> Maybe Doc
248maybeYouWant' maybeStarter suggestions =
255 [ maybe id (<+>) maybeStarter "Maybe you want one of the following?"
256 , P.indent 4 $ P.vcat $ map (P.dullyellow . text) (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