ogma-cli 1.14.0 → 1.15.0
raw patch · 12 files changed
+959/−181 lines, 12 filesdep ~ogma-core
Dependency ranges changed: ogma-core
Files
- CHANGELOG.md +26/−0
- ogma-cli.cabal +4/−2
- src/CLI/CommandCFSApp.hs +120/−31
- src/CLI/CommandFPrimeApp.hs +101/−25
- src/CLI/CommandOverview.hs +129/−35
- src/CLI/CommandROSApp.hs +118/−29
- src/CLI/CommandReport.hs +89/−20
- src/CLI/CommandSearch.hs +243/−0
- src/CLI/CommandStandalone.hs +100/−25
- src/CLI/CommandTop.hs +23/−9
- src/CLI/Result.hs +2/−1
- src/Main.hs +4/−4
CHANGELOG.md view
@@ -1,5 +1,31 @@ # Revision history for ogma-cli +## [1.15.0] - 2026-07-21++* Version bump (1.15.0) (#508).+* Fix typo in README (#428).+* Update CI job to install Copilot 4.7.1 by default (#446).+* Fix style of record definitions, constructions in multiple commands (#454).+* Adjust `overview` command to accept multiple input files (#456).+* Adjust `overview`, `standalone`, app commands to support projects (#460).+* Expose `search` command (#464).+* Fix syntax, grammatical errors in diagram tutorial (#466).+* Fix links in documentation (#468).+* Remove unnecessary vertical space (#470).+* Update variable DBs in examples to indicate which inputs are active (#474).+* Expose diagram mode argument to cFS backend (#476).+* Add example explaining cFS app generation from state machine diagrams (#478).+* Add example containing Doorstop requirements (#480).+* Remove mentions of ICAROUS (#482).+* Replace ROS2 with ROS 2 in help message (#484).+* Adjust `report` command to accept multiple input files (#486).+* Adjust `report` command to support projects (#488).+* Remove unused import from `CLI.CommandStandalone` module (#490).+* Apply multiple style fixes (#492).+* Standardize option name in `report` command (#505).+* Update CI job, examples for cFS 7.0 (#509).+* Add example demonstrating how to generate monitor for Turtlesim demo (#507).+ ## [1.14.0] - 2026-05-21 * Version bump (1.14.0) (#425).
ogma-cli.cabal view
@@ -19,7 +19,7 @@ build-type: Simple name: ogma-cli-version: 1.14.0+version: 1.15.0 homepage: https://github.com/nasa/ogma bug-reports: https://github.com/nasa/ogma/issues license: Apache-2.0@@ -78,6 +78,7 @@ > >Available commands: > overview Generate an overview of the input specification(s)+ > search List items that match search query > structs Generate Copilot structs from C structs > handlers Generate message handlers from C structs > cfs Generate a complete CFS/Copilot application@@ -134,6 +135,7 @@ CLI.CommandOverview CLI.CommandReport CLI.CommandROSApp+ CLI.CommandSearch CLI.CommandStandalone CLI.CommandTop CLI.Result@@ -145,7 +147,7 @@ , microstache >= 1.0 && < 1.1 , text >= 1.2.3.1 && < 2.2 - , ogma-core >= 1.14.0 && < 1.15+ , ogma-core >= 1.15.0 && < 1.16 hs-source-dirs: src
src/CLI/CommandCFSApp.hs view
@@ -30,11 +30,16 @@ where -- External imports+import Control.Applicative ( (<|>) )+import Data.Functor ( (<&>) )+import Data.Maybe ( fromMaybe ) import Options.Applicative ( Parser, help, long, many, metavar, optional, short, showDefault, strOption, value ) --- External imports: command results-import Command.Result ( Result )+-- External imports: handling of input projects and command results+import Command.Result ( Result (..) )+import Data.Location ( Location ( LocationFile ) )+import Data.Project ( Project (..), readProject ) -- External imports: actions or commands supported import Command.CFSApp ( ErrorCode )@@ -44,17 +49,19 @@ -- | Options needed to generate the cFS application. data CommandOpts = CommandOpts- { cFSAppConditionExpr :: Maybe String- , cFSAppInputFiles :: [String]- , cFSAppTarget :: String- , cFSAppTemplateDir :: Maybe String- , cFSAppVarNames :: Maybe String- , cFSAppVarDB :: Maybe String- , cFSAppHandlers :: Maybe String- , cFSAppFormat :: String- , cFSAppPropFormat :: String- , cFSAppPropVia :: Maybe String- , cFSAppTemplateVars :: Maybe String+ { cFSAppProject :: Maybe String+ , cFSAppConditionExpr :: Maybe String+ , cFSAppInputFiles :: [String]+ , cFSAppTarget :: String+ , cFSAppTemplateDir :: Maybe String+ , cFSAppVarNames :: Maybe String+ , cFSAppVarDB :: Maybe String+ , cFSAppHandlers :: Maybe String+ , cFSAppFormat :: String+ , cFSAppPropFormat :: String+ , cFSAppPropVia :: Maybe String+ , cFSAppDiagramMode :: String+ , cFSAppTemplateVars :: Maybe String } -- | Create <https://cfs.gsfc.nasa.gov/ NASA core Flight System> (cFS)@@ -63,22 +70,78 @@ -- -- This is just an uncurried version of "Command.CFSApp". command :: CommandOpts -> IO (Result ErrorCode)-command c = Command.CFSApp.command options- where- options = Command.CFSApp.CommandOptions- { Command.CFSApp.commandConditionExpr = cFSAppConditionExpr c- , Command.CFSApp.commandInputFiles = cFSAppInputFiles c- , Command.CFSApp.commandTargetDir = cFSAppTarget c- , Command.CFSApp.commandTemplateDir = cFSAppTemplateDir c- , Command.CFSApp.commandVariables = cFSAppVarNames c- , Command.CFSApp.commandVariableDB = cFSAppVarDB c- , Command.CFSApp.commandHandlers = cFSAppHandlers c- , Command.CFSApp.commandFormat = cFSAppFormat c- , Command.CFSApp.commandPropFormat = cFSAppPropFormat c- , Command.CFSApp.commandPropVia = cFSAppPropVia c- , Command.CFSApp.commandExtraVars = cFSAppTemplateVars c- }+command c+ | Just p <- cFSAppProject c+ = do optE <- commandProjectOptions p c+ case optE of+ Left msg -> return $ Error cannotReadProject msg (LocationFile p)+ Right opt -> Command.CFSApp.command opt + | otherwise+ = Command.CFSApp.command $+ Command.CFSApp.CommandOptions+ { Command.CFSApp.commandConditionExpr = cFSAppConditionExpr c+ , Command.CFSApp.commandInputFiles = cFSAppInputFiles c+ , Command.CFSApp.commandTargetDir = cFSAppTarget c+ , Command.CFSApp.commandTemplateDir = cFSAppTemplateDir c+ , Command.CFSApp.commandVariables = cFSAppVarNames c+ , Command.CFSApp.commandVariableDB = cFSAppVarDB c+ , Command.CFSApp.commandHandlers = cFSAppHandlers c+ , Command.CFSApp.commandFormat = cFSAppFormat c+ , Command.CFSApp.commandPropFormat = cFSAppPropFormat c+ , Command.CFSApp.commandPropVia = cFSAppPropVia c+ , Command.CFSApp.commandDiagramMode = cFSAppDiagramMode c+ , Command.CFSApp.commandExtraVars = cFSAppTemplateVars c+ }++-- | Produce default command options based on project settings.+commandProjectOptions :: FilePath+ -> CommandOpts+ -> IO (Either String Command.CFSApp.CommandOptions)+commandProjectOptions projectFile c = do+ projectE <- readProject projectFile+ return $ projectE <&> \project ->+ Command.CFSApp.CommandOptions+ { Command.CFSApp.commandConditionExpr = cFSAppConditionExpr c++ , Command.CFSApp.commandInputFiles = concat+ [ map (\(f, _, _) -> f) $ projectInputFiles project+ , cFSAppInputFiles c+ ]++ , Command.CFSApp.commandTargetDir =+ fromMaybe (cFSAppTarget c) (projectTargetDir project)++ , Command.CFSApp.commandTemplateDir =+ projectTemplateDir project <|> cFSAppTemplateDir c++ , Command.CFSApp.commandVariables =+ projectVariableFiles project <|> cFSAppVarNames c++ , Command.CFSApp.commandVariableDB =+ projectVariableDBFile project <|> cFSAppVarDB c++ , Command.CFSApp.commandHandlers =+ projectHandlerFile project <|> cFSAppHandlers c++ , Command.CFSApp.commandFormat = case projectInputFiles project of+ [] -> cFSAppFormat c+ ((_, f, _):_) -> f++ , Command.CFSApp.commandPropFormat = case projectInputFiles project of+ [] -> cFSAppPropFormat c+ ((_, _, f):_) -> f++ , Command.CFSApp.commandPropVia =+ projectCommandPropVia project <|> cFSAppPropVia c++ , Command.CFSApp.commandDiagramMode = cFSAppDiagramMode c++ , Command.CFSApp.commandExtraVars =+ projectExtraJSONFile project <|> cFSAppTemplateVars c++ }+ -- * CLI -- | cFS command description@@ -91,6 +154,13 @@ commandOptsParser = CommandOpts <$> optional ( strOption+ ( long "project"+ <> metavar "FILENAME"+ <> help strCFSAppProjectArgDesc+ )+ )+ <*> optional+ ( strOption ( long "condition-expr" <> metavar "EXPRESSION" <> help strCFSAppConditionExprArgDesc@@ -161,6 +231,13 @@ <> help strCFSAppPropViaDesc ) )+ <*> strOption+ ( long "mode"+ <> metavar "MODE"+ <> help strCFSAppDiagramModeDesc+ <> showDefault+ <> value "calculate"+ ) <*> optional ( strOption ( long "template-vars"@@ -169,6 +246,10 @@ ) ) +-- | Argument project to cFS app generation command.+strCFSAppProjectArgDesc :: String+strCFSAppProjectArgDesc = "Project file"+ -- | Argument target directory to cFS app generation command strCFSAppDirArgDesc :: String strCFSAppDirArgDesc = "Target directory"@@ -188,16 +269,15 @@ strCFSAppFileNameArgDesc = "File containing input specification" - -- | Argument variable list to cFS app generation command strCFSAppVarListArgDesc :: String strCFSAppVarListArgDesc =- "File containing list of cFS/ICAROUS variables to make accessible"+ "File containing list of cFS variables to make accessible" -- | Argument variable database to cFS app generation command strCFSAppVarDBArgDesc :: String strCFSAppVarDBArgDesc =- "File containing a DB of known cFS/ICAROUS variables"+ "File containing a DB of known cFS variables" -- | Argument handler list to cFS app generation command strCFSAppHandlerListArgDesc :: String@@ -217,7 +297,16 @@ strCFSAppPropViaDesc = "Command to pre-process individual properties" +-- | Mode name flag description.+strCFSAppDiagramModeDesc :: String+strCFSAppDiagramModeDesc =+ "Mode of operation for diagrams (check, calculate, safeguard)"+ -- | Argument template variables to cFS app generation command strCFSAppTemplateVarsArgDesc :: String strCFSAppTemplateVarsArgDesc = "JSON file containing additional variables to expand in template"++-- | Error code for when a project cannot be read.+cannotReadProject :: ErrorCode+cannotReadProject = 1
src/CLI/CommandFPrimeApp.hs view
@@ -30,11 +30,16 @@ where -- External imports+import Control.Applicative ( (<|>) )+import Data.Functor ( (<&>) )+import Data.Maybe ( fromMaybe ) import Options.Applicative ( Parser, help, long, many, metavar, optional, short, showDefault, strOption, value ) --- External imports: command results-import Command.Result ( Result )+-- External imports: handling of input projects and command results+import Command.Result ( Result (..) )+import Data.Location ( Location (LocationFile) )+import Data.Project ( Project (..), readProject ) -- External imports: actions or commands supported import Command.FPrimeApp (ErrorCode)@@ -44,17 +49,18 @@ -- | Options needed to generate the FPrime component. data CommandOpts = CommandOpts- { fprimeAppConditionExpr :: Maybe String- , fprimeAppInputFiles :: [String]- , fprimeAppTarget :: String- , fprimeAppTemplateDir :: Maybe String- , fprimeAppVariables :: Maybe String- , fprimeAppVarDB :: Maybe String- , fprimeAppHandlers :: Maybe String- , fprimeAppFormat :: String- , fprimeAppPropFormat :: String- , fprimeAppPropVia :: Maybe String- , fprimeAppTemplateVars :: Maybe String+ { fprimeAppProject :: Maybe String+ , fprimeAppConditionExpr :: Maybe String+ , fprimeAppInputFiles :: [String]+ , fprimeAppTarget :: String+ , fprimeAppTemplateDir :: Maybe String+ , fprimeAppVariables :: Maybe String+ , fprimeAppVarDB :: Maybe String+ , fprimeAppHandlers :: Maybe String+ , fprimeAppFormat :: String+ , fprimeAppPropFormat :: String+ , fprimeAppPropVia :: Maybe String+ , fprimeAppTemplateVars :: Maybe String } -- | Create <https://github.com/nasa/fprime FPrime> component that subscribe@@ -63,23 +69,77 @@ -- -- This is just a wrapper around "Command.fprimeApp". command :: CommandOpts -> IO (Result ErrorCode)-command c = Command.FPrimeApp.command options+command c+ | Just p <- fprimeAppProject c+ = do optE <- commandProjectOptions p c+ case optE of+ Left msg -> return $ Error cannotReadProject msg (LocationFile p)+ Right opt -> Command.FPrimeApp.command opt++ | otherwise+ = Command.FPrimeApp.command options where options = Command.FPrimeApp.CommandOptions { Command.FPrimeApp.commandConditionExpr = fprimeAppConditionExpr c- , Command.FPrimeApp.commandInputFiles = fprimeAppInputFiles c- , Command.FPrimeApp.commandTargetDir = fprimeAppTarget c- , Command.FPrimeApp.commandTemplateDir = fprimeAppTemplateDir c- , Command.FPrimeApp.commandVariables = fprimeAppVariables c- , Command.FPrimeApp.commandVariableDB = fprimeAppVarDB c- , Command.FPrimeApp.commandHandlers = fprimeAppHandlers c- , Command.FPrimeApp.commandFormat = fprimeAppFormat c- , Command.FPrimeApp.commandPropFormat = fprimeAppPropFormat c- , Command.FPrimeApp.commandPropVia = fprimeAppPropVia c- , Command.FPrimeApp.commandExtraVars = fprimeAppTemplateVars c+ , Command.FPrimeApp.commandInputFiles = fprimeAppInputFiles c+ , Command.FPrimeApp.commandTargetDir = fprimeAppTarget c+ , Command.FPrimeApp.commandTemplateDir = fprimeAppTemplateDir c+ , Command.FPrimeApp.commandVariables = fprimeAppVariables c+ , Command.FPrimeApp.commandVariableDB = fprimeAppVarDB c+ , Command.FPrimeApp.commandHandlers = fprimeAppHandlers c+ , Command.FPrimeApp.commandFormat = fprimeAppFormat c+ , Command.FPrimeApp.commandPropFormat = fprimeAppPropFormat c+ , Command.FPrimeApp.commandPropVia = fprimeAppPropVia c+ , Command.FPrimeApp.commandExtraVars = fprimeAppTemplateVars c } +-- | Produce default command options based on project settings.+commandProjectOptions :: FilePath+ -> CommandOpts+ -> IO (Either String Command.FPrimeApp.CommandOptions)+commandProjectOptions projectFile c = do+ projectE <- readProject projectFile+ return $ projectE <&> \project ->+ Command.FPrimeApp.CommandOptions+ { Command.FPrimeApp.commandConditionExpr = fprimeAppConditionExpr c++ , Command.FPrimeApp.commandInputFiles = concat+ [ map (\(f, _, _) -> f) $ projectInputFiles project+ , fprimeAppInputFiles c+ ]++ , Command.FPrimeApp.commandTargetDir =+ fromMaybe (fprimeAppTarget c) (projectTargetDir project)++ , Command.FPrimeApp.commandTemplateDir =+ maybe (fprimeAppTemplateDir c) Just (projectTemplateDir project)++ , Command.FPrimeApp.commandVariables =+ projectVariableFiles project <|> fprimeAppVariables c++ , Command.FPrimeApp.commandVariableDB =+ projectVariableDBFile project <|> fprimeAppVarDB c++ , Command.FPrimeApp.commandHandlers =+ projectHandlerFile project <|> fprimeAppHandlers c++ , Command.FPrimeApp.commandFormat = case projectInputFiles project of+ [] -> fprimeAppFormat c+ ((_, f, _):_) -> f++ , Command.FPrimeApp.commandPropFormat = case projectInputFiles project of+ [] -> fprimeAppPropFormat c+ ((_, _, f):_) -> f++ , Command.FPrimeApp.commandPropVia =+ projectCommandPropVia project <|> fprimeAppPropVia c++ , Command.FPrimeApp.commandExtraVars =+ projectExtraJSONFile project <|> fprimeAppTemplateVars c++ }+ -- * CLI -- | FPrime command description@@ -92,6 +152,13 @@ commandOptsParser = CommandOpts <$> optional ( strOption+ ( long "project"+ <> metavar "FILENAME"+ <> help strFPrimeAppProjectArgDesc+ )+ )+ <*> optional+ ( strOption ( long "condition-expr" <> metavar "EXPRESSION" <> help strFPrimeAppConditionExprArgDesc@@ -170,6 +237,10 @@ ) ) +-- | Argument project to FPrime app generation command.+strFPrimeAppProjectArgDesc :: String+strFPrimeAppProjectArgDesc = "Project file"+ -- | Argument target directory to FPrime component generation command strFPrimeAppDirArgDesc :: String strFPrimeAppDirArgDesc = "Target directory"@@ -181,7 +252,8 @@ -- | Argument expression to FPrime app generation command. strFPrimeAppConditionExprArgDesc :: String-strFPrimeAppConditionExprArgDesc = "Expression used as guard or trigger condition"+strFPrimeAppConditionExprArgDesc =+ "Expression used as guard or trigger condition" -- | Argument input file to FPrime component generation command strFPrimeAppFileNameArgDesc :: String@@ -220,3 +292,7 @@ strFPrimeAppTemplateVarsArgDesc :: String strFPrimeAppTemplateVarsArgDesc = "JSON file containing additional variables to expand in template"++-- | Error code for when a project cannot be read.+cannotReadProject :: ErrorCode+cannotReadProject = 1
src/CLI/CommandOverview.hs view
@@ -32,14 +32,19 @@ -- External imports import Data.Aeson (toJSON)+import Data.Functor ((<&>))+import Data.List (dropWhileEnd) import qualified Data.Text.Lazy as T import qualified Data.Text.Lazy.IO as T-import Options.Applicative (Parser, help, long, metavar, optional,- short, showDefault, strOption, value)-import Text.Microstache+import Options.Applicative (Parser, help, long, many, metavar,+ optional, short, showDefault, strOption,+ value)+import Text.Microstache (compileMustacheText, renderMustache) --- External imports: command results+-- External imports: handling of input projects and command results import Command.Result ( Result(..) )+import Data.Location ( Location(..) )+import Data.Project ( Project (..), readProject ) -- External imports: actions or commands supported import Command.Overview (ErrorCode)@@ -49,61 +54,129 @@ -- | Options to generate an overview from the input specification(s). data CommandOpts = CommandOpts- { overviewInputFile :: FilePath- , overviewFormat :: String- , overviewPropFormat :: String- , overviewPropVia :: Maybe String+ { overviewProject :: Maybe String+ , overviewInputFiles :: [OverviewFile] } +-- | Options associated to a specific input file.+data OverviewFile = OverviewFile+ { overviewFilePath :: FilePath+ , overviewFileFormat :: String+ , overviewFilePropFormat :: String+ , overviewFilePropVia :: Maybe String+ }+ -- | Print an overview of the input specification(s). command :: CommandOpts -> IO (Result ErrorCode)-command c = do- (mOutput, result) <-- Command.Overview.command (overviewInputFile c) internalCommandOpts+command c+ | Just p <- overviewProject c+ = do optE <- commandProjectOptions p c+ case optE of+ Left msg -> return $ Error cannotReadProject msg (LocationFile p)+ Right opt -> do+ (mOutput, result) <- Command.Overview.command opt+ case mOutput of+ Just output ->+ case outputString of+ Right template -> T.putStr $ trimEnd+ $ renderMustache template (toJSON output)+ _ -> putStrLn "Error"+ _ -> putStrLn "Error"+ return result - case mOutput of- Just output ->- case outputString output of- Right template -> T.putStr $ renderMustache template (toJSON output)- _ -> putStrLn "Error"- _ -> putStrLn "Error"- return result+ | otherwise+ = do (mOutput, result) <-+ Command.Overview.command internalCommandOpts + case mOutput of+ Just output ->+ case outputString of+ Right template ->+ T.putStr $ trimEnd $ renderMustache template (toJSON output)+ _ -> putStrLn "Error"+ _ -> putStrLn "Error"+ return result+ where++ trimEnd :: T.Text -> T.Text+ trimEnd = T.unlines . dropWhileEnd T.null . T.lines+ internalCommandOpts :: Command.Overview.CommandOptions- internalCommandOpts = Command.Overview.CommandOptions- { Command.Overview.commandFormat = overviewFormat c- , Command.Overview.commandPropFormat = overviewPropFormat c- , Command.Overview.commandPropVia = overviewPropVia c+ internalCommandOpts = Command.Overview.CommandOptions $+ map fileInfo (overviewInputFiles c)++ fileInfo f = Command.Overview.OverviewFile+ { Command.Overview.overviewFilePath = overviewFilePath f+ , Command.Overview.overviewFileFormat = overviewFileFormat f+ , Command.Overview.overviewFilePropFormat = overviewFilePropFormat f+ , Command.Overview.overviewFilePropVia = overviewFilePropVia f } - outputString (Command.Overview.CommandSummaryRequirement {}) =+ outputString = compileMustacheText "output" $ T.unlines- [ "The requirements file has:"+ [ "{{#commandSummaryRequirements}}"+ , "The requirements file {{commandRequirementsFile}} has:" , " - {{commandExternalVariables}} external variables." , " - {{commandInternalVariables}} internal variables." , " - {{commandRequirements}} requirements."- , " - {{commandRequirementsTrue}} requirements are constantly or always true."- , " - {{commandRequirementsFalse}} requirements are constantly or always false."+ , " - {{commandRequirementsTrue}} requirements are constantly or "+ <> "always true."+ , " - {{commandRequirementsFalse}} requirements are constantly or "+ <> "always false." , "{{#commandRequirementsConsistent}}" , " - No inconsistencies detected in the requirements." , "{{/commandRequirementsConsistent}}" , "{{^commandRequirementsConsistent}}" , " - The requirements are not mutually consistent." , "{{/commandRequirementsConsistent}}"- ]- outputString (Command.Overview.CommandSummaryDiagram {}) =- compileMustacheText "output" $ T.unlines- [ "The diagram file:"- , " - Has {{commandNumStates}} states."- , "{{#commandDeterministic}}"+ , ""+ , "{{/commandSummaryRequirements}}"+ , "{{#commandSummaryDiagrams}}"+ , "The diagram file {{commandDiagramFile}}:"+ , " - Has {{commandDiagramNumStates}} states."+ , "{{#commandDiagramDeterministic}}" , " - Is deterministic."- , "{{/commandDeterministic}}"- , "{{^commandDeterministic}}"+ , "{{/commandDiagramDeterministic}}"+ , "{{^commandDiagramDeterministic}}" , " - Is not deterministic."- , "{{/commandDeterministic}}"+ , "{{/commandDiagramDeterministic}}"+ , ""+ , "{{/commandSummaryDiagrams}}" ] +-- | Produce command options based on project settings and user-provided+-- command options.+commandProjectOptions :: FilePath+ -> CommandOpts+ -> IO (Either String Command.Overview.CommandOptions)+commandProjectOptions projectFile c = do+ projectE <- readProject projectFile+ return $ projectE <&> \project ->+ Command.Overview.CommandOptions+ { Command.Overview.commandInputFiles = concat+ [ map (convertProjectFile project) $ projectInputFiles project+ , map convertInputFile $ overviewInputFiles c+ ]+ }++ where++ convertProjectFile project (fp, format, propFormat) =+ Command.Overview.OverviewFile+ { Command.Overview.overviewFilePath = fp+ , Command.Overview.overviewFileFormat = format+ , Command.Overview.overviewFilePropFormat = propFormat+ , Command.Overview.overviewFilePropVia =+ projectCommandPropVia project+ }+ convertInputFile f = Command.Overview.OverviewFile+ { Command.Overview.overviewFilePath = overviewFilePath f+ , Command.Overview.overviewFileFormat = overviewFileFormat f+ , Command.Overview.overviewFilePropFormat = overviewFilePropFormat f+ , Command.Overview.overviewFilePropVia = overviewFilePropVia f+ }+ -- * CLI -- | Command description for CLI help.@@ -114,6 +187,19 @@ -- of the input specifications. commandOptsParser :: Parser CommandOpts commandOptsParser = CommandOpts+ <$> optional+ ( strOption+ ( long "project"+ <> metavar "FILENAME"+ <> help strOverviewProjectArgDesc+ )+ )+ <*> many overviewFileOptsParser++-- | Subparser for information on one input file to be used with the @overview@+-- command.+overviewFileOptsParser :: Parser OverviewFile+overviewFileOptsParser = OverviewFile <$> strOption ( long "input-file" <> metavar "FILENAME"@@ -143,6 +229,10 @@ ) ) +-- | Project flag description.+strOverviewProjectArgDesc :: String+strOverviewProjectArgDesc = "Project file"+ -- | Input file flag description. strOverviewInputFileDesc :: String strOverviewInputFileDesc = "File with properties or requirements"@@ -159,3 +249,7 @@ strOverviewPropViaDesc :: String strOverviewPropViaDesc = "Command to pre-process individual properties"++-- | Error code for when a project cannot be read.+cannotReadProject :: ErrorCode+cannotReadProject = 1
src/CLI/CommandROSApp.hs view
@@ -30,11 +30,16 @@ where -- External imports+import Control.Applicative ( (<|>) )+import Data.Functor ( (<&>) )+import Data.Maybe ( fromMaybe ) import Options.Applicative ( Parser, help, long, metavar, many, optional, short, showDefault, strOption, value ) --- External imports: command results-import Command.Result ( Result )+-- External imports: handling of input projects and command results+import Command.Result ( Result (..) )+import Data.Location ( Location ( LocationFile ) )+import Data.Project ( Project (..), readProject ) -- External imports: actions or commands supported import Command.ROSApp (ErrorCode)@@ -44,19 +49,20 @@ -- | Options needed to generate the ROS application. data CommandOpts = CommandOpts- { rosAppConditionExpr :: Maybe String- , rosAppInputFiles :: [String]- , rosAppTarget :: String- , rosAppTemplateDir :: Maybe String- , rosAppVarNames :: Maybe String- , rosAppVarDB :: Maybe String- , rosAppHandlers :: Maybe String- , rosAppFormat :: String- , rosAppPropFormat :: String- , rosAppPropVia :: Maybe String- , rosAppTemplateVars :: Maybe String- , rosAppTestingApps :: [String]- , rosAppTestingVars :: [String]+ { rosAppProject :: Maybe String+ , rosAppConditionExpr :: Maybe String+ , rosAppInputFiles :: [String]+ , rosAppTarget :: String+ , rosAppTemplateDir :: Maybe String+ , rosAppVarNames :: Maybe String+ , rosAppVarDB :: Maybe String+ , rosAppHandlers :: Maybe String+ , rosAppFormat :: String+ , rosAppPropFormat :: String+ , rosAppPropVia :: Maybe String+ , rosAppTemplateVars :: Maybe String+ , rosAppTestingApps :: [String]+ , rosAppTestingVars :: [String] } -- | Create <https://www.ros.org/ Robot Operating System> (ROS) applications@@ -65,22 +71,30 @@ -- -- This is just a wrapper around "Command.ROSApp". command :: CommandOpts -> IO (Result ErrorCode)-command c = Command.ROSApp.command options+command c+ | Just p <- rosAppProject c+ = do optE <- commandProjectOptions p c+ case optE of+ Left msg -> return $ Error cannotReadProject msg (LocationFile p)+ Right opt -> Command.ROSApp.command opt++ | otherwise+ = Command.ROSApp.command options where options = Command.ROSApp.CommandOptions { Command.ROSApp.commandConditionExpr = rosAppConditionExpr c- , Command.ROSApp.commandInputFiles = rosAppInputFiles c- , Command.ROSApp.commandTargetDir = rosAppTarget c- , Command.ROSApp.commandTemplateDir = rosAppTemplateDir c- , Command.ROSApp.commandVariables = rosAppVarNames c- , Command.ROSApp.commandVariableDB = rosAppVarDB c- , Command.ROSApp.commandHandlers = rosAppHandlers c- , Command.ROSApp.commandFormat = rosAppFormat c- , Command.ROSApp.commandPropFormat = rosAppPropFormat c- , Command.ROSApp.commandPropVia = rosAppPropVia c- , Command.ROSApp.commandExtraVars = rosAppTemplateVars c- , Command.ROSApp.commandTestingApps = appNames- , Command.ROSApp.commandTestingVars = rosAppTestingVars c+ , Command.ROSApp.commandInputFiles = rosAppInputFiles c+ , Command.ROSApp.commandTargetDir = rosAppTarget c+ , Command.ROSApp.commandTemplateDir = rosAppTemplateDir c+ , Command.ROSApp.commandVariables = rosAppVarNames c+ , Command.ROSApp.commandVariableDB = rosAppVarDB c+ , Command.ROSApp.commandHandlers = rosAppHandlers c+ , Command.ROSApp.commandFormat = rosAppFormat c+ , Command.ROSApp.commandPropFormat = rosAppPropFormat c+ , Command.ROSApp.commandPropVia = rosAppPropVia c+ , Command.ROSApp.commandExtraVars = rosAppTemplateVars c+ , Command.ROSApp.commandTestingApps = appNames+ , Command.ROSApp.commandTestingVars = rosAppTestingVars c } -- Turn the qualified app names into tuples of package and node name.@@ -90,6 +104,66 @@ where (package, nodeT) = break (== ':') name +-- | Produce default command options based on project settings.+commandProjectOptions :: FilePath+ -> CommandOpts+ -> IO (Either String Command.ROSApp.CommandOptions)+commandProjectOptions projectFile c = do+ projectE <- readProject projectFile+ return $ projectE <&> \project ->+ Command.ROSApp.CommandOptions+ { Command.ROSApp.commandConditionExpr = rosAppConditionExpr c++ , Command.ROSApp.commandInputFiles = concat+ [ map (\(f, _, _) -> f) $ projectInputFiles project+ , rosAppInputFiles c+ ]++ , Command.ROSApp.commandTargetDir =+ fromMaybe (rosAppTarget c) (projectTargetDir project)++ , Command.ROSApp.commandTemplateDir =+ projectTemplateDir project <|> rosAppTemplateDir c++ , Command.ROSApp.commandVariables =+ projectVariableFiles project <|> rosAppVarNames c++ , Command.ROSApp.commandVariableDB =+ projectVariableDBFile project <|> rosAppVarDB c++ , Command.ROSApp.commandHandlers =+ projectHandlerFile project <|> rosAppHandlers c++ , Command.ROSApp.commandFormat = case projectInputFiles project of+ [] -> rosAppFormat c+ ((_, f, _):_) -> f++ , Command.ROSApp.commandPropFormat =+ case projectInputFiles project of+ [] -> rosAppPropFormat c+ ((_, _, f):_) -> f++ , Command.ROSApp.commandPropVia =+ projectCommandPropVia project <|> rosAppPropVia c++ , Command.ROSApp.commandExtraVars =+ projectExtraJSONFile project <|> rosAppTemplateVars c++ , Command.ROSApp.commandTestingApps = appNames++ , Command.ROSApp.commandTestingVars = rosAppTestingVars c++ }++ where++ -- Turn the qualified app names into tuples of package and node name.+ appNames = map splitAppName $ rosAppTestingApps c++ splitAppName name = Command.ROSApp.Node package (drop 1 nodeT)+ where+ (package, nodeT) = break (== ':') name+ -- * CLI -- | ROS command description@@ -102,6 +176,13 @@ commandOptsParser = CommandOpts <$> optional ( strOption+ ( long "project"+ <> metavar "FILENAME"+ <> help strROSAppProjectArgDesc+ )+ )+ <*> optional+ ( strOption ( long "condition-expr" <> metavar "EXPRESSION" <> help strROSAppConditionExprArgDesc@@ -193,6 +274,10 @@ ) ) +-- | Argument project to ROS app generation command.+strROSAppProjectArgDesc :: String+strROSAppProjectArgDesc = "Project file"+ -- | Argument target directory to ROS app generation command strROSAppDirArgDesc :: String strROSAppDirArgDesc = "Target directory"@@ -247,9 +332,13 @@ -- | Argument packages to tested list to ROS app generation command strROSAppROSNodesTestingListArgDesc :: String strROSAppROSNodesTestingListArgDesc =- "Turn on ROS2 package node during testing"+ "Turn on ROS 2 package node during testing" -- | Argument variables to be tested list to ROS app generation command strROSAppVarsTestingListArgDesc :: String strROSAppVarsTestingListArgDesc = "Limit random input generation to these variables"++-- | Error code for when a project cannot be read.+cannotReadProject :: ErrorCode+cannotReadProject = 1
src/CLI/CommandReport.hs view
@@ -43,11 +43,16 @@ where -- External imports-import Options.Applicative (Parser, help, long, metavar, optional, short,+import Control.Applicative ((<|>))+import Data.Functor ((<&>))+import Data.Maybe (fromMaybe)+import Options.Applicative (Parser, help, long, many, metavar, optional, short, showDefault, strOption, value) --- External imports: command results+-- External imports: handling of input projects and command results import Command.Result (Result (..))+import Data.Location (Location (LocationFile))+import Data.Project (Project (..), readProject) -- External imports: actions or commands supported import Command.Report (ErrorCode)@@ -57,33 +62,76 @@ -- | Options to generate Copilot from specification. data CommandOpts = CommandOpts- { commandTargetDir :: FilePath -- ^ Target directory where the+ { commandProject :: Maybe String -- ^ Project file.+ , commandTargetDir :: FilePath -- ^ Target directory where the -- reoprt should be created. , commandTemplateDir :: Maybe FilePath -- ^ Directory where the template -- is to be found.- , commandFileName :: FilePath- , commandFormat :: String- , commandPropFormat :: String- , commandPropVia :: Maybe String+ , commandInputFiles :: [ReportFile] } +-- | Options associated to a specific input file.+data ReportFile = ReportFile+ { reportFilePath :: FilePath+ , reportFileFormat :: String+ , reportFilePropFormat :: String+ , reportFilePropVia :: Maybe String+ }+ -- | Generate a report of the input specification(s). command :: CommandOpts -- ^ Customization options -> IO (Result ErrorCode)-command options = do- Command.Report.command internalCommandOpts+command options+ | Just p <- commandProject options+ = do optE <- commandProjectOptions p options+ case optE of+ Left msg -> return $ Error cannotReadProject msg (LocationFile p)+ Right opt -> Command.Report.command opt + | otherwise+ = Command.Report.command internalCommandOpts+ where internalCommandOpts :: Command.Report.CommandOptions internalCommandOpts = Command.Report.CommandOptions { Command.Report.commandTargetDir = commandTargetDir options , Command.Report.commandTemplateDir = commandTemplateDir options- , Command.Report.commandInputFile = commandFileName options- , Command.Report.commandFormat = commandFormat options- , Command.Report.commandPropFormat = commandPropFormat options- , Command.Report.commandPropVia = commandPropVia options+ , Command.Report.commandInputFiles =+ map argumentToReportFile $ commandInputFiles options } +-- | Produce default command options based on project settings.+commandProjectOptions :: FilePath+ -> CommandOpts+ -> IO (Either String Command.Report.CommandOptions)+commandProjectOptions projectFile c = do+ projectE <- readProject projectFile+ return $ projectE <&> \project ->++ let projectToReportFile (fp, c1, c2) =+ Command.Report.ReportFile fp c1 c2 (projectCommandPropVia project)++ in Command.Report.CommandOptions+ { Command.Report.commandTargetDir =+ fromMaybe (commandTargetDir c) (projectTargetDir project)+ , Command.Report.commandTemplateDir =+ projectTemplateDir project <|> commandTemplateDir c+ , Command.Report.commandInputFiles = concat+ [ map projectToReportFile $ projectInputFiles project+ , map argumentToReportFile $ commandInputFiles c+ ]+ }++-- | Convert an input argument file into an internal+-- 'Command.Report.ReportFile'.+argumentToReportFile :: ReportFile -> Command.Report.ReportFile+argumentToReportFile f = Command.Report.ReportFile+ { Command.Report.reportFilePath = reportFilePath f+ , Command.Report.reportFileFormat = reportFileFormat f+ , Command.Report.reportFilePropFormat = reportFilePropFormat f+ , Command.Report.reportFilePropVia = reportFilePropVia f+ }+ -- * CLI -- | Command description for CLI help.@@ -94,7 +142,14 @@ -- specification from an input specification file. commandOptsParser :: Parser CommandOpts commandOptsParser = CommandOpts- <$> strOption+ <$> optional+ ( strOption+ ( long "project"+ <> metavar "FILENAME"+ <> help strReportProjectArgDesc+ )+ )+ <*> strOption ( long "target-dir" <> metavar "DIR" <> showDefault@@ -108,10 +163,16 @@ <> help strReportTemplateDirArgDesc ) )- <*> strOption- ( long "file-name"+ <*> many reportFileOptsParser++-- | Subparser for information on one input file to be used with the @report@+-- command.+reportFileOptsParser :: Parser ReportFile+reportFileOptsParser = ReportFile+ <$> strOption+ ( long "input-file" <> metavar "FILENAME"- <> help strReportFilenameDesc+ <> help strReportInputFileDesc ) <*> strOption ( long "input-format"@@ -137,6 +198,10 @@ ) ) +-- | Project flag description.+strReportProjectArgDesc :: String+strReportProjectArgDesc = "Project file"+ -- | Target dir flag description. strReportTargetDirDesc :: String strReportTargetDirDesc = "Target directory"@@ -145,9 +210,9 @@ strReportTemplateDirArgDesc :: String strReportTemplateDirArgDesc = "Directory holding report template" --- | Filename flag description.-strReportFilenameDesc :: String-strReportFilenameDesc = "File with properties, requirements or a diagram"+-- | Input file flag description.+strReportInputFileDesc :: String+strReportInputFileDesc = "File with properties, requirements or a diagram" -- | Format flag description. strReportFormatDesc :: String@@ -160,3 +225,7 @@ -- | External command to pre-process individual properties. strReportPropViaDesc :: String strReportPropViaDesc = "Command to pre-process individual properties"++-- | Error code for when a project cannot be read.+cannotReadProject :: ErrorCode+cannotReadProject = 1
+ src/CLI/CommandSearch.hs view
@@ -0,0 +1,243 @@+{-# LANGUAGE OverloadedStrings #-}+-- Copyright 2020 United States Government as represented by the Administrator+-- of the National Aeronautics and Space Administration. All Rights Reserved.+--+-- Disclaimers+--+-- Licensed under the Apache License, Version 2.0 (the "License"); you may+-- not use this file except in compliance with the License. You may obtain a+-- copy of the License at+--+-- https://www.apache.org/licenses/LICENSE-2.0+--+-- Unless required by applicable law or agreed to in writing, software+-- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT+-- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the+-- License for the specific language governing permissions and limitations+-- under the License.+--+-- | CLI interface to the Search subcommand.+module CLI.CommandSearch+ (+ -- * Direct command access+ command+ , CommandOpts+ , ErrorCode++ -- * CLI+ , commandDesc+ , commandOptsParser+ )+ where++-- External imports+import Data.Aeson (toJSON)+import Data.Functor ((<&>))+import qualified Data.Text.Lazy as T+import qualified Data.Text.Lazy.IO as T+import Options.Applicative (Parser, help, long, many, metavar,+ optional, short, showDefault, strOption,+ value)+import Text.Microstache (compileMustacheText, renderMustache)++-- External imports: handling of input projects and command results+import Command.Result (Result (..))+import Data.Location (Location (..))+import Data.Project (Project (..), readProject)++-- External imports: actions or commands supported+import Command.Search (ErrorCode)+import qualified Command.Search++-- * Command++-- | Options to generate an search from the input specification(s).+data CommandOpts = CommandOpts+ { searchProject :: Maybe String+ , searchQuery :: String+ , searchInputFiles :: [SearchFile]+ }++-- | Options associated to a specific input file.+data SearchFile = SearchFile+ { searchFilePath :: FilePath+ , searchFileFormat :: String+ , searchFilePropFormat :: String+ , searchFilePropVia :: Maybe String+ }++-- | Print an search of the input specification(s).+command :: CommandOpts -> IO (Result ErrorCode)+command c+ | Just p <- searchProject c+ = do optE <- commandProjectOptions p c+ case optE of+ Left msg -> return $ Error cannotReadProject msg (LocationFile p)+ Right opt -> do+ (mOutput, result) <- Command.Search.command opt+ case mOutput of+ Just output ->+ case outputString of+ Right template ->+ T.putStr $ renderMustache template (toJSON output)+ _ -> putStrLn "Error"+ _ -> putStrLn "Error"+ return result++ | otherwise+ = do (mOutput, result) <-+ Command.Search.command internalCommandOpts++ case mOutput of+ Just output ->+ case outputString of+ Right template ->+ T.putStr $ renderMustache template (toJSON output)+ _ -> putStrLn "Error"+ _ -> putStrLn "Error"+ return result++ where++ internalCommandOpts :: Command.Search.CommandOptions+ internalCommandOpts = Command.Search.CommandOptions+ { Command.Search.commandInputFiles = map fileInfo (searchInputFiles c)+ , Command.Search.commandSearchQuery = searchQuery c+ }++ fileInfo f = Command.Search.SearchFile+ { Command.Search.searchFilePath = searchFilePath f+ , Command.Search.searchFileFormat = searchFileFormat f+ , Command.Search.searchFilePropFormat = searchFilePropFormat f+ , Command.Search.searchFilePropVia = searchFilePropVia f+ }++ outputString =+ compileMustacheText "output" $ T.unlines+ [ "{{#searchResultRequirements}}"+ , "{{requirementInfoLocation}}: requirement "+ <> "\"{{requirementInfoName}}\" matches"+ , "{{/searchResultRequirements}}"+ , "{{#searchResultDiagrams}}"+ , "{{diagramInfoLocation}}: diagram file matches"+ , "{{/searchResultDiagrams}}"+ ]++-- | Produce command options based on project settings and user-provided+-- command options.+commandProjectOptions :: FilePath+ -> CommandOpts+ -> IO (Either String Command.Search.CommandOptions)+commandProjectOptions projectFile c = do+ projectE <- readProject projectFile+ return $ projectE <&> \project ->+ Command.Search.CommandOptions+ { Command.Search.commandInputFiles = concat+ [ map (convertProjectFile project) $ projectInputFiles project+ , map convertInputFile $ searchInputFiles c+ ]+ , Command.Search.commandSearchQuery = searchQuery c+ }++ where++ convertProjectFile project (fp, format, propFormat) =+ Command.Search.SearchFile+ { Command.Search.searchFilePath = fp+ , Command.Search.searchFileFormat = format+ , Command.Search.searchFilePropFormat = propFormat+ , Command.Search.searchFilePropVia =+ projectCommandPropVia project+ }+ convertInputFile f = Command.Search.SearchFile+ { Command.Search.searchFilePath = searchFilePath f+ , Command.Search.searchFileFormat = searchFileFormat f+ , Command.Search.searchFilePropFormat = searchFilePropFormat f+ , Command.Search.searchFilePropVia = searchFilePropVia f+ }++-- * CLI++-- | Command description for CLI help.+commandDesc :: String+commandDesc = "List items that match search query"++-- | Subparser for the @search@ command, used to generate an search+-- of the input specifications.+commandOptsParser :: Parser CommandOpts+commandOptsParser = CommandOpts+ <$> optional+ ( strOption+ ( long "project"+ <> metavar "FILENAME"+ <> help strSearchProjectArgDesc+ )+ )+ <*> strOption+ ( long "query"+ <> metavar "STRING"+ <> help strSearchQueryArgDesc+ )+ <*> many searchFileOptsParser++-- | Subparser for information on one input file to be used with the @search@+-- command.+searchFileOptsParser :: Parser SearchFile+searchFileOptsParser = SearchFile+ <$> strOption+ ( long "input-file"+ <> metavar "FILENAME"+ <> help strSearchInputFileDesc+ )+ <*> strOption+ ( long "input-format"+ <> short 'f'+ <> metavar "FORMAT_NAME"+ <> help strSearchFormatDesc+ <> showDefault+ <> value "fcs"+ )+ <*> strOption+ ( long "prop-format"+ <> short 'p'+ <> metavar "FORMAT_NAME"+ <> help strSearchPropFormatDesc+ <> showDefault+ <> value "smv"+ )+ <*> optional+ ( strOption+ ( long "parse-prop-via"+ <> metavar "COMMAND"+ <> help strSearchPropViaDesc+ )+ )++-- | Project flag description.+strSearchProjectArgDesc :: String+strSearchProjectArgDesc = "Project file"++-- | Query flag description.+strSearchQueryArgDesc :: String+strSearchQueryArgDesc = "Search string"++-- | Input file flag description.+strSearchInputFileDesc :: String+strSearchInputFileDesc = "File with properties or requirements"++-- | Format flag description.+strSearchFormatDesc :: String+strSearchFormatDesc = "Format of the input file"++-- | Property format flag description.+strSearchPropFormatDesc :: String+strSearchPropFormatDesc = "Format of temporal or boolean properties"++-- | External command to pre-process individual properties.+strSearchPropViaDesc :: String+strSearchPropViaDesc =+ "Command to pre-process individual properties"++-- | Error code for when a project cannot be read.+cannotReadProject :: ErrorCode+cannotReadProject = 1
src/CLI/CommandStandalone.hs view
@@ -30,12 +30,16 @@ where -- External imports+import Control.Applicative ((<|>))+import Data.Functor ((<&>))+import Data.Maybe (fromMaybe) import Options.Applicative (Parser, help, long, many, metavar, optional, short,- showDefault, strOption, switch, value)+ showDefault, strOption, value) --- External imports: command results+-- External imports: handling of input projects and command results import Command.Result ( Result(..) ) import Data.Location ( Location(..) )+import Data.Project ( Project (..), readProject ) -- External imports: actions or commands supported import Command.Standalone (ErrorCode)@@ -45,40 +49,96 @@ -- | Options to generate Copilot from specification. data CommandOpts = CommandOpts- { standaloneTargetDir :: FilePath- , standaloneTemplateDir :: Maybe FilePath- , standaloneConditionExpr :: Maybe String- , standaloneInputFiles :: [FilePath]- , standaloneFormat :: String- , standalonePropFormat :: String- , standaloneTypes :: [String]- , standaloneTarget :: String- , standalonePropVia :: Maybe String- , standaloneTemplateVars :: Maybe String+ { standaloneProject :: Maybe String+ , standaloneTargetDir :: FilePath+ , standaloneTemplateDir :: Maybe FilePath+ , standaloneConditionExpr :: Maybe String+ , standaloneInputFiles :: [FilePath]+ , standaloneFormat :: String+ , standalonePropFormat :: String+ , standaloneTypes :: [String]+ , standaloneTarget :: String+ , standalonePropVia :: Maybe String+ , standaloneTemplateVars :: Maybe String } -- | Transform an input specification into a Copilot specification. command :: CommandOpts -> IO (Result ErrorCode)-command c =- Command.Standalone.command internalCommandOpts+command c+ | Just p <- standaloneProject c+ = do optE <- commandProjectOptions p c+ case optE of+ Left msg -> return $ Error cannotReadProject msg (LocationFile p)+ Right opt -> Command.Standalone.command opt++ | otherwise+ = Command.Standalone.command internalCommandOpts where internalCommandOpts :: Command.Standalone.CommandOptions internalCommandOpts = Command.Standalone.CommandOptions { Command.Standalone.commandConditionExpr = standaloneConditionExpr c- , Command.Standalone.commandInputFiles = standaloneInputFiles c- , Command.Standalone.commandTargetDir = standaloneTargetDir c- , Command.Standalone.commandTemplateDir = standaloneTemplateDir c- , Command.Standalone.commandFormat = standaloneFormat c- , Command.Standalone.commandPropFormat = standalonePropFormat c- , Command.Standalone.commandTypeMapping = types- , Command.Standalone.commandFilename = standaloneTarget c- , Command.Standalone.commandPropVia = standalonePropVia c- , Command.Standalone.commandExtraVars = standaloneTemplateVars c+ , Command.Standalone.commandInputFiles = standaloneInputFiles c+ , Command.Standalone.commandTargetDir = standaloneTargetDir c+ , Command.Standalone.commandTemplateDir = standaloneTemplateDir c+ , Command.Standalone.commandFormat = standaloneFormat c+ , Command.Standalone.commandPropFormat = standalonePropFormat c+ , Command.Standalone.commandTypeMapping = types+ , Command.Standalone.commandFilename = standaloneTarget c+ , Command.Standalone.commandPropVia = standalonePropVia c+ , Command.Standalone.commandExtraVars = standaloneTemplateVars c } types :: [(String, String)]- types = map splitTypeMapping (standaloneTypes c)+ types = typeMapping (standaloneTypes c) +-- | Produce command options based on project settings and user-provided+-- command options.+commandProjectOptions :: FilePath+ -> CommandOpts+ -> IO (Either String Command.Standalone.CommandOptions)+commandProjectOptions projectFile c = do+ projectE <- readProject projectFile+ return $ projectE <&> \project ->+ Command.Standalone.CommandOptions+ { Command.Standalone.commandConditionExpr = standaloneConditionExpr c++ , Command.Standalone.commandInputFiles = concat+ [ map (\(f, _, _) -> f) $ projectInputFiles project+ , standaloneInputFiles c+ ]++ , Command.Standalone.commandTargetDir =+ fromMaybe (standaloneTargetDir c) (projectTargetDir project)++ , Command.Standalone.commandTemplateDir =+ projectTemplateDir project <|> standaloneTemplateDir c++ , Command.Standalone.commandFormat =+ case projectInputFiles project of+ [] -> standaloneFormat c+ ((_, f, _):_) -> f++ , Command.Standalone.commandPropFormat =+ case projectInputFiles project of+ [] -> standalonePropFormat c+ ((_, _, f):_) -> f++ , Command.Standalone.commandPropVia =+ projectCommandPropVia project <|> standalonePropVia c++ , Command.Standalone.commandExtraVars =+ projectExtraJSONFile project <|> standaloneTemplateVars c++ , Command.Standalone.commandFilename = standaloneTarget c++ , Command.Standalone.commandTypeMapping = typeMapping (standaloneTypes c)++ }++-- | Parse a list of type associations, where two types are separated by ':'.+typeMapping :: [String] -> [(String, String)]+typeMapping = map splitTypeMapping+ where splitTypeMapping :: String -> (String, String) splitTypeMapping s = (h, safeTail t) where@@ -96,7 +156,14 @@ -- specification from an input specification file. commandOptsParser :: Parser CommandOpts commandOptsParser = CommandOpts- <$> strOption+ <$> optional+ ( strOption+ ( long "project"+ <> metavar "FILENAME"+ <> help strStandaloneProjectArgDesc+ )+ )+ <*> strOption ( long "target-dir" <> metavar "DIR" <> showDefault@@ -169,6 +236,10 @@ ) ) +-- | Project flag description.+strStandaloneProjectArgDesc :: String+strStandaloneProjectArgDesc = "Project file"+ -- | Target dir flag description. strStandaloneTargetDirDesc :: String strStandaloneTargetDirDesc = "Target directory"@@ -212,3 +283,7 @@ strStandaloneTemplateVarsArgDesc :: String strStandaloneTemplateVarsArgDesc = "JSON file containing additional variables to expand in template"++-- | Error code for when a project cannot be read.+cannotReadProject :: ErrorCode+cannotReadProject = 1
src/CLI/CommandTop.hs view
@@ -81,6 +81,7 @@ import qualified CLI.CommandOverview import qualified CLI.CommandReport import qualified CLI.CommandROSApp+import qualified CLI.CommandSearch import qualified CLI.CommandStandalone -- * Command@@ -91,15 +92,16 @@ -- @CommandOpts@ to capture their respective arguments. These types are -- different for each subcommand. data CommandOpts =- CommandOptsCFSApp CLI.CommandCFSApp.CommandOpts- | CommandOptsCStructs2Copilot CLI.CommandCStructs2Copilot.CommandOpts- | CommandOptsCStructs2MsgHandlers CLI.CommandCStructs2MsgHandlers.CommandOpts- | CommandOptsDiagram CLI.CommandDiagram.CommandOpts- | CommandOptsFPrimeApp CLI.CommandFPrimeApp.CommandOpts- | CommandOptsOverview CLI.CommandOverview.CommandOpts- | CommandOptsROSApp CLI.CommandROSApp.CommandOpts- | CommandOptsStandalone CLI.CommandStandalone.CommandOpts- | CommandOptsReport CLI.CommandReport.CommandOpts+ CommandOptsCFSApp CLI.CommandCFSApp.CommandOpts+ | CommandOptsCStructs2Copilot CLI.CommandCStructs2Copilot.CommandOpts+ | CommandOptsCStructs2MsgHandlers CLI.CommandCStructs2MsgHandlers.CommandOpts+ | CommandOptsDiagram CLI.CommandDiagram.CommandOpts+ | CommandOptsFPrimeApp CLI.CommandFPrimeApp.CommandOpts+ | CommandOptsOverview CLI.CommandOverview.CommandOpts+ | CommandOptsROSApp CLI.CommandROSApp.CommandOpts+ | CommandOptsSearch CLI.CommandSearch.CommandOpts+ | CommandOptsStandalone CLI.CommandStandalone.CommandOpts+ | CommandOptsReport CLI.CommandReport.CommandOpts -- * CLI @@ -112,6 +114,7 @@ commandOptsParser :: Parser CommandOpts commandOptsParser = subparser ( subcommandOverview+ <> subcommandSearch <> subcommandCStructs <> subcommandMsgHandlers <> subcommandCFSApp@@ -131,6 +134,15 @@ (CommandOptsOverview <$> CLI.CommandOverview.commandOptsParser) CLI.CommandOverview.commandDesc +-- | Modifier for the search subcommand, linking the subcommand options and+-- description to the command @search@ at top level.+subcommandSearch :: Mod CommandFields CommandOpts+subcommandSearch =+ subcommand+ "search"+ (CommandOptsSearch <$> CLI.CommandSearch.commandOptsParser)+ CLI.CommandSearch.commandDesc+ -- | Modifier for the CStruct to Copilot Struct generation subcommand, linking -- the subcommand options and description to the command @structs@ at top -- level.@@ -240,6 +252,8 @@ id <$> CLI.CommandOverview.command c command (CommandOptsROSApp c) = id <$> CLI.CommandROSApp.command c+command (CommandOptsSearch c) =+ id <$> CLI.CommandSearch.command c command (CommandOptsStandalone c) = id <$> CLI.CommandStandalone.command c command (CommandOptsDiagram c) =
src/CLI/Result.hs view
@@ -41,4 +41,5 @@ showLocation LocationNothing = "<no location info>: " showLocation (LocationFile f) = f ++ ": " showLocation (LocationFileLine f l) = f ++ ":" ++ show l ++ ": "- showLocation (LocationFileLC f l c) = f ++ ":" ++ show l ++ ":" ++ show c ++ ": "+ showLocation (LocationFileLC f l c) =+ f ++ ":" ++ show l ++ ":" ++ show c ++ ": "
src/Main.hs view
@@ -15,14 +15,14 @@ -- License for the specific language governing permissions and limitations -- under the License. ----- | Ogma: Tool to interoperate between <https://cfs.gsfc.nasa.gov/ Copilot>--- and other languages.+-- | Ogma: Tool to interoperate between+-- <https://github.com/Copilot-Language/copilot Copilot> and other languages. -- -- Ogma is a tool to facilitate integration of safe runtime monitors into other -- systems. It takes information from a system created in a language (e.g., -- Lustre) and produces specifications for the runtime verification--- framework <https://cfs.gsfc.nasa.gov/ Copilot>. Currently, features--- supported are:+-- framework <https://github.com/Copilot-Language/copilot Copilot>. Currently,+-- features supported are: -- -- * Translation properties defined in structured natural language into -- corresponding expressions in Copilot.