-- |
--
-- Module      : Ronn
-- Copyright   : (c) 2024 Patrick Brisbin
-- License     : AGPL-3
-- Maintainer  : pbrisbin@gmail.com
-- Stability   : experimental
-- Portability : POSIX
module Ronn
  ( module Ronn.AST
  , module Ronn.Render
  , ronnFilePath

    -- * Parser-based sections
  , HasSections (..)
  , getSections

    -- * Higher-level builders
  , synopsisSection
  , seeAlsoSection
  , oneLineSection
  , definitionsSection
  )
where

import Prelude

import Data.List (intersperse, sort)
import Data.Maybe (catMaybes)
import Data.Text (Text, unpack)
import Ronn.AST
import Ronn.Render

ronnFilePath :: Ronn -> FilePath
ronnFilePath :: Ronn -> FilePath
ronnFilePath Ronn
ronn =
  Text -> FilePath
unpack ManRef
ref.name FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
"." FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> Int -> FilePath
forall a. Show a => a -> FilePath
show (ManSection -> Int
manSectionNumber ManRef
ref.section) FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
".ronn"
 where
  ref :: ManRef
ref = Ronn
ronn.name

-- | Parser types can be made an instance of this for use with 'getSections'
class HasSections p where
  -- | Options parsers should produce @[-f|--foo] --bar@ synopsis parts
  getSynopsis :: p a -> Maybe [Part]
  getSynopsis p a
_ = Maybe [Part]
forall a. Maybe a
Nothing

  -- | Options parsers should produce a list of option/help definitions
  getOptDefinitions :: p a -> Maybe [Definition]
  getOptDefinitions p a
_ = Maybe [Definition]
forall a. Maybe a
Nothing

  -- | Environment parsers should produce a list of variable/help definitions
  getEnvDefinitions :: p a -> Maybe [Definition]
  getEnvDefinitions p a
_ = Maybe [Definition]
forall a. Maybe a
Nothing

getSections :: HasSections p => Text -> p a -> [Section]
getSections :: forall {k} (p :: k -> *) (a :: k).
HasSections p =>
Text -> p a -> [Section]
getSections Text
name p a
p =
  [Maybe Section] -> [Section]
forall a. [Maybe a] -> [a]
catMaybes
    [ Text -> [Part] -> Section
synopsisSection Text
name ([Part] -> Section) -> Maybe [Part] -> Maybe Section
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> p a -> Maybe [Part]
forall (a :: k). p a -> Maybe [Part]
forall {k} (p :: k -> *) (a :: k).
HasSections p =>
p a -> Maybe [Part]
getSynopsis p a
p
    , Text -> [Definition] -> Section
definitionsSection Text
"OPTIONS" ([Definition] -> Section) -> Maybe [Definition] -> Maybe Section
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> p a -> Maybe [Definition]
forall (a :: k). p a -> Maybe [Definition]
forall {k} (p :: k -> *) (a :: k).
HasSections p =>
p a -> Maybe [Definition]
getOptDefinitions p a
p
    , Text -> [Definition] -> Section
definitionsSection Text
"ENVIRONMENT" ([Definition] -> Section) -> Maybe [Definition] -> Maybe Section
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> p a -> Maybe [Definition]
forall (a :: k). p a -> Maybe [Definition]
forall {k} (p :: k -> *) (a :: k).
HasSections p =>
p a -> Maybe [Definition]
getEnvDefinitions p a
p
    ]

synopsisSection :: Text -> [Part] -> Section
synopsisSection :: Text -> [Part] -> Section
synopsisSection Text
name = Text -> [Part] -> Section
oneLineSection Text
"SYNOPSIS" ([Part] -> Section) -> ([Part] -> [Part]) -> [Part] -> Section
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Part -> Part
Code (Text -> Part
Raw Text
name) :)

seeAlsoSection :: [ManRef] -> Section
seeAlsoSection :: [ManRef] -> Section
seeAlsoSection [ManRef]
refs =
  Text -> [Part] -> Section
oneLineSection
    Text
"SEE ALSO"
    [ [Part] -> Part
forall a. Monoid a => [a] -> a
mconcat ([Part] -> Part) -> [Part] -> Part
forall a b. (a -> b) -> a -> b
$
        Part -> [Part] -> [Part]
forall a. a -> [a] -> [a]
intersperse Part
", " ([Part] -> [Part]) -> [Part] -> [Part]
forall a b. (a -> b) -> a -> b
$
          (ManRef -> Part) -> [ManRef] -> [Part]
forall a b. (a -> b) -> [a] -> [b]
map ManRef -> Part
Ref ([ManRef] -> [Part]) -> [ManRef] -> [Part]
forall a b. (a -> b) -> a -> b
$
            [ManRef] -> [ManRef]
forall a. Ord a => [a] -> [a]
sort [ManRef]
refs
    ]

oneLineSection :: Text -> [Part] -> Section
oneLineSection :: Text -> [Part] -> Section
oneLineSection Text
name [Part]
ps =
  Section
    { Text
name :: Text
$sel:name:Section :: Text
name
    , $sel:content:Section :: [Content]
content = [[Group] -> Content
Groups [[Line] -> Group
Lines [[Part] -> Line
Line [Part]
ps]]]
    }

definitionsSection :: Text -> [Definition] -> Section
definitionsSection :: Text -> [Definition] -> Section
definitionsSection Text
name [Definition]
definitions =
  Section
    { Text
$sel:name:Section :: Text
name :: Text
name
    , $sel:content:Section :: [Content]
content = [[Definition] -> Content
Definitions [Definition]
definitions]
    }