packages feed

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 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.