{-| Copyright : (c) Galois, Inc. 2025 Maintainer : Langston Barrett -} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} module Lang.Crucible.Debug.Command ( Command(..) , CommandExt(..) , voidExts , allCmds , name , abbrev , parse , detail , help , regex ) where import Data.List qualified as List import Data.Parameterized.Some (Some) import Data.Text (Text) import Data.Void (Void, absurd) import Lang.Crucible.Debug.Arg.Type (ArgTypeRepr) import Lang.Crucible.Debug.Command.Base qualified as BCmd import Lang.Crucible.Debug.Regex qualified as Rgx import Prettyprinter qualified as PP data CommandExt cExt = CommandExt { -- | Used in 'abbrev', 'parse' extAbbrev :: cExt -> Text , extList :: [cExt] -- | Multi-line help string. Used in 'detail'. -- -- This is always displayed as a new paragraph following 'extHelp', so it -- should not repeat the information there. -- -- Should be long-form prose, with proper capitalization and punctuation. -- Should not rely on being shown in monospaced font. , extDetail :: cExt -> Maybe Text -- | Single-line help string. Used in 'help'. -- -- The first letter should be capitalized, it should not end in a period. -- It should probably be less than about 70 characters long. , extHelp :: cExt -> Text -- | Used in 'help', 'parse' , extName :: cExt -> Text -- | Used in 'help' , extRegex :: cExt -> Some (Rgx.RegexRepr ArgTypeRepr) } voidExts :: CommandExt Void voidExts = CommandExt { extAbbrev = absurd , extDetail = absurd , extHelp = absurd , extList = [] , extName = absurd , extRegex = absurd } data Command cExt = Base BCmd.BaseCommand | Ext cExt deriving (Functor, Show) instance PP.Pretty cExt => PP.Pretty (Command cExt) where pretty = \case Base bCmd -> PP.pretty bCmd Ext xCmd -> PP.pretty xCmd name :: CommandExt cExt -> Command cExt -> Text name cExts = \case Base bCmd -> BCmd.name bCmd Ext xCmd -> extName cExts xCmd abbrev :: CommandExt cExt -> Command cExt -> Text abbrev cExts = \case Base bCmd -> BCmd.abbrev bCmd Ext xCmd -> extAbbrev cExts xCmd allCmds :: CommandExt cExt -> [Command cExt] allCmds cExts = map Base [minBound..maxBound] ++ map Ext (extList cExts) parse :: CommandExt cExt -> Text -> Maybe (Command cExt) parse cExts txt = List.find (\c -> name cExts c == txt || abbrev cExts c == txt) (allCmds cExts) detail :: CommandExt cExt -> Command cExt -> Maybe Text detail cExts = \case Base bCmd -> BCmd.detail bCmd Ext xCmd -> extDetail cExts xCmd help :: CommandExt cExt -> Command cExt -> Text help cExts = \case Base bCmd -> BCmd.help bCmd Ext xCmd -> extHelp cExts xCmd regex :: CommandExt cExt -> Command cExt -> Some (Rgx.RegexRepr ArgTypeRepr) regex cExts = \case Base bCmd -> BCmd.regex bCmd Ext xCmd -> extRegex cExts xCmd