syntax_search 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +2 -29
- data/Gemfile.lock +3 -1
- data/exe/syntax_search +5 -71
- data/lib/syntax_search/auto.rb +5 -49
- data/syntax_search.gemspec +3 -3
- metadata +17 -19
- data/lib/syntax_search.rb +0 -145
- data/lib/syntax_search/around_block_scan.rb +0 -193
- data/lib/syntax_search/block_expand.rb +0 -74
- data/lib/syntax_search/capture_code_context.rb +0 -62
- data/lib/syntax_search/code_block.rb +0 -78
- data/lib/syntax_search/code_frontier.rb +0 -151
- data/lib/syntax_search/code_line.rb +0 -128
- data/lib/syntax_search/code_search.rb +0 -154
- data/lib/syntax_search/display_code_with_line_numbers.rb +0 -56
- data/lib/syntax_search/display_invalid_blocks.rb +0 -100
- data/lib/syntax_search/fyi.rb +0 -7
- data/lib/syntax_search/heredoc_block_parse.rb +0 -30
- data/lib/syntax_search/lex_all.rb +0 -58
- data/lib/syntax_search/parse_blocks_from_indent_line.rb +0 -56
- data/lib/syntax_search/version.rb +0 -5
- data/lib/syntax_search/who_dis_syntax_error.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 739770be9259abf88e8ea3c7dc1223e279cc79ab35d907312b0cc268d00363ed
|
4
|
+
data.tar.gz: ca7fbab5999100db76c5758f3f920fc7f91872d678b028157761cd6b72e348d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60c1aea7c3f075f0486d85e72bc4761879efd09d5805c6581efa21765c78edd335f172094dcc961f77e00f1bf4e0867f8382b32e7d13e2de248085679e3728e6
|
7
|
+
data.tar.gz: adf40fe0011de00194eef22b5f4caa86196f0b8bf1439c8d48a7f3fbe465521ab04bf856f9cd20407dace52ab154cf1c27d0a519c00d15e862e6100322f2c4f2
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,32 +1,5 @@
|
|
1
1
|
## HEAD (unreleased)
|
2
2
|
|
3
|
-
## 0.2.
|
3
|
+
## 0.2.1
|
4
4
|
|
5
|
-
|
6
|
-
- Block expansion is now lexically aware of keywords (def/do/end etc.) (https://github.com/zombocom/syntax_search/pull/24)
|
7
|
-
- Fix bug where not all of a source is lexed which is used in heredoc detection/removal (https://github.com/zombocom/syntax_search/pull/23)
|
8
|
-
|
9
|
-
## 0.1.5
|
10
|
-
|
11
|
-
- Strip out heredocs in documents first (https://github.com/zombocom/syntax_search/pull/19)
|
12
|
-
|
13
|
-
## 0.1.4
|
14
|
-
|
15
|
-
- Parser gem replaced with Ripper (https://github.com/zombocom/syntax_search/pull/17)
|
16
|
-
|
17
|
-
## 0.1.3
|
18
|
-
|
19
|
-
- Internal refactor (https://github.com/zombocom/syntax_search/pull/13)
|
20
|
-
|
21
|
-
## 0.1.2
|
22
|
-
|
23
|
-
- Codeblocks in output are now indented with 4 spaces and "code fences" are removed (https://github.com/zombocom/syntax_search/pull/11)
|
24
|
-
- "Unmatched end" and "missing end" not generate different error text instructions (https://github.com/zombocom/syntax_search/pull/10)
|
25
|
-
|
26
|
-
## 0.1.1
|
27
|
-
|
28
|
-
- Fire search on both unexpected end-of-input and unexected end (https://github.com/zombocom/syntax_search/pull/8)
|
29
|
-
|
30
|
-
## 0.1.0
|
31
|
-
|
32
|
-
- Initial release
|
5
|
+
This gem is moved to the `dead_end` gem. Please use that instead
|
data/Gemfile.lock
CHANGED
data/exe/syntax_search
CHANGED
@@ -1,74 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
warn "syntax_search gem is deprecated please use `dead_end` instead"
|
4
|
+
warn
|
5
|
+
warn " $ gem install dead_end`"
|
6
|
+
warn
|
6
7
|
|
7
|
-
|
8
|
-
options[:terminal] = true
|
9
|
-
options[:record_dir] = ENV["SYNTAX_SEARCH_RECORD_DIR"]
|
10
|
-
|
11
|
-
parser = OptionParser.new do |opts|
|
12
|
-
opts.banner = <<~EOM
|
13
|
-
Usage: syntax_search <file> [options]
|
14
|
-
|
15
|
-
Parses a ruby source file and searches for syntax error(s) unexpected `end', expecting end-of-input.
|
16
|
-
|
17
|
-
Example:
|
18
|
-
|
19
|
-
$ syntax_search dog.rb
|
20
|
-
|
21
|
-
# ...
|
22
|
-
|
23
|
-
```
|
24
|
-
1 require 'animals'
|
25
|
-
2
|
26
|
-
❯ 10 defdog
|
27
|
-
❯ 15 end
|
28
|
-
❯ 16
|
29
|
-
20 def cat
|
30
|
-
22 end
|
31
|
-
```
|
32
|
-
|
33
|
-
Env options:
|
34
|
-
|
35
|
-
SYNTAX_SEARCH_RECORD_DIR=<dir>
|
36
|
-
|
37
|
-
When enabled, records the steps used to search for a syntax error to the given directory
|
38
|
-
|
39
|
-
Options:
|
40
|
-
EOM
|
41
|
-
|
42
|
-
opts.on("--help", "Help - displays this message") do |v|
|
43
|
-
puts opts
|
44
|
-
exit
|
45
|
-
end
|
46
|
-
|
47
|
-
opts.on("--record <dir>", "When enabled, records the steps used to search for a syntax error to the given directory") do |v|
|
48
|
-
options[:record_dir] = v
|
49
|
-
end
|
50
|
-
|
51
|
-
opts.on("--no-terminal", "Disable terminal highlighting") do |v|
|
52
|
-
options[:terminal] = false
|
53
|
-
end
|
54
|
-
end
|
55
|
-
parser.parse!
|
56
|
-
|
57
|
-
file = ARGV[0]
|
58
|
-
|
59
|
-
if file.nil? || file.empty?
|
60
|
-
# Display help if raw command
|
61
|
-
parser.parse! %w[--help]
|
62
|
-
end
|
63
|
-
|
64
|
-
file = Pathname(file)
|
65
|
-
options[:record_dir] = "tmp" if ENV["DEBUG"]
|
66
|
-
|
67
|
-
$stderr.puts "Record dir: #{options[:record_dir]}" if options[:record_dir]
|
68
|
-
|
69
|
-
SyntaxErrorSearch.call(
|
70
|
-
source: file.read,
|
71
|
-
filename: file.expand_path,
|
72
|
-
terminal: options[:terminal],
|
73
|
-
record_dir: options[:record_dir]
|
74
|
-
)
|
8
|
+
exit 1
|
data/lib/syntax_search/auto.rb
CHANGED
@@ -1,51 +1,7 @@
|
|
1
|
-
|
1
|
+
warn "syntax_search gem is deprecated please use `dead_end` instead"
|
2
|
+
warn
|
3
|
+
warn " $ gem install dead_end`"
|
4
|
+
warn
|
2
5
|
|
3
|
-
|
4
|
-
# method
|
5
|
-
module Kernel
|
6
|
-
alias_method :original_require, :require
|
7
|
-
alias_method :original_require_relative, :require_relative
|
8
|
-
alias_method :original_load, :load
|
9
|
-
|
10
|
-
def load(file, wrap = false)
|
11
|
-
original_load(file)
|
12
|
-
rescue SyntaxError => e
|
13
|
-
SyntaxErrorSearch.handle_error(e)
|
14
|
-
end
|
15
|
-
|
16
|
-
def require(file)
|
17
|
-
original_require(file)
|
18
|
-
rescue SyntaxError => e
|
19
|
-
SyntaxErrorSearch.handle_error(e)
|
20
|
-
end
|
21
|
-
|
22
|
-
def require_relative(file)
|
23
|
-
if Pathname.new(file).absolute?
|
24
|
-
original_require file
|
25
|
-
else
|
26
|
-
original_require File.expand_path("../#{file}", caller_locations(1, 1)[0].absolute_path)
|
27
|
-
end
|
28
|
-
rescue SyntaxError => e
|
29
|
-
SyntaxErrorSearch.handle_error(e)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# I honestly have no idea why this Object delegation is needed
|
34
|
-
# I keep staring at bootsnap and it doesn't have to do this
|
35
|
-
# is there a bug in their implementation they haven't caught or
|
36
|
-
# am I doing something different?
|
37
|
-
class Object
|
38
|
-
private
|
39
|
-
def load(path, wrap = false)
|
40
|
-
Kernel.load(path, wrap)
|
41
|
-
rescue SyntaxError => e
|
42
|
-
SyntaxErrorSearch.handle_error(e)
|
43
|
-
end
|
44
|
-
|
45
|
-
def require(path)
|
46
|
-
Kernel.require(path)
|
47
|
-
rescue SyntaxError => e
|
48
|
-
SyntaxErrorSearch.handle_error(e)
|
49
|
-
end
|
50
|
-
end
|
6
|
+
require "dead_end"
|
51
7
|
|
data/syntax_search.gemspec
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'lib/syntax_search/version'
|
4
|
-
|
5
3
|
Gem::Specification.new do |spec|
|
6
4
|
spec.name = "syntax_search"
|
7
|
-
spec.version =
|
5
|
+
spec.version = "0.2.1"
|
8
6
|
spec.authors = ["schneems"]
|
9
7
|
spec.email = ["richard.schneeman+foo@gmail.com"]
|
10
8
|
|
@@ -25,4 +23,6 @@ Gem::Specification.new do |spec|
|
|
25
23
|
spec.bindir = "exe"
|
26
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
25
|
spec.require_paths = ["lib"]
|
26
|
+
|
27
|
+
spec.add_dependency "dead_end", "> 0"
|
28
28
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: syntax_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- schneems
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-12-
|
12
|
-
dependencies:
|
11
|
+
date: 2020-12-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dead_end
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
description: When you get an "unexpected end" in your syntax this gem helps you find
|
14
28
|
it
|
15
29
|
email:
|
@@ -35,23 +49,7 @@ files:
|
|
35
49
|
- bin/console
|
36
50
|
- bin/setup
|
37
51
|
- exe/syntax_search
|
38
|
-
- lib/syntax_search.rb
|
39
|
-
- lib/syntax_search/around_block_scan.rb
|
40
52
|
- lib/syntax_search/auto.rb
|
41
|
-
- lib/syntax_search/block_expand.rb
|
42
|
-
- lib/syntax_search/capture_code_context.rb
|
43
|
-
- lib/syntax_search/code_block.rb
|
44
|
-
- lib/syntax_search/code_frontier.rb
|
45
|
-
- lib/syntax_search/code_line.rb
|
46
|
-
- lib/syntax_search/code_search.rb
|
47
|
-
- lib/syntax_search/display_code_with_line_numbers.rb
|
48
|
-
- lib/syntax_search/display_invalid_blocks.rb
|
49
|
-
- lib/syntax_search/fyi.rb
|
50
|
-
- lib/syntax_search/heredoc_block_parse.rb
|
51
|
-
- lib/syntax_search/lex_all.rb
|
52
|
-
- lib/syntax_search/parse_blocks_from_indent_line.rb
|
53
|
-
- lib/syntax_search/version.rb
|
54
|
-
- lib/syntax_search/who_dis_syntax_error.rb
|
55
53
|
- syntax_search.gemspec
|
56
54
|
homepage: https://github.com/zombocom/syntax_search.git
|
57
55
|
licenses:
|
data/lib/syntax_search.rb
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "syntax_search/version"
|
4
|
-
|
5
|
-
require 'tmpdir'
|
6
|
-
require 'stringio'
|
7
|
-
require 'pathname'
|
8
|
-
require 'ripper'
|
9
|
-
|
10
|
-
module SyntaxErrorSearch
|
11
|
-
class Error < StandardError; end
|
12
|
-
SEARCH_SOURCE_ON_ERROR_DEFAULT = true
|
13
|
-
|
14
|
-
def self.handle_error(e, search_source_on_error: SEARCH_SOURCE_ON_ERROR_DEFAULT)
|
15
|
-
raise e if !e.message.include?("end-of-input")
|
16
|
-
|
17
|
-
filename = e.message.split(":").first
|
18
|
-
|
19
|
-
$stderr.sync = true
|
20
|
-
$stderr.puts "Run `$ syntax_search #{filename}` for more options\n"
|
21
|
-
|
22
|
-
if search_source_on_error
|
23
|
-
self.call(
|
24
|
-
source: Pathname(filename).read,
|
25
|
-
filename: filename,
|
26
|
-
terminal: true,
|
27
|
-
)
|
28
|
-
end
|
29
|
-
|
30
|
-
$stderr.puts ""
|
31
|
-
$stderr.puts ""
|
32
|
-
raise e
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.call(source: , filename: , terminal: false, record_dir: nil)
|
36
|
-
search = CodeSearch.new(source, record_dir: record_dir).call
|
37
|
-
|
38
|
-
blocks = search.invalid_blocks
|
39
|
-
DisplayInvalidBlocks.new(
|
40
|
-
blocks: blocks,
|
41
|
-
filename: filename,
|
42
|
-
terminal: terminal,
|
43
|
-
code_lines: search.code_lines,
|
44
|
-
invalid_type: invalid_type(source),
|
45
|
-
io: $stderr
|
46
|
-
).call
|
47
|
-
end
|
48
|
-
|
49
|
-
# Used for counting spaces
|
50
|
-
module SpaceCount
|
51
|
-
def self.indent(string)
|
52
|
-
string.split(/\S/).first&.length || 0
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# This will tell you if the `code_lines` would be valid
|
57
|
-
# if you removed the `without_lines`. In short it's a
|
58
|
-
# way to detect if we've found the lines with syntax errors
|
59
|
-
# in our document yet.
|
60
|
-
#
|
61
|
-
# code_lines = [
|
62
|
-
# CodeLine.new(line: "def foo\n", index: 0)
|
63
|
-
# CodeLine.new(line: " def bar\n", index: 1)
|
64
|
-
# CodeLine.new(line: "end\n", index: 2)
|
65
|
-
# ]
|
66
|
-
#
|
67
|
-
# SyntaxErrorSearch.valid_without?(
|
68
|
-
# without_lines: code_lines[1],
|
69
|
-
# code_lines: code_lines
|
70
|
-
# ) # => true
|
71
|
-
#
|
72
|
-
# SyntaxErrorSearch.valid?(code_lines) # => false
|
73
|
-
def self.valid_without?(without_lines: , code_lines:)
|
74
|
-
lines = code_lines - Array(without_lines).flatten
|
75
|
-
|
76
|
-
if lines.empty?
|
77
|
-
return true
|
78
|
-
else
|
79
|
-
return valid?(lines)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def self.invalid?(source)
|
84
|
-
source = source.join if source.is_a?(Array)
|
85
|
-
source = source.to_s
|
86
|
-
|
87
|
-
Ripper.new(source).tap(&:parse).error?
|
88
|
-
end
|
89
|
-
|
90
|
-
# Returns truthy if a given input source is valid syntax
|
91
|
-
#
|
92
|
-
# SyntaxErrorSearch.valid?(<<~EOM) # => true
|
93
|
-
# def foo
|
94
|
-
# end
|
95
|
-
# EOM
|
96
|
-
#
|
97
|
-
# SyntaxErrorSearch.valid?(<<~EOM) # => false
|
98
|
-
# def foo
|
99
|
-
# def bar # Syntax error here
|
100
|
-
# end
|
101
|
-
# EOM
|
102
|
-
#
|
103
|
-
# You can also pass in an array of lines and they'll be
|
104
|
-
# joined before evaluating
|
105
|
-
#
|
106
|
-
# SyntaxErrorSearch.valid?(
|
107
|
-
# [
|
108
|
-
# "def foo\n",
|
109
|
-
# "end\n"
|
110
|
-
# ]
|
111
|
-
# ) # => true
|
112
|
-
#
|
113
|
-
# SyntaxErrorSearch.valid?(
|
114
|
-
# [
|
115
|
-
# "def foo\n",
|
116
|
-
# " def bar\n", # Syntax error here
|
117
|
-
# "end\n"
|
118
|
-
# ]
|
119
|
-
# ) # => false
|
120
|
-
#
|
121
|
-
# As an FYI the CodeLine class instances respond to `to_s`
|
122
|
-
# so passing a CodeLine in as an object or as an array
|
123
|
-
# will convert it to it's code representation.
|
124
|
-
def self.valid?(source)
|
125
|
-
!invalid?(source)
|
126
|
-
end
|
127
|
-
|
128
|
-
|
129
|
-
def self.invalid_type(source)
|
130
|
-
WhoDisSyntaxError.new(source).call.error_symbol
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
require_relative "syntax_search/code_line"
|
135
|
-
require_relative "syntax_search/code_block"
|
136
|
-
require_relative "syntax_search/code_frontier"
|
137
|
-
require_relative "syntax_search/display_invalid_blocks"
|
138
|
-
require_relative "syntax_search/around_block_scan"
|
139
|
-
require_relative "syntax_search/block_expand"
|
140
|
-
require_relative "syntax_search/parse_blocks_from_indent_line"
|
141
|
-
|
142
|
-
require_relative "syntax_search/code_search"
|
143
|
-
require_relative "syntax_search/who_dis_syntax_error"
|
144
|
-
require_relative "syntax_search/heredoc_block_parse"
|
145
|
-
require_relative "syntax_search/lex_all"
|
@@ -1,193 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
#
|
3
|
-
module SyntaxErrorSearch
|
4
|
-
# This class is useful for exploring contents before and after
|
5
|
-
# a block
|
6
|
-
#
|
7
|
-
# It searches above and below the passed in block to match for
|
8
|
-
# whatever criteria you give it:
|
9
|
-
#
|
10
|
-
# Example:
|
11
|
-
#
|
12
|
-
# def dog
|
13
|
-
# puts "bark"
|
14
|
-
# puts "bark"
|
15
|
-
# end
|
16
|
-
#
|
17
|
-
# scan = AroundBlockScan.new(
|
18
|
-
# code_lines: code_lines
|
19
|
-
# block: CodeBlock.new(lines: code_lines[1])
|
20
|
-
# )
|
21
|
-
#
|
22
|
-
# scan.scan_while { true }
|
23
|
-
#
|
24
|
-
# puts scan.before_index # => 0
|
25
|
-
# puts scan.after_index # => 3
|
26
|
-
#
|
27
|
-
# Contents can also be filtered using AroundBlockScan#skip
|
28
|
-
#
|
29
|
-
# To grab the next surrounding indentation use AroundBlockScan#scan_adjacent_indent
|
30
|
-
class AroundBlockScan
|
31
|
-
def initialize(code_lines: , block:)
|
32
|
-
@code_lines = code_lines
|
33
|
-
@orig_before_index = block.lines.first.index
|
34
|
-
@orig_after_index = block.lines.last.index
|
35
|
-
@orig_indent = block.current_indent
|
36
|
-
@skip_array = []
|
37
|
-
@after_array = []
|
38
|
-
@before_array = []
|
39
|
-
@stop_after_kw = false
|
40
|
-
end
|
41
|
-
|
42
|
-
def skip(name)
|
43
|
-
@skip_array << name
|
44
|
-
self
|
45
|
-
end
|
46
|
-
|
47
|
-
def stop_after_kw
|
48
|
-
@stop_after_kw = true
|
49
|
-
self
|
50
|
-
end
|
51
|
-
|
52
|
-
def scan_while(&block)
|
53
|
-
stop_next = false
|
54
|
-
|
55
|
-
kw_count = 0
|
56
|
-
end_count = 0
|
57
|
-
@before_index = before_lines.reverse_each.take_while do |line|
|
58
|
-
next false if stop_next
|
59
|
-
next true if @skip_array.detect {|meth| line.send(meth) }
|
60
|
-
|
61
|
-
kw_count += 1 if line.is_kw?
|
62
|
-
end_count += 1 if line.is_end?
|
63
|
-
if @stop_after_kw && kw_count > end_count
|
64
|
-
stop_next = true
|
65
|
-
end
|
66
|
-
|
67
|
-
block.call(line)
|
68
|
-
end.reverse.first&.index
|
69
|
-
|
70
|
-
stop_next = false
|
71
|
-
kw_count = 0
|
72
|
-
end_count = 0
|
73
|
-
@after_index = after_lines.take_while do |line|
|
74
|
-
next false if stop_next
|
75
|
-
next true if @skip_array.detect {|meth| line.send(meth) }
|
76
|
-
|
77
|
-
kw_count += 1 if line.is_kw?
|
78
|
-
end_count += 1 if line.is_end?
|
79
|
-
if @stop_after_kw && end_count > kw_count
|
80
|
-
stop_next = true
|
81
|
-
end
|
82
|
-
|
83
|
-
block.call(line)
|
84
|
-
end.last&.index
|
85
|
-
self
|
86
|
-
end
|
87
|
-
|
88
|
-
def capture_neighbor_context
|
89
|
-
lines = []
|
90
|
-
kw_count = 0
|
91
|
-
end_count = 0
|
92
|
-
before_lines.reverse.each do |line|
|
93
|
-
next if line.empty?
|
94
|
-
break if line.indent < @orig_indent
|
95
|
-
next if line.indent != @orig_indent
|
96
|
-
|
97
|
-
kw_count += 1 if line.is_kw?
|
98
|
-
end_count += 1 if line.is_end?
|
99
|
-
if kw_count != 0 && kw_count == end_count
|
100
|
-
lines << line
|
101
|
-
break
|
102
|
-
end
|
103
|
-
|
104
|
-
lines << line
|
105
|
-
end
|
106
|
-
|
107
|
-
lines.reverse!
|
108
|
-
|
109
|
-
kw_count = 0
|
110
|
-
end_count = 0
|
111
|
-
after_lines.each do |line|
|
112
|
-
# puts "line: #{line.number} #{line.original_line}, indent: #{line.indent}, #{line.empty?} #{line.indent == @orig_indent}"
|
113
|
-
|
114
|
-
next if line.empty?
|
115
|
-
break if line.indent < @orig_indent
|
116
|
-
next if line.indent != @orig_indent
|
117
|
-
|
118
|
-
kw_count += 1 if line.is_kw?
|
119
|
-
end_count += 1 if line.is_end?
|
120
|
-
if kw_count != 0 && kw_count == end_count
|
121
|
-
lines << line
|
122
|
-
break
|
123
|
-
end
|
124
|
-
|
125
|
-
lines << line
|
126
|
-
end
|
127
|
-
lines.select! {|line| !line.is_comment? }
|
128
|
-
|
129
|
-
lines
|
130
|
-
end
|
131
|
-
|
132
|
-
def on_falling_indent
|
133
|
-
last_indent = @orig_indent
|
134
|
-
before_lines.reverse.each do |line|
|
135
|
-
next if line.empty?
|
136
|
-
if line.indent < last_indent
|
137
|
-
yield line
|
138
|
-
last_indent = line.indent
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
last_indent = @orig_indent
|
143
|
-
after_lines.each do |line|
|
144
|
-
next if line.empty?
|
145
|
-
if line.indent < last_indent
|
146
|
-
yield line
|
147
|
-
last_indent = line.indent
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def scan_neighbors
|
153
|
-
self.scan_while {|line| line.not_empty? && line.indent >= @orig_indent }
|
154
|
-
end
|
155
|
-
|
156
|
-
def scan_adjacent_indent
|
157
|
-
before_indent = @code_lines[@orig_before_index.pred]&.indent || 0
|
158
|
-
after_indent = @code_lines[@orig_after_index.next]&.indent || 0
|
159
|
-
|
160
|
-
indent = [before_indent, after_indent].min
|
161
|
-
self.scan_while {|line| line.not_empty? && line.indent >= indent }
|
162
|
-
|
163
|
-
self
|
164
|
-
end
|
165
|
-
|
166
|
-
def start_at_next_line
|
167
|
-
before_index; after_index
|
168
|
-
@before_index -= 1
|
169
|
-
@after_index += 1
|
170
|
-
self
|
171
|
-
end
|
172
|
-
|
173
|
-
def code_block
|
174
|
-
CodeBlock.new(lines: @code_lines[before_index..after_index])
|
175
|
-
end
|
176
|
-
|
177
|
-
def before_index
|
178
|
-
@before_index ||= @orig_before_index
|
179
|
-
end
|
180
|
-
|
181
|
-
def after_index
|
182
|
-
@after_index ||= @orig_after_index
|
183
|
-
end
|
184
|
-
|
185
|
-
private def before_lines
|
186
|
-
@code_lines[0...@orig_before_index]
|
187
|
-
end
|
188
|
-
|
189
|
-
private def after_lines
|
190
|
-
@code_lines[@orig_after_index.next..-1]
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|