rufo 0.0.24 → 0.0.25

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bd6cf27bd7b2fb2451482dff10c6fe5a3930311e
4
- data.tar.gz: 7a4eebf1d5df0dc1ae9e05f9a04030cef866cdf2
3
+ metadata.gz: 200fb638506091280a985b092c7f56d51cc78ee6
4
+ data.tar.gz: fa2aa0c202892a85c4683b5fe50c39f7fdc9f440
5
5
  SHA512:
6
- metadata.gz: bd58dc896ab51bc57c5901fd5d1b46f29784d8f934de72176e21723bf542889520dc1a03f741ca14d2eddf618bbf66522ef758bd4612c1276937d533855d7ced
7
- data.tar.gz: a0e7d72efa0b67fc29bb893eac4be54dfdd3dfb9b90700aaef306e34de7303c947f86c3116cad7b0a3c06357a8eaf4ee786954cb6862e83d2998e429f0c3187c
6
+ metadata.gz: 461fd9e0fc701a914e1c5d8a8174f913ed1b1cb7c2d820d8b451c584558058b3bcd249e8cb8cd7dc0d2ecade21111cbdf4ac63e5246daf71374a860c32699331
7
+ data.tar.gz: 4ec02ecd32126046a380e6fff1a521605013b585320cbadc76f909aacbbed6af2c56cdbf20a289519d7c6be3d462bb14b3188b2d7688d2b74f9478a319120f07
data/README.md CHANGED
@@ -4,6 +4,21 @@
4
4
 
5
5
  **Ru**by **fo**rmatter
6
6
 
7
+ ## Why
8
+
9
+ Rufo's primary use case is as a text-editor plugin, to autoformat files on save or
10
+ on demand. For this reason it needs to be fast. If the formatter is slow, saving
11
+ a file becomes painful.
12
+
13
+ Right now, Rufo can format it's [formatter](https://github.com/asterite/rufo/blob/master/lib/rufo/formatter.rb),
14
+ a 3000+ lines file, in about 290ms. It can format a ~500 lines file in 180ms. Since most files
15
+ have less than 500 lines, the time is acceptable.
16
+
17
+ There's at least one other good Ruby formatter I know: [RuboCop](https://github.com/bbatsov/rubocop).
18
+ However, it takes between 2 and 5 seconds to format a 3000+ lines file, and about 1 second to format
19
+ a 500 lines file. A second is too much delay for a plugin editor. Additionally, RuboCop is much more
20
+ than just a code formatter. Rufo is and will always be a code formatter.
21
+
7
22
  ## Installation
8
23
 
9
24
  Add this line to your application's Gemfile:
@@ -47,6 +62,12 @@ according to **rufo**, and will exit with exit code 1.
47
62
 
48
63
  - Sublime Text: [sublime-rufo](https://github.com/asterite/sublime-rufo)
49
64
 
65
+ Did you write a plugin for your favorite editor? That's great! Let me know about it and
66
+ I will list it here.
67
+
68
+ Right now it would be great to have [Vim](http://www.vim.org/),
69
+ [Atom](https://atom.io/) and [Emacs](https://www.gnu.org/software/emacs/) plugins :-)
70
+
50
71
  ## Configuration
51
72
 
52
73
  Rufo follows most of the conventions found in this [Ruby style guide](https://github.com/bbatsov/ruby-style-guide). It does a bit more than that, and it can also be configured a bit.
@@ -214,7 +214,7 @@ class Rufo::Formatter
214
214
  end
215
215
  when :string_content
216
216
  # [:string_content, exp]
217
- visit_exps node[1..-1], false, false
217
+ visit_exps node[1..-1], with_lines: false
218
218
  when :string_embexpr
219
219
  # String interpolation piece ( #{exp} )
220
220
  visit_string_interpolation node
@@ -425,8 +425,8 @@ class Rufo::Formatter
425
425
  end
426
426
  end
427
427
 
428
- def visit_exps(exps, with_indent = false, with_lines = true)
429
- consume_end_of_line(true)
428
+ def visit_exps(exps, with_indent: false, with_lines: true)
429
+ consume_end_of_line(at_prefix: true)
430
430
 
431
431
  line_before_endline = nil
432
432
 
@@ -459,7 +459,7 @@ class Rufo::Formatter
459
459
  if with_lines
460
460
  exp_needs_two_lines = needs_two_lines?(exp)
461
461
 
462
- consume_end_of_line(false, !is_last, !is_last, exp_needs_two_lines)
462
+ consume_end_of_line(want_semicolon: !is_last, want_multiline: !is_last, needs_two_lines_on_comment: exp_needs_two_lines)
463
463
 
464
464
  # Make sure to put two lines before defs, class and others
465
465
  if !is_last && (exp_needs_two_lines || needs_two_lines?(exps[i + 1])) && @line <= line_before_endline + 1
@@ -514,7 +514,7 @@ class Rufo::Formatter
514
514
  def visit_string_literal_end(node)
515
515
  inner = node[1]
516
516
  inner = inner[1..-1] unless node[0] == :xstring_literal
517
- visit_exps(inner, false, false)
517
+ visit_exps(inner, with_lines: false)
518
518
 
519
519
  case current_token_kind
520
520
  when :on_heredoc_end
@@ -560,7 +560,7 @@ class Rufo::Formatter
560
560
  # [:string_embexpr, exps]
561
561
  consume_token :on_embexpr_beg
562
562
  skip_space_or_newline
563
- visit_exps node[1], false, false
563
+ visit_exps(node[1], with_lines: false)
564
564
  skip_space_or_newline
565
565
  consume_token :on_embexpr_end
566
566
  end
@@ -587,7 +587,7 @@ class Rufo::Formatter
587
587
  #
588
588
  # [:symbol, [:@ident, "foo", [1, 1]]]
589
589
  consume_token :on_symbeg
590
- visit_exps node[1..-1], false, false
590
+ visit_exps node[1..-1], with_lines: false
591
591
  end
592
592
 
593
593
  def visit_quoted_symbol_literal(node)
@@ -603,7 +603,7 @@ class Rufo::Formatter
603
603
  consume_token :on_label_end
604
604
  else
605
605
  consume_token :on_symbeg
606
- visit_exps exps, false, false
606
+ visit_exps exps, with_lines: false
607
607
  consume_token :on_tstring_end
608
608
  end
609
609
  end
@@ -633,7 +633,7 @@ class Rufo::Formatter
633
633
  line = @line
634
634
 
635
635
  visit target
636
- consume_space(!@align_assignments)
636
+ consume_space(want_preserve_whitespace: !@align_assignments)
637
637
  track_assignment
638
638
  consume_op "="
639
639
  visit_assign_value value
@@ -650,7 +650,7 @@ class Rufo::Formatter
650
650
  line = @line
651
651
 
652
652
  visit target
653
- consume_space(!@align_assignments)
653
+ consume_space(want_preserve_whitespace: !@align_assignments)
654
654
 
655
655
  # [:@op, "+=", [1, 2]],
656
656
  check :on_op
@@ -678,7 +678,7 @@ class Rufo::Formatter
678
678
  # A trailing comma can come after the left hand side
679
679
  consume_token :on_comma if comma?
680
680
 
681
- consume_space(!@align_assignments)
681
+ consume_space(want_preserve_whitespace: !@align_assignments)
682
682
  track_assignment
683
683
  consume_op "="
684
684
  visit_assign_value right
@@ -688,7 +688,7 @@ class Rufo::Formatter
688
688
  first_space = current_token if space?
689
689
  skip_space
690
690
 
691
- indent_after_space value, indentable_value?(value), true, first_space
691
+ indent_after_space value, sticky: indentable_value?(value), want_space: true, first_space: first_space
692
692
  end
693
693
 
694
694
  def indentable_value?(value)
@@ -748,7 +748,7 @@ class Rufo::Formatter
748
748
  _, cond, then_body, else_body = node
749
749
 
750
750
  visit cond
751
- consume_space(true)
751
+ consume_space(want_preserve_whitespace: true)
752
752
  consume_op "?"
753
753
 
754
754
  first_space = current_token if space?
@@ -764,7 +764,7 @@ class Rufo::Formatter
764
764
  end
765
765
 
766
766
  visit then_body
767
- consume_space(true)
767
+ consume_space(want_preserve_whitespace: true)
768
768
  consume_op ":"
769
769
 
770
770
  first_space = current_token if space?
@@ -796,9 +796,9 @@ class Rufo::Formatter
796
796
 
797
797
  visit body
798
798
 
799
- consume_space(true)
799
+ consume_space(want_preserve_whitespace: true)
800
800
  consume_keyword(suffix)
801
- consume_space(true)
801
+ consume_space(want_preserve_whitespace: true)
802
802
  visit cond
803
803
  end
804
804
 
@@ -967,6 +967,16 @@ class Rufo::Formatter
967
967
  end
968
968
 
969
969
  def flush_heredocs
970
+ if comment?
971
+ write_space unless @output[-1] == " "
972
+ write current_token_value.rstrip
973
+ next_token
974
+ write_line
975
+ if @heredocs.last[1]
976
+ write_indent(next_indent)
977
+ end
978
+ end
979
+
970
980
  printed = false
971
981
 
972
982
  until @heredocs.empty?
@@ -1038,7 +1048,7 @@ class Rufo::Formatter
1038
1048
  if args[0].is_a?(Symbol)
1039
1049
  visit args
1040
1050
  else
1041
- visit_exps args, false, false
1051
+ visit_exps args, with_lines: false
1042
1052
  end
1043
1053
  end
1044
1054
  end
@@ -1075,7 +1085,7 @@ class Rufo::Formatter
1075
1085
  consume_block_args args
1076
1086
 
1077
1087
  consume_space
1078
- visit_exps body, false, false
1088
+ visit_exps body, with_lines: false
1079
1089
  consume_space
1080
1090
 
1081
1091
  consume_token :on_rbrace
@@ -1138,7 +1148,7 @@ class Rufo::Formatter
1138
1148
  end
1139
1149
 
1140
1150
  consume_token :on_op
1141
- found_semicolon = skip_space_or_newline(true, true)
1151
+ found_semicolon = skip_space_or_newline(_want_semicolon: true, write_first_semicolon: true)
1142
1152
 
1143
1153
  if found_semicolon
1144
1154
  # Nothing
@@ -1276,7 +1286,7 @@ class Rufo::Formatter
1276
1286
  if node[0].is_a?(Symbol)
1277
1287
  visit node
1278
1288
  else
1279
- visit_exps node, false, false
1289
+ visit_exps node, with_lines: false
1280
1290
  end
1281
1291
  end
1282
1292
 
@@ -1389,7 +1399,7 @@ class Rufo::Formatter
1389
1399
  if current_token[0][0] == closing_brace_token[0][0]
1390
1400
  consume_token :on_lbrace
1391
1401
  consume_space
1392
- visit_exps body, false, false
1402
+ visit_exps body, with_lines: false
1393
1403
  consume_space
1394
1404
  consume_token :on_rbrace
1395
1405
  else
@@ -1440,7 +1450,7 @@ class Rufo::Formatter
1440
1450
 
1441
1451
  if newline? || comment?
1442
1452
  indent(base_column || @indent) do
1443
- consume_end_of_line(false, false, false)
1453
+ consume_end_of_line(want_multiline: false)
1444
1454
  write_indent
1445
1455
  end
1446
1456
  elsif first_space && @preserve_whitespace
@@ -1480,7 +1490,7 @@ class Rufo::Formatter
1480
1490
  consume_op_or_keyword op
1481
1491
 
1482
1492
  if op == :not
1483
- consume_space(true)
1493
+ consume_space(want_preserve_whitespace: true)
1484
1494
  else
1485
1495
  skip_space_or_newline
1486
1496
  end
@@ -1512,7 +1522,7 @@ class Rufo::Formatter
1512
1522
  end
1513
1523
 
1514
1524
  consume_op_or_keyword op
1515
- indent_after_space right, false, needs_space
1525
+ indent_after_space right, want_space: needs_space
1516
1526
  end
1517
1527
 
1518
1528
  def consume_op_or_keyword(op)
@@ -1685,7 +1695,7 @@ class Rufo::Formatter
1685
1695
  if node[1][0].is_a?(Symbol)
1686
1696
  visit node[1]
1687
1697
  else
1688
- visit_exps node[1], false, false
1698
+ visit_exps node[1], with_lines: false
1689
1699
  end
1690
1700
 
1691
1701
  skip_space_or_newline
@@ -1914,7 +1924,7 @@ class Rufo::Formatter
1914
1924
  if elements
1915
1925
  # [:assoclist_from_args, elements]
1916
1926
  push_hash(node) do
1917
- visit_literal_elements(elements[1], true)
1927
+ visit_literal_elements(elements[1], inside_hash: true)
1918
1928
  end
1919
1929
  else
1920
1930
  skip_space_or_newline
@@ -1938,7 +1948,7 @@ class Rufo::Formatter
1938
1948
 
1939
1949
  visit key
1940
1950
 
1941
- consume_space(!@align_hash_keys)
1951
+ consume_space(want_preserve_whitespace: !@align_hash_keys)
1942
1952
 
1943
1953
  track_hash_key
1944
1954
 
@@ -1946,7 +1956,7 @@ class Rufo::Formatter
1946
1956
  # or `"label": value`
1947
1957
  if symbol || !(key[0] == :@label || key[0] == :dyna_symbol)
1948
1958
  consume_op "=>"
1949
- consume_space(!@align_hash_keys)
1959
+ consume_space(want_preserve_whitespace: !@align_hash_keys)
1950
1960
  end
1951
1961
 
1952
1962
  visit value
@@ -1980,7 +1990,7 @@ class Rufo::Formatter
1980
1990
  write current_token_value
1981
1991
  next_token
1982
1992
 
1983
- visit_exps pieces, false, false
1993
+ visit_exps pieces, with_lines: false
1984
1994
 
1985
1995
  check :on_regexp_end
1986
1996
  write current_token_value
@@ -2132,7 +2142,7 @@ class Rufo::Formatter
2132
2142
  if node[1][0].is_a?(Symbol)
2133
2143
  visit node[1]
2134
2144
  else
2135
- visit_exps node[1], false, false
2145
+ visit_exps node[1], with_lines: false
2136
2146
  end
2137
2147
  end
2138
2148
  end
@@ -2177,7 +2187,7 @@ class Rufo::Formatter
2177
2187
  consume_token :on_tlambeg
2178
2188
 
2179
2189
  consume_space
2180
- visit_exps body, false, false
2190
+ visit_exps body, with_lines: false
2181
2191
  consume_space
2182
2192
 
2183
2193
  consume_token :on_rbrace
@@ -2267,7 +2277,7 @@ class Rufo::Formatter
2267
2277
  visit_comma_separated_list exps
2268
2278
  end
2269
2279
 
2270
- def visit_literal_elements(elements, inside_hash = false)
2280
+ def visit_literal_elements(elements, inside_hash: false)
2271
2281
  base_column = @column
2272
2282
  needs_final_space = inside_hash && space?
2273
2283
  skip_space
@@ -2298,20 +2308,35 @@ class Rufo::Formatter
2298
2308
  needed_indent = base_column
2299
2309
  end
2300
2310
 
2311
+ wrote_comma = false
2312
+
2301
2313
  elements.each_with_index do |elem, i|
2314
+ is_last = last?(i, elements)
2315
+ wrote_comma = false
2316
+
2302
2317
  if needs_trailing_comma
2303
2318
  indent(needed_indent) { visit elem }
2304
2319
  else
2305
2320
  visit elem
2306
2321
  end
2307
- skip_space
2322
+
2323
+ # We have to be careful not to aumatically write a heredoc on next_token,
2324
+ # because we miss the chance to write a comma to separate elements
2325
+ skip_space_no_heredoc_check
2326
+ wrote_comma = check_heredocs_in_literal_elements(is_last, needs_trailing_comma, wrote_comma)
2308
2327
 
2309
2328
  next unless comma?
2310
- is_last = last?(i, elements)
2311
2329
 
2312
- write "," unless is_last
2313
- next_token
2314
- skip_space
2330
+ unless is_last
2331
+ write ","
2332
+ wrote_comma = true
2333
+ end
2334
+
2335
+ # We have to be careful not to aumatically write a heredoc on next_token,
2336
+ # because we miss the chance to write a comma to separate elements
2337
+ next_token_no_heredoc_check
2338
+ skip_space_no_heredoc_check
2339
+ wrote_comma = check_heredocs_in_literal_elements(is_last, needs_trailing_comma, wrote_comma)
2315
2340
 
2316
2341
  if newline? || comment?
2317
2342
  if is_last
@@ -2326,7 +2351,8 @@ class Rufo::Formatter
2326
2351
  end
2327
2352
 
2328
2353
  if needs_trailing_comma
2329
- write ","
2354
+ write "," unless wrote_comma
2355
+
2330
2356
  consume_end_of_line
2331
2357
  write_indent
2332
2358
  elsif comment?
@@ -2340,6 +2366,18 @@ class Rufo::Formatter
2340
2366
  end
2341
2367
  end
2342
2368
 
2369
+ def check_heredocs_in_literal_elements(is_last, needs_trailing_comma, wrote_comma)
2370
+ if (newline? || comment?) && !@heredocs.empty?
2371
+ if !is_last || needs_trailing_comma
2372
+ write "," unless wrote_comma
2373
+ wrote_comma = true
2374
+ end
2375
+
2376
+ flush_heredocs
2377
+ end
2378
+ wrote_comma
2379
+ end
2380
+
2343
2381
  def visit_if(node)
2344
2382
  visit_if_or_unless node, "if"
2345
2383
  end
@@ -2348,7 +2386,7 @@ class Rufo::Formatter
2348
2386
  visit_if_or_unless node, "unless"
2349
2387
  end
2350
2388
 
2351
- def visit_if_or_unless(node, keyword, check_end = true)
2389
+ def visit_if_or_unless(node, keyword, check_end: true)
2352
2390
  # if cond
2353
2391
  # then_body
2354
2392
  # else
@@ -2378,7 +2416,7 @@ class Rufo::Formatter
2378
2416
  consume_keyword "else"
2379
2417
  indent_body else_body[1]
2380
2418
  when :elsif
2381
- visit_if_or_unless else_body, "elsif", false
2419
+ visit_if_or_unless else_body, "elsif", check_end: false
2382
2420
  else
2383
2421
  bug "expected else or elsif, not #{else_body[0]}"
2384
2422
  end
@@ -2444,7 +2482,7 @@ class Rufo::Formatter
2444
2482
  else
2445
2483
  write " do "
2446
2484
  end
2447
- visit_exps body, false, false
2485
+ visit_exps body, with_lines: false
2448
2486
  skip_space_or_newline
2449
2487
  write_space if is_do
2450
2488
  end
@@ -2544,7 +2582,7 @@ class Rufo::Formatter
2544
2582
  end
2545
2583
  end
2546
2584
 
2547
- def consume_space(want_preserve_whitespace = false)
2585
+ def consume_space(want_preserve_whitespace: false)
2548
2586
  first_space = current_token if space?
2549
2587
  skip_space
2550
2588
  if want_preserve_whitespace && @preserve_whitespace && !newline? && !comment? && first_space
@@ -2560,6 +2598,12 @@ class Rufo::Formatter
2560
2598
  next_token while space?
2561
2599
  end
2562
2600
 
2601
+ def skip_space_no_heredoc_check
2602
+ while space?
2603
+ next_token_no_heredoc_check
2604
+ end
2605
+ end
2606
+
2563
2607
  def skip_space_backslash
2564
2608
  return [false, false] unless space?
2565
2609
 
@@ -2572,7 +2616,7 @@ class Rufo::Formatter
2572
2616
  [has_slash_newline, first_space]
2573
2617
  end
2574
2618
 
2575
- def skip_space_or_newline(_want_semicolon = false, write_first_semicolon = false)
2619
+ def skip_space_or_newline(_want_semicolon: false, write_first_semicolon: false)
2576
2620
  found_newline = false
2577
2621
  found_comment = false
2578
2622
  found_semicolon = false
@@ -2668,7 +2712,7 @@ class Rufo::Formatter
2668
2712
  # - at_prefix: are we at a point before an expression? (if so, we don't need a space before the first comment)
2669
2713
  # - want_semicolon: do we want do print a semicolon to separate expressions?
2670
2714
  # - want_multiline: do we want multiple lines to appear, or at most one?
2671
- def consume_end_of_line(at_prefix = false, want_semicolon = false, want_multiline = true, needs_two_lines_on_comment = false)
2715
+ def consume_end_of_line(at_prefix: false, want_semicolon: false, want_multiline: true, needs_two_lines_on_comment: false)
2672
2716
  found_newline = false # Did we find any newline during this method?
2673
2717
  last = nil # Last token kind found
2674
2718
  multilple_lines = false # Did we pass through more than one newline?
@@ -2819,7 +2863,7 @@ class Rufo::Formatter
2819
2863
 
2820
2864
  def indent_body(exps)
2821
2865
  indent do
2822
- consume_end_of_line(false, false, false)
2866
+ consume_end_of_line(want_multiline: false)
2823
2867
  end
2824
2868
 
2825
2869
  # A then keyword can appear after a newline after an `if`, `unless`, etc.
@@ -2836,7 +2880,7 @@ class Rufo::Formatter
2836
2880
  skip_space_or_newline
2837
2881
  else
2838
2882
  indent do
2839
- visit_exps exps, true
2883
+ visit_exps exps, with_indent: true
2840
2884
  end
2841
2885
  write_line unless @last_was_newline
2842
2886
  end
@@ -2876,7 +2920,7 @@ class Rufo::Formatter
2876
2920
  @last_was_newline = false
2877
2921
  end
2878
2922
 
2879
- def indent_after_space(node, sticky = false, want_space = true, first_space = nil)
2923
+ def indent_after_space(node, sticky: false, want_space: true, first_space: nil)
2880
2924
  first_space = current_token if space?
2881
2925
 
2882
2926
  skip_space
@@ -3000,11 +3044,15 @@ class Rufo::Formatter
3000
3044
  def next_token
3001
3045
  @tokens.pop
3002
3046
 
3003
- if newline? && !@heredocs.empty?
3047
+ if (newline? || comment?) && !@heredocs.empty?
3004
3048
  flush_heredocs
3005
3049
  end
3006
3050
  end
3007
3051
 
3052
+ def next_token_no_heredoc_check
3053
+ @tokens.pop
3054
+ end
3055
+
3008
3056
  def last?(i, array)
3009
3057
  i == array.size - 1
3010
3058
  end
data/lib/rufo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rufo
2
- VERSION = "0.0.24"
2
+ VERSION = "0.0.25"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.24
4
+ version: 0.0.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ary Borenszweig