import Data.Eq (Eq)
import Data.Function (($), (.), id)
import Data.Kind (Constraint)
-import Data.Maybe (Maybe(..))
-import Data.String (String)
+import Data.Maybe (Maybe(..), fromJust)
+import Data.String (String, IsString(..))
import Text.Show (Show)
-- * Class 'App'
| TagLong Name
| TagShort Char
deriving (Eq, Show)
+instance IsString Tag where
+ fromString = \case
+ [c] -> TagShort c
+ c:'|':cs -> Tag c cs
+ cs -> TagLong cs
-- * Class 'CLI_Tag'
class (App repr, Permutable repr, CLI_Var repr) => CLI_Tag repr where
type TagConstraint repr a :: Constraint
- tagged :: Tag -> repr f k -> repr f k
+ tag :: Tag -> repr f k -> repr f k
+ -- tag n = (tag n <.>)
endOpts :: repr k k
- -- tagged n = (tag n <.>)
- short :: TagConstraint repr a => Char -> repr (a->k) k -> Permutation repr k a
- short n = toPermutation . tagged (TagShort n)
- long :: TagConstraint repr a => Name -> repr (a->k) k -> Permutation repr k a
- long n = toPermutation . tagged (TagLong n)
-
- option :: TagConstraint repr a => a -> repr (a->k) k -> Permutation repr k a
- option = toPermDefault
flag :: TagConstraint repr Bool => Tag -> Permutation repr k Bool
- flag n = toPermDefault False $ tagged n $ just True
- shortOpt :: TagConstraint repr a => Char -> a -> repr (a->k) k -> Permutation repr k a
- shortOpt n a = toPermDefault a . tagged (TagShort n)
- longOpt :: TagConstraint repr a => Name -> a -> repr (a->k) k -> Permutation repr k a
- longOpt n a = toPermDefault a . tagged (TagLong n)
+ flag n = toPermDefault False $ tag n $ just True
+
+ optionalTag ::
+ TagConstraint repr a => AltApp repr => Alt repr => Pro repr =>
+ Tag -> repr (a->k) k -> Permutation repr k (Maybe a)
+ optionalTag n = toPermDefault Nothing . tag n . dimap Just fromJust
+
+ defaultTag ::
+ TagConstraint repr a =>
+ Tag -> a -> repr (a->k) k -> Permutation repr k a
+ defaultTag n a = toPermDefault a . tag n
+
+ requiredTag ::
+ TagConstraint repr a =>
+ Tag -> repr (a->k) k -> Permutation repr k a
+ requiredTag n = toPermutation . tag n
+
+ many0Tag ::
+ TagConstraint repr a => AltApp repr =>
+ Tag -> repr (a->k) k -> Permutation repr k [a]
+ many0Tag n = toPermDefault [] . many1 . tag n
+ many1Tag ::
+ TagConstraint repr a => AltApp repr =>
+ Tag -> repr (a->k) k -> Permutation repr k [a]
+ many1Tag n = toPermutation . many1 . tag n
-- Trans defaults
type TagConstraint repr a = TagConstraint (UnTrans repr) a
- default tagged ::
+ default tag ::
Trans repr =>
CLI_Tag (UnTrans repr) =>
Tag -> repr f k -> repr f k
Trans repr =>
CLI_Tag (UnTrans repr) =>
repr k k
- tagged n = noTrans . tagged n . unTrans
+ tag n = noTrans . tag n . unTrans
endOpts = noTrans endOpts
-- * Class 'CLI_Response'
Doc.from (Doc.Word n)
instance SchemaDoc d => CLI_Tag (Help d) where
type TagConstraint (Help d) a = ()
- tagged n (Help h s) =
+ tag n (Help h s) =
Help (\inh ->
if (isJust (helpInh_message inh)
|| helpInh_helpless_options inh)
[ Tree.Node (HelpNode_Tag, d) ts ]
else []
) schema
- where schema = tagged n s
+ where schema = tag n s
endOpts = Help mempty endOpts
instance SchemaDoc d => CLI_Help (Help d) where
type HelpConstraint (Help d) d' = d ~ d'
(`execState`id) $
l defLayoutInh
+coerceLayout :: Layout d f k -> Layout d f' k'
+coerceLayout (Layout s h l) = Layout (coerceSchema s) h l
+
+instance Semigroup d => Semigroup (Layout d f k) where
+ Layout xs xh xm <> Layout ys yh ym =
+ Layout (xs<>ys) (xh<>yh) $ \inh ->
+ xm inh >> ym inh
+
-- ** Type 'LayoutInh'
newtype LayoutInh d = LayoutInh
{ layoutInh_message :: {-!-}[d]
Doc.space <> Doc.align (Doc.justify (Doc.catV h))
LayoutNode_Forest sch ds ts ->
[Doc.whiter sch] <>
- (if List.null ds then [] else [Doc.catV ds]) <>
+ (if List.null ds || not full then [] else [Doc.catV ds]) <>
(if List.null ts then [] else [runLayoutForest' full ts])
) <> docSubTrees ts0
where
where sch = command n xl
instance (LayoutDoc d, Doc.Justifiable d) => CLI_Tag (Layout d) where
type TagConstraint (Layout d) a = TagConstraint (Schema d) a
- tagged n (Layout xs xh xm) = Layout (tagged n xs) xh $ \inh -> do
+ tag n (Layout xs xh xm) = Layout (tag n xs) xh $ \inh -> do
modify' $ \k -> \case
Nothing -> k Nothing
Just ts -> k $ Just
[ Tree.Node
( LayoutNode_List [] [
- ( docSchema (tagged n nothing)
+ ( docSchema (tag n nothing)
, layoutInh_message inh
)
]
-- ** Type 'LayoutNode'
data LayoutNode d
- = LayoutNode_Help [d] d
- | LayoutNode_Tags [([d], d)]
+ = LayoutNode_Single d {-help-}[d]
+ | LayoutNode_List [d] [(d, {-help-}[d])]
+ | LayoutNode_Forest d [d] (Tree.Forest (LayoutNode d))
deriving (Show)
command n x = commands Map.empty (Map.singleton n x)
instance Ord e => CLI_Tag (Parser e d) where
type TagConstraint (Parser e d) a = ()
- tagged name p = Parser $ P.try $ do
+ tag name p = Parser $ P.try $ do
void $ (`P.token` exp) $ \tok ->
if lookupTag tok name
then Just tok
-- ** Class 'CLI_Routing'
class CLI_Routing repr where
commands :: Map Name (repr a k) -> Map Name (repr a k) -> repr a k
- -- taggeds :: TagConstraint repr a => Map (Either Char Name) (repr (a -> k) k) -> repr (a -> k) k
+ -- tags :: TagConstraint repr a => Map (Either Char Name) (repr (a -> k) k) -> repr (a -> k) k
instance Ord e => CLI_Routing (Parser e d) where
commands preCmds cmds = Parser $
P.token check exp >>= unParser
Map Name (Router repr a k) ->
Map Name (Router repr a k) ->
Router repr a k
- -- | Represent 'tagged'.
- Router_Tagged :: Tag -> Router repr f k -> Router repr f k
+ -- | Represent 'tag'.
+ Router_Tag :: Tag -> Router repr f k -> Router repr f k
-- | Represent ('<.>').
Router_App :: Router repr a b -> Router repr b c -> Router repr a c
-- | Represent ('<!>').
case xs of
[] -> id
_ -> showString ", " . go xs
- Router_Tagged n x -> showsPrec 10 n . showString " " . showsPrec p x
+ Router_Tag n x -> showsPrec 10 n . showString " " . showsPrec p x
Router_App x y -> showParen (p>=4) $ showsPrec 4 x . showString " <.> " . showsPrec 4 y
Router_Alt x y -> showParen (p>=3) $ showsPrec 3 x . showString " <!> " . showsPrec 3 y
Router_Union _u x -> showString "Union [" . showsPrec 0 x . showString "]"
unTrans (Router_Alt x y) = unTrans x <!> unTrans y
unTrans (Router_App x y) = unTrans x <.> unTrans y
unTrans (Router_Commands preCmds cmds) = commands (unTrans <$> preCmds) (unTrans <$> cmds)
- unTrans (Router_Tagged n x) = tagged n (unTrans x)
+ unTrans (Router_Tag n x) = tag n (unTrans x)
unTrans (Router_Union u x) = Parser $ (. u) <$> unParser (unTrans x)
instance Ord e => App (Router (Parser e d)) where
instance Ord e => CLI_Var (Router (Parser e d))
instance Ord e => CLI_Env (Router (Parser e d))
instance Ord e => CLI_Tag (Router (Parser e d)) where
- tagged = Router_Tagged
+ tag = Router_Tag
instance CLI_Help (Router (Parser e d)) where
-- NOTE: set manually (instead of the 'Trans' default 'Router_Any')
-- to remove them all, since they are useless for 'Parser'
rule _n = id
instance Ord e => CLI_Response (Router (Parser e d))
instance Ord e => CLI_Routing (Router (Parser e d)) where
- -- taggeds = Router_Taggeds
+ -- tags = Router_Tags
commands = Router_Commands
router ::
Router repr a b -> Router repr a b
router = {-debug1 "router" $-} \case
x@Router_Any{} -> x
- Router_Tagged n x -> Router_Tagged n (router x)
+ Router_Tag n x -> Router_Tag n (router x)
Router_Alt x y -> router x`router_Alt`router y
Router_Commands preCmds cmds ->
Router_Commands
-- only in the help.
instance SchemaDoc d => CLI_Tag (Schema d) where
type TagConstraint (Schema d) a = ()
- tagged n r = Schema $ \inh ->
+ tag n r = Schema $ \inh ->
unSchema (prefix n <.> r) inh
where
prefix = \case
-- PVP: +-+------- breaking API changes
-- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change
-version: 2.3.5.20190714
+version: 2.4.0.20190719
category: System, CLI, Options, Parsing
synopsis: Symantics for parsing and documenting a CLI
description: