Module: Docscribe::CLI::Options

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

Constant Summary collapse

DEFAULT =
{
  stdin: false,
  mode: :check,       # :check, :write, :stdin
  strategy: :safe,    # :safe, :aggressive
  verbose: false,
  explain: false,
  config: nil,
  include: [],
  exclude: [],
  include_file: [],
  exclude_file: [],
  rbs: false,
  sig_dirs: [],
  sorbet: false,
  rbi_dirs: [],
  rbs_collection: false
}.freeze

Class Method Summary collapse

Class Method Details

.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)


204
205
206
207
208
# File 'lib/docscribe/cli/options.rb', line 204

def looks_like_file_pattern?(pat)
  return false if pat.start_with?('/') && pat.end_with?('/') && pat.length >= 2

  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



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/docscribe/cli/options.rb', line 42

def parse!(argv)
  options = Marshal.load(Marshal.dump(DEFAULT))
  autocorrect_mode = nil

  parser = OptionParser.new do |opts|
    opts.banner = <<~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

    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

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

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

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

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

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

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

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

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

    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

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

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

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

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

    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

  parser.parse!(argv)

  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

  options
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



188
189
190
191
192
193
194
# File 'lib/docscribe/cli/options.rb', line 188

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