bullet_train-super_scaffolding 1.2.9 → 1.2.10
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 +4 -4
- data/lib/bullet_train/super_scaffolding/version.rb +1 -1
- data/lib/scaffolding/block_manipulator.rb +213 -180
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6a6b8531f537d4602893ec912e8b2a5d4c0098418d247273d0bd3b06f6bc6b52
|
4
|
+
data.tar.gz: 2df15d02e422183c0ff5120e886081cde75396ec444fce92c5ec3e0c28c20f81
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe62bc608b0af044613a6a6d6ef2653f8143a76ef3f0e261df8d77ccdc98460f78349267624791c261b8c9be0b223c75e53179e189b7c4343b821bc0c5719cf6
|
7
|
+
data.tar.gz: 1191a1288797016d937ba7d8af3a466dda7050545d65a3bc3b58ebf28eca98792554f65280ea94f8e30d559cd478bd215beb0c7f307ec3ab66241e874fc9b532
|
@@ -1,209 +1,242 @@
|
|
1
1
|
require "scaffolding/file_manipulator"
|
2
2
|
|
3
|
-
module Scaffolding
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
3
|
+
module Scaffolding
|
4
|
+
class BlockManipulator
|
5
|
+
class << self
|
6
|
+
#
|
7
|
+
# Wrap a block of ruby code with another block on the outside.
|
8
|
+
#
|
9
|
+
# @param [String] `starting` A string to search for at the start of the block. Eg "<%= updates_for context, collection do"
|
10
|
+
# @param [Array] `with` An array with two String elements. The text that should wrap the block. Eg ["<%= action_model_select_controller do %>", "<% end %>"]
|
11
|
+
#
|
12
|
+
def wrap_block(starting:, with:, lines:)
|
13
|
+
with[0] += "\n" unless with[0].match?(/\n$/)
|
14
|
+
with[1] += "\n" unless with[1].match?(/\n$/)
|
15
|
+
starting_line = find_block_start(starting_from: starting, lines: lines)
|
16
|
+
end_line = find_block_end(starting_from: starting_line, lines: lines)
|
17
|
+
|
18
|
+
final = []
|
19
|
+
block_indent = ""
|
20
|
+
spacer = " "
|
21
|
+
lines.each_with_index do |line, index|
|
22
|
+
line += "\n" unless line.match?(/\n$/)
|
23
|
+
if index < starting_line
|
24
|
+
final << line
|
25
|
+
elsif index == starting_line
|
26
|
+
block_indent = line.match(/^\s*/).to_s
|
27
|
+
final << block_indent + with[0]
|
28
|
+
final << (line.blank? ? "\n" : "#{spacer}#{line}")
|
29
|
+
elsif index > starting_line && index < end_line
|
30
|
+
final << (line.blank? ? "\n" : "#{spacer}#{line}")
|
31
|
+
elsif index == end_line
|
32
|
+
final << (line.blank? ? "\n" : "#{spacer}#{line}")
|
33
|
+
final << block_indent + with[1]
|
34
|
+
else
|
35
|
+
final << line
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
lines = final
|
40
|
+
unless lines.last.match?(/\n$/)
|
41
|
+
lines[-1] += "\n"
|
42
|
+
end
|
43
|
+
lines
|
34
44
|
end
|
35
|
-
end
|
36
45
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
46
|
+
# This method unwraps the block from the perspective of the child.
|
47
|
+
#
|
48
|
+
# 2.times do
|
49
|
+
# 3.times do
|
50
|
+
# puts "foo"
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# Here we would pass the index of `"3.times do\n"` to
|
55
|
+
# `block_start` which would result in removing the outer block.
|
56
|
+
def unwrap_block(lines:, block_start:)
|
57
|
+
block_start = if block_start.is_a? String
|
58
|
+
block_start_line = lines.find { |line| line.match?(block_start) }
|
59
|
+
lines.index(block_start_line)
|
60
|
+
end
|
43
61
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
# 3.times do
|
48
|
-
# puts "foo"
|
49
|
-
# end
|
50
|
-
# end
|
51
|
-
#
|
52
|
-
# Here we would pass the index of `"3.times do\n"` to
|
53
|
-
# `block_start` which would result in removing the outer block.
|
54
|
-
def self.unwrap_block(lines:, block_start:)
|
55
|
-
block_start = if block_start.is_a? String
|
56
|
-
block_start_line = lines.find { |line| line.match?(block_start) }
|
57
|
-
lines.index(block_start_line)
|
58
|
-
end
|
62
|
+
# Find the proper indices for both child and parent blocks.
|
63
|
+
block_parent_start = find_block_parent(block_start, lines)
|
64
|
+
block_parent_end = find_block_end(starting_from: block_parent_start, lines: lines)
|
59
65
|
|
60
|
-
|
61
|
-
|
62
|
-
|
66
|
+
new_lines = shift_block(lines: lines, block_start: block_start)
|
67
|
+
new_lines.reject.with_index { |lines, idx| idx == block_parent_start || idx == block_parent_end }
|
68
|
+
end
|
63
69
|
|
64
|
-
|
65
|
-
|
66
|
-
end
|
70
|
+
def insert(content, lines:, within: nil, after: nil, before: nil, after_block: nil, append: false)
|
71
|
+
content = prepare_content_array(content)
|
67
72
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
if after_block.present?
|
83
|
-
block_start = find_block_start(starting_from: after_block, lines: lines)
|
84
|
-
block_end = find_block_end(starting_from: block_start, lines: lines)
|
85
|
-
start_line = block_end
|
86
|
-
end_line = lines.count - 1
|
87
|
-
end
|
88
|
-
index = start_line
|
89
|
-
match = false
|
90
|
-
while index < end_line && !match
|
91
|
-
line = lines[index]
|
92
|
-
if after.nil? || line.match?(after)
|
93
|
-
unless append
|
94
|
-
match = true
|
95
|
-
# We adjust the injection point if we really wanted to insert before.
|
96
|
-
lines = insert_line(content, index - (before ? 1 : 0), lines)
|
73
|
+
# We initialize the search with the entire file's lines and look for the block below.
|
74
|
+
start_line = 0
|
75
|
+
end_line = lines.count - 1
|
76
|
+
|
77
|
+
# Search for before like we do after, we'll just inject before it.
|
78
|
+
after ||= before
|
79
|
+
|
80
|
+
# If within is given, find the start and end lines of the block
|
81
|
+
if within.present?
|
82
|
+
start_line = find_block_start(starting_from: within, lines: lines)
|
83
|
+
end_line = find_block_end(starting_from: start_line, lines: lines)
|
84
|
+
# start_line += 1 # ensure we actually insert the content _within_ the given block
|
85
|
+
# end_line += 1 if end_line == start_line
|
97
86
|
end
|
98
|
-
end
|
99
|
-
index += 1
|
100
|
-
end
|
101
87
|
|
102
|
-
|
88
|
+
if after_block.present?
|
89
|
+
block_start = find_block_start(starting_from: after_block, lines: lines)
|
90
|
+
block_end = find_block_end(starting_from: block_start, lines: lines)
|
91
|
+
start_line = block_end
|
92
|
+
end_line = lines.count - 1
|
93
|
+
end
|
103
94
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
95
|
+
index = start_line
|
96
|
+
match = false
|
97
|
+
while index < end_line && !match
|
98
|
+
line = lines[index]
|
99
|
+
if after.nil? || line.match?(after)
|
100
|
+
unless append
|
101
|
+
match = true
|
102
|
+
indent = !(before.present? || after.present? || after_block.present?)
|
103
|
+
|
104
|
+
# We adjust the injection point if we really wanted to insert before.
|
105
|
+
lines = insert_lines(content, index - (before ? 1 : 0), lines, indent)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
index += 1
|
109
|
+
end
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
final << indent + content
|
111
|
+
return lines if match
|
112
|
+
|
113
|
+
# Match should always be false here.
|
114
|
+
if append && !match
|
115
|
+
lines = insert_lines(content, index - 1, lines)
|
116
|
+
end
|
117
|
+
lines
|
119
118
|
end
|
120
|
-
end
|
121
|
-
final
|
122
|
-
end
|
123
119
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
120
|
+
def insert_lines(content, insert_at_index, lines, indent)
|
121
|
+
final = []
|
122
|
+
lines.each_with_index do |line, index|
|
123
|
+
indentation = line.match(/^\s*/).to_s
|
124
|
+
indentation += "\s" * 2 if indent
|
125
|
+
|
126
|
+
final << line
|
127
|
+
content.each { |new_line| final << indentation + new_line } if index == insert_at_index
|
128
|
+
end
|
129
|
+
final
|
130
|
+
end
|
130
131
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
unless lines[cursor].match?(/^#{indentation_of(starting_line_number, lines)}/) || !lines[cursor].present?
|
136
|
-
return cursor
|
132
|
+
# TODO: We should eventually replace this with `insert_lines``,
|
133
|
+
# I just want to make sure everything doesn't break first.
|
134
|
+
def insert_line(content, insert_at_index, lines, indent = true)
|
135
|
+
insert_lines(prepare_content_array(content), insert_at_index, lines, indent)
|
137
136
|
end
|
138
|
-
cursor -= 1
|
139
|
-
end
|
140
|
-
nil
|
141
|
-
end
|
142
137
|
|
143
|
-
|
144
|
-
|
145
|
-
|
138
|
+
def insert_block(block_content, after_block:, lines:)
|
139
|
+
# Since `after_block` must be present for this method to work,
|
140
|
+
# the assumption is we never inseart a block inside an empty block, but
|
141
|
+
# always after the end of one. For that reason, ident defaults to false.
|
142
|
+
indent = false
|
143
|
+
block_start = find_block_start(starting_from: after_block, lines: lines)
|
144
|
+
block_end = find_block_end(starting_from: block_start, lines: lines)
|
145
|
+
lines = insert_line(block_content[0], block_end, lines, indent)
|
146
|
+
insert_line(block_content[1], block_end + 1, lines, indent)
|
147
|
+
end
|
146
148
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
149
|
+
def find_block_parent(starting_line_number, lines)
|
150
|
+
return nil unless indentation_of(starting_line_number, lines)
|
151
|
+
cursor = starting_line_number
|
152
|
+
while cursor >= 0
|
153
|
+
unless lines[cursor].match?(/^#{indentation_of(starting_line_number, lines)}/) || !lines[cursor].present?
|
154
|
+
return cursor
|
155
|
+
end
|
156
|
+
cursor -= 1
|
157
|
+
end
|
158
|
+
nil
|
151
159
|
end
|
152
|
-
end
|
153
|
-
starting_line
|
154
|
-
end
|
155
160
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
161
|
+
def find_block_start(starting_from:, lines:)
|
162
|
+
matcher = Regexp.escape(starting_from)
|
163
|
+
starting_line = 0
|
164
|
+
|
165
|
+
lines.each_with_index do |line, index|
|
166
|
+
if line.match?(matcher)
|
167
|
+
starting_line = index
|
168
|
+
break
|
169
|
+
end
|
170
|
+
end
|
171
|
+
starting_line
|
162
172
|
end
|
163
|
-
end
|
164
173
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
break current_line if depth == 0
|
174
|
-
end
|
175
|
-
current_line
|
176
|
-
end
|
174
|
+
def find_block_end(starting_from:, lines:)
|
175
|
+
# This loop was previously in the RoutesFileManipulator.
|
176
|
+
lines.each_with_index do |line, line_number|
|
177
|
+
next unless line_number > starting_from
|
178
|
+
if /^#{indentation_of(starting_from, lines)}end\s*/.match?(line)
|
179
|
+
return line_number
|
180
|
+
end
|
181
|
+
end
|
177
182
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
183
|
+
depth = 0
|
184
|
+
current_line = starting_from
|
185
|
+
lines[starting_from..lines.count].each_with_index do |line, index|
|
186
|
+
current_line = starting_from + index
|
187
|
+
depth += 1 if line.match?(/\s*<%.+ do .*%>/)
|
188
|
+
depth += 1 if line.match?(/\s*<% if .*%>/)
|
189
|
+
depth += 1 if line.match?(/\s*<% unless .*%>/)
|
190
|
+
depth -= 1 if line.match?(/\s*<%.* end .*%>/)
|
191
|
+
break current_line if depth == 0
|
192
|
+
end
|
193
|
+
current_line
|
194
|
+
end
|
186
195
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
if
|
199
|
-
|
200
|
-
|
201
|
-
|
196
|
+
# TODO: We shouldn't need this second argument, but since
|
197
|
+
# we have `lines` here and in the RoutesFileManipulator,
|
198
|
+
# the lines diverge from one another when we edit them individually.
|
199
|
+
def indentation_of(line_number, lines)
|
200
|
+
lines[line_number].match(/^( +)/)[1]
|
201
|
+
rescue
|
202
|
+
nil
|
203
|
+
end
|
204
|
+
|
205
|
+
# Shifts the block either to the left or right.
|
206
|
+
def shift_block(lines:, block_start:, direction: :left, amount: 2, shift_contents_only: false)
|
207
|
+
block_start = lines.index(block_start) if block_start.is_a? String
|
208
|
+
block_range = (block_start..(find_block_end(starting_from: block_start, lines: lines)))
|
209
|
+
block_range = (block_range.first + 1)..(block_range.last - 1) if shift_contents_only
|
210
|
+
new_lines = []
|
211
|
+
|
212
|
+
lines.each_with_index do |line, line_number|
|
213
|
+
if block_range.cover?(line_number)
|
214
|
+
# If we're shifting a block to the left, we want to safeguard
|
215
|
+
# the String so it doesn't delete any excess characters.
|
216
|
+
if direction == :left
|
217
|
+
amount.times { line = line.gsub(/^\s/, "") }
|
218
|
+
elsif direction == :right
|
219
|
+
line = "\s" * amount + line
|
220
|
+
end
|
221
|
+
end
|
222
|
+
new_lines << line
|
202
223
|
end
|
224
|
+
|
225
|
+
new_lines
|
203
226
|
end
|
204
|
-
new_lines << line
|
205
|
-
end
|
206
227
|
|
207
|
-
|
228
|
+
private
|
229
|
+
|
230
|
+
def prepare_content_array(content)
|
231
|
+
# Ensure content is an Array
|
232
|
+
content = [content].flatten
|
233
|
+
|
234
|
+
# Ensure there are no stray new lines within each string
|
235
|
+
content = content.map { |line| line.split("\n") }.flatten
|
236
|
+
|
237
|
+
# Ensure each new line has a line break at the end.
|
238
|
+
content.map { |line| line.match?(/\n$/) ? line : "#{line}\n" }
|
239
|
+
end
|
240
|
+
end
|
208
241
|
end
|
209
242
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bullet_train-super_scaffolding
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Culver
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
11
|
+
date: 2022-12-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: standard
|
@@ -198,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
198
|
- !ruby/object:Gem::Version
|
199
199
|
version: '0'
|
200
200
|
requirements: []
|
201
|
-
rubygems_version: 3.
|
201
|
+
rubygems_version: 3.4.1
|
202
202
|
signing_key:
|
203
203
|
specification_version: 4
|
204
204
|
summary: Bullet Train Super Scaffolding
|