bullet_train-super_scaffolding 1.2.9 → 1.2.10

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: 850aff688799324e6aea7b1569259f09160a10401a2f298fec0c81a9ec418658
4
- data.tar.gz: f8fbdf234386a2931731c6e82efdd8fd2ee99f4d627bad2b1fdd07fd3fd32c30
3
+ metadata.gz: 6a6b8531f537d4602893ec912e8b2a5d4c0098418d247273d0bd3b06f6bc6b52
4
+ data.tar.gz: 2df15d02e422183c0ff5120e886081cde75396ec444fce92c5ec3e0c28c20f81
5
5
  SHA512:
6
- metadata.gz: 671b90bc86112e8babd7d93fc9360257b092498438b4a8f46923ac43d9039f7f0b9f289d340803574162dd2b0e4f31cce98c22bc20ba544ed30f8caace3d14ea
7
- data.tar.gz: 8cc555f6a9f895f67eb6ee2abbae34c109fcce6b75794c5788a5fd45d9bc686c9babd4d5d8ba664d73efc03102ebcbc0eae9f6a048eecca0a0fcc40069b47ff6
6
+ metadata.gz: fe62bc608b0af044613a6a6d6ef2653f8143a76ef3f0e261df8d77ccdc98460f78349267624791c261b8c9be0b223c75e53179e189b7c4343b821bc0c5719cf6
7
+ data.tar.gz: 1191a1288797016d937ba7d8af3a466dda7050545d65a3bc3b58ebf28eca98792554f65280ea94f8e30d559cd478bd215beb0c7f307ec3ab66241e874fc9b532
@@ -1,5 +1,5 @@
1
1
  module BulletTrain
2
2
  module SuperScaffolding
3
- VERSION = "1.2.9"
3
+ VERSION = "1.2.10"
4
4
  end
5
5
  end
@@ -1,209 +1,242 @@
1
1
  require "scaffolding/file_manipulator"
2
2
 
3
- module Scaffolding::BlockManipulator
4
- #
5
- # Wrap a block of ruby code with another block on the outside.
6
- #
7
- # @param [String] `starting` A string to search for at the start of the block. Eg "<%= updates_for context, collection do"
8
- # @param [Array] `with` An array with two String elements. The text that should wrap the block. Eg ["<%= action_model_select_controller do %>", "<% end %>"]
9
- #
10
- def self.wrap_block(starting:, with:, lines:)
11
- with[0] += "\n" unless with[0].match?(/\n$/)
12
- with[1] += "\n" unless with[1].match?(/\n$/)
13
- starting_line = find_block_start(starting_from: starting, lines: lines)
14
- end_line = find_block_end(starting_from: starting_line, lines: lines)
15
-
16
- final = []
17
- block_indent = ""
18
- spacer = " "
19
- lines.each_with_index do |line, index|
20
- line += "\n" unless line.match?(/\n$/)
21
- if index < starting_line
22
- final << line
23
- elsif index == starting_line
24
- block_indent = line.match(/^\s*/).to_s
25
- final << block_indent + with[0]
26
- final << (line.blank? ? "\n" : "#{spacer}#{line}")
27
- elsif index > starting_line && index < end_line
28
- final << (line.blank? ? "\n" : "#{spacer}#{line}")
29
- elsif index == end_line
30
- final << (line.blank? ? "\n" : "#{spacer}#{line}")
31
- final << block_indent + with[1]
32
- else
33
- final << line
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
- lines = final
38
- unless lines.last.match?(/\n$/)
39
- lines[-1] += "\n"
40
- end
41
- lines
42
- end
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
- # This method unwraps the block from the perspective of the child.
45
- #
46
- # 2.times do
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
- # Find the proper indices for both child and parent blocks.
61
- block_parent_start = find_block_parent(block_start, lines)
62
- block_parent_end = find_block_end(starting_from: block_parent_start, lines: lines)
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
- new_lines = shift_block(lines: lines, block_start: block_start)
65
- new_lines.reject.with_index { |lines, idx| idx == block_parent_start || idx == block_parent_end }
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
- def self.insert(content, lines:, within: nil, after: nil, before: nil, after_block: nil, append: false)
69
- # Search for before like we do after, we'll just inject before it.
70
- after ||= before
71
-
72
- # If within is given, find the start and end lines of the block
73
- content += "\n" unless content.match?(/\n$/)
74
- start_line = 0
75
- end_line = lines.count - 1
76
- if within.present?
77
- start_line = find_block_start(starting_from: within, lines: lines)
78
- end_line = find_block_end(starting_from: start_line, lines: lines)
79
- # start_line += 1 # ensure we actually insert the content _within_ the given block
80
- # end_line += 1 if end_line == start_line
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
- return lines if match
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
- # Match should always be false here.
105
- if append && !match
106
- lines = insert_line(content, index - 1, lines)
107
- end
108
- lines
109
- end
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
- def self.insert_line(content, insert_at_index, lines)
112
- content += "\n" unless content.match?(/\n$/)
113
- final = []
114
- lines.each_with_index do |line, index|
115
- indent = line.match(/^\s*/).to_s
116
- final << line
117
- if index == insert_at_index
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
- def self.insert_block(block_content, after_block:, lines:)
125
- block_start = find_block_start(starting_from: after_block, lines: lines)
126
- block_end = find_block_end(starting_from: block_start, lines: lines)
127
- lines = insert_line(block_content[0], block_end, lines)
128
- insert_line(block_content[1], block_end + 1, lines)
129
- end
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
- def self.find_block_parent(starting_line_number, lines)
132
- return nil unless indentation_of(starting_line_number, lines)
133
- cursor = starting_line_number
134
- while cursor >= 0
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
- def self.find_block_start(starting_from:, lines:)
144
- matcher = Regexp.escape(starting_from)
145
- starting_line = 0
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
- lines.each_with_index do |line, index|
148
- if line.match?(matcher)
149
- starting_line = index
150
- break
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
- def self.find_block_end(starting_from:, lines:)
157
- # This loop was previously in the RoutesFileManipulator.
158
- lines.each_with_index do |line, line_number|
159
- next unless line_number > starting_from
160
- if /^#{indentation_of(starting_from, lines)}end\s*/.match?(line)
161
- return line_number
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
- depth = 0
166
- current_line = starting_from
167
- lines[starting_from..lines.count].each_with_index do |line, index|
168
- current_line = starting_from + index
169
- depth += 1 if line.match?(/\s*<%.+ do .*%>/)
170
- depth += 1 if line.match?(/\s*<% if .*%>/)
171
- depth += 1 if line.match?(/\s*<% unless .*%>/)
172
- depth -= 1 if line.match?(/\s*<%.* end .*%>/)
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
- # TODO: We shouldn't need this second argument, but since
179
- # we have `lines` here and in the RoutesFileManipulator,
180
- # the lines diverge from one another when we edit them individually.
181
- def self.indentation_of(line_number, lines)
182
- lines[line_number].match(/^( +)/)[1]
183
- rescue
184
- nil
185
- end
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
- # Shifts the block either to the left or right.
188
- def self.shift_block(lines:, block_start:, direction: :left, amount: 2, shift_contents_only: false)
189
- block_start = lines.index(block_start) if block_start.is_a? String
190
- block_range = (block_start..(find_block_end(starting_from: block_start, lines: lines)))
191
- block_range = (block_range.first + 1)..(block_range.last - 1) if shift_contents_only
192
- new_lines = []
193
-
194
- lines.each_with_index do |line, line_number|
195
- if block_range.cover?(line_number)
196
- # If we're shifting a block to the left, we want to safeguard
197
- # the String so it doesn't delete any excess characters.
198
- if direction == :left
199
- amount.times { line = line.gsub(/^\s/, "") }
200
- elsif direction == :right
201
- line = "\s" * amount + line
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
- new_lines
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.9
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-28 00:00:00.000000000 Z
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.3.7
201
+ rubygems_version: 3.4.1
202
202
  signing_key:
203
203
  specification_version: 4
204
204
  summary: Bullet Train Super Scaffolding