ruby-beautify 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,119 @@
1
+ module RBeautify
2
+
3
+ class BlockStart
4
+
5
+ attr_reader :block_matcher, :parent, :offset, :match, :after_match, :line_number
6
+
7
+ class << self
8
+ def first_common_ancestor(first, second)
9
+ if first.nil? || second.nil?
10
+ nil
11
+ else
12
+ (first.ancestors & second.ancestors).last
13
+ end
14
+ end
15
+ end
16
+
17
+ def initialize(block_matcher, parent, line_number, offset, match, after_match)
18
+ @block_matcher = block_matcher
19
+ @parent = parent
20
+ @offset = offset
21
+ @match = match
22
+ @after_match = after_match
23
+ @line_number = line_number
24
+ end
25
+
26
+ def end_offset
27
+ offset + match.length
28
+ end
29
+
30
+ def parse_block_end(string, offset)
31
+ block_end = parse_explicit_block_end(string, offset)
32
+
33
+ # Handle case where end is implicit
34
+ if block_end.nil? && end_is_implicit? && parent
35
+ block_end = parent.parse_block_end(string, offset)
36
+ end
37
+
38
+ block_end
39
+ end
40
+
41
+ def format_content?
42
+ block_matcher.format_content?
43
+ end
44
+
45
+ def parse_content?
46
+ block_matcher.parse_content?
47
+ end
48
+
49
+ def indent_end_line?
50
+ block_matcher.indent_end_line?(self)
51
+ end
52
+
53
+ def total_indent_size
54
+ parent.nil? ? indent_size : parent.total_indent_size + indent_size
55
+ end
56
+
57
+ def indent_size
58
+ block_matcher.indent_size(self)
59
+ end
60
+
61
+ def end_is_implicit?
62
+ block_matcher.end_is_implicit?
63
+ end
64
+
65
+ def name
66
+ block_matcher.name
67
+ end
68
+
69
+ # Returns true if strict ancestor of
70
+ def strict_ancestor_of?(block_start)
71
+ block_start && block_start.parent && (self == block_start.parent || strict_ancestor_of?(block_start.parent))
72
+ end
73
+
74
+ def ancestors
75
+ if parent
76
+ parent.ancestors + [self]
77
+ else
78
+ [self]
79
+ end
80
+ end
81
+
82
+ private
83
+ def ends?
84
+ block_matcher.ends?
85
+ end
86
+
87
+ def negate_ends_match?
88
+ block_matcher.negate_ends_match?
89
+ end
90
+
91
+ def escape_character?
92
+ block_matcher.escape_character?
93
+ end
94
+
95
+ def parse_explicit_block_end(string, offset)
96
+ block_end = nil
97
+
98
+ if ends?
99
+
100
+ if match = block_matcher.ends.match(string)
101
+ unless negate_ends_match?
102
+ if escape_character? &&
103
+ ((escape_chars = match.pre_match.match(/\\*$/)) && (escape_chars[0].size % 2 == 1))
104
+ # If there are an odd number of escape characters just before
105
+ # the match then this match should be skipped
106
+ return parse_explicit_block_end(match.post_match, offset + escape_chars[0].size + match[0].length)
107
+ else
108
+ return RBeautify::BlockEnd.new(self, offset + match.begin(0), match[0], match.post_match)
109
+ end
110
+ end
111
+ elsif negate_ends_match?
112
+ return RBeautify::BlockEnd.new(self, offset, '', string)
113
+ end
114
+
115
+ end
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,131 @@
1
+ # define ruby language
2
+
3
+ unless RBeautify::Language.language(:ruby)
4
+
5
+ ruby = RBeautify::Language.add_language(:ruby)
6
+
7
+ pre_keyword_boundary = '(^|[^a-z0-9A-Z:._])' # like \b but with : , . _ all added to list of exceptions
8
+ start_statement_boundary = '(^|(;|=)\s*)'
9
+ continue_statement_boundary = '(^|;\s*)'
10
+ ruby.indent_size = 2
11
+
12
+ ruby.add_matcher(:program_end, /^__END__$/, false, :format_content => false, :parse_content => false)
13
+
14
+ ruby.add_matcher(:multiline_comment, /^=begin/, /^=end/, :format_content => false, :parse_content => false)
15
+
16
+ ruby.add_matcher(:double_quote,
17
+ /"/,
18
+ /"/,
19
+ :parse_content => true,
20
+ :format_content => false,
21
+ :escape_character => true,
22
+ :nest_except => [:double_quote, :single_quote, :regex, :back_tick])
23
+
24
+ # NEED TO MODIFY DOUBLE QUOTE TO BE FORMATTED to get this to work
25
+ ruby.add_matcher(:interpolation,
26
+ /#\{/,
27
+ /\}/,
28
+ :nest_only => [:double_quote, :regex, :backtick])
29
+
30
+ ruby.add_matcher(:single_quote,
31
+ /'/,
32
+ /'/,
33
+ :parse_content => false,
34
+ :format_content => false,
35
+ :escape_character => true,
36
+ :nest_except => [:double_quote, :single_quote, :regex, :back_tick])
37
+
38
+ ruby.add_matcher(:regex,
39
+ /(^|((,|=|~)\s*))\//, # Try to distinguish it from division sign
40
+ /\//,
41
+ :format_content => false,
42
+ :escape_character => true,
43
+ :end_can_also_be_start => false,
44
+ :nest_except => [:double_quote, :single_quote, :regex, :back_tick])
45
+
46
+ ruby.add_matcher(:back_tick,
47
+ /`/,
48
+ /`/,
49
+ :format_content => false,
50
+ :escape_character => true,
51
+ :nest_except => [:double_quote, :single_quote, :regex, :back_tick])
52
+
53
+ ruby.add_matcher(:standard,
54
+ /((#{start_statement_boundary}(module|class|def))|#{pre_keyword_boundary}do)\b/,
55
+ /(((^|;|\s)end)|#{continue_statement_boundary}(rescue|ensure))\b/,
56
+ :nest_except => [:double_quote, :regex, :backtick])
57
+
58
+ ruby.add_matcher(:more,
59
+ /#{start_statement_boundary}(until|for|while)\b/,
60
+ /(((^|;|\s)end)|#{continue_statement_boundary}(rescue|ensure))\b/,
61
+ :nest_except => [:double_quote, :regex, :backtick])
62
+
63
+ ruby.add_matcher(:begin,
64
+ /((#{start_statement_boundary}begin)|(#{continue_statement_boundary}(ensure|rescue)))\b/,
65
+ /(((^|;|\s)end)|#{continue_statement_boundary}(rescue|ensure|else))\b/,
66
+ :nest_except => [:double_quote, :regex, :backtick])
67
+
68
+ ruby.add_matcher(:if,
69
+ /((#{start_statement_boundary}(if|unless))|#{continue_statement_boundary}(then|elsif|else))\b/,
70
+ /(((^|;|\s)end)|(#{continue_statement_boundary}(then|elsif|else)))\b/,
71
+ :nest_except => [:case, :double_quote, :regex, :backtick])
72
+
73
+ ruby.add_matcher(:case,
74
+ /#{pre_keyword_boundary}case\b/,
75
+ /(^|;|\s)end\b/,
76
+ :nest_except => [:double_quote, :regex, :backtick],
77
+ :indent_size => 0)
78
+
79
+ ruby.add_matcher(:inner_case,
80
+ /#{continue_statement_boundary}(when|else|then)\b/,
81
+ /#{continue_statement_boundary}(when|else|then)\b/,
82
+ :nest_only => [:case],
83
+ :end => :implicit,
84
+ :end_can_also_be_start => true,
85
+ :nest_except => [:double_quote, :regex, :backtick])
86
+
87
+ # TODO: Improve the check that this is not a block with arguments. Will
88
+ # currently match any bracket followed by spaces and |.
89
+ bracket_indent_end_line_proc = Proc.new { |block| !block.after_match.empty? && !block.after_match.match(/^\|/) }
90
+ bracket_indent_size_proc = Proc.new do |block|
91
+ if bracket_indent_end_line_proc.call(block)
92
+ strict_ancestors_on_same_line = block.ancestors.select { |a| a != block && a.line_number == block.line_number }
93
+ block.end_offset - strict_ancestors_on_same_line.inject(0) { |sum, a| sum + a.indent_size }
94
+ end
95
+ end
96
+
97
+ ruby.add_matcher(:curly_bracket,
98
+ /\{\s*/,
99
+ /\}/,
100
+ :indent_end_line => bracket_indent_end_line_proc,
101
+ :indent_size => bracket_indent_size_proc,
102
+ :nest_except => [:double_quote, :regex, :backtick])
103
+
104
+ ruby.add_matcher(:round_bracket,
105
+ /\(\s*/,
106
+ /\)/,
107
+ :indent_end_line => bracket_indent_end_line_proc,
108
+ :indent_size => bracket_indent_size_proc,
109
+ :nest_except => [:double_quote, :regex, :backtick])
110
+
111
+ ruby.add_matcher(:square_bracket,
112
+ /\[\s*/,
113
+ /\]/,
114
+ :indent_end_line => bracket_indent_end_line_proc,
115
+ :indent_size => bracket_indent_size_proc,
116
+ :nest_except => [:double_quote, :regex, :backtick])
117
+
118
+ ruby.add_matcher(:comment, /(\s*)?#/,
119
+ /$/,
120
+ :parse_content => false,
121
+ :format_content => false,
122
+ :nest_except => [:double_quote, :single_quote, :regex, :back_tick])
123
+
124
+ ruby.add_matcher(:continuing_line,
125
+ /(,|\.|\+|-|=\>|=|&&|\|\||\\|==|\s\?|:|<<)(\s*)?(#.*)?$/,
126
+ /(^|(,|\.|\+|-|=\>|=|&&|\|\||\\|==|\s\?|:|<<)(\s*)?)(#.*)?$/,
127
+ :indent_end_line => true,
128
+ :negate_ends_match => true,
129
+ :nest_except => [:continuing_line, :curly_bracket, :round_bracket, :square_bracket, :double_quote, :single_quote, :regex, :back_tick])
130
+
131
+ end
@@ -0,0 +1,37 @@
1
+ module RBeautify
2
+ class Language
3
+
4
+ @@languages = {}
5
+
6
+ attr_reader :matchers
7
+ attr_accessor :indent_size
8
+
9
+ class << self
10
+
11
+ def language(name)
12
+ languages[name]
13
+ end
14
+
15
+ def languages
16
+ @@languages
17
+ end
18
+
19
+ def add_language(name)
20
+ languages[name] = new()
21
+ end
22
+ end
23
+
24
+ def initialize
25
+ @matchers = []
26
+ end
27
+
28
+ def add_matcher(name, starts, ends, options = {})
29
+ self.matchers << BlockMatcher.new(self, name, starts, ends, options)
30
+ end
31
+
32
+ def matcher(name)
33
+ self.matchers.detect { |matcher| matcher.name == name}
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,53 @@
1
+ module RBeautify
2
+ class Line
3
+
4
+ attr_reader :language, :content, :line_number, :original_block, :block, :indent_character
5
+
6
+ def initialize(language, content, line_number, original_block = nil, use_tabs = false)
7
+ @language = language
8
+ @content = content
9
+ @original_block = original_block
10
+ @indent_character = use_tabs ? "\t" : " "
11
+ @block = BlockMatcher.parse(language, original_block, line_number, stripped, 0)
12
+ end
13
+
14
+ def format
15
+ if @formatted.nil?
16
+ if format?
17
+ if stripped.length == 0
18
+ @formatted = ""
19
+ else
20
+ @formatted = tab_string + stripped
21
+ end
22
+ else
23
+ @formatted = content
24
+ end
25
+ end
26
+
27
+ @formatted
28
+ end
29
+
30
+ private
31
+ def format?
32
+ original_block.nil? || original_block.format_content?
33
+ end
34
+
35
+ def indent_size
36
+ if (block.nil? || block.strict_ancestor_of?(original_block)) && (original_block && original_block.indent_end_line?)
37
+ original_block.total_indent_size
38
+ else
39
+ common_ancestor = BlockStart.first_common_ancestor(original_block, block)
40
+ common_ancestor.nil? ? 0 : common_ancestor.total_indent_size
41
+ end
42
+ end
43
+
44
+ def tab_string
45
+ indent_character * (indent_size / 2 ) + (indent_size.odd? ? ' ' : '')
46
+ end
47
+
48
+ def stripped
49
+ @stripped = content.strip
50
+ end
51
+
52
+ end
53
+ end
data/license.txt ADDED
@@ -0,0 +1,77 @@
1
+ All software in this package is covered by the MIT license and beerware (rev42).
2
+
3
+ Copyright (c) 2011 Ernie Brodeur
4
+
5
+ Permission is hereby granted, free of charge, to any person
6
+ obtaining a copy of this software and associated documentation
7
+ files (the "Software"), to deal in the Software without
8
+ restriction, including without limitation the rights to use,
9
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the
11
+ Software is furnished to do so, subject to the following
12
+ conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ /*
27
+ * ----------------------------------------------------------------------------
28
+ * "THE BEER-WARE LICENSE" (Revision 42):
29
+ * Ernie Brodeur wrote this package. As long as you retain this notice you
30
+ * can do whatever you want with his stuff. If we meet some day, and you think
31
+ * this stuff is worth it, you can buy me a beer in return.
32
+ * ----------------------------------------------------------------------------
33
+ */
34
+
35
+ Further supported by: https://github.com/CraigWilliams/BeautifyRuby/blob/master/lib/rbeautify.rb
36
+
37
+ All of BeautifyRuby is licensed under the MIT license.
38
+
39
+ Copyright (c) 2011 Craig Williams <cwilliams.allancraig@gmail.com>
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining a copy
42
+ of this software and associated documentation files (the "Software"), to deal
43
+ in the Software without restriction, including without limitation the rights
44
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
45
+ copies of the Software, and to permit persons to whom the Software is
46
+ furnished to do so, subject to the following conditions:
47
+
48
+ The above copyright notice and this permission notice shall be included in
49
+ all copies or substantial portions of the Software.
50
+
51
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
54
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
55
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
56
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57
+ THE SOFTWARE.
58
+
59
+ Pieces provided originally by: http://www.arachnoid.com/ruby/rubyBeautifier.html
60
+
61
+ /***************************************************************************
62
+ * Copyright (C) 2008, Joel Chippindale, Paul Lutus *
63
+ * *
64
+ * This program is free software: you can redistribute it and/or modify *
65
+ * it under the terms of the GNU General Public License as published by *
66
+ * the Free Software Foundation, either version 3 of the License, or *
67
+ * (at your option) any later version. *
68
+ * *
69
+ * This program is distributed in the hope that it will be useful, *
70
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
71
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
72
+ * GNU General Public License for more details. *
73
+ * *
74
+ * You should have received a copy of the GNU General Public License *
75
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
76
+ * *
77
+ ***************************************************************************/
data/rbeautify.gemspec ADDED
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = 'ruby-beautify'
3
+ gem.version = '0.9.0'
4
+ gem.summary = "a cli tool (and module) to beautify ruby code."
5
+ gem.description = gem.summary
6
+ gem.authors = ["Ernie Brodeur", "Craig Williams", "Joel Chippindale", "Paul Lutus"]
7
+ gem.email = 'ebrodeur@ujami.net'
8
+ gem.homepage = "https://github.com/erniebrodeur/ruby-beautify"
9
+
10
+ gem.add_development_dependency "rspec"
11
+ gem.files = `git ls-files`.split("\n")
12
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
13
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
+ gem.require_paths = ["lib"]
15
+ end
@@ -0,0 +1,408 @@
1
+ - name: indent if else end statement
2
+ input: |
3
+ if foo
4
+ bar = 1
5
+ elsif foo2
6
+ bar = 2
7
+ else
8
+ bar = 3
9
+ end
10
+ output: |
11
+ if foo
12
+ bar = 1
13
+ elsif foo2
14
+ bar = 2
15
+ else
16
+ bar = 3
17
+ end
18
+
19
+ - name: handle case where if begins and ends on same line
20
+ input: |
21
+ foo do
22
+ if a then b = 1 else b = 2 end
23
+ end
24
+ output: |
25
+ foo do
26
+ if a then b = 1 else b = 2 end
27
+ end
28
+
29
+ - name: indent not double indent case/when statement
30
+ input: |
31
+ case foo
32
+ when 1
33
+ bar = 'some string'
34
+ when 2
35
+ bar = 'some other string'
36
+ when 3 then bar = '3'
37
+ else
38
+ bar = '4'
39
+ end
40
+ output: |
41
+ case foo
42
+ when 1
43
+ bar = 'some string'
44
+ when 2
45
+ bar = 'some other string'
46
+ when 3 then bar = '3'
47
+ else
48
+ bar = '4'
49
+ end
50
+
51
+ - name: indent while statement
52
+ input: |
53
+ def foo
54
+ bar = 1
55
+ while bar < 3
56
+ puts bar
57
+ bar = bar.next
58
+ end
59
+ end
60
+ output: |
61
+ def foo
62
+ bar = 1
63
+ while bar < 3
64
+ puts bar
65
+ bar = bar.next
66
+ end
67
+ end
68
+
69
+ - name: ignore code after end of line comment
70
+ input: |
71
+ def method_containing_end_of_line_comment
72
+ a = b # Comment containing do
73
+ end
74
+ output: |
75
+ def method_containing_end_of_line_comment
76
+ a = b # Comment containing do
77
+ end
78
+
79
+ - name :not indent multineline comment:
80
+ input: |
81
+ =begin
82
+ Comment
83
+ =end
84
+ foo
85
+
86
+ - name: indent lines after first of multiline code
87
+ input: |
88
+ def method_with_multiline_method_call
89
+ multiline_method_call \
90
+ first_arg,
91
+ second_arg,
92
+ third_arg
93
+ end
94
+ output: |
95
+ def method_with_multiline_method_call
96
+ multiline_method_call \
97
+ first_arg,
98
+ second_arg,
99
+ third_arg
100
+ end
101
+
102
+ - name: indent method call with bracketed multiline arguments
103
+ input: |
104
+ def method_with_multiline_method_call
105
+ multiline_method_call(foo,
106
+ bar,
107
+ foobar)
108
+ end
109
+ output: |
110
+ def method_with_multiline_method_call
111
+ multiline_method_call(foo,
112
+ bar,
113
+ foobar)
114
+ end
115
+
116
+ - name: indent method call with bracketed multiline arguments_even_if_not_first_block_on_line
117
+ input: |
118
+ if (foo = bar(first_arg,
119
+ second_arg))
120
+ do_something
121
+ end
122
+ output: |
123
+ if (foo = bar(first_arg,
124
+ second_arg))
125
+ do_something
126
+ end
127
+
128
+ - name: indent method call with multiline arguments (implicit brackets)
129
+ input: |
130
+ def method_with_multiline_method_call
131
+ multiline_method_call first_arg,
132
+ second_arg,
133
+ # Comment in the middle of all this
134
+ third_arg
135
+
136
+ another_method_call
137
+ end
138
+ output: |
139
+ def method_with_multiline_method_call
140
+ multiline_method_call first_arg,
141
+ second_arg,
142
+ # Comment in the middle of all this
143
+ third_arg
144
+
145
+ another_method_call
146
+ end
147
+
148
+ - name: should indent multiline method call chains
149
+ input: |
150
+ def method_with_multiline_method_call_chain
151
+ multiline_method_call.
152
+ foo.
153
+ bar
154
+
155
+ another_method_call
156
+ end
157
+ output: |
158
+ def method_with_multiline_method_call_chain
159
+ multiline_method_call.
160
+ foo.
161
+ bar
162
+
163
+ another_method_call
164
+ end
165
+
166
+ - name: handle multiline code with escaped quotes in strings
167
+ input: |
168
+ def method_containing_multiline_code_with_strings
169
+ a = "foo #{method}" +
170
+ "bar"
171
+ end
172
+ output: |
173
+ def method_containing_multiline_code_with_strings
174
+ a = "foo #{method}" +
175
+ "bar"
176
+ end
177
+
178
+ - name: not change the indentation of multiline strings
179
+ input: |
180
+ def method_containing_long_string
181
+ a = "
182
+ Some text across multiple lines
183
+ And another line
184
+ "
185
+ b = 5
186
+ end
187
+ output: |
188
+ def method_containing_long_string
189
+ a = "
190
+ Some text across multiple lines
191
+ And another line
192
+ "
193
+ b = 5
194
+ end
195
+
196
+ - name: not treat divison as start of regex
197
+ input: |
198
+ def foo
199
+ a = 1/2
200
+ b = :foo
201
+ end
202
+ output: |
203
+ def foo
204
+ a = 1/2
205
+ b = :foo
206
+ end
207
+
208
+ - name: not indent multiline string even if it uses non quote delimiter
209
+ pending: implementation of block matcher for non quote delimited strings
210
+ input: |
211
+ foo = <<TEXT
212
+ some string
213
+ and more string
214
+ TEXT
215
+
216
+ - name: recognize when two blocks end on the same line
217
+ input: |
218
+ class Foo
219
+ def foobar
220
+ if a = 3
221
+ return 5
222
+ end; end
223
+ end
224
+ output: |
225
+ class Foo
226
+ def foobar
227
+ if a = 3
228
+ return 5
229
+ end; end
230
+ end
231
+
232
+ - name: indent multiline array definition
233
+ input: |
234
+ class Foo
235
+ @@bar = [1, 2,
236
+ 3, 4]
237
+ end
238
+ output: |
239
+ class Foo
240
+ @@bar = [1, 2,
241
+ 3, 4]
242
+ end
243
+
244
+ - name: indent multiline array definition (all on separate lines)
245
+ input: |
246
+ class Foo
247
+ @@bar = [
248
+ 1,
249
+ 2,
250
+ 3,
251
+ 4
252
+ ]
253
+ end
254
+ output: |
255
+ class Foo
256
+ @@bar = [
257
+ 1,
258
+ 2,
259
+ 3,
260
+ 4
261
+ ]
262
+ end
263
+
264
+ - name: indent multiline hash definition
265
+ input: |
266
+ class Foo
267
+ @@bar = { :foo => 1, :bar => 2
268
+ :c => 3, :d => 4 }
269
+ end
270
+ output: |
271
+ class Foo
272
+ @@bar = { :foo => 1, :bar => 2
273
+ :c => 3, :d => 4 }
274
+ end
275
+
276
+ - name: indent multiline block delimited with curly brackets
277
+ input: |
278
+ foo = bar.collect { |paragraph|
279
+ paragraph.strip
280
+ }.join("\n")
281
+ output: |
282
+ foo = bar.collect { |paragraph|
283
+ paragraph.strip
284
+ }.join("\n")
285
+
286
+ - name: indent method call with bracketed multiline arguments including continuing statements
287
+ pending: Implementation of support for continuing statements in bracketed multline arguments
288
+ input: |
289
+ def foo
290
+ bar(first_arg,
291
+ second_part_a +
292
+ second_part_b,
293
+ third_arg)
294
+ end
295
+ output: |
296
+ def foo
297
+ bar(first_arg,
298
+ second_part_a +
299
+ second_part_b,
300
+ third_arg)
301
+ end
302
+
303
+ - name: indent continuing lines ending in = and +
304
+ input: |
305
+ def foo
306
+ @bar ||=
307
+ 1 +
308
+ 2
309
+ end
310
+ output: |
311
+ def foo
312
+ @bar ||=
313
+ 1 +
314
+ 2
315
+ end
316
+
317
+ - name: indent block within implicit brackets
318
+ pending: Implementation of support for this feature
319
+ input: |
320
+ def foo
321
+ bar first_arg,
322
+ second_arg,
323
+ [
324
+ 1,
325
+ 2,
326
+ 3
327
+ ],
328
+ last_arg
329
+ end
330
+ output: |
331
+ def foo
332
+ bar first_arg,
333
+ second_arg,
334
+ [
335
+ 1,
336
+ 2,
337
+ 3
338
+ ],
339
+ last_arg
340
+ end
341
+
342
+ - name: "should not treat ':', '_' or '.' as word boundaries before keywords"
343
+ input: |
344
+ case params[:do]
345
+ when "update_if"
346
+ update_if.if
347
+ when "update_do"
348
+ update_do.do
349
+ end
350
+ output: |
351
+ case params[:do]
352
+ when "update_if"
353
+ update_if.if
354
+ when "update_do"
355
+ update_do.do
356
+ end
357
+
358
+ - name: should recognize interpolation and not match other content within double quotes
359
+ input: |
360
+ def foo
361
+ return "Foo#{" (#{bar})"}"
362
+ end
363
+ output: |
364
+ def foo
365
+ return "Foo#{" (#{bar})"}"
366
+ end
367
+
368
+ - name: should not non interpolated content within regexes and strings and backticks
369
+ input: |
370
+ def foo
371
+ @foo = [
372
+ /" if bar/,
373
+ `ls if`,
374
+ "if fun =",
375
+ 'else'
376
+ ]
377
+ end
378
+ output: |
379
+ def foo
380
+ @foo = [
381
+ /" if bar/,
382
+ `ls if`,
383
+ "if fun =",
384
+ 'else'
385
+ ]
386
+ end
387
+
388
+ - name: should handle one liners that include an end statement correctly
389
+ input: |
390
+ def foo; puts 'foo' end
391
+ def bar; puts 'bar' end
392
+ output: |
393
+ def foo; puts 'foo' end
394
+ def bar; puts 'bar' end
395
+
396
+ - name: should handle if and unless statements that are terminated implicitly
397
+ input: |
398
+ def foo
399
+ bar = (1 + 2) if foobar
400
+ baz unless foobaz
401
+ Boo.new(:boo) rescue raise('Houston we have a problem')
402
+ end
403
+ output: |
404
+ def foo
405
+ bar = (1 + 2) if foobar
406
+ baz unless foobaz
407
+ Boo.new(:boo) rescue raise('Houston we have a problem')
408
+ end