@@ -12,6 +12,7 @@ priv struct CliOptions {
1212 patterns : Array [@rule_model.RulePatternSpec ]
1313 scan_root : String
1414 exclude_dirs : Array [String ]
15+ exclude_rules : Array [String ]
1516 verbose : Bool
1617 enable_builtin_rules : Bool
1718 no_color : Bool
@@ -65,6 +66,11 @@ let scan_command : @argparse.Command = Command(
6566 action=Append ,
6667 about="Directory name or path to skip while recursively scanning.",
6768 ),
69+ OptionArg (
70+ "exclude-rules",
71+ action=Append ,
72+ about="Rule id to disable after loading rules.",
73+ ),
6874 ],
6975 positionals=[PositionArg ("scan-root", about="Directory to scan.")],
7076)
@@ -229,6 +235,7 @@ fn scan_cli_options(
229235 let exclude_dirs = normalize_scan_exclude_dirs(
230236 all_cli_values(scan_matches.values, "exclude-dir"),
231237 )
238+ let exclude_rules = all_cli_values(scan_matches.values, "exclude-rules")
232239 if rules_root is None &&
233240 rule_file is None &&
234241 patterns.is_empty() &&
@@ -250,6 +257,7 @@ fn scan_cli_options(
250257 patterns,
251258 scan_root,
252259 exclude_dirs,
260+ exclude_rules,
253261 verbose,
254262 enable_builtin_rules,
255263 no_color,
@@ -366,28 +374,28 @@ fn parse_cli_guard_map(source : String) -> Map[String, String] raise {
366374}
367375
368376///|
369- fn normalize_scan_exclude_dir_args(argv : Array [String ]) -> Array [String ] raise {
377+ fn normalize_scan_multi_value_option_args(
378+ argv : Array [String ],
379+ option_names : Array [String ],
380+ ) -> Array [String ] raise {
370381 if argv.length() == 0 || argv[0] != "scan" {
371382 return argv
372383 }
373384 let normalized : Array [String ] = [argv[0]]
374385 let mut index = 1
375386 while index < argv.length() {
376387 let arg = argv[index]
377- if arg == "--exclude-dir" {
388+ if option_names.contains( arg) {
378389 let mut value_count = 0
379390 index += 1
380391 while index < argv.length() && !argv[index].has_prefix("-") {
381- normalized.push("--exclude-dir" )
392+ normalized.push(arg )
382393 normalized.push(argv[index])
383394 value_count += 1
384395 index += 1
385396 }
386397 if value_count == 0 {
387- raise CliError ::Usage (
388- message="missing value for --exclude-dir",
389- exit_code=2,
390- )
398+ raise CliError ::Usage (message="missing value for \{arg}", exit_code=2)
391399 }
392400 } else {
393401 normalized.push(arg)
@@ -405,18 +413,22 @@ fn normalize_scan_exclude_dir_args(argv : Array[String]) -> Array[String] raise
405413/// `--rule <rule-file>`, at least one `--pattern <pattern>`, or
406414/// `--enable-builtin-rules` is required, and `--verbose` is optional.
407415/// `--exclude-dir <dir>...` skips matching child directory names or paths
408- /// during recursive source scanning.
416+ /// during recursive source scanning. `--exclude-rules <rule-id>...` disables
417+ /// loaded rules by exact rule id before matching.
409418/// One optional scan-root positional may appear in the argument list. If the
410419/// rules option or single rule option appears multiple times, the last value
411- /// wins. Repeated patterns and exclude directories are appended in order.
420+ /// wins. Repeated patterns, exclude directories, and excluded rules are
421+ /// appended in order.
412422/// Missing subcommands, required arguments, unknown options, or more than one
413423/// scan root raise `CliError::Usage` with exit code 2.
414424#moongrep.skip
415425fn parse_cli_command(
416426 argv : Array [String ],
417427 env? : Map [String , String ] = {},
418428) -> (String , CliOptions? , String? ) raise {
419- let normalized_argv = normalize_scan_exclude_dir_args(argv)
429+ let normalized_argv = normalize_scan_multi_value_option_args(argv, [
430+ "--exclude-dir", "--exclude-rules",
431+ ])
420432 let matches = moongrep_command.parse(argv=normalized_argv, env~) catch {
421433 err => {
422434 let message = "\{err}"
0 commit comments