-- | This module contains various datatypes and functions which are -- common for contract registry packages (e.g. morley-ledgers and morley-multisig). module Lorentz.ContractRegistry ( ContractInfo (..) , ContractRegistry (..) , getContract , printContractFromRegistryDoc , (?::) -- Common CLI stuff , CmdLnArgs (..) , argParser ) where import qualified Data.Map as Map import qualified Data.Text.Lazy.IO as TL import Fmt (Buildable(..), blockListF, nameF, (+|), (|+)) import qualified Options.Applicative as Opt import Lorentz.Base import Lorentz.Constraints import Lorentz.Doc import Util.IO data ContractInfo = forall cp st. (NiceParameterFull cp, NiceStorage st) => ContractInfo { ciContract :: Contract cp st , ciIsDocumented :: Bool } (?::) :: Text -> a -> (Text, a) (?::) = (,) newtype ContractRegistry = ContractRegistry { unContractRegistry :: Map Text ContractInfo } getContract :: Text -> ContractRegistry -> Either String ContractInfo getContract name registry = case Map.lookup name (unContractRegistry registry) of Nothing -> Left $ "No contract with name '" +| name |+ "' found\n" +| registry |+ "" Just c -> Right c instance Buildable ContractRegistry where build registry = nameF "Available contracts" (blockListF $ keys (unContractRegistry registry)) printContractFromRegistryDoc :: Text -> ContractRegistry -> Maybe FilePath -> IO () printContractFromRegistryDoc name contracts mOutput = do ContractInfo{..} <- either die pure $ getContract name contracts let writeFunc = case mOutput of Nothing -> TL.putStrLn Just "def" -> writeFileUtf8 $ toString name <> ".md" Just output -> writeFileUtf8 output if ciIsDocumented then writeFunc $ contractDocToMarkdown $ buildLorentzDoc ciContract else die "This contract is not documented" data CmdLnArgs = List | Print Text (Maybe FilePath) Bool | Document Text (Maybe FilePath) argParser :: Opt.Parser CmdLnArgs argParser = Opt.subparser $ mconcat [ listSubCmd , printSubCmd , documentSubCmd ] where mkCommandParser commandName parser desc = Opt.command commandName $ Opt.info (Opt.helper <*> parser) $ Opt.progDesc desc listSubCmd = mkCommandParser "list" (pure List) "Show all available contracts" printSubCmd = mkCommandParser "print" (Print <$> printOptions <*> outputOptions <*> onelineOption) "Dump a contract in form of Michelson code" documentSubCmd = mkCommandParser "document" (Document <$> printOptions <*> outputOptions) "Dump contract documentation in Markdown" printOptions = Opt.strOption $ mconcat [ Opt.short 'n' , Opt.long "name" , Opt.metavar "IDENTIFIER" , Opt.help "Name of a contract returned by `list` command." ] outputOptions = optional . Opt.strOption $ mconcat [ Opt.short 'o' , Opt.long "output" , Opt.metavar "FILEPATH" , Opt.help "File to use as output. If not specified, stdout is used." ] onelineOption :: Opt.Parser Bool onelineOption = Opt.switch ( Opt.long "oneline" <> Opt.help "Force single line output")