Module: Docscribe::CLI::Options

Defined in:
lib/docscribe/cli/options.rb

Overview

CLI option parsing and defaults.

Constant Summary collapse

DEFAULT =
{
  stdin: false,
  mode: :check,       # :check, :write, :stdin
  strategy: :safe,    # :safe, :aggressive
  verbose: false,
  explain: false,
  config: nil,
  include: [], #: Array[String]
  exclude: [], #: Array[String]
  include_file: [], #: Array[String]
  exclude_file: [], #: Array[String]
  rbs: false,
  sig_dirs: [], #: Array[String]
  sorbet: false,
  rbi_dirs: [], #: Array[String]
  rbs_collection: false
}.freeze
<<~TEXT
  Usage: docscribe [options] [files...]

  Default behavior:
    Inspect files and report what safe doc updates would be applied.

  Autocorrect:
      -a, --autocorrect              Apply safe doc updates in place
                                     (insert missing docs, merge existing doc-like blocks,
                                     normalize tag order)
      -A, --autocorrect-all          Apply aggressive doc updates in place
                                     (rebuild existing doc blocks)

  Input / config:
          --stdin                    Read code from STDIN and print rewritten output
      -C, --config PATH              Path to config YAML (default: docscribe.yml)

  Type information:
          --rbs                      Use RBS signatures for @param/@return when available
          --sig-dir DIR              Add an RBS signature directory (repeatable). Implies `--rbs`.
          --sorbet                   Use Sorbet signatures from inline sigs / RBI files when available
          --rbi-dir DIR              Add a Sorbet RBI directory (repeatable). Implies --sorbet.
          --rbs-collection           Auto-discover RBS collection from rbs_collection.lock.yaml. Implies --rbs.

  Filtering:
          --include PATTERN          Include PATTERN (method id or file path; glob or /regex/)
          --exclude PATTERN          Exclude PATTERN (method id or file path; glob or /regex/)
          --include-file PATTERN     Only process files matching PATTERN (glob or /regex/)
          --exclude-file PATTERN     Skip files matching PATTERN (glob or /regex/)

  Output:
          --verbose                  Print per-file actions
      -e, --explain                  Show detailed reasons for changes

  Other:
      -v, --version                  Print version and exit
      -h, --help                     Show this help
TEXT

Class Method Summary collapse

Class Method Details

.build_option_parser(options, autocorrect) ⇒ OptionParser

Note:

module_function: when included, also defines #build_option_parser (instance visibility: private)

Build the OptionParser instance and register all CLI option groups.

Parameters:

  • options (Hash)

    mutable parsed options hash

  • autocorrect (Hash{Symbol => Symbol,nil})

    mutable container for autocorrect mode

Returns:

  • (OptionParser)


97
98
99
100
101
102
103
104
105
106
107
# File 'lib/docscribe/cli/options.rb', line 97

def build_option_parser(options, autocorrect)
  OptionParser.new do |opts|
    opts.banner = BANNER
    define_autocorrect_options(opts, autocorrect)
    define_input_options(opts, options)
    define_type_options(opts, options)
    define_filter_options(opts, options)
    define_output_options(opts, options)
    define_misc_options(opts)
  end
end

.define_autocorrect_options(opts, autocorrect) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • autocorrect (Hash{Symbol => Symbol,nil})

    mutable container for autocorrect mode (:safe, :aggressive, nil)



114
115
116
117
118
119
120
121
122
# File 'lib/docscribe/cli/options.rb', line 114

def define_autocorrect_options(opts, autocorrect)
  opts.on('-a', '--autocorrect', 'Apply safe doc updates in place') do
    autocorrect[:mode] = :safe
  end

  opts.on('-A', '--autocorrect-all', 'Apply aggressive doc updates in place') do
    autocorrect[:mode] = :aggressive
  end
end

.define_config_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



150
151
152
153
154
# File 'lib/docscribe/cli/options.rb', line 150

def define_config_option(opts, options)
  opts.on('-C', '--config PATH', 'Path to config YAML (default: docscribe.yml)') do |v|
    options[:config] = v
  end
end

.define_exclude_file_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



278
279
280
281
282
# File 'lib/docscribe/cli/options.rb', line 278

def define_exclude_file_option(opts, options)
  opts.on('--exclude-file PATTERN', 'Skip files matching PATTERN (glob or /regex/). Exclude wins.') do |v|
    options[:exclude_file] << v
  end
end

.define_exclude_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



255
256
257
258
259
260
# File 'lib/docscribe/cli/options.rb', line 255

def define_exclude_option(opts, options)
  opts.on('--exclude PATTERN',
          'Exclude PATTERN (method id or file path; glob or /regex/). Exclude wins.') do |v|
    route_include_exclude(options, :exclude, v)
  end
end

.define_explain_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



310
311
312
313
314
# File 'lib/docscribe/cli/options.rb', line 310

def define_explain_option(opts, options)
  opts.on('-e', '--explain', 'Show detailed reasons for changes') do
    options[:explain] = true
  end
end

.define_filter_options(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



232
233
234
235
236
237
# File 'lib/docscribe/cli/options.rb', line 232

def define_filter_options(opts, options)
  define_include_option(opts, options)
  define_exclude_option(opts, options)
  define_include_file_option(opts, options)
  define_exclude_file_option(opts, options)
end

.define_include_file_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



267
268
269
270
271
# File 'lib/docscribe/cli/options.rb', line 267

def define_include_file_option(opts, options)
  opts.on('--include-file PATTERN', 'Only process files matching PATTERN (glob or /regex/)') do |v|
    options[:include_file] << v
  end
end

.define_include_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



244
245
246
247
248
# File 'lib/docscribe/cli/options.rb', line 244

def define_include_option(opts, options)
  opts.on('--include PATTERN', 'Include PATTERN (method id or file path; glob or /regex/)') do |v|
    route_include_exclude(options, :include, v)
  end
end

.define_input_options(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



129
130
131
132
# File 'lib/docscribe/cli/options.rb', line 129

def define_input_options(opts, options)
  define_stdin_option(opts, options)
  define_config_option(opts, options)
end

.define_misc_options(opts) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)


320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/docscribe/cli/options.rb', line 320

def define_misc_options(opts)
  opts.on('-v', '--version', 'Print version and exit') do
    require 'docscribe/version'
    puts Docscribe::VERSION
    exit 0
  end

  opts.on('-h', '--help', 'Show this help') do
    puts opts
    exit 0
  end
end

.define_output_options(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



289
290
291
292
# File 'lib/docscribe/cli/options.rb', line 289

def define_output_options(opts, options)
  define_verbose_option(opts, options)
  define_explain_option(opts, options)
end

.define_rbi_dir_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)


208
209
210
211
212
213
# File 'lib/docscribe/cli/options.rb', line 208

def define_rbi_dir_option(opts, options)
  opts.on('--rbi-dir DIR', 'Add a Sorbet RBI directory (repeatable). Implies --sorbet.') do |v|
    options[:sorbet] = true
    options[:rbi_dirs] << v
  end
end

.define_rbs_collection_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)


220
221
222
223
224
225
# File 'lib/docscribe/cli/options.rb', line 220

def define_rbs_collection_option(opts, options)
  opts.on('--rbs-collection', 'Auto-discover RBS collection from rbs_collection.lock.yaml. Implies --rbs.') do
    options[:rbs] = true
    options[:rbs_collection] = true
  end
end

.define_rbs_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)


174
175
176
177
178
# File 'lib/docscribe/cli/options.rb', line 174

def define_rbs_option(opts, options)
  opts.on('--rbs', 'Use RBS signatures for @param/@return when available (falls back to inference)') do
    options[:rbs] = true
  end
end

.define_sig_dir_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)


185
186
187
188
189
190
# File 'lib/docscribe/cli/options.rb', line 185

def define_sig_dir_option(opts, options)
  opts.on('--sig-dir DIR', 'Add an RBS signature directory (repeatable). Implies --rbs.') do |v|
    options[:rbs] = true
    options[:sig_dirs] << v
  end
end

.define_sorbet_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)


197
198
199
200
201
# File 'lib/docscribe/cli/options.rb', line 197

def define_sorbet_option(opts, options)
  opts.on('--sorbet', 'Use Sorbet signatures from inline sigs / RBI files when available') do
    options[:sorbet] = true
  end
end

.define_stdin_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



139
140
141
142
143
# File 'lib/docscribe/cli/options.rb', line 139

def define_stdin_option(opts, options)
  opts.on('--stdin', 'Read code from STDIN and print rewritten output') do
    options[:stdin] = true
  end
end

.define_type_options(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



161
162
163
164
165
166
167
# File 'lib/docscribe/cli/options.rb', line 161

def define_type_options(opts, options)
  define_rbs_option(opts, options)
  define_sig_dir_option(opts, options)
  define_sorbet_option(opts, options)
  define_rbi_dir_option(opts, options)
  define_rbs_collection_option(opts, options)
end

.define_verbose_option(opts, options) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Parameters:

  • opts (OptionParser)
  • options (Hash)

    mutable parsed options hash



299
300
301
302
303
# File 'lib/docscribe/cli/options.rb', line 299

def define_verbose_option(opts, options)
  opts.on('--verbose', 'Print per-file actions') do
    options[:verbose] = true
  end
end

.looks_like_file_pattern?(pat) ⇒ Boolean

Note:

module_function: when included, also defines #looks_like_file_pattern? (instance visibility: private)

Heuristically decide whether a pattern looks like a file path or file glob.

Regex syntax (‘/…/`) is intentionally treated as a method-id pattern, not a file pattern.

Parameters:

  • pat (String)

    pattern passed via CLI

Returns:

  • (Boolean)


379
380
381
382
383
384
# File 'lib/docscribe/cli/options.rb', line 379

def looks_like_file_pattern?(pat)
  return false if pat.start_with?('/') && pat.end_with?('/') && pat.length >= 2
  return false if pat.match?(%r{\A\*/})

  pat.include?('/') || pat.include?('**') || pat.end_with?('.rb')
end

.parse!(argv) ⇒ Hash

Note:

module_function: when included, also defines #parse! (instance visibility: private)

Parse CLI arguments into normalized Docscribe runtime options.

CLI behavior model:

  • default: inspect mode using the safe strategy

  • ‘-a` / `–autocorrect`: write mode using the safe strategy

  • ‘-A` / `–autocorrect-all`: write mode using the aggressive strategy

  • ‘–stdin`: stdin mode using the selected strategy (safe by default)

Filtering, config, verbosity, and external type options are applied orthogonally.

Parameters:

  • argv (Array<String>)

    raw CLI arguments

Returns:

  • (Hash)

    normalized runtime options



82
83
84
85
86
87
88
89
# File 'lib/docscribe/cli/options.rb', line 82

def parse!(argv)
  options = Marshal.load(Marshal.dump(DEFAULT))
  autocorrect = { mode: nil }

  build_option_parser(options, autocorrect).parse!(argv)
  resolve_mode_and_strategy!(options, autocorrect[:mode])
  options
end

.resolve_mode_and_strategy!(options, autocorrect_mode) ⇒ void

Note:

module_function: when included, also defines # (instance visibility: private)

This method returns an undefined value.

Set the runtime mode and strategy after all options have been parsed.

Parameters:

  • options (Hash)

    mutable parsed options hash

  • autocorrect_mode (Symbol, nil)

    autocorrect mode selected (:safe, :aggressive, or nil)



340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/docscribe/cli/options.rb', line 340

def resolve_mode_and_strategy!(options, autocorrect_mode)
  if options[:stdin]
    options[:mode] = :stdin
    options[:strategy] = autocorrect_mode || :safe
  elsif autocorrect_mode
    options[:mode] = :write
    options[:strategy] = autocorrect_mode
  else
    options[:mode] = :check
    options[:strategy] = :safe
  end
end

.route_include_exclude(options, kind, value) ⇒ void

Note:

module_function: when included, also defines #route_include_exclude (instance visibility: private)

This method returns an undefined value.

Route an include/exclude pattern into method filters or file filters.

Regex-looking patterns (‘/…/`) are treated as method-id filters. File-like patterns are routed into `*_file`.

Parameters:

  • options (Hash)

    mutable parsed options hash

  • kind (Symbol)

    either :include or :exclude

  • value (String)

    raw pattern from the CLI



363
364
365
366
367
368
369
# File 'lib/docscribe/cli/options.rb', line 363

def route_include_exclude(options, kind, value)
  if looks_like_file_pattern?(value)
    options[:"#{kind}_file"] << value
  else
    options[kind] << value
  end
end