descriptive 0.0.0 → 0.0.1
raw patch · 7 files changed
+141/−88 lines, 7 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Descriptive: runConsumer :: Consumer s d a -> s -> (Either (Description d) a, s)
+ Descriptive: runDescription :: Consumer s d a -> s -> (Description d, s)
- Descriptive: consume :: Consumer s d a -> s -> (Either (Description d) a, s)
+ Descriptive: consume :: Consumer s d a -> s -> Either (Description d) a
- Descriptive: describe :: Consumer s d a -> s -> (Description d, s)
+ Descriptive: describe :: Consumer s d a -> s -> Description d
Files
- descriptive.cabal +1/−1
- src/Descriptive.hs +53/−27
- src/Descriptive/Char.hs +0/−14
- src/Descriptive/Form.hs +12/−5
- src/Descriptive/Formlet.hs +9/−1
- src/Descriptive/JSON.hs +20/−5
- src/Descriptive/Options.hs +46/−35
descriptive.cabal view
@@ -1,5 +1,5 @@ name: descriptive-version: 0.0.0+version: 0.0.1 synopsis: Self-describing consumers/parsers; forms, cmd-line args, JSON, etc. description: Self-describing consumers/parsers. See the README.md for more information. It is currently EXPERIMENTAL. stability: Experimental
src/Descriptive.hs view
@@ -8,14 +8,20 @@ -- | Descriptive parsers. module Descriptive- (Description(..)+ (-- * Consuming and describing+ consume+ ,describe+ -- * Lower-level runners+ ,runConsumer+ ,runDescription+ -- * Types+ ,Description(..) ,Bound(..) ,Consumer(..)+ -- * Combinators ,consumer ,wrap- ,sequencing- ,consume- ,describe)+ ,sequencing) where import Control.Applicative@@ -24,6 +30,35 @@ import Data.Monoid --------------------------------------------------------------------------------+-- Running++-- | Run a consumer.+consume :: Consumer s d a -- ^ The consumer to run.+ -> s -- ^ Initial state.+ -> Either (Description d) a+consume (Consumer _ m) = fst . m++-- | Describe a consumer.+describe :: Consumer s d a -- ^ The consumer to run.+ -> s -- ^ Initial state. Can be empty if you don't use it for+ -- generating descriptions.+ -> Description d -- ^ A description and resultant state.+describe (Consumer desc _) = fst . desc++-- | Run a consumer.+runConsumer :: Consumer s d a -- ^ The consumer to run.+ -> s -- ^ Initial state.+ -> (Either (Description d) a,s)+runConsumer (Consumer _ m) = m++-- | Describe a consumer.+runDescription :: Consumer s d a -- ^ The consumer to run.+ -> s -- ^ Initial state. Can be empty if you don't use it for+ -- generating descriptions.+ -> (Description d,s) -- ^ A description and resultant state.+runDescription (Consumer desc _) = desc++-------------------------------------------------------------------------------- -- Types -- | Description of a consumable thing.@@ -92,12 +127,12 @@ in (Or d1 d2,s'')) (\s -> case consumerParse a s of- (Left e1,s') ->- case consumerParse b s' of- (Left e2,s'') ->- (Left (Or e1 e2),s'')- (Right a2,s'') ->- (Right a2,s'')+ (Left e1,_) ->+ case consumerParse b s of+ (Left e2,s') ->+ (Left (Or e1 e2),s')+ (Right a2,s') ->+ (Right a2,s') (Right a1,s') -> (Right a1,s')) some = sequenceHelper 1 many = sequenceHelper 0@@ -143,20 +178,22 @@ -- Combinators -- | Make a consumer.-consumer :: (s -> (Description d,s)) -> (s -> (Either (Description d) a,s)) -> Consumer s d a+consumer :: (s -> (Description d,s)) -- ^ Produce description based on the state.+ -> (s -> (Either (Description d) a,s)) -- ^ Parse the state and maybe transform it if desired.+ -> Consumer s d a consumer d p = Consumer d p -- | Wrap a consumer with another consumer.-wrap :: (s -> (t -> (Description d,t)) -> (Description d,s))- -> (s -> (t -> (Description d,t)) -> (t -> (Either (Description d) a,t)) -> (Either (Description d) b,s))- -> Consumer t d a- -> Consumer s d b+wrap :: (s -> (t -> (Description d,t)) -> (Description d,s)) -- ^ Transformer the description.+ -> (s -> (t -> (Description d,t)) -> (t -> (Either (Description d) a,t)) -> (Either (Description d) b,s)) -- ^ Transform the parser. Can re-run the parser if desired.+ -> Consumer t d a -- ^ The consumer to transform.+ -> Consumer s d b -- ^ A new consumer with a potentially new state type. wrap redescribe reparse (Consumer d p) = Consumer (\s -> redescribe s d) (\s -> reparse s d p) --- | Compose contiguous items into one sequence.+-- | Compose contiguous items into one sequence. Similar to 'sequenceA'. sequencing :: [Consumer d s a] -> Consumer d s [a] sequencing = wrap (\s d ->@@ -169,14 +206,3 @@ se x = [x] go (x:xs) = (:) <$> x <*> sequencing xs go [] = mempty------------------------------------------------------------------------------------- Running---- | Run a consumer.-consume :: Consumer s d a -> s -> (Either (Description d) a,s)-consume (Consumer _ m) = m---- | Describe a consumer.-describe :: Consumer s d a -> s -> (Description d,s)-describe (Consumer desc _) = desc
src/Descriptive/Char.hs view
@@ -3,20 +3,6 @@ {-# LANGUAGE FlexibleContexts #-} -- | Consuming form a list of characters.------ Examples:------ λ> describe (zeroOrMore (char 'k') <> string "abc") []--- (And (Bounded 0 UnlimitedBound (Unit "k")) (And (Unit "a") (And (Unit "b") (And (Unit "c") None))),"")------ λ> consumer (zeroOrMore (char 'k') <> string "abc") "kkkabc"--- (Right "kkkabc","")------ λ> consumer (zeroOrMore (char 'k') <> string "abc") "kkkabq"--- (Left (Unit "c"),"")------ λ> consumer (zeroOrMore (char 'k') <> string "abc") "kkkab"--- (Left (Unit "a character"),"") module Descriptive.Char where
src/Descriptive/Form.hs view
@@ -3,7 +3,14 @@ -- | Validating form with named inputs. -module Descriptive.Form where+module Descriptive.Form+ (-- * Combinators+ input+ ,validate+ -- * Description+ ,Form (..)+ )+ where import Descriptive @@ -18,7 +25,7 @@ | Constraint !Text deriving (Show) --- | Consume any character.+-- | Consume any input value. input :: Text -> Consumer (Map Text Text) Form Text input name = consumer (d,)@@ -30,9 +37,9 @@ where d = Unit (Input name) -- | Validate a form input with a description of what's required.-validate :: Text- -> (a -> Maybe b)- -> Consumer (Map Text Text) Form a+validate :: Text -- ^ Description of what it expects.+ -> (a -> Maybe b) -- ^ Attempt to parse the value.+ -> Consumer (Map Text Text) Form a -- ^ Consumer to add validation to. -> Consumer (Map Text Text) Form b validate d' check = wrap (\s d -> redescribe (d s))
src/Descriptive/Formlet.hs view
@@ -3,7 +3,13 @@ -- | Validating indexed formlet with auto-generated input names. -module Descriptive.Formlet where+module Descriptive.Formlet+ (-- * Combinators+ indexed+ ,FormletState(..)+ -- * Description+ ,Formlet(..))+ where import Descriptive @@ -11,11 +17,13 @@ import qualified Data.Map.Strict as M import Data.Text (Text) +-- | Description of a formlet. data Formlet = Index !Integer | Constrained !Text deriving (Show) +-- | State used when running a formlet. data FormletState = FormletState {formletMap :: (Map Integer Text) ,formletIndex :: !Integer}
src/Descriptive/JSON.hs view
@@ -7,7 +7,16 @@ -- | A JSON API which describes itself. -module Descriptive.JSON where+module Descriptive.JSON+ (-- * Combinators+ obj+ ,key+ ,string+ ,integer+ -- * Description+ ,Doc(..)+ )+ where import Data.Bifunctor import Data.Monoid@@ -26,7 +35,9 @@ deriving (Show) -- | Consume an object.-obj :: Text -> Consumer Object Doc a -> Consumer Value Doc a+obj :: Text -- ^ Description of what the object is.+ -> Consumer Object Doc a -- ^ An object consumer.+ -> Consumer Value Doc a obj desc = wrap (\v d -> (Wrap doc (fst (d mempty)),v)) (\v _ p ->@@ -40,7 +51,9 @@ where doc = Struct desc -- | Consume from object at the given key.-key :: Text -> Consumer Value Doc a -> Consumer Object Doc a+key :: Text -- ^ The key to lookup.+ -> Consumer Value Doc a -- ^ A value consumer of the object at the key.+ -> Consumer Object Doc a key k = wrap (\o d -> first (Wrap doc)@@ -57,7 +70,8 @@ where doc = Key k -- | Consume a string.-string :: Text -> Consumer Value Doc Text+string :: Text -- ^ Description of what the string is for.+ -> Consumer Value Doc Text string doc = consumer (d,) (\s ->@@ -67,7 +81,8 @@ where d = Unit (Text doc) -- | Consume an integer.-integer :: Text -> Consumer Value Doc Integer+integer :: Text -- ^ Description of what the integer is for.+ -> Consumer Value Doc Integer integer doc = consumer (d,) (\s ->
src/Descriptive/Options.hs view
@@ -5,7 +5,18 @@ -- | Command-line options parser. -module Descriptive.Options where+module Descriptive.Options+ (-- * Combinators+ anyString+ ,constant+ ,flag+ ,prefix+ ,arg+ -- * Description+ ,Option(..)+ ,textDescription+ ,textOpt)+ where import Descriptive @@ -24,40 +35,6 @@ | Prefix !Text !Text deriving (Show) --- | Make a text description of the command line options.-textDescription :: Description Option -> Text-textDescription = go . clean- where clean (And None a) = clean a- clean (And a None) = clean a- clean (Or a None) = clean a- clean (Or None a) = clean a- clean (And a b) = And (clean a) (clean b)- clean (Or a b) = Or (clean a) (clean b)- clean a = a- go d =- case d of- Unit o -> textOpt o- Bounded min' _ d' ->- "[" <> go d' <> "]" <>- if min' == 0- then "*"- else "+"- And a b -> go a <> " " <> go b- Or a b -> "(" <> go a <> "|" <> go b <> ")"- Sequence xs ->- T.intercalate " "- (map go xs)- Wrap o d' -> textOpt o <> " " <> go d'- None -> ""---- | Make a text description of an option.-textOpt :: Option -> Text-textOpt (AnyString t) = T.map toUpper t-textOpt (Constant t) = t-textOpt (Flag t _) = "-f" <> t-textOpt (Arg t _) = "-" <> t <> " <...>"-textOpt (Prefix t _) = "-" <> t <> "<...>"- -- | Consume one argument from the argument list. anyString :: Text -> Consumer [Text] Option Text anyString help =@@ -113,3 +90,37 @@ (Right text ,map snd (filter (\(j,_) -> j /= i && j /= i + 1) indexedArgs))) where d = Unit (Arg name help)++-- | Make a text description of the command line options.+textDescription :: Description Option -> Text+textDescription = go . clean+ where clean (And None a) = clean a+ clean (And a None) = clean a+ clean (Or a None) = clean a+ clean (Or None a) = clean a+ clean (And a b) = And (clean a) (clean b)+ clean (Or a b) = Or (clean a) (clean b)+ clean a = a+ go d =+ case d of+ Unit o -> textOpt o+ Bounded min' _ d' ->+ "[" <> go d' <> "]" <>+ if min' == 0+ then "*"+ else "+"+ And a b -> go a <> " " <> go b+ Or a b -> "(" <> go a <> "|" <> go b <> ")"+ Sequence xs ->+ T.intercalate " "+ (map go xs)+ Wrap o d' -> textOpt o <> " " <> go d'+ None -> ""++-- | Make a text description of an option.+textOpt :: Option -> Text+textOpt (AnyString t) = T.map toUpper t+textOpt (Constant t) = t+textOpt (Flag t _) = "-f" <> t+textOpt (Arg t _) = "-" <> t <> " <...>"+textOpt (Prefix t _) = "-" <> t <> "<...>"