rufo 0.0.31 → 0.0.32

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
  SHA1:
3
- metadata.gz: 208020c1cfc4ae639637febda545a3c3752980fe
4
- data.tar.gz: 17da5ed34f7765ff9e08daa305965e41c568a6ac
3
+ metadata.gz: 567434311fc51fc2df58435a9b746c8bceb677b6
4
+ data.tar.gz: 952b5fde3de3a1a1613b80da0f2b77a1bbf08883
5
5
  SHA512:
6
- metadata.gz: 696a53c1d4d30504a01c677fe87f54db384c68c8e8e38f510184c7bd2fd1bb4e9b18a04171b75318f722356bdcca93eef28e96feafb21d403336b0432d2821cc
7
- data.tar.gz: a5783f444cb5b20a2ef8d0b8eadd4a7e62502f4782e98bf5938ac484d6abbeda167384749a47b81ca10949c548e737a967706b420f64424225f94180bc753fb6
6
+ metadata.gz: c2922786da9e59ad5077d32fbe48b233416bf44d8c8e8719a02d73731ced2158f9051fb3e8fff8d1090d91d647e87e0b29cee7e58c8abcc73dcdc9fcdca239d4
7
+ data.tar.gz: 2c535a76bb09f8af19f0582873b58dab19b66d3fda4d784ad4dfc1e86dcf29539bd7f938ad0a0d916446e1ab18c67545e1d641bf186bbc2f72db324936c6bc62
data/README.md CHANGED
@@ -84,7 +84,7 @@ available configurations:
84
84
  # * :dynamic: if there's a space, keep it. If not, don't add it
85
85
  # * :always: always put a space after an array bracket (default)
86
86
  # * :never: never put a space after an array bracket
87
- space_after_array_bracket :never
87
+ space_after_array_bracket :dynamic
88
88
 
89
89
  # Whether to put a space after a hash brace. Valid values are:
90
90
  #
@@ -93,20 +93,20 @@ space_after_array_bracket :never
93
93
  # * :never: never put a space after a hash brace
94
94
  space_after_hash_brace :dynamic
95
95
 
96
- # Whether to align successive comments (default: true)
97
- align_comments true
96
+ # Whether to align successive comments (default: false)
97
+ align_comments false
98
98
 
99
99
  # Whether to align successive assignments (default: false)
100
100
  align_assignments false
101
101
 
102
- # Whether to align successive hash keys (default: true)
103
- align_hash_keys true
102
+ # Whether to align successive hash keys (default: false)
103
+ align_hash_keys false
104
104
 
105
- # Whether to align successive case when (default: true)
106
- align_case_when true
105
+ # Whether to align successive case when (default: false)
106
+ align_case_when false
107
107
 
108
- # Whether to align chained calls to the dot (default: true)
109
- align_chained_calls true
108
+ # Whether to align chained calls to the first dot in the first line (default: false)
109
+ align_chained_calls false
110
110
 
111
111
  # Preserve whitespace after assignments target and values,
112
112
  # after calls that start with a space, hash arrows and commas (default: true).
@@ -116,6 +116,12 @@ align_chained_calls true
116
116
  #
117
117
  # If `align_assignments` is true, this doesn't apply to assignments.
118
118
  # If `align_hash_keys` is true, this doesn't apply to hash keys.
119
+ #
120
+ #
121
+ # Can also be set to `:YES` to preserve whitespace in many more places,
122
+ # in case there's no clear rule in your workplace/project as to when
123
+ # to leave spaces or not. This includes spaces (or the absence of them)
124
+ # around dots, braces, pipes and hash keys and values.
119
125
  preserve_whitespace true
120
126
 
121
127
  # The indent size (default: 2)
@@ -123,10 +129,10 @@ indent_size 2
123
129
 
124
130
  # Whether to place commas at the end of a multi-line list
125
131
  #
126
- # * :dynamic: if there's a comma, keep it. If not, don't add it
127
- # * :always: always put a comma (default)
132
+ # * :dynamic: if there's a comma, keep it. If not, don't add it (default)
133
+ # * :always: always put a comma
128
134
  # * :never: never put a comma
129
- trailing_commas :always
135
+ trailing_commas :dyanmic
130
136
  ```
131
137
 
132
138
  As time passes there might be more configurations available. Please open an
@@ -26,6 +26,10 @@ class Rufo::Formatter
26
26
  # calls to that dot
27
27
  @dot_column = nil
28
28
 
29
+ # Same as above, but the column of the original dot, not
30
+ # the one we finally wrote
31
+ @original_dot_column = nil
32
+
29
33
  # Did this line already set the `@dot_column` variable?
30
34
  @line_has_dot_column = nil
31
35
 
@@ -68,6 +72,28 @@ class Rufo::Formatter
68
72
  # However, for these cases it's better to not align it like that.
69
73
  @line_to_call_info = {}
70
74
 
75
+ # Lists [first_line, last_line, indent] of lines that need an indent because
76
+ # of alignment of literals. For example this:#
77
+ #
78
+ # foo [
79
+ # 1,
80
+ # ]
81
+ #
82
+ # is normally formatted to:
83
+ #
84
+ # foo [
85
+ # 1,
86
+ # ]
87
+ #
88
+ # However, if it's already formatted like the above we preserve it.
89
+ @literal_indents = []
90
+
91
+ # First non-space token in this line
92
+ @first_token_in_line = nil
93
+
94
+ # Do we want to compute the above?
95
+ @want_first_token_in_line = false
96
+
71
97
  # Each line that belongs to a heredoc content is put here
72
98
  @heredoc_lines = {}
73
99
 
@@ -114,14 +140,14 @@ class Rufo::Formatter
114
140
  # Settings
115
141
  indent_size options.fetch(:indent_size, 2)
116
142
  space_after_hash_brace options.fetch(:space_after_hash_brace, :dynamic)
117
- space_after_array_bracket options.fetch(:space_after_array_bracket, :never)
118
- align_comments options.fetch(:align_comments, true)
143
+ space_after_array_bracket options.fetch(:space_after_array_bracket, :dynamic)
144
+ align_comments options.fetch(:align_comments, false)
119
145
  align_assignments options.fetch(:align_assignments, false)
120
- align_hash_keys options.fetch(:align_hash_keys, true)
121
- align_case_when options.fetch(:align_case_when, true)
122
- align_chained_calls options.fetch(:align_chained_calls, true)
146
+ align_hash_keys options.fetch(:align_hash_keys, false)
147
+ align_case_when options.fetch(:align_case_when, false)
148
+ align_chained_calls options.fetch(:align_chained_calls, false)
123
149
  preserve_whitespace options.fetch(:preserve_whitespace, true)
124
- trailing_commas options.fetch(:trailing_commas, :always)
150
+ trailing_commas options.fetch(:trailing_commas, :dynamic)
125
151
  end
126
152
 
127
153
  # The indent size (default: 2)
@@ -145,9 +171,9 @@ class Rufo::Formatter
145
171
 
146
172
  # Whether to put a space after an array bracket. Valid values are:
147
173
  #
148
- # * :dynamic: if there's a space, keep it. If not, don't keep it
174
+ # * :dynamic: if there's a space, keep it. If not, don't keep it (default)
149
175
  # * :always: always put a space after an array bracket
150
- # * :never: never put a space after an array bracket (default)
176
+ # * :never: never put a space after an array bracket
151
177
  def space_after_array_bracket(value)
152
178
  case value
153
179
  when :dynamic, :always, :never
@@ -157,7 +183,7 @@ class Rufo::Formatter
157
183
  end
158
184
  end
159
185
 
160
- # Whether to align successive comments (default: true)
186
+ # Whether to align successive comments (default: false)
161
187
  def align_comments(value)
162
188
  @align_comments = value
163
189
  end
@@ -167,17 +193,17 @@ class Rufo::Formatter
167
193
  @align_assignments = value
168
194
  end
169
195
 
170
- # Whether to align successive hash keys (default: true)
196
+ # Whether to align successive hash keys (default: false)
171
197
  def align_hash_keys(value)
172
198
  @align_hash_keys = value
173
199
  end
174
200
 
175
- # Whether to align successive case when (default: true)
201
+ # Whether to align successive case when (default: false)
176
202
  def align_case_when(value)
177
203
  @align_case_when = value
178
204
  end
179
205
 
180
- # Whether to align chained calls to the dot (default: true)
206
+ # Whether to align chained calls to the first dot in the first line (default: false)
181
207
  def align_chained_calls(value)
182
208
  @align_chained_calls = value
183
209
  end
@@ -190,14 +216,19 @@ class Rufo::Formatter
190
216
  #
191
217
  # If `align_assignments` is true, this doesn't apply to assignments.
192
218
  # If `align_hash_keys` is true, this doesn't apply to hash keys.
219
+ #
220
+ # Can also be set to `:YES` to preserve whitespace in many more places,
221
+ # in case there's no clear rule in your workplace/project as to when
222
+ # to leave spaces or not. This includes spaces (or the absence of them)
223
+ # around dots, braces, pipes and hash keys and values.
193
224
  def preserve_whitespace(value)
194
225
  @preserve_whitespace = value
195
226
  end
196
227
 
197
228
  # Whether to place commas at the end of a multi-line list
198
229
  #
199
- # * :dynamic: if there's a comma, keep it. If not, don't add it
200
- # * :always: always put a comma (default)
230
+ # * :dynamic: if there's a comma, keep it. If not, don't add it (default)
231
+ # * :always: always put a comma
201
232
  # * :never: never put a comma
202
233
  def trailing_commas(value)
203
234
  case value
@@ -215,6 +246,7 @@ class Rufo::Formatter
215
246
  @output.chomp! if @output.end_with?("\n\n")
216
247
 
217
248
  dedent_calls
249
+ indent_literals
218
250
  do_align_assignments if @align_assignments
219
251
  do_align_hash_keys if @align_hash_keys
220
252
  do_align_case_when if @align_case_when
@@ -806,8 +838,8 @@ class Rufo::Formatter
806
838
 
807
839
  def current_comment_aligned_to_previous_one?
808
840
  @last_comment &&
809
- @last_comment[0][0] + 1 == current_token[0][0] &&
810
- @last_comment[0][1] == current_token[0][1]
841
+ @last_comment[0][0] + 1 == current_token_line &&
842
+ @last_comment[0][1] == current_token_column
811
843
  end
812
844
 
813
845
  def track_comment(id: nil, match_previous_id: false)
@@ -912,25 +944,36 @@ class Rufo::Formatter
912
944
  @dot_column = nil
913
945
  visit obj
914
946
 
947
+ first_space = current_token if space? && @preserve_whitespace == :YES
915
948
  skip_space
916
949
 
917
950
  if newline? || comment?
918
951
  consume_end_of_line
919
952
 
920
- if @align_chained_calls
953
+ # If align_chained_calls if off, we still want to preserve alignment if it's already there
954
+ if @align_chained_calls || (@original_dot_column && @original_dot_column == current_token_column)
921
955
  @name_dot_column = @dot_column || next_indent
922
956
  write_indent(@dot_column || next_indent)
923
957
  else
958
+ # Make sure to reset dot_column so next lines don't align to the first dot
959
+ @dot_column = next_indent
924
960
  @name_dot_column = next_indent
925
961
  write_indent(next_indent)
926
962
  end
963
+ elsif first_space
964
+ write_space first_space[2]
927
965
  end
928
966
 
929
967
  # Remember dot column, but only if there isn't one already set
930
- dot_column = @column unless @dot_column
968
+ unless @dot_column
969
+ dot_column = @column
970
+ original_dot_column = current_token_column
971
+ end
931
972
 
932
973
  consume_call_dot
933
974
 
975
+ first_space = nil
976
+ first_space = current_token if space? && @preserve_whitespace == :YES
934
977
  skip_space
935
978
 
936
979
  if newline? || comment?
@@ -938,6 +981,9 @@ class Rufo::Formatter
938
981
  write_indent(next_indent)
939
982
  else
940
983
  skip_space_or_newline
984
+ if first_space
985
+ write_space first_space[2]
986
+ end
941
987
  end
942
988
 
943
989
  if name == :call
@@ -949,6 +995,7 @@ class Rufo::Formatter
949
995
  # Only set it after we visit the call after the dot,
950
996
  # so we remember the outmost dot position
951
997
  @dot_column = dot_column if dot_column
998
+ @original_dot_column = original_dot_column if original_dot_column
952
999
  end
953
1000
 
954
1001
  def consume_call_dot
@@ -975,6 +1022,8 @@ class Rufo::Formatter
975
1022
 
976
1023
  # Remember dot column so it's not affected by args
977
1024
  dot_column = @dot_column
1025
+ original_dot_column = @original_dot_column
1026
+
978
1027
  want_indent = @name_dot_column && @name_dot_column > @indent
979
1028
 
980
1029
  maybe_indent(want_indent, @name_dot_column) do
@@ -983,6 +1032,7 @@ class Rufo::Formatter
983
1032
 
984
1033
  # Restore dot column so it's not affected by args
985
1034
  @dot_column = dot_column
1035
+ @original_dot_column = original_dot_column
986
1036
  end
987
1037
 
988
1038
  def visit_call_at_paren(node, args)
@@ -1060,7 +1110,11 @@ class Rufo::Formatter
1060
1110
  skip_space_or_newline
1061
1111
  end
1062
1112
 
1063
- call_info << @line if call_info
1113
+ # If the closing parentheses matches the indent of the first parameter,
1114
+ # keep it like that. Otherwise dedent.
1115
+ if call_info && call_info[1] != current_token_column
1116
+ call_info << @line
1117
+ end
1064
1118
 
1065
1119
  consume_token :on_rparen
1066
1120
  end
@@ -1071,17 +1125,19 @@ class Rufo::Formatter
1071
1125
  # [:command, name, args]
1072
1126
  _, name, args = node
1073
1127
 
1128
+ base_column = current_token_column
1129
+
1074
1130
  push_call(node) do
1075
1131
  visit name
1076
1132
  consume_space_after_command_name
1077
1133
  end
1078
1134
 
1079
- visit_command_end(node, args)
1135
+ visit_command_end(node, args, base_column)
1080
1136
  end
1081
1137
 
1082
- def visit_command_end(node, args)
1138
+ def visit_command_end(node, args, base_column)
1083
1139
  push_call(node) do
1084
- visit_command_args(args)
1140
+ visit_command_args(args, base_column)
1085
1141
  end
1086
1142
  end
1087
1143
 
@@ -1117,11 +1173,19 @@ class Rufo::Formatter
1117
1173
  # [:args_add_block, [[:@int, "1", [1, 8]]], block]]
1118
1174
  _, receiver, dot, name, args = node
1119
1175
 
1176
+ base_column = current_token_column
1177
+
1120
1178
  visit receiver
1179
+
1180
+ first_space = current_token if space? && @preserve_whitespace == :YES
1181
+
1182
+ line = @line
1121
1183
  skip_space_or_newline
1122
1184
 
1123
1185
  # Remember dot column
1124
1186
  dot_column = @column
1187
+ original_dot_column = @original_dot_column
1188
+
1125
1189
  consume_call_dot
1126
1190
 
1127
1191
  skip_space
@@ -1135,11 +1199,12 @@ class Rufo::Formatter
1135
1199
 
1136
1200
  visit name
1137
1201
  consume_space_after_command_name
1138
- visit_command_args(args)
1202
+ visit_command_args(args, base_column)
1139
1203
 
1140
1204
  # Only set it after we visit the call after the dot,
1141
1205
  # so we remember the outmost dot position
1142
1206
  @dot_column = dot_column
1207
+ @original_dot_column = original_dot_column
1143
1208
  end
1144
1209
 
1145
1210
  def consume_space_after_command_name
@@ -1156,8 +1221,10 @@ class Rufo::Formatter
1156
1221
  end
1157
1222
  end
1158
1223
 
1159
- def visit_command_args(args)
1224
+ def visit_command_args(args, base_column)
1160
1225
  needed_indent = @column
1226
+ args_is_def_class_or_module = false
1227
+ param_column = current_token_column
1161
1228
 
1162
1229
  # Check if there's a single argument and it's
1163
1230
  # a def, class or module. In that case we don't
@@ -1171,11 +1238,13 @@ class Rufo::Formatter
1171
1238
  case first[0]
1172
1239
  when :def, :class, :module
1173
1240
  needed_indent = @indent
1241
+ args_is_def_class_or_module = true
1174
1242
  end
1175
1243
  end
1176
1244
  end
1177
1245
  end
1178
1246
 
1247
+ base_line = @line
1179
1248
  call_info = @line_to_call_info[@line]
1180
1249
  if call_info
1181
1250
  call_info = nil
@@ -1184,6 +1253,10 @@ class Rufo::Formatter
1184
1253
  @line_to_call_info[@line] = call_info
1185
1254
  end
1186
1255
 
1256
+ old_want_first_token_in_line = @want_first_token_in_line
1257
+ @want_first_token_in_line = true
1258
+
1259
+ # We align call parameters to the first paramter
1187
1260
  indent(needed_indent) do
1188
1261
  if args[0].is_a?(Symbol)
1189
1262
  visit args
@@ -1193,8 +1266,35 @@ class Rufo::Formatter
1193
1266
  end
1194
1267
 
1195
1268
  if call_info && call_info.size > 2
1269
+ # A call like:
1270
+ #
1271
+ # foo, 1, [
1272
+ # 2,
1273
+ # ]
1274
+ #
1275
+ # would normally be aligned like this (with the first parameter):
1276
+ #
1277
+ # foo, 1, [
1278
+ # 2,
1279
+ # ]
1280
+ #
1281
+ # However, the first style is valid too and we preserve it if it's
1282
+ # already formatted like that.
1196
1283
  call_info << @line
1284
+ elsif !args_is_def_class_or_module && @first_token_in_line && param_column == @first_token_in_line[0][1]
1285
+ # If the last line of the call is aligned with the first parameter, leave it like that:
1286
+ #
1287
+ # foo 1,
1288
+ # 2
1289
+ elsif !args_is_def_class_or_module && @first_token_in_line && base_column + @indent_size == @first_token_in_line[0][1]
1290
+ # Otherwise, align it just by two spaces (so we need to dedent, we fake a dedent here)
1291
+ #
1292
+ # foo 1,
1293
+ # 2
1294
+ @line_to_call_info[base_line] = [0, needed_indent - next_indent, true, @line, @line]
1197
1295
  end
1296
+
1297
+ @want_first_token_in_line = old_want_first_token_in_line
1198
1298
  end
1199
1299
 
1200
1300
  def visit_call_with_block(node)
@@ -1203,7 +1303,16 @@ class Rufo::Formatter
1203
1303
 
1204
1304
  visit call
1205
1305
 
1206
- consume_space
1306
+ if block[0] == :brace_block
1307
+ if space? || !@preserve_whitespace
1308
+ consume_space
1309
+ else
1310
+ consume_space unless @preserve_whitespace == :YES
1311
+ end
1312
+ else
1313
+ consume_space
1314
+ end
1315
+
1207
1316
  visit block
1208
1317
  end
1209
1318
 
@@ -1227,14 +1336,14 @@ class Rufo::Formatter
1227
1336
  closing_brace_token, index = find_closing_brace_token
1228
1337
 
1229
1338
  # If the whole block fits into a single line, use braces
1230
- if current_token[0][0] == closing_brace_token[0][0]
1339
+ if current_token_line == closing_brace_token[0][0]
1231
1340
  consume_token :on_lbrace
1232
1341
 
1233
1342
  consume_block_args args
1234
1343
 
1235
- consume_space
1344
+ consume_space unless !space? && @preserve_whitespace == :YES
1236
1345
  visit_exps body, with_lines: false
1237
- consume_space
1346
+ consume_space unless !space? && @preserve_whitespace == :YES
1238
1347
 
1239
1348
  consume_token :on_rbrace
1240
1349
  return
@@ -1251,7 +1360,11 @@ class Rufo::Formatter
1251
1360
  indent_body body, force_multiline: true
1252
1361
  write_indent
1253
1362
 
1254
- call_info << @line if call_info
1363
+ # If the closing bracket matches the indent of the first parameter,
1364
+ # keep it like that. Otherwise dedent.
1365
+ if call_info && call_info[1] != current_token_column
1366
+ call_info << @line
1367
+ end
1255
1368
 
1256
1369
  consume_token :on_rbrace
1257
1370
  end
@@ -1274,7 +1387,15 @@ class Rufo::Formatter
1274
1387
 
1275
1388
  def consume_block_args(args)
1276
1389
  if args
1277
- consume_space
1390
+ if space?
1391
+ consume_space(want_preserve_whitespace: @preserve_whitespace == :YES)
1392
+ else
1393
+ if @preserve_whitespace == :YES
1394
+ skip_space
1395
+ else
1396
+ consume_space
1397
+ end
1398
+ end
1278
1399
  # + 1 because of |...|
1279
1400
  # ^
1280
1401
  indent(@column + 1) do
@@ -1574,7 +1695,7 @@ class Rufo::Formatter
1574
1695
 
1575
1696
  # If the whole block fits into a single line, format
1576
1697
  # in a single line
1577
- if current_token[0][0] == closing_brace_token[0][0]
1698
+ if current_token_line == closing_brace_token[0][0]
1578
1699
  consume_token :on_lbrace
1579
1700
  consume_space
1580
1701
  visit_exps body, with_lines: false
@@ -1646,8 +1767,19 @@ class Rufo::Formatter
1646
1767
  _, before, star, after = node
1647
1768
 
1648
1769
  if before && !before.empty?
1649
- visit_comma_separated_list before
1650
- write_params_comma
1770
+ # Maybe a Ripper bug, but if there's something before a star
1771
+ # then a star shouldn't be here... but if it is... handle it
1772
+ # somehow...
1773
+ if current_token_kind == :on_op && current_token_value == "*"
1774
+ before, star, after = nil, before, after
1775
+ else
1776
+ if before[0].is_a?(Symbol)
1777
+ visit before
1778
+ else
1779
+ visit_comma_separated_list before
1780
+ end
1781
+ write_params_comma
1782
+ end
1651
1783
  end
1652
1784
 
1653
1785
  consume_op "*"
@@ -1715,6 +1847,8 @@ class Rufo::Formatter
1715
1847
  # right_exp
1716
1848
  # end
1717
1849
  needed_indent = @column == @indent ? next_indent : @column
1850
+ base_column = @column
1851
+ token_column = current_token_column
1718
1852
 
1719
1853
  visit left
1720
1854
  if space?
@@ -1736,7 +1870,7 @@ class Rufo::Formatter
1736
1870
  end
1737
1871
 
1738
1872
  consume_op_or_keyword op
1739
- indent_after_space right, want_space: needs_space, needed_indent: needed_indent
1873
+ indent_after_space right, want_space: needs_space, needed_indent: needed_indent, token_column: token_column, base_column: base_column
1740
1874
  end
1741
1875
 
1742
1876
  def consume_op_or_keyword(op)
@@ -2024,6 +2158,8 @@ class Rufo::Formatter
2024
2158
 
2025
2159
  _, elements = node
2026
2160
 
2161
+ token_column = current_token_column
2162
+
2027
2163
  check :on_lbracket
2028
2164
  write "["
2029
2165
  next_token
@@ -2034,7 +2170,7 @@ class Rufo::Formatter
2034
2170
  visit elements
2035
2171
  skip_space_or_newline
2036
2172
  else
2037
- visit_literal_elements elements, inside_array: true
2173
+ visit_literal_elements elements, inside_array: true, token_column: token_column
2038
2174
  end
2039
2175
  else
2040
2176
  skip_space_or_newline
@@ -2124,6 +2260,8 @@ class Rufo::Formatter
2124
2260
  # [:hash, elements]
2125
2261
  _, elements = node
2126
2262
 
2263
+ token_column = current_token_column
2264
+
2127
2265
  check :on_lbrace
2128
2266
  write "{"
2129
2267
  next_token
@@ -2131,7 +2269,7 @@ class Rufo::Formatter
2131
2269
  if elements
2132
2270
  # [:assoclist_from_args, elements]
2133
2271
  push_hash(node) do
2134
- visit_literal_elements(elements[1], inside_hash: true)
2272
+ visit_literal_elements(elements[1], inside_hash: true, token_column: token_column)
2135
2273
  end
2136
2274
  else
2137
2275
  skip_space_or_newline
@@ -2156,7 +2294,9 @@ class Rufo::Formatter
2156
2294
 
2157
2295
  visit key
2158
2296
 
2159
- consume_space(want_preserve_whitespace: @preserve_whitespace)
2297
+ unless @preserve_whitespace == :YES && !space? && !newline? && !comment?
2298
+ consume_space(want_preserve_whitespace: @preserve_whitespace)
2299
+ end
2160
2300
 
2161
2301
  track_hash_key
2162
2302
 
@@ -2164,7 +2304,10 @@ class Rufo::Formatter
2164
2304
  # or `"label": value`
2165
2305
  if arrow
2166
2306
  consume_op "=>"
2167
- consume_space(want_preserve_whitespace: !@align_hash_keys)
2307
+
2308
+ unless @preserve_whitespace == :YES && !space? && !newline? && !comment?
2309
+ consume_space(want_preserve_whitespace: !@align_hash_keys)
2310
+ end
2168
2311
  end
2169
2312
 
2170
2313
  visit value
@@ -2227,6 +2370,8 @@ class Rufo::Formatter
2227
2370
  def visit_array_getter_or_setter(name, args)
2228
2371
  visit name
2229
2372
 
2373
+ token_column = current_token_column
2374
+
2230
2375
  check :on_lbracket
2231
2376
  write "["
2232
2377
  next_token
@@ -2237,7 +2382,7 @@ class Rufo::Formatter
2237
2382
 
2238
2383
  # Sometimes args comes with an array...
2239
2384
  if args && args[0].is_a?(Array)
2240
- visit_literal_elements args
2385
+ visit_literal_elements args, token_column: token_column
2241
2386
  else
2242
2387
  if newline? || comment?
2243
2388
  needed_indent = next_indent
@@ -2287,18 +2432,30 @@ class Rufo::Formatter
2287
2432
  _, receiver, dot, name = node
2288
2433
 
2289
2434
  @dot_column = nil
2435
+ @original_dot_column = nil
2436
+
2290
2437
  visit receiver
2438
+
2439
+ first_space = current_token if space? && @preserve_whitespace == :YES
2440
+
2291
2441
  skip_space
2292
2442
 
2293
2443
  if newline? || comment?
2294
2444
  consume_end_of_line
2295
2445
 
2296
2446
  write_indent(@dot_column || next_indent)
2447
+ elsif first_space
2448
+ write_space first_space[2]
2297
2449
  end
2298
2450
 
2299
2451
  # Remember dot column
2300
2452
  dot_column = @column
2453
+ original_dot_column = current_token_column
2454
+
2301
2455
  consume_call_dot
2456
+
2457
+ first_space = nil
2458
+ first_space = current_token if space? && @preserve_whitespace == :YES
2302
2459
  skip_space
2303
2460
 
2304
2461
  if newline? || comment?
@@ -2306,6 +2463,9 @@ class Rufo::Formatter
2306
2463
  write_indent(next_indent)
2307
2464
  else
2308
2465
  skip_space_or_newline
2466
+ if first_space
2467
+ write_space first_space[2]
2468
+ end
2309
2469
  end
2310
2470
 
2311
2471
  visit name
@@ -2313,6 +2473,7 @@ class Rufo::Formatter
2313
2473
  # Only set it after we visit the call after the dot,
2314
2474
  # so we remember the outmost dot position
2315
2475
  @dot_column = dot_column
2476
+ @original_dot_column = original_dot_column
2316
2477
  end
2317
2478
 
2318
2479
  def visit_return(node)
@@ -2394,12 +2555,12 @@ class Rufo::Formatter
2394
2555
  closing_brace_token, index = find_closing_brace_token
2395
2556
 
2396
2557
  # Check if the whole block fits into a single line
2397
- if current_token[0][0] == closing_brace_token[0][0]
2558
+ if current_token_line == closing_brace_token[0][0]
2398
2559
  consume_token :on_tlambeg
2399
2560
 
2400
- consume_space
2561
+ consume_space unless !space? && @preserve_whitespace == :YES
2401
2562
  visit_exps body, with_lines: false
2402
- consume_space
2563
+ consume_space unless !space? && @preserve_whitespace == :YES
2403
2564
 
2404
2565
  consume_token :on_rbrace
2405
2566
  return
@@ -2425,11 +2586,13 @@ class Rufo::Formatter
2425
2586
  # [:super, args]
2426
2587
  _, args = node
2427
2588
 
2589
+ base_column = current_token_column
2590
+
2428
2591
  consume_keyword "super"
2429
2592
 
2430
2593
  if space?
2431
2594
  consume_space
2432
- visit_command_end node, args
2595
+ visit_command_end node, args, base_column
2433
2596
  else
2434
2597
  visit_call_at_paren node, args
2435
2598
  end
@@ -2486,8 +2649,9 @@ class Rufo::Formatter
2486
2649
  visit_comma_separated_list exps
2487
2650
  end
2488
2651
 
2489
- def visit_literal_elements(elements, inside_hash: false, inside_array: false)
2652
+ def visit_literal_elements(elements, inside_hash: false, inside_array: false, token_column:)
2490
2653
  base_column = @column
2654
+ base_line = @line
2491
2655
  needs_final_space = (inside_hash || inside_array) && space?
2492
2656
  skip_space
2493
2657
 
@@ -2605,7 +2769,20 @@ class Rufo::Formatter
2605
2769
  end
2606
2770
  end
2607
2771
 
2608
- call_info << @line if call_info
2772
+ if current_token_column == token_column && needed_indent < token_column
2773
+ # If the closing token is aligned with the opening token, we want to
2774
+ # keep it like that, for example in:
2775
+ #
2776
+ # foo([
2777
+ # 2,
2778
+ # ])
2779
+ @literal_indents << [base_line, @line, token_column + @indent_size - needed_indent]
2780
+ elsif call_info && call_info[0] == current_token_column
2781
+ # If the closing literal position matches the column where
2782
+ # the call started, we want to preserve it like that
2783
+ # (otherwise we align it to the first parameter)
2784
+ call_info << @line
2785
+ end
2609
2786
  end
2610
2787
 
2611
2788
  def check_heredocs_in_literal_elements(is_last, needs_trailing_comma, wrote_comma)
@@ -2718,11 +2895,16 @@ class Rufo::Formatter
2718
2895
  # [:when, conds, body, next_exp]
2719
2896
  _, conds, body, next_exp = node
2720
2897
 
2898
+ preserve_whitespace = @preserve_whitespace && !@align_case_when
2899
+
2721
2900
  consume_keyword "when"
2722
- consume_space
2901
+ consume_space(want_preserve_whitespace: preserve_whitespace)
2902
+
2903
+ space_after_when = nil
2723
2904
 
2724
2905
  indent(@column) do
2725
2906
  visit_comma_separated_list conds
2907
+ space_after_when = current_token if space? && preserve_whitespace
2726
2908
  skip_space
2727
2909
  end
2728
2910
 
@@ -2730,7 +2912,10 @@ class Rufo::Formatter
2730
2912
  inline = then_keyword || semicolon?
2731
2913
  if then_keyword
2732
2914
  next_token
2915
+
2916
+ space_after_then = current_token if space? && preserve_whitespace
2733
2917
  skip_space
2918
+
2734
2919
  track_case_when
2735
2920
  skip_semicolons
2736
2921
 
@@ -2740,7 +2925,19 @@ class Rufo::Formatter
2740
2925
  # Cancel tracking of `case when ... then` on a nelwine.
2741
2926
  @case_when_positions.pop
2742
2927
  else
2743
- write " then "
2928
+ if space_after_when
2929
+ write_space space_after_when[2]
2930
+ else
2931
+ write_space
2932
+ end
2933
+
2934
+ write "then"
2935
+
2936
+ if space_after_then
2937
+ write_space space_after_then[2]
2938
+ else
2939
+ write_space
2940
+ end
2744
2941
  end
2745
2942
  elsif semicolon?
2746
2943
  skip_semicolons
@@ -2913,11 +3110,12 @@ class Rufo::Formatter
2913
3110
  # - want_semicolon: do we want do print a semicolon to separate expressions?
2914
3111
  # - want_multiline: do we want multiple lines to appear, or at most one?
2915
3112
  def consume_end_of_line(at_prefix: false, want_semicolon: false, want_multiline: true, needs_two_lines_on_comment: false)
2916
- found_newline = false # Did we find any newline during this method?
2917
- last = nil # Last token kind found
2918
- multilple_lines = false # Did we pass through more than one newline?
2919
- last_comment_has_newline = false # Does the last comment has a newline?
2920
- newline_count = 0 # Number of newlines we passed
3113
+ found_newline = false # Did we find any newline during this method?
3114
+ found_comment_after_newline = false # Did we find a comment after some newline?
3115
+ last = nil # Last token kind found
3116
+ multilple_lines = false # Did we pass through more than one newline?
3117
+ last_comment_has_newline = false # Does the last comment has a newline?
3118
+ newline_count = 0 # Number of newlines we passed
2921
3119
 
2922
3120
  loop do
2923
3121
  case current_token_kind
@@ -2939,11 +3137,10 @@ class Rufo::Formatter
2939
3137
  else
2940
3138
  # If we just printed a comment that had a newline,
2941
3139
  # we must print two newlines because we remove newlines from comments (rstrip call)
3140
+ write_line
2942
3141
  if last == :comment && last_comment_has_newline
2943
- write_line
2944
3142
  multilple_lines = true
2945
3143
  else
2946
- write_line
2947
3144
  multilple_lines = false
2948
3145
  end
2949
3146
  end
@@ -3053,6 +3250,7 @@ class Rufo::Formatter
3053
3250
  @last_comment_column = @column
3054
3251
  last_comment_has_newline = current_token_value.end_with?("\n")
3055
3252
  last = :comment
3253
+ found_comment_after_newline = found_newline
3056
3254
  multilple_lines = false
3057
3255
 
3058
3256
  write current_token_value.rstrip
@@ -3074,7 +3272,7 @@ class Rufo::Formatter
3074
3272
  # or we just passed multiple lines (but printed only one)
3075
3273
  if (!found_newline && !at_prefix && !(want_semicolon && last == :semicolon)) ||
3076
3274
  last == :comment ||
3077
- (multilple_lines && want_multiline)
3275
+ (multilple_lines && (want_multiline || found_comment_after_newline))
3078
3276
  write_line
3079
3277
  end
3080
3278
  end
@@ -3095,7 +3293,7 @@ class Rufo::Formatter
3095
3293
  def consume_end
3096
3294
  return unless current_token_kind == :on___end__
3097
3295
 
3098
- line = current_token[0][0]
3296
+ line = current_token_line
3099
3297
 
3100
3298
  write_line
3101
3299
  consume_token :on___end__
@@ -3225,7 +3423,7 @@ class Rufo::Formatter
3225
3423
  @column += indent
3226
3424
  end
3227
3425
 
3228
- def indent_after_space(node, sticky: false, want_space: true, first_space: nil, needed_indent: next_indent)
3426
+ def indent_after_space(node, sticky: false, want_space: true, first_space: nil, needed_indent: next_indent, token_column: nil, base_column: nil)
3229
3427
  first_space = current_token if space?
3230
3428
 
3231
3429
  skip_space
@@ -3233,8 +3431,19 @@ class Rufo::Formatter
3233
3431
  when :on_ignored_nl, :on_comment
3234
3432
  indent(needed_indent) do
3235
3433
  consume_end_of_line
3236
- write_indent
3237
- visit node
3434
+ end
3435
+
3436
+ if token_column && base_column && token_column == current_token_column
3437
+ # If the expression is aligned with the one above, keep it like that
3438
+ indent(base_column) do
3439
+ write_indent
3440
+ visit node
3441
+ end
3442
+ else
3443
+ indent(needed_indent) do
3444
+ write_indent
3445
+ visit node
3446
+ end
3238
3447
  end
3239
3448
  else
3240
3449
  if want_space
@@ -3283,6 +3492,14 @@ class Rufo::Formatter
3283
3492
  tok ? tok[2] : ""
3284
3493
  end
3285
3494
 
3495
+ def current_token_line
3496
+ current_token[0][0]
3497
+ end
3498
+
3499
+ def current_token_column
3500
+ current_token[0][1]
3501
+ end
3502
+
3286
3503
  def keyword?(kw)
3287
3504
  current_token_kind == :on_kw && current_token_value == kw
3288
3505
  end
@@ -3347,11 +3564,26 @@ class Rufo::Formatter
3347
3564
  end
3348
3565
 
3349
3566
  def next_token
3567
+ prev_token = self.current_token
3568
+
3350
3569
  @tokens.pop
3351
3570
 
3352
3571
  if (newline? || comment?) && !@heredocs.empty?
3353
3572
  flush_heredocs
3354
3573
  end
3574
+
3575
+ # First first token in newline if requested
3576
+ if @want_first_token_in_line && prev_token && (prev_token[1] == :on_nl || prev_token[1] == :on_ignored_nl)
3577
+ @tokens.reverse_each do |token|
3578
+ case token[1]
3579
+ when :on_sp
3580
+ next
3581
+ else
3582
+ @first_token_in_line = token
3583
+ break
3584
+ end
3585
+ end
3586
+ end
3355
3587
  end
3356
3588
 
3357
3589
  def next_token_no_heredoc_check
@@ -3420,6 +3652,25 @@ class Rufo::Formatter
3420
3652
  @output = lines.join
3421
3653
  end
3422
3654
 
3655
+ def indent_literals
3656
+ return if @literal_indents.empty?
3657
+
3658
+ lines = @output.lines
3659
+
3660
+ @literal_indents.each do |first_line, last_line, indent|
3661
+ (first_line + 1..last_line).each do |line|
3662
+ next if @heredoc_lines[line]
3663
+
3664
+ current_line = lines[line]
3665
+ current_line = "#{" " * indent}#{current_line}"
3666
+ lines[line] = current_line
3667
+ adjust_other_alignments nil, line, 0, indent
3668
+ end
3669
+ end
3670
+
3671
+ @output = lines.join
3672
+ end
3673
+
3423
3674
  def do_align_comments
3424
3675
  do_align @comments_positions, :comment
3425
3676
  end
data/lib/rufo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rufo
2
- VERSION = "0.0.31"
2
+ VERSION = "0.0.32"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.31
4
+ version: 0.0.32
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ary Borenszweig
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-30 00:00:00.000000000 Z
11
+ date: 2017-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler