@@ -1,5 +1,6 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE GADTs #-}
2{-# LANGUAGE GADTs #-}
3+{-# LANGUAGE OverloadedStrings #-}
3module CommandLine.Args.Internal
4module CommandLine.Args.Internal
5 , Flags, noFlags, flags, (|--)
6 , Flags, noFlags, flags, (|--)
@@ -12,16 +13,15 @@ module CommandLine.Args.Internal
17+import Data.Monoid ((<>))
15import qualified Data.Char as Char
18import qualified Data.Char as Char
16import qualified Data.List as List
19import qualified Data.List as List
17import GHC.IO.Handle (hIsTerminalDevice)
20import GHC.IO.Handle (hIsTerminalDevice)
18import System.Environment (getArgs)
21import System.Environment (getArgs)
19import System.Exit (exitFailure)
22import System.Exit (exitFailure)
20import System.IO (hPutStrLn, stderr)
23import System.IO (hPutStrLn, stderr)
21−import Text.PrettyPrint.ANSI.Leijen
24+import qualified Text.PrettyPrint.ANSI.Leijen as P
22− ( Doc, (<>), comma, displayIO, fillSep, green
23− , plain, red, renderPretty, text, vcat
26import Elm.Utils (nearbyNames)
26import Elm.Utils (nearbyNames)
@@ -667,23 +667,21 @@ failure :: Error -> IO a
667failure err =
667failure err =
668 do let doc = toDoc err
668 do let doc = toDoc err
669 isTerminal <- hIsTerminalDevice stderr
669 isTerminal <- hIsTerminalDevice stderr
670− displayIO stderr $ renderPretty 1 80 $
670+ P.displayIO stderr $ P.renderPretty 1 80 $
671− if isTerminal then doc else plain doc
671+ if isTerminal then doc else P.plain doc
672 hPutStrLn stderr ""
672 hPutStrLn stderr ""
673 exitFailure
673 exitFailure
676−toDoc :: Error -> Doc
676+toDoc :: Error -> P.Doc
677toDoc err =
677toDoc err =
678 case err of
678 case err of
679 BadCommand badName suggestions lastSuggestion ->
679 BadCommand badName suggestions lastSuggestion ->
680− fillSep $
680+ P.fillSep $
681− [ text "There is no"
681+ ["There","is","no",toRed badName,"command.","Try"
684− , text "Did you mean"
686− ++ oxfordify (map code suggestions) "or" (code lastSuggestion <> text "?")
683+ ++ oxfordify (map toGreen suggestions) "or" (toGreen lastSuggestion)
688 NoCommand (BadArgs argError) ->
686 NoCommand (BadArgs argError) ->
689 argErrorToDoc Nothing argError
687 argErrorToDoc Nothing argError
@@ -698,31 +696,41 @@ toDoc err =
698 flagErrorToDoc (Just name) flagError
696 flagErrorToDoc (Just name) flagError
699+toRed :: String -> P.Doc
704+toGreen :: String -> P.Doc
706+ P.green (P.text str)
702-- ARG FAILURE
710-- ARG FAILURE
705−argErrorToDoc :: Maybe String -> ArgError -> Doc
713+argErrorToDoc :: Maybe String -> ArgError -> P.Doc
706argErrorToDoc maybeCommand argError =
714argErrorToDoc maybeCommand argError =
707 case argError of
715 case argError of
708 NoneOf argErrors ->
716 NoneOf argErrors ->
709− text $ "TODO - " ++ show (map (argErrorToDoc maybeCommand) argErrors)
717+ P.text $ "TODO - " ++ show (map (argErrorToDoc maybeCommand) argErrors)
711 MissingArg (ParserInfo tipe) ->
719 MissingArg (ParserInfo tipe) ->
712− text $ "TODO - " ++ tipe
720+ P.text $ "TODO - " ++ tipe
714 BadArg chunk _parserError ->
722 BadArg chunk _parserError ->
715− text $ "TODO - " ++ chunk
723+ P.text $ "TODO - " ++ chunk
717 ExtraArgs extraChunks ->
725 ExtraArgs extraChunks ->
718− text $ "TODO - " ++ show extraChunks
726+ P.text $ "TODO - " ++ show extraChunks
722-- FLAG FAILURE
730-- FLAG FAILURE
725−flagErrorToDoc :: Maybe String -> FlagError -> Doc
733+flagErrorToDoc :: Maybe String -> FlagError -> P.Doc
726flagErrorToDoc maybeCommand flagError =
734flagErrorToDoc maybeCommand flagError =
727 case flagError of
735 case flagError of
728 BadOnOff name value ->
736 BadOnOff name value ->
@@ -731,121 +739,108 @@ flagErrorToDoc maybeCommand flagError =
731 "--" ++ name ++ "=" ++ value
739 "--" ++ name ++ "=" ++ value
733 if null value then
741 if null value then
734− flagErrorToDocHelp "This on/off flag has a trailing equals sign:" chunk
743+ "This on/off flag has a trailing equals sign:"
735− [ fillSep
745+ [ P.fillSep
736− [ text "Just get rid of the equals sign, like this:"
746+ ["Just","get","rid","of","the","equals","sign,","like","this:"
737− , green (text ("--" ++ name))
747+ , toGreen ("--" ++ name)
742− flagErrorToDocHelp "This on/off flag was given a value:" chunk
753+ "This on/off flag was given a value:"
743− [ text "An on/off flag either exists or not, no need for an equals sign and value."
755+ [ "An on/off flag either exists or not, no need for an equals sign and value.\n\
744− , text "Maybe you want this instead?"
756+ \Maybe you want this instead?"
745− , text ""
757+ , P.indent 4 (toGreen ("--" ++ name))
746− , text " " <> green (text ("--" ++ name))
750 BadFlag name (ParserInfo tipe) Nothing ->
760 BadFlag name (ParserInfo tipe) Nothing ->
751 flagErrorToDocHelp
761 flagErrorToDocHelp
752 "This flag cannot appear without a value:"
762 "This flag cannot appear without a value:"
753 ("--" ++ name)
763 ("--" ++ name)
754− [ text $ "It needs a " ++ tipe ++ " value."
764+ [ P.fillSep ["It","needs","a",toGreen tipe,"value."]
757 BadFlag name (ParserInfo tipe) (Just (value, parserError)) ->
767 BadFlag name (ParserInfo tipe) (Just (value, parserError)) ->
758 flagErrorToDocHelp
768 flagErrorToDocHelp
759 "This flag was given a bad value:"
769 "This flag was given a bad value:"
760 ("--" ++ name ++ "=" ++ value)
770 ("--" ++ name ++ "=" ++ value)
761− [ fillSep $ map text $ words $
771+ [ P.fillSep $
762− "I need a " ++ tipe ++ " value, but "
772+ ["I","need","a",toGreen tipe,"value,","but"
764 case parserError of
775 case parserError of
765 Expecting expectedType ->
776 Expecting expectedType ->
766− value ++ " is not a valid " ++ expectedType ++ "."
777+ [P.text value,"is","not","a","valid",P.text expectedType <> "."]
769 Unrecognized chunk [] ->
780 Unrecognized chunk [] ->
772− case maybeCommand of
774− "I am not expecting any flags."
777− "The `" ++ command ++ "` command does not expect any flags."
779− flagErrorToDocHelp "Get rid of this flag:" chunk $
781+ flagErrorToDocHelp
782+ "Get rid of this flag:"
780− [ fillSep (map text (words explanation))
784+ [ P.fillSep $ map P.text $ words $
785+ case maybeCommand of
787+ "I am not expecting any flags."
790+ "The `" ++ command ++ "` command does not expect any flags."
783 Unrecognized chunk info ->
793 Unrecognized chunk info ->
784 case takeWhile ('=' /=) (dropWhile ('-' ==) chunk) of
794 case takeWhile ('=' /=) (dropWhile ('-' ==) chunk) of
786− flagErrorToDocHelp "This is not a valid flag:" chunk
797+ "This is not a valid flag:"
787− [ text "Valid flags look like --output=FILE"
799+ [ P.fillSep ["Valid","flags","look","like",P.green "--output=FILE"]
793− nearbyNames id name (map fst info)
804+ closeNames = nearbyNames id name (map fst info)
805+ suggestions = if null closeNames then map fst info else closeNames
806+ toFlag str = toGreen ("--" ++ str)
795− flagErrorToDocHelp "I do not recognize this flag:" chunk $
809+ "I do not recognize this flag:"
796− unrecognizedExplanation $
810+ chunk
797− if null suggestions then map fst info else suggestions
811+ (
817+ [ P.fillSep ["Looks","like","a","typo.","Maybe","you","want",toFlag suggestion,"instead?"]
821+ [ P.fillSep ["Maybe","you","want","one","of","these","instead?"]
822+ , P.indent 4 (P.vcat (map toFlag suggestions))
800−flagErrorToDocHelp :: String -> String -> [Doc] -> Doc
827+flagErrorToDocHelp :: String -> String -> [P.Doc] -> P.Doc
801flagErrorToDocHelp summary original explanation =
828flagErrorToDocHelp summary original explanation =
802− vcat $
829+ P.vcat $ concatMap (\d -> [d,""]) $
803− [ text summary
830+ [ P.fillSep (map P.text (words summary))
805− , text " " <> red (text original)
831+ , P.indent 4 (toRed original)
808 ++ explanation
833 ++ explanation
811−unrecognizedExplanation :: [String] -> [Doc]
812−unrecognizedExplanation suggestions =
815− text " " <> green (text ("--" ++ name))
822− [ text "Looks like a typo. Maybe you want:"
824− , toBullet suggestion
829− [ text "Maybe you want one of these?"
832− ++ map toBullet suggestions
836−code :: String -> Doc
841−oxfordify :: [Doc] -> String -> Doc -> [Doc]
836+oxfordify :: [P.Doc] -> String -> P.Doc -> [P.Doc]
842oxfordify chunks conjuction lastChunk =
837oxfordify chunks conjuction lastChunk =
843 case chunks of
838 case chunks of
845 [ lastChunk ]
840 [ lastChunk ]
847 [chunk] ->
842 [chunk] ->
848− [ chunk, text conjuction, lastChunk ]
843+ [ chunk, P.text conjuction, lastChunk ]
851− map (<> comma) chunks ++ [ text conjuction, lastChunk ]
846+ map (<> P.comma) chunks ++ [ P.text conjuction, lastChunk ]