Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BREAKING CHANGE: Change required arg syntax #16

Merged
merged 4 commits into from
Jul 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ readme = "README.md"
keywords = ["cli", "task", "command", "make", "markdown"]
categories = ["command-line-interface", "command-line-utilities", "development-tools::build-utils", "parser-implementations"]
edition = "2018"
exclude = ["maskfile.md", ".gitignore", "CHANGELOG.md", "test/**"]
exclude = ["maskfile.md", ".gitignore", "CHANGELOG.md", "test/**", ".circleci/**"]
license = "MIT"

[lib]
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ mask test

### Positional arguments

These are defined beside the command name within `<angle_brackets>`. They are required arguments that must be supplied for the command to run. [Optional args][2] are coming soon. The argument name is injected into the script's scope as an environment variable.
These are defined beside the command name within `(round_brackets)`. They are required arguments that must be supplied for the command to run. [Optional args][2] are coming soon. The argument name is injected into the script's scope as an environment variable.

**Example:**

```markdown
## test <file> <test_case>
## test (file) (test_case)

> Run tests

Expand Down Expand Up @@ -129,15 +129,15 @@ Nested command structures can easily be created since they are simply defined by

> Commands related to starting, stopping, and restarting services

### services start <service_name>
### services start (service_name)

> Start a service.

~~~bash
echo "Starting service $service_name"
~~~

### services stop <service_name>
### services stop (service_name)

> Stop a service.

Expand All @@ -161,7 +161,7 @@ On top of shell/bash scripts, `mask` also supports using node, python, ruby and
**Example:**

```markdown
## shell <name>
## shell (name)

> An example shell script

Expand All @@ -173,19 +173,19 @@ echo "Hello, $name!"
~~~


## node <name>
## node (name)

> An example node script

Valid lang codes: js, javascript

~~~js
const { name } = process.env;
console.log(`Hello, ${name}!`)
console.log(`Hello, ${name}!`);
~~~


## python <name>
## python (name)

> An example python script

Expand All @@ -200,7 +200,7 @@ print("Hello, " + name + "!")
~~~


## ruby <name>
## ruby (name)

> An example ruby script

Expand All @@ -213,7 +213,7 @@ puts "Hello, #{name}!"
~~~


## php <name>
## php (name)

> An example php script

Expand Down
2 changes: 1 addition & 1 deletion maskfile.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@



## run <maskfile_command>
## run (maskfile_command)

> Build and run mask in development mode

Expand Down
106 changes: 101 additions & 5 deletions src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use pulldown_cmark::{
Event::{End, InlineHtml, Start, Text},
Event::{Code, End, InlineHtml, Start, Text},
Options, Parser, Tag,
};

Expand Down Expand Up @@ -112,6 +112,9 @@ pub fn build_command_structure(maskfile_contents: String) -> Command {
InlineHtml(html) => {
text += &html.to_string();
}
Code(inline_code) => {
text += &format!("`{}`", inline_code);
}
_ => (),
};
}
Expand Down Expand Up @@ -183,8 +186,8 @@ fn parse_command_name_and_required_args(
// and level 2 can't be a subcommand so no need to split.
let name = if heading_level > 2 {
// Takes a subcommand name like this:
// "#### db flush postgres <required_arg>"
// and returns "postgres <required_arg>" as the actual name
// "#### db flush postgres (required_arg_name)"
// and returns "postgres (required_arg_name)" as the actual name
text.clone()
.split(" ")
.collect::<Vec<&str>>()
Expand All @@ -196,8 +199,8 @@ fn parse_command_name_and_required_args(
text.clone()
};

// Find any required arguments. They look like this: <required_arg_name>
let name_and_args: Vec<&str> = name.split(|c| c == '<' || c == '>').collect();
// Find any required arguments. They look like this: (required_arg_name)
let name_and_args: Vec<&str> = name.split(|c| c == '(' || c == ')').collect();
let (name, args) = name_and_args.split_at(1);
let name = name.join(" ").trim().to_string();
let mut required_args: Vec<RequiredArg> = vec![];
Expand All @@ -215,3 +218,96 @@ fn parse_command_name_and_required_args(

(name, required_args)
}

#[cfg(test)]
const TEST_MASKFILE: &str = r#"
# Document Title

This is an example maskfile for the tests below.

## serve (port)

> Serve the app on the `port`

~~~bash
echo "Serving on port $port"
~~~

## node (name)

> An example node script

Valid lang codes: js, javascript

```js
const { name } = process.env;
console.log(`Hello, ${name}!`);
```
"#;

#[cfg(test)]
mod build_command_structure {
use super::*;

#[test]
fn parses_serve_command_name() {
let tree = build_command_structure(TEST_MASKFILE.to_string());
let serve_command = &tree.subcommands[0];
assert_eq!(serve_command.name, "serve");
}

#[test]
fn parses_serve_command_description() {
let tree = build_command_structure(TEST_MASKFILE.to_string());
let serve_command = &tree.subcommands[0];
assert_eq!(serve_command.desc, "Serve the app on the `port`");
}

#[test]
fn parses_serve_required_positional_arguments() {
let tree = build_command_structure(TEST_MASKFILE.to_string());
let serve_command = &tree.subcommands[0];
assert_eq!(serve_command.required_args.len(), 1);
assert_eq!(serve_command.required_args[0].name, "port");
}

#[test]
fn adds_default_verbose_optional_flag() {
let tree = build_command_structure(TEST_MASKFILE.to_string());
let serve_command = &tree.subcommands[0];
assert_eq!(serve_command.option_flags.len(), 1);
assert_eq!(serve_command.option_flags[0].name, "verbose");
assert_eq!(
serve_command.option_flags[0].desc,
"Sets the level of verbosity"
);
assert_eq!(serve_command.option_flags[0].short, "v");
assert_eq!(serve_command.option_flags[0].long, "verbose");
assert_eq!(serve_command.option_flags[0].multiple, false);
assert_eq!(serve_command.option_flags[0].takes_value, false);
}

#[test]
fn parses_serve_command_executor() {
let tree = build_command_structure(TEST_MASKFILE.to_string());
let serve_command = &tree.subcommands[0];
assert_eq!(serve_command.executor, "bash");
}

#[test]
fn parses_serve_command_source_with_tildes() {
let tree = build_command_structure(TEST_MASKFILE.to_string());
let serve_command = &tree.subcommands[0];
assert_eq!(serve_command.source, "echo \"Serving on port $port\"\n");
}

#[test]
fn parses_node_command_source_with_backticks() {
let tree = build_command_structure(TEST_MASKFILE.to_string());
let node_command = &tree.subcommands[1];
assert_eq!(
node_command.source,
"const { name } = process.env;\nconsole.log(`Hello, ${name}!`);\n"
);
}
}
16 changes: 8 additions & 8 deletions test/maskfile.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<!-- Cmd description goes here. -->
> Commands related to starting, stopping, and restarting services
### services start <service_name>
### services start (service_name)

> Start or restart a service.
Expand All @@ -20,7 +20,7 @@ echo "Starting service $service_name"
~~~


### services stop <service_name>
### services stop (service_name)

> Stop a service.
Expand Down Expand Up @@ -65,15 +65,15 @@ echo "Flushed postgres"
echo "Flushed redis"
~~~

### db snapshot <snapshot_name>
### db snapshot (snapshot_name)

> Take a snapshot of the database.
~~~bash
echo "Saved db snapshot as '$snapshot_name'"
~~~

### db restore <snapshot_name>
### db restore (snapshot_name)

> Restore the database to a snapshot.
Expand Down Expand Up @@ -111,7 +111,7 @@ server.listen(PORT, () => {



## input <arg1> <arg2>
## input (arg1) (arg2)

> Example of how to accept user input and sleep
Expand Down Expand Up @@ -152,7 +152,7 @@ fi



## python <name>
## python (name)

> An example python script
Expand All @@ -168,7 +168,7 @@ print("Hello, " + name + "!")



## ruby <name>
## ruby (name)

> An example ruby script
Expand All @@ -182,7 +182,7 @@ puts "Hello, #{name}!"



## php <name>
## php (name)

> An example php script
Expand Down