dead_end 2.0.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9fb84957790492d9f453b8863ea276ffc603ccb365fee3621f322e3f19e172e5
4
- data.tar.gz: 798626bcc0dfa8457ef1fed8fb9ab8c9783a12ee109d94310a0cf787b2a0491a
3
+ metadata.gz: c232ccfce002bd3a79d6a5508ea46b27684a9a0ae2bb5d6f843d49e5ba59c0ac
4
+ data.tar.gz: 745847314c5c3ff09cb85b525a5d583f89c1c597e1f5b785ed54e01299bb72c4
5
5
  SHA512:
6
- metadata.gz: 44624834e772d2c0d5c0035eb373571cb379cf6417a1d3422528f312c06771ef00c45e3c1ceebb8f78fa4ebce232fd99798f957c408a8a3a78710e65f18da7ce
7
- data.tar.gz: 478fce76c26ffcf975111bb51a8ea71c20aa0ecbabb606d621d715e3d7055a818e82e5b1bc11cc7143e5cd4e120da257c1b33dc30a1b07356dacb782ad7299bf
6
+ metadata.gz: c49f5b58a7a2f222606a01efc3256a2a0eceade66ff6e46f7c15172cf972a48aa4b6d55212eb714ad69dde1b6d80e91cf8589a9b7026ad2b3e9baafabb8c2e6c
7
+ data.tar.gz: f70fc9947a92d8de2d8f05e08ab803a791c9fc396f03a0bed812b0a88bdb74af33658b23ebdf148adbc716cc41870bee8fabe57c3ae62bd6c9e9b063717f0bbc
data/.circleci/config.yml CHANGED
@@ -13,6 +13,14 @@ references:
13
13
  command: bundle exec standardrb
14
14
 
15
15
  jobs:
16
+ "ruby-2-5":
17
+ docker:
18
+ - image: circleci/ruby:2.5
19
+ steps:
20
+ - checkout
21
+ - ruby/install-deps
22
+ - <<: *unit
23
+
16
24
  "ruby-2-6":
17
25
  docker:
18
26
  - image: circleci/ruby:2.6
@@ -49,6 +57,7 @@ workflows:
49
57
  version: 2
50
58
  build:
51
59
  jobs:
60
+ - "ruby-2-5"
52
61
  - "ruby-2-6"
53
62
  - "ruby-2-7"
54
63
  - "ruby-3-0"
@@ -1,13 +1,20 @@
1
1
  name: Check Changelog
2
2
 
3
3
  on:
4
- pull_request:
5
- types: [opened, reopened, edited, synchronize]
4
+ pull_request:
5
+ types: [opened, reopened, edited, labeled, unlabeled, synchronize]
6
+
6
7
  jobs:
7
- build:
8
+ check-changelog:
8
9
  runs-on: ubuntu-latest
10
+ if: |
11
+ !contains(github.event.pull_request.body, '[skip changelog]') &&
12
+ !contains(github.event.pull_request.body, '[changelog skip]') &&
13
+ !contains(github.event.pull_request.body, '[skip ci]') &&
14
+ !contains(github.event.pull_request.labels.*.name, 'skip changelog')
9
15
  steps:
10
- - uses: actions/checkout@v1
11
- - name: Check that CHANGELOG is touched
12
- run: |
13
- cat $GITHUB_EVENT_PATH | jq .pull_request.title | grep -i '\[\(\(changelog skip\)\|\(ci skip\)\)\]' || git diff remotes/origin/${{ github.base_ref }} --name-only | grep CHANGELOG.md
16
+ - uses: actions/checkout@v2.3.5
17
+ - name: Check that CHANGELOG is touched
18
+ run: |
19
+ git fetch origin ${{ github.base_ref }} --depth 1 && \
20
+ git diff remotes/origin/${{ github.base_ref }} --name-only | grep CHANGELOG.md
data/.standard.yml CHANGED
@@ -1 +1 @@
1
- ruby_version: 2.6.6
1
+ ruby_version: 2.5.9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  ## HEAD (unreleased)
2
2
 
3
+ ## 3.0.1
4
+
5
+ - Fix CLI parsing when flags come before filename (https://github.com/zombocom/dead_end/pull/102)
6
+
7
+ ## 3.0.0
8
+
9
+ - [Breaking] Remove previously deprecated `require "dead_end/fyi"` interface (https://github.com/zombocom/dead_end/pull/94)
10
+ - Fix double output bug (https://github.com/zombocom/dead_end/pull/99)
11
+ - Fix bug causing poor results (fix #95, fix #88) (https://github.com/zombocom/dead_end/pull/96)
12
+ - DeadEnd is now fired on EVERY syntax error (https://github.com/zombocom/dead_end/pull/94)
13
+ - Output format changes:
14
+ - Parse errors emitted per-block rather than for the whole document (https://github.com/zombocom/dead_end/pull/94)
15
+ - The "banner" is now based on lexical analysis rather than parser regex (fix #68, fix #87) (https://github.com/zombocom/dead_end/pull/96)
16
+
17
+ ## 2.0.2
18
+
19
+ - Don't print terminal color codes when output is not tty (https://github.com/zombocom/dead_end/pull/91)
20
+
21
+ ## 2.0.1
22
+
23
+ - Reintroduce Ruby 2.5 support (https://github.com/zombocom/dead_end/pull/90)
24
+ - Support naked braces/brackets/parens, invert labels on banner (https://github.com/zombocom/dead_end/pull/89)
25
+ - Handle mismatched end when using rescue without begin (https://github.com/zombocom/dead_end/pull/83)
26
+ - CLI returns non-zero exit code when syntax error is found (https://github.com/zombocom/dead_end/pull/86)
27
+ - Let -v respond with gem version instead of 'unknown' (https://github.com/zombocom/dead_end/pull/82)
28
+
3
29
  ## 2.0.0
4
30
 
5
31
  - Support "endless" oneline method definitions for Ruby 3+ (https://github.com/zombocom/dead_end/pull/80)
data/Gemfile CHANGED
@@ -9,3 +9,4 @@ gem "rake", "~> 12.0"
9
9
  gem "rspec", "~> 3.0"
10
10
  gem "stackprof"
11
11
  gem "standard"
12
+ gem "ruby-prof"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dead_end (2.0.0)
4
+ dead_end (3.0.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -42,6 +42,7 @@ GEM
42
42
  rubocop-performance (1.11.5)
43
43
  rubocop (>= 1.7.0, < 2.0)
44
44
  rubocop-ast (>= 0.4.0)
45
+ ruby-prof (1.4.3)
45
46
  ruby-progressbar (1.11.0)
46
47
  stackprof (0.2.16)
47
48
  standard (1.3.0)
@@ -56,8 +57,9 @@ DEPENDENCIES
56
57
  dead_end!
57
58
  rake (~> 12.0)
58
59
  rspec (~> 3.0)
60
+ ruby-prof
59
61
  stackprof
60
62
  standard
61
63
 
62
64
  BUNDLED WITH
63
- 2.2.27
65
+ 2.2.30
data/README.md CHANGED
@@ -2,19 +2,14 @@
2
2
 
3
3
  An error in your code forces you to stop. DeadEnd helps you find those errors to get you back on your way faster.
4
4
 
5
- DeadEnd: Unmatched `end` detected
6
-
7
- This code has an unmatched `end`. Ensure that all `end` lines
8
- in your code have a matching syntax keyword (`def`, `do`, etc.)
9
- and that you don't have any extra `end` lines.
10
-
11
- file: path/to/dog.rb
12
- simplified:
5
+ ```
6
+ Unmatched `end', missing keyword (`do', `def`, `if`, etc.) ?
13
7
 
14
- 3 class Dog
15
- 5 defbark
16
- 7 end
17
- 12 end
8
+ 1 class Dog
9
+ 2 defbark
10
+ 4 end
11
+ 5 end
12
+ ```
18
13
 
19
14
  ## Installation in your codebase
20
15
 
@@ -52,34 +47,99 @@ This gives you the CLI command `$ dead_end` for more info run `$ dead_end --help
52
47
 
53
48
  ## What syntax errors does it handle?
54
49
 
50
+ Dead end will fire against all syntax errors and can isolate any syntax error. In addition, dead_end attempts to produce human readable descriptions of what needs to be done to resolve the issue. For example:
51
+
55
52
  - Missing `end`:
56
53
 
54
+ <!--
57
55
  ```ruby
58
56
  class Dog
59
57
  def bark
60
58
  puts "bark"
61
-
62
- def woof
63
- puts "woof"
64
- end
65
59
  end
66
- # => scratch.rb:8: syntax error, unexpected end-of-input, expecting `end'
67
60
  ```
61
+ -->
68
62
 
69
- - Unexpected `end`
63
+ ```
64
+ Unmatched keyword, missing `end' ?
65
+
66
+ ❯ 1 class Dog
67
+ ❯ 2 def bark
68
+ ❯ 4 end
69
+ ```
70
70
 
71
+ - Missing keyword
72
+ <!--
71
73
  ```ruby
72
74
  class Dog
73
75
  def speak
74
- @sounds.each |sound| # Note the missing `do` here
76
+ @sounds.each |sound|
75
77
  puts sound
76
78
  end
77
79
  end
78
80
  end
79
- # => scratch.rb:7: syntax error, unexpected `end', expecting end-of-input
80
81
  ```
82
+ -->
83
+
84
+ ```
85
+ Unmatched `end', missing keyword (`do', `def`, `if`, etc.) ?
86
+
87
+ 1 class Dog
88
+ 2 def speak
89
+ ❯ 3 @sounds.each |sound|
90
+ ❯ 5 end
91
+ 6 end
92
+ 7 end
93
+ ```
94
+
95
+ - Missing pair characters (like `{}`, `[]`, `()` , or `|<var>|`)
96
+ <!--
97
+
98
+ ```ruby
99
+ class Dog
100
+ def speak(sound
101
+ puts sound
102
+ end
103
+ end
104
+ ```
105
+ -->
106
+
107
+ ```
108
+ Unmatched `(', missing `)' ?
109
+
110
+ 1 class Dog
111
+ ❯ 2 def speak(sound
112
+ ❯ 4 end
113
+ 5 end
114
+ ```
115
+
116
+ - Any ambiguous or unknown errors will be annotated by the original ripper error output:
117
+
118
+ <!--
119
+ class Dog
120
+ def meals_last_month
121
+ puts 3 *
122
+ end
123
+ end
124
+ -->
125
+
126
+ ```
127
+ syntax error, unexpected end-of-input
128
+
129
+ 1 class Dog
130
+ 2 def meals_last_month
131
+ ❯ 3 puts 3 *
132
+ 4 end
133
+ 5 end
134
+ ```
135
+
136
+ ## How is it better than `ruby -wc`?
81
137
 
82
- As well as unmatched `|` and unmatched `}`. These errors can be time consuming to debug because Ruby often only tells you the last line in the file. The command `ruby -wc path/to/file.rb` can narrow it down a little bit, but this library does a better job.
138
+ Ruby allows you to syntax check a file with warnings using `ruby -wc`. This emits a parser error instead of a human focused error. Ruby's parse errors attempt to narrow down the location and can tell you if there is a glaring indentation error involving `end`.
139
+
140
+ The `dead_end` algorithm doesn't just guess at the location of syntax errors, it re-parses the document to prove that it captured them.
141
+
142
+ This library focuses on the human side of syntax errors. It cares less about why the document could not be parsed (computer problem) and more on what the programmer needs (human problem) to fix the problem.
83
143
 
84
144
  ## Sounds cool, but why isn't this baked into Ruby directly?
85
145
 
@@ -105,6 +165,34 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
105
165
 
106
166
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
107
167
 
168
+ ### How to debug changes to output display
169
+
170
+ You can see changes to output against a variety of invalid code by running specs and using the `DEBUG_DISPLAY=1` environment variable. For example:
171
+
172
+ ```
173
+ $ DEBUG_DISPLAY=1 bundle exec rspec spec/ --format=failures
174
+ ```
175
+
176
+ ### Run profiler
177
+
178
+ You can output profiler data to the `tmp` directory by running:
179
+
180
+ ```
181
+ $ DEBUG_PERF=1 bundle exec rspec spec/integration/dead_end_spec.rb
182
+ ```
183
+
184
+ Some outputs are in text format, some are html, the raw marshaled data is available in `raw.rb.marshal`. See https://ruby-prof.github.io/#reports for more info. One interesting one, is the "kcachegrind" interface. To view this on mac:
185
+
186
+ ```
187
+ $ brew install qcachegrind
188
+ ```
189
+
190
+ Open:
191
+
192
+ ```
193
+ $ qcachegrind tmp/last/profile.callgrind.out.<numbers>
194
+ ```
195
+
108
196
  ## Contributing
109
197
 
110
198
  Bug reports and pull requests are welcome on GitHub at https://github.com/zombocom/dead_end. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/zombocom/dead_end/blob/master/CODE_OF_CONDUCT.md).
data/exe/dead_end CHANGED
@@ -1,70 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "pathname"
4
- require "optparse"
5
3
  require_relative "../lib/dead_end"
6
4
 
7
- options = {}
8
- options[:terminal] = true
9
- options[:record_dir] = ENV["DEAD_END_RECORD_DIR"]
10
-
11
- parser = OptionParser.new do |opts|
12
- opts.banner = <<~EOM
13
- Usage: dead_end <file> [options]
14
-
15
- Parses a ruby source file and searches for syntax error(s) such as
16
- unexpected `end', expecting end-of-input.
17
-
18
- Example:
19
-
20
- $ dead_end dog.rb
21
-
22
- # ...
23
-
24
- ❯ 10 defdog
25
- ❯ 15 end
26
- ❯ 16
27
-
28
- Env options:
29
-
30
- DEAD_END_RECORD_DIR=<dir>
31
-
32
- When enabled, records the steps used to search for a syntax error to the
33
- given directory
34
-
35
- Options:
36
- EOM
37
-
38
- opts.on("--help", "Help - displays this message") do |v|
39
- puts opts
40
- exit
41
- end
42
-
43
- opts.on("--record <dir>", "When enabled, records the steps used to search for a syntax error to the given directory") do |v|
44
- options[:record_dir] = v
45
- end
46
-
47
- opts.on("--no-terminal", "Disable terminal highlighting") do |v|
48
- options[:terminal] = false
49
- end
50
- end
51
- parser.parse!
52
-
53
- file = ARGV[0]
54
-
55
- if file.nil? || file.empty?
56
- # Display help if raw command
57
- parser.parse! %w[--help]
58
- end
59
-
60
- file = Pathname(file)
61
- options[:record_dir] = "tmp" if ENV["DEBUG"]
62
-
63
- warn "Record dir: #{options[:record_dir]}" if options[:record_dir]
64
-
65
- DeadEnd.call(
66
- source: file.read,
67
- filename: file.expand_path,
68
- terminal: options[:terminal],
69
- record_dir: options[:record_dir]
70
- )
5
+ DeadEnd::Cli.new(
6
+ argv: ARGV
7
+ ).call
@@ -194,7 +194,7 @@ module DeadEnd
194
194
  end
195
195
 
196
196
  private def after_lines
197
- @code_lines[after_index.next..] || []
197
+ @code_lines[after_index.next..-1] || []
198
198
  end
199
199
  end
200
200
  end
data/lib/dead_end/auto.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../dead_end/internals"
3
+ require_relative "../dead_end"
4
4
 
5
5
  # Monkey patch kernel to ensure that all `require` calls call the same
6
6
  # method
@@ -33,23 +33,3 @@ module Kernel
33
33
  DeadEnd.handle_error(e)
34
34
  end
35
35
  end
36
-
37
- # I honestly have no idea why this Object delegation is needed
38
- # I keep staring at bootsnap and it doesn't have to do this
39
- # is there a bug in their implementation they haven't caught or
40
- # am I doing something different?
41
- class Object
42
- private
43
-
44
- def load(path, wrap = false)
45
- Kernel.load(path, wrap)
46
- rescue SyntaxError => e
47
- DeadEnd.handle_error(e)
48
- end
49
-
50
- def require(path)
51
- Kernel.require(path)
52
- rescue SyntaxError => e
53
- DeadEnd.handle_error(e)
54
- end
55
- end
@@ -85,17 +85,16 @@ module DeadEnd
85
85
  #
86
86
  class CleanDocument
87
87
  def initialize(source:)
88
- @source = source
88
+ @source = clean_sweep(source: source)
89
89
  @document = CodeLine.from_source(@source)
90
90
  end
91
91
 
92
92
  # Call all of the document "cleaners"
93
93
  # and return self
94
94
  def call
95
- clean_sweep
96
- .join_trailing_slash!
97
- .join_consecutive!
98
- .join_heredoc!
95
+ join_trailing_slash!
96
+ join_consecutive!
97
+ join_heredoc!
99
98
 
100
99
  self
101
100
  end
@@ -122,17 +121,15 @@ module DeadEnd
122
121
  # puts "world"
123
122
  # EOM
124
123
  #
125
- # lines = CleanDocument.new(source: source).clean_sweep.lines
124
+ # lines = CleanDocument.new(source: source).lines
126
125
  # expect(lines[0].to_s).to eq("\n")
127
126
  # expect(lines[1].to_s).to eq("puts "hello")
128
127
  # expect(lines[2].to_s).to eq("\n")
129
128
  # expect(lines[3].to_s).to eq("puts "world")
130
129
  #
131
- # WARNING:
132
- # If you run this after any of the "join" commands, they
133
- # will be un-joined.
130
+ # Important: This must be done before lexing.
134
131
  #
135
- # After this change is made, we re-lex the document because
132
+ # After this change is made, we lex the document because
136
133
  # removing comments can change how the doc is parsed.
137
134
  #
138
135
  # For example:
@@ -142,7 +139,9 @@ module DeadEnd
142
139
  # # comment
143
140
  # where(name: 'schneems')
144
141
  # EOM
145
- # expect(values.count {|v| v.type == :on_ignored_nl}).to eq(1)
142
+ # expect(
143
+ # values.count {|v| v.type == :on_ignored_nl}
144
+ # ).to eq(1)
146
145
  #
147
146
  # After the comment is removed:
148
147
  #
@@ -151,26 +150,18 @@ module DeadEnd
151
150
  #
152
151
  # where(name: 'schneems')
153
152
  # EOM
154
- # expect(values.count {|v| v.type == :on_ignored_nl}).to eq(2)
153
+ # expect(
154
+ # values.count {|v| v.type == :on_ignored_nl}
155
+ # ).to eq(2)
155
156
  #
156
- def clean_sweep
157
- source = @document.map do |code_line|
158
- # Clean trailing whitespace on empty line
159
- if code_line.line.strip.empty?
160
- next CodeLine.new(line: "\n", index: code_line.index, lex: [])
157
+ def clean_sweep(source:)
158
+ source.lines.map do |line|
159
+ if line.match?(/^\s*(#[^{].*)?$/) # https://rubular.com/r/LLE10D8HKMkJvs
160
+ $/
161
+ else
162
+ line
161
163
  end
162
-
163
- # Remove comments
164
- if code_line.lex.detect { |lex| lex.type != :on_sp }&.type == :on_comment
165
- next CodeLine.new(line: "\n", index: code_line.index, lex: [])
166
- end
167
-
168
- code_line
169
164
  end.join
170
-
171
- @source = source
172
- @document = CodeLine.from_source(source)
173
- self
174
165
  end
175
166
 
176
167
  # Smushes all heredoc lines into one line
@@ -231,7 +222,7 @@ module DeadEnd
231
222
  #
232
223
  def join_consecutive!
233
224
  consecutive_groups = @document.select(&:ignore_newline_not_beg?).map do |code_line|
234
- take_while_including(code_line.index..) do |line|
225
+ take_while_including(code_line.index..-1) do |line|
235
226
  line.ignore_newline_not_beg?
236
227
  end
237
228
  end
@@ -252,7 +243,7 @@ module DeadEnd
252
243
  # expect(lines[1].to_s).to eq("")
253
244
  def join_trailing_slash!
254
245
  trailing_groups = @document.select(&:trailing_slash?).map do |code_line|
255
- take_while_including(code_line.index..) { |x| x.trailing_slash? }
246
+ take_while_including(code_line.index..-1) { |x| x.trailing_slash? }
256
247
  end
257
248
  join_groups(trailing_groups)
258
249
  self
@@ -286,7 +277,7 @@ module DeadEnd
286
277
  )
287
278
 
288
279
  # Hide the rest of the lines
289
- lines[1..].each do |line|
280
+ lines[1..-1].each do |line|
290
281
  # The above lines already have newlines in them, if add more
291
282
  # then there will be double newline, use an empty line instead
292
283
  @document[line.index] = CodeLine.new(line: "", index: line.index, lex: [])
@@ -300,7 +291,7 @@ module DeadEnd
300
291
  # Like `take_while` except when it stops
301
292
  # iterating, it also returns the line
302
293
  # that caused it to stop
303
- def take_while_including(range = 0..)
294
+ def take_while_including(range = 0..-1)
304
295
  take_next_and_stop = false
305
296
  @document[range].take_while do |line|
306
297
  next if take_next_and_stop
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "optparse"
5
+
6
+ module DeadEnd
7
+ # All the logic of the exe/dead_end CLI in one handy spot
8
+ #
9
+ # Cli.new(argv: ["--help"]).call
10
+ # Cli.new(argv: ["<path/to/file>.rb"]).call
11
+ # Cli.new(argv: ["<path/to/file>.rb", "--record=tmp"]).call
12
+ # Cli.new(argv: ["<path/to/file>.rb", "--terminal"]).call
13
+ #
14
+ class Cli
15
+ attr_accessor :options
16
+
17
+ # ARGV is Everything passed to the executable, does not include executable name
18
+ #
19
+ # All other intputs are dependency injection for testing
20
+ def initialize(argv:, exit_obj: Kernel, io: $stdout, env: ENV)
21
+ @options = {}
22
+ @parser = nil
23
+ options[:record_dir] = env["DEAD_END_RECORD_DIR"]
24
+ options[:record_dir] = "tmp" if env["DEBUG"]
25
+ options[:terminal] = DeadEnd::DEFAULT_VALUE
26
+
27
+ @io = io
28
+ @argv = argv
29
+ @exit_obj = exit_obj
30
+ end
31
+
32
+ def call
33
+ if @argv.empty?
34
+ # Display help if raw command
35
+ parser.parse! %w[--help]
36
+ return
37
+ else
38
+ # Mutates @argv
39
+ parse
40
+ return if options[:exit]
41
+ end
42
+
43
+ file_name = @argv.first
44
+ if file_name.nil?
45
+ @io.puts "No file given"
46
+ @exit_obj.exit(1)
47
+ return
48
+ end
49
+
50
+ file = Pathname(file_name)
51
+ if !file.exist?
52
+ @io.puts "file not found: #{file.expand_path} "
53
+ @exit_obj.exit(1)
54
+ return
55
+ end
56
+
57
+ @io.puts "Record dir: #{options[:record_dir]}" if options[:record_dir]
58
+
59
+ display = DeadEnd.call(
60
+ io: @io,
61
+ source: file.read,
62
+ filename: file.expand_path,
63
+ terminal: options.fetch(:terminal, DeadEnd::DEFAULT_VALUE),
64
+ record_dir: options[:record_dir]
65
+ )
66
+
67
+ if display.document_ok?
68
+ @exit_obj.exit(0)
69
+ else
70
+ @exit_obj.exit(1)
71
+ end
72
+ end
73
+
74
+ def parse
75
+ parser.parse!(@argv)
76
+
77
+ self
78
+ end
79
+
80
+ def parser
81
+ @parser ||= OptionParser.new do |opts|
82
+ opts.banner = <<~EOM
83
+ Usage: dead_end <file> [options]
84
+
85
+ Parses a ruby source file and searches for syntax error(s) such as
86
+ unexpected `end', expecting end-of-input.
87
+
88
+ Example:
89
+
90
+ $ dead_end dog.rb
91
+
92
+ # ...
93
+
94
+ ❯ 10 defdog
95
+ ❯ 15 end
96
+
97
+ ENV options:
98
+
99
+ DEAD_END_RECORD_DIR=<dir>
100
+
101
+ Records the steps used to search for a syntax error
102
+ to the given directory
103
+
104
+ Options:
105
+ EOM
106
+
107
+ opts.version = DeadEnd::VERSION
108
+
109
+ opts.on("--help", "Help - displays this message") do |v|
110
+ @io.puts opts
111
+ options[:exit] = true
112
+ @exit_obj.exit
113
+ end
114
+
115
+ opts.on("--record <dir>", "Records the steps used to search for a syntax error to the given directory") do |v|
116
+ options[:record_dir] = v
117
+ end
118
+
119
+ opts.on("--terminal", "Enable terminal highlighting") do |v|
120
+ options[:terminal] = true
121
+ end
122
+
123
+ opts.on("--no-terminal", "Disable terminal highlighting") do |v|
124
+ options[:terminal] = false
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end