1 {-# LANGUAGE DeriveFunctor #-}
2 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
3 {-# LANGUAGE OverloadedStrings #-}
4 {-# LANGUAGE ScopedTypeVariables #-}
5 module Language.Symantic.CLI.Read where
7 import Control.Applicative (Applicative(..), Alternative(..))
8 import Control.Arrow ((***))
9 import Control.Monad (Monad(..), MonadPlus(..))
11 import Data.Either (Either(..))
12 import Data.Eq (Eq(..))
13 import Data.Foldable (Foldable(..))
14 import Data.Function (($), (.))
15 import Data.Functor (Functor(..), (<$>))
16 import Data.Maybe (Maybe(..))
17 import Data.Monoid (Monoid(..))
18 import Data.Ord (Ord(..), Ordering(..))
19 import Data.Semigroup (Semigroup(..))
20 import Data.String (String)
21 import Text.Show (Show(..))
22 import qualified Data.List as List
23 import qualified Data.Set as Set
24 import qualified Text.Megaparsec as P
25 import qualified Text.Megaparsec.Perm as P
27 import Language.Symantic.CLI.Sym as Sym
30 newtype Arg = Arg { unArg :: String }
31 deriving (Eq, Ord, Show)
34 newtype Args = Args { unArgs :: [Arg] }
35 deriving (Eq, Ord, Show, Semigroup, Monoid)
36 instance P.Stream Args where
38 type Tokens Args = Args
39 tokenToChunk _s = Args . pure
40 tokensToChunk _s = Args
41 chunkToTokens _s = unArgs
42 chunkLength _s = List.length . unArgs
43 chunkEmpty _s = List.null . unArgs
44 advance1 _s _ind (P.SourcePos n l c) _ = P.SourcePos n l (c <> P.pos1)
45 advanceN s ind pos = foldl' (P.advance1 s ind) pos . unArgs
49 t:ts -> Just (t, Args ts)
50 takeN_ n as | n <= 0 = Just (Args [], as)
51 | null (unArgs as) = Nothing
52 | otherwise = Just $ (Args *** Args) $ List.splitAt n $ unArgs as
53 takeWhile_ f = (Args *** Args) . List.span f . unArgs
54 instance P.ShowToken Arg where
56 List.intercalate ", " $ toList $ showArg <$> toks
58 showArg :: Arg -> String
59 showArg (Arg a@('-':_)) = a
60 showArg (Arg a) = "\""<>a<>"\""
64 = Parser { unParser :: P.Parsec (ErrorRead e) Args a }
65 deriving (Functor, Applicative, Alternative, Monad, MonadPlus, P.MonadParsec (ErrorRead e) Args)
67 coerceParser :: Parser e s a -> Parser e t a
68 coerceParser = Parser . unParser
70 instance Sym_Fun Parser where
71 f <$$> Parser a = Parser $ f <$> a
72 instance Sym_App Parser where
75 Parser f <**> Parser a = Parser $ f <*> a
76 instance Sym_Alt Parser where
82 instance Sym_AltApp Parser where
85 type instance Perm (Parser e s) = P.PermParser Args (Parser e s)
86 instance Sym_Interleaved Parser where
87 interleaved = P.makePermParser
92 f <<$*>> a = f P.<$?> ([],P.some a)
93 f <<|*>> a = f P.<|?> ([],P.some a)
94 instance Sym_Command Parser where
96 command n p = P.token check (Just expected) *> coerceParser p
99 check a | a == expected = Right ()
101 ( Just $ P.Tokens $ pure t
102 , Set.singleton $ P.Tokens $ pure expected )
103 instance Sym_Option Parser where
106 let expected | List.null n = Arg "<string>"
107 | otherwise = Arg $ "<"<>n<>">"
108 Arg arg <- P.token check (Just expected)
111 Left err -> P.customFailure $ ErrorRead err
114 let check t | t == expected = Right ()
115 | otherwise = Left ( Just $ P.Tokens $ pure t
116 , Set.singleton $ P.Tokens $ pure expected )
117 P.token check (Just expected)
119 (*> coerceParser p) $
122 P.token (checkLong l) (Just $ expectedLong l)
124 P.token (checkShort s) (Just $ expectedShort s)
126 P.token (checkShort s) (Just $ expectedShort s) <|>
127 P.token (checkLong l) (Just $ expectedLong l)
129 expectedShort s = Arg ['-', s]
130 checkShort s a | a == expectedShort s = Right ()
131 checkShort s t = Left
132 ( Just $ P.Tokens $ pure t
133 , Set.singleton $ P.Tokens $ pure $ expectedShort s)
134 expectedLong l = Arg $ "--"<>l
135 checkLong l a | a == expectedLong l = Right ()
137 ( Just $ P.Tokens $ pure t
138 , Set.singleton $ P.Tokens $ pure $ expectedLong l)
139 instance Sym_Help d Parser where
141 instance Sym_Rule Parser where
142 rule _n = coerceParser
143 instance Sym_Exit Parser where
146 P.fancyFailure $ Set.singleton $
147 P.ErrorCustom $ ErrorRead e
149 -- * Type 'ErrorRead'
153 instance Show e => Show (ErrorRead e) where
154 showsPrec p (ErrorRead e) = showsPrec p e
155 instance Eq (ErrorRead a) where
157 instance Ord (ErrorRead a) where
159 instance Show e => P.ShowErrorComponent (ErrorRead e) where
160 showErrorComponent = show
162 readArgs :: Parser e s a -> Args -> Either (P.ParseError (P.Token Args) (ErrorRead e)) a
163 readArgs p = P.runParser (unParser $ p <* end) ""