packages feed

mdoc 0.1.0.1 → 0.1.0.2

raw patch · 18 files changed

+257/−103 lines, 18 filesdep −semigroupsPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: semigroups

API changes (from Hackage documentation)

- Mdoc.Gen.Flag: data FlagOrder
- Mdoc.Gen.Flag: flagOrder :: Flag -> FlagOrder
- Mdoc.Gen.Flag: instance GHC.Classes.Eq Mdoc.Gen.Flag.FlagOrder
- Mdoc.Gen.Flag: instance GHC.Classes.Ord Mdoc.Gen.Flag.FlagOrder
+ Mdoc.Gen.Flag: instance GHC.Classes.Ord Mdoc.Gen.Flag.Flag
+ Mdoc.Gen.Optionality: opLine :: MacroName -> [MacroArg] -> Optionality -> MdocLine
+ Mdoc.Pretty: ColorDefault :: Color
+ Mdoc.Pretty: instance GHC.Base.Semigroup Mdoc.Pretty.Color
- Mdoc.Dump.Env: Env :: Maybe Color -> Bool -> Env
+ Mdoc.Dump.Env: Env :: Color -> Bool -> Env
- Mdoc.Dump.Env: [color] :: Env -> Maybe Color
+ Mdoc.Dump.Env: [color] :: Env -> Color
- Mdoc.Dump.Options: Options :: Bool -> Bool -> Maybe Color -> Bool -> [FilePath] -> Options
+ Mdoc.Dump.Options: Options :: Bool -> Bool -> Color -> Bool -> [FilePath] -> Options
- Mdoc.Dump.Options: [color] :: Options -> Maybe Color
+ Mdoc.Dump.Options: [color] :: Options -> Color
- Mdoc.Gen.Description: optionLines :: Described Option -> (FlagOrder, [MdocLine])
+ Mdoc.Gen.Description: optionLines :: Described Option -> (Flag, [MdocLine])
- Mdoc.Gen.Description: switchLines :: Described Flag -> (FlagOrder, [MdocLine])
+ Mdoc.Gen.Description: switchLines :: Described Flag -> (Flag, [MdocLine])

Files

mdoc.cabal view
@@ -1,10 +1,30 @@ cabal-version:      1.18 name:               mdoc-version:            0.1.0.1+version:            0.1.0.2 license:            AGPL-3 maintainer:         Pat Brisbin synopsis:           Parser and pretty-printer for the mdoc(7) language-description:        Please see README.md+description:+    This library parses, represents, pretty-prints, or generates man-page content+    using the [mdoc(7)](https://mandoc.bsd.lv/man/mdoc.7.html) language.+    .+    To parse a man-page and work with its data in a structured way,+    .+    * See 'parseMdoc' and 'Mdoc'+    .+    To pretty-print parsed (or constructed) man-page data,+    .+    * Use 'prettyMdoc' (or 'putDoc')+    .+    To generate a man-page from a supported parser library, check the appropriate+    integration module,+    .+    * @envparse@ -- "Env.Mdoc"+    * @opt-env-conf@ -- "OptEnvConf.Mdoc"+    * @optparse-applicative@ -- "Options.Applicative.Mdoc"+    .+    An example and screenshots are present in the project [README](#readme).+ build-type:         Simple extra-source-files:     data/man1.template@@ -106,7 +126,6 @@         optparse-applicative >=0.18.1.0,         prettyprinter >=1.7.1,         prettyprinter-ansi-terminal >=1.1.3,-        semigroups >=0.20,         text >=2.1.1,         time >=1.12.2,         zlib >=0.7.1.0@@ -169,6 +188,7 @@     other-modules:         Mdoc.Gen.DescriptionSpec         Mdoc.Gen.ExitStatusSpec+        Mdoc.Gen.FlagSpec         Mdoc.GenSpec         Mdoc.Parse.MacroArgSpec         Mdoc.Parse.MdocLineSpec
src/Mdoc/Dump/Env.hs view
@@ -21,7 +21,7 @@ import Mdoc.Pretty (Color (..), readColor)  data Env = Env-  { color :: Maybe Color+  { color :: Color   , debug :: Bool   } @@ -35,8 +35,10 @@ envParser =   Env.prefixed "MDOC_DUMP_"     $ Env-      <$> optional colorEnv+      <$> colorEnv       <*> switch "DEBUG" (help "Log more verbosely")  colorEnv :: Parser Error Color-colorEnv = var (eitherReader readColor) "COLOR" $ help "When to colorize the output"+colorEnv =+  var (eitherReader readColor) "COLOR"+    $ help "When to colorize the output" <> def ColorDefault
src/Mdoc/Dump/Main.hs view
@@ -19,7 +19,7 @@ import Mdoc.Dump.Options import Mdoc.Input import Mdoc.Parse (exitParseError)-import Mdoc.Pretty (Ann (..), Color (..), putDoc, renderPlain)+import Mdoc.Pretty (Ann (..), putDoc, renderPlain) import Mdoc.UpdateMdocdate import Prettyprinter import System.Exit (exitFailure)@@ -29,19 +29,16 @@ main = do   options <- parseOptions -  let-    color = fromMaybe ColorAuto options.color--    postProcess mdoc =-      if options.updateMdocdate-        then updateMdocdate mdoc-        else pure mdoc+  let postProcess mdoc =+        if options.updateMdocdate+          then updateMdocdate mdoc+          else pure mdoc    forInputs_ options.input $ \input -> do     case input.parsed of       SkipParse reason ->         when options.debug-          $ putDoc color stderr+          $ putDoc options.color stderr           $ annotate AnnFile (pretty input.name)           <> ":"           <+> "refusing to parse"@@ -49,7 +46,7 @@       ParseError err -> exitParseError err       Parsed mdoc -> do         mdoc' <- postProcess mdoc-        putDoc color stdout $ prettyMdoc mdoc'+        putDoc options.color stdout $ prettyMdoc mdoc'          -- NB. The --check option operates on mdoc before any --update-mdocdate         -- changes. Unclear what the least surprising behavior is here.@@ -61,7 +58,7 @@            case diffs of             NoDifferences ->-              putDoc color stdout $ prettyDifferences input.name diffs+              putDoc options.color stdout $ prettyDifferences input.name diffs             Differences {} -> do-              putDoc color stderr $ prettyDifferences input.name diffs+              putDoc options.color stderr $ prettyDifferences input.name diffs               exitFailure
src/Mdoc/Dump/Options.hs view
@@ -20,13 +20,13 @@ import Prelude  import Mdoc.Dump.Env-import Mdoc.Pretty (Color (..), readColor)+import Mdoc.Pretty (Color (..), readColor, showColor) import Options.Applicative  data Options = Options   { check :: Bool   , updateMdocdate :: Bool-  , color :: Maybe Color+  , color :: Color   , debug :: Bool   , input :: [FilePath]   }@@ -41,7 +41,7 @@    pure     (opt :: Options)-      { color = opt.color <|> env.color+      { color = env.color <> opt.color       , debug = env.debug || opt.debug       } @@ -64,15 +64,15 @@           , help "Update any $Mdocdate$ macros in the output"           ]       )-    <*> optional-      ( option-          (eitherReader readColor)-          ( mconcat-              [ long "color"-              , help "When to colorize the output"-              , metavar "auto|always|never"-              ]-          )+    <*> option+      (eitherReader readColor)+      ( mconcat+          [ long "color"+          , help "When to colorize the output"+          , metavar "auto|always|never"+          , value ColorDefault+          , showDefaultWith showColor+          ]       )     <*> switch       ( mconcat
src/Mdoc/Gen/Argument.hs view
@@ -44,18 +44,15 @@  renderArgumentForLong :: String -> Argument -> [MacroArg] renderArgumentForLong x arg@Argument {optionality} =-  case optionality of-    Required ->-      [ Bare $ esc $ pack $ x <> "="-      , Callable Ns-      ]-        <> renderArgument arg-    _ ->-      [ Bare $ esc $ pack x-      , Callable Ns-      , Callable Op-      , Callable Cm-      , Bare "="-      , Callable Ns-      ]-        <> renderArgument arg+  prefix <> [Callable Ns] <> renderArgument arg+ where+  prefix =+    case optionality of+      Required -> [Bare $ esc $ pack $ x <> "="]+      _ ->+        [ Bare $ esc $ pack x+        , Callable Ns+        , Callable Op+        , Callable Cm+        , Bare "="+        ]
src/Mdoc/Gen/CrossRef.hs view
@@ -25,7 +25,8 @@   deriving stock (Eq, Show)  instance Ord CrossRef where-  a `compare` b = a.section `compare` b.section <> a.name `compare` b.name+  -- SEE ALSO is sorted section then name+  compare = comparing $ \x -> (x.section, x.name)  renderCrossRefs :: NonEmpty CrossRef -> NonEmpty MdocLine renderCrossRefs = go . NE.sort
src/Mdoc/Gen/Description.hs view
@@ -58,15 +58,15 @@     $ map switchLines switches     <> map optionLines options -switchLines :: Described Flag -> (FlagOrder, [MdocLine])+switchLines :: Described Flag -> (Flag, [MdocLine]) switchLines d =-  ( flagOrder d.item+  ( d.item   , renderDescribedItem (`renderFlag` Nothing) d   ) -optionLines :: Described Option -> (FlagOrder, [MdocLine])+optionLines :: Described Option -> (Flag, [MdocLine]) optionLines d =-  ( flagOrder d.item.flag+  ( d.item.flag   , renderDescribedItem ((`renderFlag` (Just d.item.argument)) . (.flag)) d   ) 
src/Mdoc/Gen/Environment.hs view
@@ -1,3 +1,11 @@+-- |+--+-- Module      : Mdoc.Gen.Environment+-- Copyright   : (c) 2026 Patrick Brisbin+-- License     : AGPL-3+-- Maintainer  : pbrisbin@gmail.com+-- Stability   : experimental+-- Portability : POSIX module Mdoc.Gen.Environment   ( man1Environment   ) where
src/Mdoc/Gen/ExitStatus.hs view
@@ -1,3 +1,11 @@+-- |+--+-- Module      : Mdoc.Gen.ExitStatus+-- Copyright   : (c) 2026 Patrick Brisbin+-- License     : AGPL-3+-- Maintainer  : pbrisbin@gmail.com+-- Stability   : experimental+-- Portability : POSIX module Mdoc.Gen.ExitStatus   ( NonZeroStatus (..)   , renderExitStatuses@@ -10,9 +18,9 @@  data NonZeroStatus = NonZeroStatus   { status :: Text-  -- ^ @>0@+  -- ^ For example, @\">0\"@   , condition :: Text-  -- ^ @if an error occurs@+  -- ^ For example, @\"if an error occurs\"@   }   deriving stock (Eq, Generic, Show) 
src/Mdoc/Gen/Flag.hs view
@@ -8,8 +8,6 @@ -- Portability : POSIX module Mdoc.Gen.Flag   ( Flag (..)-  , FlagOrder-  , flagOrder   , renderFlag   , renderShort   , renderLong@@ -29,18 +27,14 @@   | GNUFlag String [Flag]   deriving stock (Eq, Show) -data FlagOrder = FlagOrder-  { _byType :: Int-  , _byNameLower :: String-  , _byUpperThenLower :: Bool-  }-  deriving stock (Eq, Ord)---- | Shorts before longs, capital then lower together-flagOrder :: Flag -> FlagOrder-flagOrder = \case-  Flag c _ -> FlagOrder 1 [toLower c] $ isLower c-  GNUFlag s _ -> FlagOrder 2 (map toLower s) False+instance Ord Flag where+  compare = comparing @(Int, String, Bool) $ \case+    --           1. short before long+    --           |  2. case-insensitive alphabetically+    --           |  |            3. upper before lower+    --           |  |            |+    Flag c _ -> (1, [toLower c], isLower c)+    GNUFlag s _ -> (2, map toLower s, False)  renderFlag :: Flag -> Maybe Argument -> [MacroArg] renderFlag flag margument =
src/Mdoc/Gen/Optionality.hs view
@@ -8,12 +8,31 @@ -- Portability : POSIX module Mdoc.Gen.Optionality   ( Optionality (..)+  , opLine   ) where  import Mdoc.Prelude +import Mdoc.MacroArg+import Mdoc.MacroName+import Mdoc.MdocLine+ data Optionality   = Optional   | Required   | Defaulted String   deriving stock (Eq, Show)++-- | Render a macro line as @.Op@ or not+--+-- >>> opLine Fl ["A", Ar, "num"] Required+-- .Fl A Ar num+-- -A num+--+-- >>> opLine Fl ["A", Ar, "num"] Optional+-- .Op Fl A Ar num+-- [-A num]+opLine :: MacroName -> [MacroArg] -> Optionality -> MdocLine+opLine n args = \case+  Required -> MacroLine n args+  _ -> MacroLine Op $ Callable n : args
src/Mdoc/Gen/Synopsis.hs view
@@ -28,8 +28,7 @@   MacroLine Nm [Bare $ esc $ pack $ m.name.primary]     :| concat       [ [MacroLine Bk ["-words"]]-      , maybe [] (\cs -> [MacroLine Op [Callable Fl, Bare $ esc $ pack $ toList cs]])-          $ shortSwitchChars m.switches+      , maybe [] (pure . shortsLine) $ shortSwitchChars m.switches       , mapMaybe shortOptionLine m.options       , map snd           $ sortOn fst@@ -39,6 +38,9 @@       , [MacroLine Ek []]       ] +shortsLine :: NonEmpty Char -> MdocLine+shortsLine cs = MacroLine Op [Callable Fl, Bare $ esc $ pack $ toList cs]+ man5Synopsis :: Man5 -> NonEmpty MdocLine man5Synopsis m = renderFilesCompact m.files @@ -47,37 +49,18 @@  shortOptionLine :: Described Option -> Maybe MdocLine shortOptionLine d = withShort d.item.flag $ \c ->-  let margs = renderShort c $ Just d.item.argument-  in  case d.optionality of-        Required -> MacroLine Fl margs-        _ -> MacroLine Op $ Callable Fl : margs+  opLine Fl (renderShort c $ Just d.item.argument) d.optionality  longSwitchLine :: Described Flag -> Maybe (String, MdocLine) longSwitchLine d = withLong d.item $ \s ->-  let-    margs = renderLong s Nothing-    mline = case d.optionality of-      Required -> MacroLine Fl margs-      _ -> MacroLine Op $ Callable Fl : margs-  in-    (s, mline)+  (s, opLine Fl (renderLong s Nothing) d.optionality)  longOptionLine :: Described Option -> Maybe (String, MdocLine) longOptionLine d = withLong d.item.flag $ \s ->-  let-    margs = renderLong s $ Just d.item.argument-    mline = case d.optionality of-      Required -> MacroLine Fl margs-      _ -> MacroLine Op $ Callable Fl : margs-  in-    (s, mline)+  (s, opLine Fl (renderLong s $ Just d.item.argument) d.optionality)  argLine :: Described Argument -> MdocLine-argLine d =-  case d.optionality of-    Required -> MacroLine Ar margs-    Optional -> MacroLine Op $ Callable Ar : margs-    Defaulted {} -> MacroLine Op $ Callable Ar : margs+argLine d = opLine Ar margs d.optionality  where   margs     | d.multiple = [Bare $ esc $ pack d.item.schema, "..."]
src/Mdoc/Interpolated.hs view
@@ -52,17 +52,14 @@       InterpolatedLine Name -> toList v.name       InterpolatedLine Synopsis -> toList v.synopsis       InterpolatedLine Description -> toList v.description-      InterpolatedLine Environment -> case v.environment of-        Nothing -> []-        Just es -> MacroLine Sh ["ENVIRONMENT"] : toList es-      InterpolatedLine Files -> case v.files of-        Nothing -> []-        Just fs -> MacroLine Sh ["FILES"] : toList fs+      InterpolatedLine Environment ->+        maybe [] ((MacroLine Sh ["ENVIRONMENT"] :) . toList) v.environment+      InterpolatedLine Files ->+        maybe [] ((MacroLine Sh ["FILES"] :) . toList) v.files       InterpolatedLine ExitStatus ->         maybe [MacroLine Ex ["-std"]] toList v.exitStatus-      InterpolatedLine SeeAlso -> case v.seeAlso of-        Nothing -> []-        Just crs -> MacroLine Sh ["SEE", "ALSO"] : toList crs+      InterpolatedLine SeeAlso ->+        maybe [] ((MacroLine Sh ["SEE", "ALSO"] :) . toList) v.seeAlso       line -> [line]  instance Interpolated Mdoc where
src/Mdoc/Parse.hs view
@@ -35,7 +35,6 @@ import Control.Monad.State.Strict (StateT, evalState) import Data.Char (isSpace) import Data.Monoid (Last (..))-import Data.Semigroup.Generic (GenericSemigroupMonoid (..)) import System.Exit (exitFailure) import System.IO (hPutStrLn, stderr) import Text.Megaparsec hiding (ParseError, parseTest, runParser)@@ -60,7 +59,7 @@   -- ^ If in a macro definition with custom closer, this is it   }   deriving stock (Generic)-  deriving (Monoid, Semigroup) via GenericSemigroupMonoid MacroState+  deriving (Monoid, Semigroup) via Generically MacroState  type ParseError = ParseErrorBundle Text Void 
src/Mdoc/Pretty.hs view
@@ -50,10 +50,26 @@   | AnnDiffContext  data Color-  = ColorAuto+  = -- | Behaves like 'ColorAuto' but is an identity under 'Semigroup'+    --+    -- This means you can give parsers this as a default, and still do (e.g.):+    --+    -- @+    -- color :: Color+    -- color = env.color <> opt.color+    -- @+    --+    -- Without finding that the @opt@ default clobbers an explicit @env@.+    ColorDefault+  | ColorAuto   | ColorAlways   | ColorNever +instance Semigroup Color where+  ColorDefault <> a = a+  a <> ColorDefault = a+  _ <> a = a+ readColor :: String -> Either String Color readColor = \case   "auto" -> Right ColorAuto@@ -63,6 +79,7 @@  showColor :: Color -> String showColor = \case+  ColorDefault -> "auto"   ColorAuto -> "auto"   ColorAlways -> "always"   ColorNever -> "never"@@ -70,6 +87,7 @@ putDoc :: MonadIO m => Color -> Handle -> Doc Ann -> m () putDoc c h doc = do   useColor <- case c of+    ColorDefault -> liftIO $ hIsTerminalDevice h     ColorAuto -> liftIO $ hIsTerminalDevice h     ColorAlways -> pure True     ColorNever -> pure False
test/Mdoc/Gen/ExitStatusSpec.hs view
@@ -1,3 +1,11 @@+-- |+--+-- Module      : Mdoc.Gen.ExitStatusSpec+-- Copyright   : (c) 2026 Patrick Brisbin+-- License     : AGPL-3+-- Maintainer  : pbrisbin@gmail.com+-- Stability   : experimental+-- Portability : POSIX module Mdoc.Gen.ExitStatusSpec   ( spec   ) where
+ test/Mdoc/Gen/FlagSpec.hs view
@@ -0,0 +1,95 @@+-- |+--+-- Module      : Mdoc.Gen.FlagSpec+-- Copyright   : (c) 2026 Patrick Brisbin+-- License     : AGPL-3+-- Maintainer  : pbrisbin@gmail.com+-- Stability   : experimental+-- Portability : POSIX+module Mdoc.Gen.FlagSpec+  ( spec+  ) where++import Mdoc.Prelude++import Data.List (sort)+import Mdoc.Gen.Flag+import Test.Hspec++spec :: Spec+spec = do+  describe "Ord" $ do+    it "sorts short before long, capital-then-lower together" $ do+      let+        unsorted =+          [ Flag 'q' []+          , Flag 'e' []+          , Flag 'n' []+          , Flag 'G' []+          , Flag 'b' []+          , Flag 'A' []+          , Flag 'I' []+          , Flag 's' []+          , GNUFlag "binary-files" []+          , Flag 'B' []+          , GNUFlag "line-buffered" []+          , Flag 'L' []+          , Flag 'F' []+          , GNUFlag "null" []+          , Flag 'w' []+          , Flag 'o' []+          , Flag 'Z' []+          , Flag 'x' []+          , Flag 'E' []+          , Flag 'v' []+          , GNUFlag "label" []+          , Flag 'h' []+          , Flag 'c' []+          , Flag 'U' []+          , Flag 'H' []+          , Flag 'l' []+          , Flag 'V' []+          , Flag 'f' []+          , Flag 'C' [GNUFlag "context" []]+          , Flag 'i' []+          , Flag 'a' []+          , Flag 'm' []+          , Flag 'R' []+          ]+        sorted =+          [ Flag 'A' []+          , Flag 'a' []+          , Flag 'B' []+          , Flag 'b' []+          , Flag 'C' [GNUFlag "context" []]+          , Flag 'c' []+          , Flag 'E' []+          , Flag 'e' []+          , Flag 'F' []+          , Flag 'f' []+          , Flag 'G' []+          , Flag 'H' []+          , Flag 'h' []+          , Flag 'I' []+          , Flag 'i' []+          , Flag 'L' []+          , Flag 'l' []+          , Flag 'm' []+          , Flag 'n' []+          , Flag 'o' []+          , Flag 'q' []+          , Flag 'R' []+          , Flag 's' []+          , Flag 'U' []+          , Flag 'V' []+          , Flag 'v' []+          , Flag 'w' []+          , Flag 'x' []+          , Flag 'Z' []+          , GNUFlag "binary-files" []+          , GNUFlag "label" []+          , GNUFlag "line-buffered" []+          , GNUFlag "null" []+          ]++      sort unsorted `shouldBe` sorted
test/Mdoc/Test/Fixtures.hs view
@@ -1,5 +1,13 @@ {-# OPTIONS_GHC -Wno-ambiguous-fields #-} +-- |+--+-- Module      : Mdoc.Test.Fixtures+-- Copyright   : (c) 2026 Patrick Brisbin+-- License     : AGPL-3+-- Maintainer  : pbrisbin@gmail.com+-- Stability   : experimental+-- Portability : POSIX module Mdoc.Test.Fixtures   ( grepBase   , grepOpt