diff --git a/src/cli.rs b/src/cli.rs index 7a2799d..016d64e 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -16,6 +16,36 @@ pub struct Cli { command: Option, } +/// The dice grammar, printed after `storied roll --help`'s usage line. This +/// mirrors the grammar in `src/dice.rs`; keep the two in sync. +const ROLL_AFTER_HELP: &str = "\ +Notation is one or more terms joined by + and -, like `3d6-1 + 4d100+5`. +A term is a dice group (XdY) or a flat modifier. + +A group's count is optional (`d20` is `1d20`); `%` means 100 (`d%` is +`d100`). Valid die sizes: 2, 3, 4, 6, 8, 10, 12, 20, 100. + +Suffixes attach to a group, in any order, case-insensitive. Rerolls and +minimums settle before a keep/drop suffix picks which dice count. + khN, klN keep the highest/lowest N; bare kh/kl keeps 1 + dhN, dlN drop the highest/lowest N + roN reroll a die once, keeping the new value + roN reroll once when the roll is greater than N + rN reroll a die until the roll no longer equals N + rN reroll until the roll is no longer greater than N + miN raise each die's value to at least N + +Examples: + 2d20kh advantage + 2d20kl disadvantage + 4d6kh3 ability score, keeping the best 3 of 4 + 4d6dl1 the same roll as 4d6kh3, said the other way + 2d6ro<3 Great Weapon Fighting + d20ro1 Halfling Luck + 8d6mi2 Elemental Adept"; + #[derive(Subcommand)] enum Command { /// Manage the SRD rules pipeline. @@ -24,6 +54,7 @@ enum Command { command: SrdCommand, }, /// Roll dice notation once and print the result. + #[command(after_help = ROLL_AFTER_HELP)] Roll { /// Dice notation to roll, like `d20` or `2d6+3`. notation: String, diff --git a/tests/roll.rs b/tests/roll.rs index 19839d7..8572680 100644 --- a/tests/roll.rs +++ b/tests/roll.rs @@ -14,6 +14,22 @@ fn rolling_valid_notation_echoes_it_and_prints_a_total() { assert!(stdout.contains("total:")); } +#[test] +fn help_documents_the_suffix_syntax() { + let output = Command::cargo_bin("storied") + .unwrap() + .args(["roll", "--help"]) + .output() + .unwrap(); + + assert!(output.status.success()); + let stdout = String::from_utf8(output.stdout).unwrap(); + assert!(stdout.contains("kh")); + assert!(stdout.contains("dl")); + assert!(stdout.contains("ro<")); + assert!(stdout.contains("mi")); +} + #[test] fn rolling_unparseable_notation_prints_the_error_and_fails() { let output = Command::cargo_bin("storied")