module
Noir::OptionsParsing
Overview
CLI option parsing: the legacy-alias rewrites, the --set-pvalue /
--include / --ai-context target tables, and the helpers that apply
them to the options hash.
These were eight top-level defs and five SCREAMING constants leaking
into every compilation unit — INCLUDE_TARGETS and AI_CONTEXT_FEATURES
under names generic enough to collide. run_options_parser stays
top-level: it is the CLI's entry point, same as detect_techs and
analysis_endpoints on the scan side.
Extended Modules
Defined in:
options.crConstant Summary
-
AI_CONTEXT_FEATURES =
NoirAIContext::ACCEPTED_FEATURES -
--ai-contextaccepts an optional comma-separated feature list. Crystal's OptionParser cannot express "optional positional value", so we rewrite the few well-defined ambiguous forms upfront:--ai-context → --ai-context= (bare, all features) --ai-context=guards,sinks → unchanged (explicit value) --ai-context guards,sinks → --ai-context=guards,sinks (heuristic) --ai-context ./app → --ai-context= (next token is a path)
The heuristic for "is the next token a feature list?": lowercase words joined by commas, where either (a) there's more than one comma-separated word, or (b) the single word matches the fixed vocabulary below exactly. A real filesystem path essentially never contains a literal comma, so any multi-word comma list — typo'd feature names included — is routed to
--ai-context=...and left for the vocabulary check in#apply_ai_contextto reject with a precise "unknown feature" error, rather than silently falling through to "Base path does not exist:". A single bare word still has to match a known feature exactly, since that shape is genuinely ambiguous with a real one-word directory name ( noir scan --ai-context myappmust keep scanningmyapp). Both this and the flag's own validator used to spell the vocabulary out by hand, and both omittedsources. -
INCLUDE_TARGETS =
{"path" => "include_path", "techs" => "include_techs", "callee" => "include_callee"} -
LEGACY_INCLUDE_TARGETS =
{"--include-path" => "include_path", "--include-techs" => "include_techs", "--include-callee" => "include_callee"} -
LEGACY_PVALUE_TARGETS =
{"--set-pvalue" => "set_pvalue", "--set-pvalue-header" => "set_pvalue_header", "--set-pvalue-cookie" => "set_pvalue_cookie", "--set-pvalue-query" => "set_pvalue_query", "--set-pvalue-form" => "set_pvalue_form", "--set-pvalue-json" => "set_pvalue_json", "--set-pvalue-path" => "set_pvalue_path"} -
Silently translate v0 flag spellings to their v1 storage. Keeping the work here (instead of
parser.on "--include-path") means the legacy names no longer clutternoir scan -h, while every v0 script keeps working untouched in v1.x. -
PVALUE_TYPE_KEYS =
{"any" => "set_pvalue", "all" => "set_pvalue", "header" => "set_pvalue_header", "cookie" => "set_pvalue_cookie", "query" => "set_pvalue_query", "form" => "set_pvalue_form", "json" => "set_pvalue_json", "path" => "set_pvalue_path"} -
Split
TYPE=VAL(or bareVAL→ all-types) and route it into the right slot in noir_options.--pvaluemay be repeated to set multiple values across different types.
Instance Method Summary
-
#apply_ai_context(noir_options : Hash(String, YAML::Any), spec : String)
--ai-context[=LIST]always enables AI context output. - #apply_include_list(noir_options : Hash(String, YAML::Any), spec : String)
- #extract_hidden_prompt_flags(noir_options : Hash(String, YAML::Any)) : Array(String)
- #extract_legacy_aliases(args : Array(String), noir_options : Hash(String, YAML::Any)) : Array(String)
- #handle_pvalue(noir_options : Hash(String, YAML::Any), spec : String)
- #normalize_ai_context_flag(args : Array(String)) : Array(String)
-
#validate_ai_context_features(spec : String, origin : String)
Rejects AI-context bucket names outside the accepted vocabulary.
Instance Method Detail
--ai-context[=LIST] always enables AI context output. An empty LIST
means "every category"; a non-empty LIST narrows the output to the
named categories.
Rejects AI-context bucket names outside the accepted vocabulary. origin
names the source in the error so a config-file typo doesn't read as a
command-line one.