docscribe 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +11 -0
- data/.rubocop_todo.yml +73 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +73 -0
- data/LICENSE.txt +21 -0
- data/README.md +451 -0
- data/Rakefile +12 -0
- data/exe/docscribe +77 -0
- data/lib/docscribe/config.rb +245 -0
- data/lib/docscribe/infer.rb +302 -0
- data/lib/docscribe/inline_rewriter.rb +534 -0
- data/lib/docscribe/version.rb +5 -0
- data/lib/docscribe.rb +10 -0
- data/rakelib/docs.rake +73 -0
- data/stingray_docs_internal.gemspec +41 -0
- metadata +144 -0
data/README.md
ADDED
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
# Docscribe
|
|
2
|
+
|
|
3
|
+
[](https://rubygems.org/gems/docscribe)
|
|
4
|
+
[](https://rubygems.org/gems/docscribe)
|
|
5
|
+
[](https://github.com/unurgunite/docscribe/actions/workflows/ci.yml)
|
|
6
|
+
[](https://github.com/unurgunite/docscribe/blob/master/LICENSE.txt)
|
|
7
|
+
[](#installation)
|
|
8
|
+
|
|
9
|
+
Generate inline, YARD-style documentation comments for Ruby methods by analyzing your code's AST. Docscribe inserts doc
|
|
10
|
+
headers before method definitions, infers parameter and return types (including rescue-aware returns), and respects Ruby
|
|
11
|
+
visibility semantics — without using YARD to parse.
|
|
12
|
+
|
|
13
|
+
- No AST reprinting. Your original code, formatting, and constructs (like `class << self`, `heredocs`, `%i[]`) are preserved.
|
|
14
|
+
- Inline-first. Comments are inserted surgically at the start of each `def`/`defs` line.
|
|
15
|
+
- Heuristic type inference for params and return values, including conditional returns in rescue branches.
|
|
16
|
+
- Optional rewrite mode for regenerating existing method docs.
|
|
17
|
+
|
|
18
|
+
Why not YARD? We started with YARD's parser, but switched to an AST-based in-place rewriter for maximum preservation of
|
|
19
|
+
source structure and exact control over Ruby semantics.
|
|
20
|
+
|
|
21
|
+
* [Docscribe](#docscribe)
|
|
22
|
+
* [Installation](#installation)
|
|
23
|
+
* [Quick start](#quick-start)
|
|
24
|
+
* [CLI](#cli)
|
|
25
|
+
* [Inline behavior](#inline-behavior)
|
|
26
|
+
* [Rewrite mode](#rewrite-mode)
|
|
27
|
+
* [Type inference](#type-inference)
|
|
28
|
+
* [Rescue-aware returns and @raise](#rescue-aware-returns-and-raise)
|
|
29
|
+
* [Visibility semantics](#visibility-semantics)
|
|
30
|
+
* [API (library) usage](#api-library-usage)
|
|
31
|
+
* [Configuration](#configuration)
|
|
32
|
+
* [CLI](#cli-1)
|
|
33
|
+
* [CI integration](#ci-integration)
|
|
34
|
+
* [Comparison to YARD's parser](#comparison-to-yards-parser)
|
|
35
|
+
* [Limitations](#limitations)
|
|
36
|
+
* [Roadmap](#roadmap)
|
|
37
|
+
* [Contributing](#contributing)
|
|
38
|
+
* [License](#license)
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
Add to your Gemfile:
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
gem 'docscribe'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Then:
|
|
49
|
+
|
|
50
|
+
```shell
|
|
51
|
+
bundle install
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Or install globally:
|
|
55
|
+
|
|
56
|
+
```shell
|
|
57
|
+
gem install docscribe
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Requires Ruby 3.0+.
|
|
61
|
+
|
|
62
|
+
## Quick start
|
|
63
|
+
|
|
64
|
+
Given code:
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
|
|
68
|
+
class Demo
|
|
69
|
+
def foo(a, options: {})
|
|
70
|
+
42
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def bar(verbose: true)
|
|
74
|
+
123
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def self.bump
|
|
80
|
+
:ok
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
class << self
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def internal; end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Run:
|
|
92
|
+
|
|
93
|
+
```shell
|
|
94
|
+
echo "...code above..." | docscribe --stdin
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Output:
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
|
|
101
|
+
class Demo
|
|
102
|
+
# +Demo#foo+ -> Integer
|
|
103
|
+
#
|
|
104
|
+
# Method documentation.
|
|
105
|
+
#
|
|
106
|
+
# @param [Object] a Param documentation.
|
|
107
|
+
# @param [Hash] options Param documentation.
|
|
108
|
+
# @return [Integer]
|
|
109
|
+
def foo(a, options: {})
|
|
110
|
+
42
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# +Demo#bar+ -> Integer
|
|
114
|
+
#
|
|
115
|
+
# Method documentation.
|
|
116
|
+
#
|
|
117
|
+
# @param [Boolean] verbose Param documentation.
|
|
118
|
+
# @return [Integer]
|
|
119
|
+
def bar(verbose: true)
|
|
120
|
+
123
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
|
|
125
|
+
# +Demo.bump+ -> Symbol
|
|
126
|
+
#
|
|
127
|
+
# Method documentation.
|
|
128
|
+
#
|
|
129
|
+
# @return [Symbol]
|
|
130
|
+
def self.bump
|
|
131
|
+
:ok
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
class << self
|
|
135
|
+
private
|
|
136
|
+
|
|
137
|
+
# +Demo.internal+ -> Object
|
|
138
|
+
#
|
|
139
|
+
# Method documentation.
|
|
140
|
+
#
|
|
141
|
+
# @private
|
|
142
|
+
# @return [Object]
|
|
143
|
+
def internal; end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Notes:
|
|
149
|
+
|
|
150
|
+
- The tool inserts doc headers at the start of def/defs lines and preserves everything else.
|
|
151
|
+
- Class methods show with a dot (`+Demo.bump+`, `+Demo.internal+`).
|
|
152
|
+
- Methods inside `class << self` under private are marked `@private.`
|
|
153
|
+
|
|
154
|
+
## CLI
|
|
155
|
+
|
|
156
|
+
```shell
|
|
157
|
+
docscribe [options] [files...]
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Options:
|
|
161
|
+
|
|
162
|
+
- `--stdin` Read source from STDIN and print with docs inserted.
|
|
163
|
+
- `--write` Rewrite files in place (inline mode).
|
|
164
|
+
- `--check` Dry-run: exit 1 if any file would change (useful in CI).
|
|
165
|
+
- `--rewrite` Replace any existing comment block above methods (see “Rewrite mode” below).
|
|
166
|
+
- `--version` Print version and exit.
|
|
167
|
+
- `-h`, `--help` Show help.
|
|
168
|
+
|
|
169
|
+
Examples:
|
|
170
|
+
|
|
171
|
+
- Print to stdout for one file:
|
|
172
|
+
```shell
|
|
173
|
+
docscribe path/to/file.rb
|
|
174
|
+
```
|
|
175
|
+
- Rewrite files in place (ensure a clean working tree):
|
|
176
|
+
```shell
|
|
177
|
+
docscribe --write lib/**/*.rb
|
|
178
|
+
```
|
|
179
|
+
- CI check (fail if docs are missing/stale):
|
|
180
|
+
```shell
|
|
181
|
+
docscribe --check lib/**/*.rb
|
|
182
|
+
```
|
|
183
|
+
- Rewrite existing doc blocks above methods (regenerate headers/tags):
|
|
184
|
+
```shell
|
|
185
|
+
docscribe --rewrite --write lib/**/*.rb
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Inline behavior
|
|
189
|
+
|
|
190
|
+
- Inserts comment blocks immediately above def/defs nodes.
|
|
191
|
+
- Skips methods that already have a comment directly above them (does not merge into existing comments) unless you pass
|
|
192
|
+
`--rewrite`.
|
|
193
|
+
- Maintains original formatting and constructs; only adds comments.
|
|
194
|
+
|
|
195
|
+
### Rewrite mode
|
|
196
|
+
|
|
197
|
+
- With `--rewrite`, Docscribe will remove the contiguous comment block immediately above a method (plus intervening
|
|
198
|
+
blank
|
|
199
|
+
lines) and replace it with a fresh generated block.
|
|
200
|
+
- This is useful to refresh docs across a codebase after improving inference or rules.
|
|
201
|
+
- Use with caution (prefer a clean working tree and review diffs).
|
|
202
|
+
|
|
203
|
+
## Type inference
|
|
204
|
+
|
|
205
|
+
Heuristics (best-effort):
|
|
206
|
+
|
|
207
|
+
Parameters:
|
|
208
|
+
|
|
209
|
+
- `*args` -> `Array`
|
|
210
|
+
- `**kwargs` -> `Hash`
|
|
211
|
+
- `&block` -> `Proc`
|
|
212
|
+
- keyword args:
|
|
213
|
+
- verbose: `true` -> `Boolean`
|
|
214
|
+
- options: `{}` -> `Hash`
|
|
215
|
+
- kw: (no default) -> `Object`
|
|
216
|
+
- positional defaults:
|
|
217
|
+
- `42` -> `Integer`, `1.0` -> `Float`, `'x'` -> `String`, `:ok` -> `Symbol`
|
|
218
|
+
- `[]` -> `Array`, `{}` -> `Hash`, `/x/` -> `Regexp`, `true`/`false` -> `Boolean`, `nil` -> `nil`
|
|
219
|
+
|
|
220
|
+
Return values:
|
|
221
|
+
|
|
222
|
+
- For simple bodies, Docscribe looks at the last expression or explicit return:
|
|
223
|
+
- `42` -> `Integer`
|
|
224
|
+
- `:ok` -> `Symbol`
|
|
225
|
+
- Unions with nil become optional types (e.g., `String` or `nil` -> `String?`).
|
|
226
|
+
- For control flow (`if`/`case`), it unifies branches conservatively.
|
|
227
|
+
|
|
228
|
+
## Rescue-aware returns and @raise
|
|
229
|
+
|
|
230
|
+
Docscribe detects exceptions and rescue branches:
|
|
231
|
+
|
|
232
|
+
- Rescue exceptions become `@raise` tags:
|
|
233
|
+
- `rescue Foo, Bar` -> `@raise [Foo]` and `@raise [Bar]`
|
|
234
|
+
- bare rescue -> `@raise [StandardError]`
|
|
235
|
+
- (optional) explicit raise/fail also adds a tag (`raise Foo` -> `@raise [Foo]`, `raise` ->
|
|
236
|
+
`@raise [StandardError]`).
|
|
237
|
+
|
|
238
|
+
- Conditional return types for rescue branches:
|
|
239
|
+
- Docscribe adds `@return [Type]` if `ExceptionA`, `ExceptionB` for each rescue clause.
|
|
240
|
+
|
|
241
|
+
Example:
|
|
242
|
+
|
|
243
|
+
```ruby
|
|
244
|
+
|
|
245
|
+
class X
|
|
246
|
+
def a
|
|
247
|
+
42
|
|
248
|
+
rescue Foo, Bar
|
|
249
|
+
"fallback"
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def b
|
|
253
|
+
risky
|
|
254
|
+
rescue
|
|
255
|
+
"n"
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Becomes:
|
|
261
|
+
|
|
262
|
+
```ruby
|
|
263
|
+
|
|
264
|
+
class X
|
|
265
|
+
# +X#a+ -> Integer
|
|
266
|
+
#
|
|
267
|
+
# Method documentation.
|
|
268
|
+
#
|
|
269
|
+
# @raise [Foo]
|
|
270
|
+
# @raise [Bar]
|
|
271
|
+
# @return [Integer]
|
|
272
|
+
# @return [String] if Foo, Bar
|
|
273
|
+
def a
|
|
274
|
+
42
|
|
275
|
+
rescue Foo, Bar
|
|
276
|
+
"fallback"
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# +X#b+ -> Object
|
|
280
|
+
#
|
|
281
|
+
# Method documentation.
|
|
282
|
+
#
|
|
283
|
+
# @raise [StandardError]
|
|
284
|
+
# @return [Object]
|
|
285
|
+
# @return [String] if StandardError
|
|
286
|
+
def b
|
|
287
|
+
risky
|
|
288
|
+
rescue
|
|
289
|
+
"n"
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Visibility semantics
|
|
295
|
+
|
|
296
|
+
We match Ruby's behavior:
|
|
297
|
+
|
|
298
|
+
- A bare `private`/`protected`/`public` in a class/module body affects instance methods only.
|
|
299
|
+
- Inside `class << self`, a bare visibility keyword affects class methods only.
|
|
300
|
+
- `def self.x` in a class body remains `public` unless `private_class_method` is used or it's inside `class << self` under
|
|
301
|
+
`private`.
|
|
302
|
+
|
|
303
|
+
Inline tags:
|
|
304
|
+
|
|
305
|
+
- `@private` is added for methods that are private in context.
|
|
306
|
+
- `@protected` is added similarly for protected methods.
|
|
307
|
+
|
|
308
|
+
## API (library) usage
|
|
309
|
+
|
|
310
|
+
```ruby
|
|
311
|
+
require 'docscribe/inline_rewriter'
|
|
312
|
+
|
|
313
|
+
code = <<~RUBY
|
|
314
|
+
class Demo
|
|
315
|
+
def foo(a, options: {}); 42; end
|
|
316
|
+
class << self; private; def internal; end; end
|
|
317
|
+
end
|
|
318
|
+
RUBY
|
|
319
|
+
|
|
320
|
+
# Insert docs (skip methods that already have a comment above)
|
|
321
|
+
out = Docscribe::InlineRewriter.insert_comments(code)
|
|
322
|
+
puts out
|
|
323
|
+
|
|
324
|
+
# Replace existing comment blocks above methods
|
|
325
|
+
out2 = Docscribe::InlineRewriter.insert_comments(code, rewrite: true)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Configuration
|
|
329
|
+
|
|
330
|
+
Docscribe can be configured via a YAML file (docscribe.yml by default, or pass --config PATH).
|
|
331
|
+
|
|
332
|
+
Example:
|
|
333
|
+
|
|
334
|
+
```yaml
|
|
335
|
+
emit:
|
|
336
|
+
header: true # controls "# +Class#method+ -> Type"
|
|
337
|
+
param_tags: true # include @param lines
|
|
338
|
+
return_tag: true # include normal @return
|
|
339
|
+
visibility_tags: true # include @private/@protected
|
|
340
|
+
raise_tags: true # include @raise [Error]
|
|
341
|
+
rescue_conditional_returns: true # include "@return [...] if Exception"
|
|
342
|
+
|
|
343
|
+
doc:
|
|
344
|
+
default_message: "Method documentation."
|
|
345
|
+
|
|
346
|
+
methods:
|
|
347
|
+
instance:
|
|
348
|
+
public:
|
|
349
|
+
return_tag: true
|
|
350
|
+
default_message: "Public API. Please document purpose and params."
|
|
351
|
+
class:
|
|
352
|
+
private:
|
|
353
|
+
return_tag: false
|
|
354
|
+
|
|
355
|
+
inference:
|
|
356
|
+
fallback_type: "Object"
|
|
357
|
+
nil_as_optional: true
|
|
358
|
+
treat_options_keyword_as_hash: true
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
- emit.* toggles control which tags are emitted globally.
|
|
362
|
+
- methods.<scope>.<visibility> allows per-method overrides:
|
|
363
|
+
- return_tag: true/false
|
|
364
|
+
- default_message: override the message for that bucket
|
|
365
|
+
- inference.* tunes type inference defaults.
|
|
366
|
+
|
|
367
|
+
### CLI
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
docscribe --config docscribe.yml --write lib/**/*.rb
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## CI integration
|
|
374
|
+
|
|
375
|
+
Fail the build if files would change:
|
|
376
|
+
|
|
377
|
+
```yaml
|
|
378
|
+
- name: Check inline docs
|
|
379
|
+
run: docscribe --check lib/**/*.rb
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
Auto-fix before test stage:
|
|
383
|
+
|
|
384
|
+
```yaml
|
|
385
|
+
- name: Insert inline docs
|
|
386
|
+
run: docscribe --write lib/**/*.rb
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Rewrite mode (regenerate existing method docs):
|
|
390
|
+
|
|
391
|
+
```yaml
|
|
392
|
+
- name: Refresh inline docs
|
|
393
|
+
run: docscribe --rewrite --write lib/**/*.rb
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## Comparison to YARD's parser
|
|
397
|
+
|
|
398
|
+
Docscribe and YARD solve different parts of the documentation problem:
|
|
399
|
+
|
|
400
|
+
- Parsing and insertion:
|
|
401
|
+
- Docscribe parses with Ruby's AST (parser gem) and inserts/updates doc comments inline. It does not reformat code
|
|
402
|
+
or produce HTML by itself.
|
|
403
|
+
- YARD parses Ruby into a registry and can generate documentation sites and perform advanced analysis (tags,
|
|
404
|
+
transitive docs, macros).
|
|
405
|
+
|
|
406
|
+
- Preservation vs generation:
|
|
407
|
+
- Docscribe preserves your original source exactly, only inserting comment blocks above methods.
|
|
408
|
+
- YARD generates documentation output (HTML, JSON) based on its registry; it's not designed to write back to your
|
|
409
|
+
source.
|
|
410
|
+
|
|
411
|
+
- Semantics:
|
|
412
|
+
- Docscribe models Ruby visibility semantics precisely for inline usage (including `class << self`).
|
|
413
|
+
- YARD has rich semantics around tags and directives; it can leverage your inline comments (including those inserted
|
|
414
|
+
by Docscribe).
|
|
415
|
+
|
|
416
|
+
- Recommended workflow:
|
|
417
|
+
- Use Docscribe to seed and maintain inline docs with inferred tags/types.
|
|
418
|
+
- Optionally use YARD (dev-only) to render HTML from those comments:
|
|
419
|
+
```shell
|
|
420
|
+
yard doc -o docs
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
## Limitations
|
|
424
|
+
|
|
425
|
+
- Does not merge into existing comments; in normal mode, a method with a comment directly above it is skipped. Use
|
|
426
|
+
`--rewrite` to regenerate.
|
|
427
|
+
- Type inference is heuristic. Complex flows and meta-programming will fall back to Object or best-effort types.
|
|
428
|
+
- Only Ruby 3.0+ is officially supported.
|
|
429
|
+
- Inline rewrite is textual; ensure a clean working tree before using `--write` or `--rewrite`.
|
|
430
|
+
|
|
431
|
+
## Roadmap
|
|
432
|
+
|
|
433
|
+
- Merge tags into existing docstrings (opt-in).
|
|
434
|
+
- Recognize common APIs for return inference (`Time.now`, `File.read`, `JSON.parse`).
|
|
435
|
+
- Configurable rules and per-project exclusions.
|
|
436
|
+
- Editor integration for on-save inline docs.
|
|
437
|
+
|
|
438
|
+
## Contributing
|
|
439
|
+
|
|
440
|
+
Issues and PRs welcome. Please run:
|
|
441
|
+
|
|
442
|
+
```shell
|
|
443
|
+
bundle exec rspec
|
|
444
|
+
bundle exec rubocop
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
See CODE_OF_CONDUCT.md.
|
|
448
|
+
|
|
449
|
+
## License
|
|
450
|
+
|
|
451
|
+
MIT
|
data/Rakefile
ADDED
data/exe/docscribe
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'optparse'
|
|
5
|
+
require 'docscribe/config'
|
|
6
|
+
require 'docscribe/inline_rewriter'
|
|
7
|
+
|
|
8
|
+
options = {
|
|
9
|
+
stdin: false,
|
|
10
|
+
write: false, # rewrite files in place
|
|
11
|
+
check: false, # dry-run (exit 1 if any file would change)
|
|
12
|
+
rewrite: false, # replace existing comment blocks when inserting
|
|
13
|
+
config: nil
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
parser = OptionParser.new do |opts|
|
|
17
|
+
opts.banner = 'Usage: docscribe [options] [files...]'
|
|
18
|
+
opts.on('--stdin', 'Read code from STDIN and print with docs inserted') { options[:stdin] = true }
|
|
19
|
+
opts.on('--write', 'Rewrite files in place') { options[:write] = true }
|
|
20
|
+
opts.on('--check', 'Dry-run: exit 1 if any file would change') { options[:check] = true }
|
|
21
|
+
opts.on('--rewrite', 'Replace existing comment blocks above methods') { options[:rewrite] = true }
|
|
22
|
+
opts.on('--config PATH', 'Path to config YAML (default: docscribe.yml)') { |v| options[:config] = v }
|
|
23
|
+
opts.on('--version', 'Print version and exit') do
|
|
24
|
+
require 'docscribe/version'
|
|
25
|
+
puts Docscribe::VERSION
|
|
26
|
+
exit
|
|
27
|
+
end
|
|
28
|
+
opts.on('-h', '--help', 'Show this help') do
|
|
29
|
+
puts opts
|
|
30
|
+
exit
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
parser.parse!(ARGV)
|
|
35
|
+
|
|
36
|
+
conf = Docscribe::Config.load(options[:config])
|
|
37
|
+
|
|
38
|
+
def transform(code, replace:, config:)
|
|
39
|
+
Docscribe::InlineRewriter.insert_comments(code, rewrite: replace, config: config)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def rewrite(code, replace:)
|
|
43
|
+
Docscribe::InlineRewriter.insert_comments(code, rewrite: replace)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
if options[:stdin]
|
|
47
|
+
code = $stdin.read
|
|
48
|
+
puts rewrite(code, replace: options[:rewrite])
|
|
49
|
+
exit 0
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
if ARGV.empty?
|
|
53
|
+
warn 'No input. Use --stdin or pass file paths. See --help.'
|
|
54
|
+
exit 1
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
changed = false
|
|
58
|
+
|
|
59
|
+
ARGV.each do |path|
|
|
60
|
+
src = File.read(path)
|
|
61
|
+
out = transform(src, replace: options[:rewrite], config: conf)
|
|
62
|
+
if options[:check]
|
|
63
|
+
if out != src
|
|
64
|
+
warn "Would change: #{path}"
|
|
65
|
+
changed = true
|
|
66
|
+
end
|
|
67
|
+
elsif options[:write]
|
|
68
|
+
if out != src
|
|
69
|
+
File.write(path, out)
|
|
70
|
+
puts "Updated: #{path}"
|
|
71
|
+
end
|
|
72
|
+
else
|
|
73
|
+
puts out
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
exit(options[:check] && changed ? 1 : 0)
|