rufo 0.0.3 → 0.0.4

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: f651b0e7deb5c6d36cbe7632aa761954e7d49939
4
- data.tar.gz: 20b7c26c352e682cf72547fdeebf25d31b467aa4
3
+ metadata.gz: 447a4661f121c8ffd43ba8fc6e5e7267ab5dc3d5
4
+ data.tar.gz: a69acf6a569e48b611a51d6105bc3081b47742fe
5
5
  SHA512:
6
- metadata.gz: b9f40a5d0fd5ad07143ccc49fafddce8bd72cad15ada182f8cdf03b239a956f5a4072fe0df639d53a3c88d928a12058a360158b1a3b61462e073b2d9973cdfb1
7
- data.tar.gz: 122c69242308b0999954d684ae4cfb4a0020d5ec9b68de7f76ce449a47076d659d8062f8c69fe9da80057031e07caddcc19f8a0fb653cd1e7ee0be3619d990c9
6
+ metadata.gz: 9e0df262618cf4ff4e6b6b4ddd9b241b734e52a2fe35c170ee70c4dbabc7d48df15e39c9432574982886dc19631a7263fb0d53f00e7deb45e50d7173fbe75275
7
+ data.tar.gz: 1aaf628a9c1ee5d2405b518048d1ae1524d5f673798c511751675cfe38680041619286f0e5056e59c81cc4deabb5e39f54775b87af31f041a8c65119b79befb4
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Rufo
2
2
 
3
+ [![Build Status](https://travis-ci.org/asterite/rufo.svg)](https://travis-ci.org/asterite/rufo)
4
+
3
5
  **Ru**by **fo**rmatter
4
6
 
5
7
  ## Installation
@@ -75,6 +77,29 @@ indent_size 2
75
77
  As time passes there might be more configurations available. Please open an
76
78
  issue if you need something else to be configurable.
77
79
 
80
+ ## Status
81
+
82
+ The current version is 0.0.3. The formatter was tested on some big files with many Ruby
83
+ syntax and idioms, but since it's so new there might be some missing stuff. Don't hesitate
84
+ to open an issue if you find something is not working well. In any case, if the formatter
85
+ chokes on some valid input you will get an error prompting you to submit a bug report here :-)
86
+
87
+ ## How it works
88
+
89
+ Rufo is a **real** formatter, not a simple find and replace one. It works by employing
90
+ a Ruby parser and a Ruby lexer. The parser is used for the shape of the program. The program
91
+ is traversed and the lexer is used to sync this structure to tokens. This is why comments
92
+ can be handled well, because they are provided by the lexer (comments are not returned by
93
+ a parser).
94
+
95
+ To parse and lex, [Ripper](https://ruby-doc.org/stdlib-2.4.0/libdoc/ripper/rdoc/Ripper.html) is used.
96
+
97
+ As a reference, this was implemented in a similar fashion to [Crystal](https://github.com/crystal-lang/crystal)'s formatter.
98
+
99
+ And as a side note, rufo has **no dependencies**. It only depends on `rspec` for tests, but that's it.
100
+ That means it loads very fast (no need to read many Ruby files), and because `Ripper` is mostly written
101
+ in C (uses Ruby's lexer and parser) it formats files pretty fast too.
102
+
78
103
  ## Development
79
104
 
80
105
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -9,9 +9,6 @@ module Rufo::Command
9
9
  else
10
10
  format_args ARGV, want_check
11
11
  end
12
- rescue Rufo::SyntaxError
13
- STDERR.puts "Error: the given text is not a valid ruby program (it has syntax errors)"
14
- exit 1
15
12
  end
16
13
 
17
14
  def self.format_stdin(want_check)
@@ -23,6 +20,9 @@ module Rufo::Command
23
20
  else
24
21
  print result
25
22
  end
23
+ rescue Rufo::SyntaxError
24
+ STDERR.puts "Error: the given text is not a valid ruby program (it has syntax errors)"
25
+ exit 1
26
26
  rescue Rufo::Bug => ex
27
27
  STDERR.puts "You've found a bug!"
28
28
  STDERR.puts "Please report it to https://github.com/asterite/rufo/issues with code that triggers it"
@@ -68,6 +68,9 @@ module Rufo::Command
68
68
  end
69
69
 
70
70
  false
71
+ rescue Rufo::SyntaxError
72
+ STDERR.puts "Error: the given text in #{filename} is not a valid ruby program (it has syntax errors)"
73
+ exit 1
71
74
  rescue Rufo::Bug => ex
72
75
  STDERR.puts "You've found a bug!"
73
76
  STDERR.puts "It happened while trying to format the file #{filename}"
@@ -110,8 +110,18 @@ class Rufo::Formatter
110
110
  #
111
111
  # [:@int, "123", [1, 0]]
112
112
  consume_token :on_int
113
+ when :@gvar
114
+ # [:@gvar, "$abc", [1, 0]]
115
+ write node[1]
116
+ next_token
117
+ when :@backref
118
+ # [:@backref, "$1", [1, 0]]
119
+ write node[1]
120
+ next_token
113
121
  when :string_literal
114
122
  visit_string_literal node
123
+ when :string_concat
124
+ visit_string_concat node
115
125
  when :@tstring_content
116
126
  # [:@tstring_content, "hello ", [1, 1]]
117
127
  heredoc, tilde = @current_heredoc
@@ -294,6 +304,8 @@ class Rufo::Formatter
294
304
  consume_keyword "super"
295
305
  when :super
296
306
  visit_super(node)
307
+ when :defined
308
+ visit_defined(node)
297
309
  else
298
310
  bug "Unhandled node: #{node.first}"
299
311
  end
@@ -397,6 +409,16 @@ class Rufo::Formatter
397
409
  end
398
410
  end
399
411
 
412
+ def visit_string_concat(node)
413
+ # string1 string2
414
+ # [:string_concat, string1, string2]
415
+ _, string1, string2 = node
416
+
417
+ visit string1
418
+ consume_space
419
+ visit string2
420
+ end
421
+
400
422
  def visit_string_interpolation(node)
401
423
  # [:string_embexpr, exps]
402
424
  consume_token :on_embexpr_beg
@@ -610,7 +632,7 @@ class Rufo::Formatter
610
632
 
611
633
  def consume_call_dot
612
634
  if current_token_kind == :on_op
613
- consume_op "::"
635
+ consume_token :on_op
614
636
  else
615
637
  check :on_period
616
638
  next_token
@@ -942,9 +964,9 @@ class Rufo::Formatter
942
964
  _, body, rescue_body, else_body, ensure_body = node
943
965
  indent_body body
944
966
 
945
- if rescue_body
946
- # [:rescue, type, name, body, nil]
947
- _, type, name, body = rescue_body
967
+ while rescue_body
968
+ # [:rescue, type, name, body, more_rescue]
969
+ _, type, name, body, more_rescue = rescue_body
948
970
  write_indent
949
971
  consume_keyword "rescue"
950
972
  if type
@@ -965,6 +987,7 @@ class Rufo::Formatter
965
987
  end
966
988
 
967
989
  indent_body body
990
+ rescue_body = more_rescue
968
991
  end
969
992
 
970
993
  if else_body
@@ -1452,9 +1475,15 @@ class Rufo::Formatter
1452
1475
  end
1453
1476
 
1454
1477
  has_newline = false
1478
+ last_token = nil
1455
1479
 
1456
1480
  while current_token_kind == :on_words_sep
1457
1481
  has_newline ||= current_token_value.include?("\n")
1482
+
1483
+ unless current_token[2].strip.empty?
1484
+ last_token = current_token
1485
+ end
1486
+
1458
1487
  next_token
1459
1488
  end
1460
1489
 
@@ -1463,8 +1492,12 @@ class Rufo::Formatter
1463
1492
  write_indent(next_indent)
1464
1493
  end
1465
1494
 
1466
- write ")"
1467
- return
1495
+ if last_token
1496
+ write last_token[2].strip
1497
+ else
1498
+ write current_token_value.strip
1499
+ next_token
1500
+ end
1468
1501
  end
1469
1502
 
1470
1503
  def visit_hash(node)
@@ -1683,7 +1716,12 @@ class Rufo::Formatter
1683
1716
  consume_space if space?
1684
1717
 
1685
1718
  indent(@column) do
1686
- visit node[1]
1719
+ # For `return a b` there comes many nodes, not just one... (see #8)
1720
+ if node[1][0].is_a?(Symbol)
1721
+ visit node[1]
1722
+ else
1723
+ visit_exps node[1], false, false
1724
+ end
1687
1725
  end
1688
1726
  end
1689
1727
  end
@@ -1764,6 +1802,39 @@ class Rufo::Formatter
1764
1802
  end
1765
1803
  end
1766
1804
 
1805
+ def visit_defined(node)
1806
+ # [:defined, exp]
1807
+ _, exp = node
1808
+
1809
+ consume_keyword "defined?"
1810
+ skip_space_or_newline
1811
+
1812
+ has_paren = current_token_kind == :on_lparen
1813
+
1814
+ if has_paren
1815
+ write "("
1816
+ next_token
1817
+ skip_space_or_newline
1818
+ else
1819
+ consume_space
1820
+ end
1821
+
1822
+ # exp can be [:paren, exp] if there's a parentheses,
1823
+ # though not always (only if there's a space after `defined?`)
1824
+ if exp[0] == :paren
1825
+ exp = exp[1]
1826
+ end
1827
+
1828
+ visit exp
1829
+
1830
+ if has_paren
1831
+ skip_space_or_newline
1832
+ check :on_rparen
1833
+ write ")"
1834
+ next_token
1835
+ end
1836
+ end
1837
+
1767
1838
  def visit_literal_elements(elements)
1768
1839
  base_column = @column
1769
1840
 
@@ -1891,20 +1962,47 @@ class Rufo::Formatter
1891
1962
  skip_space
1892
1963
 
1893
1964
  # Keep `while cond; end` as is
1894
- if semicolon? && void_exps?(body)
1965
+ semicolon = semicolon?
1966
+ is_do = keyword?("do")
1967
+
1968
+ if (semicolon || is_do) && void_exps?(body)
1895
1969
  next_token
1896
1970
  skip_space
1897
1971
 
1898
1972
  if keyword?("end")
1899
- write "; end"
1973
+ if is_do
1974
+ write " do end"
1975
+ else
1976
+ write "; end"
1977
+ end
1900
1978
  next_token
1901
1979
  return
1902
1980
  end
1903
1981
  end
1904
1982
 
1905
- indent_body body
1983
+ if semicolon || is_do
1984
+ next_token
1985
+ skip_space
1986
+ skip_semicolons
1987
+
1988
+ if newline? || comment?
1989
+ indent_body body
1990
+ write_indent
1991
+ else
1992
+ skip_space_or_newline
1993
+ if semicolon
1994
+ write "; "
1995
+ else
1996
+ write " do "
1997
+ end
1998
+ visit_exps body, false, false
1999
+ consume_space
2000
+ end
2001
+ else
2002
+ indent_body body
2003
+ write_indent
2004
+ end
1906
2005
 
1907
- write_indent
1908
2006
  consume_keyword "end"
1909
2007
  end
1910
2008
 
@@ -1991,7 +2089,7 @@ class Rufo::Formatter
1991
2089
 
1992
2090
  def consume_space
1993
2091
  skip_space_or_newline
1994
- write_space " "
2092
+ write_space " " unless @output[-1] == " "
1995
2093
  end
1996
2094
 
1997
2095
  def skip_space
@@ -1,3 +1,3 @@
1
1
  module Rufo
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
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.3
4
+ version: 0.0.4
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-22 00:00:00.000000000 Z
11
+ date: 2017-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler