Repository: jacobdeichert/mask (language: rust)

Issue:
Don't add a command for a heading that has no code blocks
When a heading has no code blocks AND its child headings have no code blocks, then we shouldn't create a command for it.

### Example:

```md
# MY COMMANDS

## Docs

Just some documentation.

## cmd
~~~bash
echo something
~~~
```

### Current Behaviour

`mask -h`

```bash
mask 0.8.0

USAGE:
    mask [OPTIONS] <SUBCOMMAND>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --maskfile <maskfile>    Path to a different maskfile you want to use

SUBCOMMANDS:
    Docs        
    cmd
```

### Desired Behaviour

`mask -h`

```bash
mask 0.8.0

USAGE:
    mask [OPTIONS] <SUBCOMMAND>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --maskfile <maskfile>    Path to a different maskfile you want to use

SUBCOMMANDS:
    cmd
```


Discussion / hints:

Fix patch:
diff --git a/src/command.rs b/src/command.rs
index fcaf0e3..866c903 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -57,7 +57,7 @@ impl Script {
     }
 
     pub fn has_script(&self) -> bool {
-        self.source != "" && self.executor != ""
+        !self.source.is_empty()
     }
 }
 
diff --git a/src/parser.rs b/src/parser.rs
index f81aa9b..b150e25 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -200,6 +200,10 @@ fn treeify_commands(commands: Vec<Command>) -> Vec<Command> {
         }
     }
 
+    // the command or any one of its subcommands must have script to be included in the tree
+    // root level commands must be retained
+    command_tree.retain(|c| c.script.has_script() || !c.subcommands.is_empty() || c.cmd_level == 1);
+
     command_tree
 }
 
@@ -375,14 +379,13 @@ mod build_command_structure {
     }
 
     #[test]
-    fn does_not_add_verbose_optional_flag_to_command_with_no_script() {
+    fn does_not_add_command_with_no_script() {
         let tree = build_command_structure(TEST_MASKFILE.to_string());
-        let no_script_command = tree
-            .subcommands
-            .iter()
-            .find(|cmd| cmd.name == "no_script")
-            .expect("no_script command missing");
+        let no_script_command = tree.subcommands.iter().find(|cmd| cmd.name == "no_script");
 
-        assert_eq!(no_script_command.option_flags.len(), 0);
+        assert!(
+            no_script_command.is_none(),
+            "no_script command should not exist"
+        )
     }
 }


Test patch:
diff --git a/tests/arguments_and_flags_test.rs b/tests/arguments_and_flags_test.rs
index 0b66c8f..dc2f5ad 100644
--- a/tests/arguments_and_flags_test.rs
+++ b/tests/arguments_and_flags_test.rs
@@ -351,7 +351,15 @@ mod version_flag {
 
     #[test]
     fn exits_with_error_when_subcommand_has_version_flag() {
-        let (_temp, maskfile_path) = common::maskfile("## foo");
+        let (_temp, maskfile_path) = common::maskfile(
+            r#"
+## foo
+
+~~~bash
+echo "This subcommand should exist"
+~~~
+"#,
+        );
 
         // The setting "VersionlessSubcommands" removes the version flags (-V, --version)
         // from subcommands. Only the root command has a version flag.
diff --git a/tests/subcommands_test.rs b/tests/subcommands_test.rs
index 921b706..473df56 100644
--- a/tests/subcommands_test.rs
+++ b/tests/subcommands_test.rs
@@ -61,6 +61,10 @@ fn exits_with_error_when_missing_subcommand() {
         r#"
 ## service
 ### service start
+
+~~~bash
+echo "subcommand should exist"
+~~~
 "#,
     );
 
@@ -102,23 +106,4 @@ echo "system, online"
             )))
             .failure();
     }
-
-    #[test]
-    fn exits_with_error_when_it_has_no_subcommands() {
-        let (_temp, maskfile_path) = common::maskfile(
-            r#"
-## start
-"#,
-        );
-
-        common::run_mask(&maskfile_path)
-            .command("start")
-            .assert()
-            .code(1)
-            .stderr(contains(format!(
-                "{} Command has no script.",
-                "ERROR:".red()
-            )))
-            .failure();
-    }
 }