ruby-beautify 0.96.0 → 0.97.0

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: 13168e4681dafb98dab93fbde6ed6df28bf935fe
4
- data.tar.gz: 905e6c45a87f5a0c64d6d959fb01095e35196386
3
+ metadata.gz: 45c73195863804f127d9481a07ec33676821e4d1
4
+ data.tar.gz: c1eaef1e3e7b2736d6f9a6272cd428636d0ef28a
5
5
  SHA512:
6
- metadata.gz: 5d8c76c28509bf4da9c6e3078039a707a3f4a5c9acba859ac877bb604877dbaeb73292fed65dfc83f89e0d51168570d20d65458e8c03f5a66e91730d2020a91e
7
- data.tar.gz: 01ff2b88dcd164966f9d3778653e009a8a08cdc51f6f51612efbdea6be7bf763c0171f1c70212d9a8d97620d7c06e25e79e3096e5e7e4fdda92485525f12920a
6
+ metadata.gz: 9370b94027a54f3b6911f818e8847b0c49c957cadfe2b6c73b049f493a24ab90dd1de91a61f48da952acc1001216fbcf8aa2721ef467c6478dfea8273d7713c7
7
+ data.tar.gz: 98f2d051bebff05ae8dce225ce5e44f3a2cef4dacf89dab2327ae094bae6cea7417062e0a476e91eb3d707a845a5aa527dc9e9d555251ce9e21c29045015bb4d
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  Gemfile.lock
2
2
  pkg/*
3
+ tmp/*
@@ -7,3 +7,6 @@ branches:
7
7
  - master
8
8
  - dev
9
9
  script: bundle exec rspec spec
10
+ addons:
11
+ code_climate:
12
+ repo_token: 596a4a033e7deae1bfd5e84da4c803ef81134158764a48b02279fe97eb83fcf4
data/CONTRIB.md CHANGED
@@ -6,7 +6,14 @@ How to contribute to this project.
6
6
  * Pull requests should be named something related to PR, `hotfix-XXX` or `feature-YYY`.
7
7
  * Do not edit the `version.rb` or the `gemspec`.
8
8
  * All pull requests have to pass tests on `travis-ci` before I'll consider merging them.
9
+ * for tests of the actual parser, make sure you include a new `usage_scenario`, not update an existing one. I'll merge stuff as it gets cluttered.
9
10
 
10
11
  ## Formatting and style
11
12
 
12
13
  Run all your code through `ruby-beautify` with default settings before committing.
14
+
15
+ This should work (and if it doesn't, please let me know)
16
+
17
+ `ruby-beautify --overwrite lib/**/*.rb bin/ruby-beautify spec/**/*_spec.rb spec/**/*_helper.rb`
18
+
19
+ Which should pretty up only the code files, and not our test files. This will help insure pretty commits and that they will be accepted.
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Ruby Beautify
2
2
  **Master** [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/erniebrodeur/ruby-beautify) [![Build Status](https://travis-ci.org/erniebrodeur/ruby-beautify.png?branch=master)](https://travis-ci.org/erniebrodeur/ruby-beautify) [![Dependency Status](https://gemnasium.com/erniebrodeur/ruby-beautify.png)](https://gemnasium.com/erniebrodeur/ruby-beautify)
3
- **Development** [![Build Status](https://travis-ci.org/erniebrodeur/ruby-beautify.png?branch=development)](https://travis-ci.org/erniebrodeur/ruby-beautify)
3
+
4
+ **Development** [![Build Status](https://travis-ci.org/erniebrodeur/ruby-beautify.png?branch=dev)](https://travis-ci.org/erniebrodeur/ruby-beautify)
4
5
 
5
6
  [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/erniebrodeur/ruby-beautify?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
7
 
@@ -10,64 +11,62 @@ Currenty, 'rbeautify' is included for backwards compatibility but will likely be
10
11
 
11
12
  ## Installation
12
13
 
13
- % gem install ruby-beautify
14
+ `gem install ruby-beautify`
14
15
 
15
16
  ## Usage
16
17
 
17
18
  To Pretty up a file:
18
19
 
19
- % ruby-beautify filename
20
+ `ruby-beautify filename`
20
21
 
21
22
  Without a filename it reads from STDIN, suitable for piping:
22
23
 
23
- % curl 'http://example.org/ugly-file.rb' | ruby-beautify
24
+ `curl https://raw.githubusercontent.com/erniebrodeur/ruby-beautify/master/spec/monolithic_example.rb | ruby-beautify`
24
25
 
25
26
  It has help:
26
27
 
27
- % ruby-beautify --help
28
+ `ruby-beautify --help`
28
29
 
29
30
  You can pick your indent character:
30
31
 
31
- % ruby-beautify --(t)abs
32
+ `ruby-beautify --(t)abs`
32
33
 
33
- % ruby-beautify --(s)paces
34
+ `ruby-beautify --(s)paces`
34
35
 
35
36
  You can also pick the count of characters:
36
37
 
37
- % ruby-beautify --indent_(c)ount 1
38
+ `ruby-beautify --indent_(c)ount 1`
38
39
 
39
40
  Examples:
40
41
 
41
- % ruby-beautify -c 2 -s filename
42
+ `ruby-beautify -c 2 -s filename`
42
43
 
43
- % ruby-beautify filename
44
+ `ruby-beautify filename`
44
45
 
45
- % ruby-beautify -t -c 2 filename
46
+ `ruby-beautify -t -c 2 filename`
46
47
 
47
- ## Bugs
48
+ ## Advanced Usage
49
+
50
+ You can over write files in place, this is useful for doing an entire directory of files at once. This will not over write any files that fail syntax check.
48
51
 
49
- I don't have every ruby style tested against, so I expect some gaps. Feel free to submit issues (please include an example) and I'll figure out how to 'beautify' it.
52
+ `ruby-beautify --overwrite **/*.rb`
53
+
54
+ ## Bugs
50
55
 
51
56
  Please feel free to open issues, I am actively working on this project again, thanks entirely to the ripper gem.
52
57
 
58
+ The gaps are getting smaller. I think we have most of the basic ruby use cases in place. I don't use rails/dsl's too often so I haven't tested those. I suspect it should 'just work' since the way we do syntax matching is really agnostic to what a DSL can change.
59
+
53
60
  ## Todo
54
61
 
55
62
  * Add vim style comment hinting.
56
- * Add overwrite in place to files.
57
- * Add 'best guest' for files that fail syntax checking.
58
- * Add syntax checking to files rendered via STDIN.
59
- * Seperate the content of the main bin into a proper namespace/library (so it doesn't pollute by default).
60
- * Split up the spec into multiple specs.
61
63
  * remove the link to rbeautify (by 1.0).
62
64
 
63
65
  Longer term I'd like to do some more to assignment, line wrapping, and spacing in/around keywords.
64
66
 
65
67
  ## Contributing
66
68
 
67
- * fork it.
68
- * create it.
69
- * push it.
70
- * pull it.
69
+ Please see the [Contribution Guide](CONTRIB.md) file for specifics on how to contribute to this project.
71
70
 
72
71
  # History
73
72
 
@@ -1,3 +1,10 @@
1
+ ## 0.97.0
2
+ * Split up the spec into usage scenarios, easier to contribut too.
3
+ * Lots of refactoring.
4
+ * Some documentation.
5
+ * Added multiple file support back so that overwrite files is more interesting.
6
+ * Added an overwrite files flag, useful for fixing up a directory of files at once.
7
+
1
8
  ## 0.96.0
2
9
  * Rewrote the syntax checker so that it pipes a string through stdout, doesn't need a temp file.
3
10
  * Moved everything into the module to clean up the bin.
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
- require 'ruby-beautify'
3
- require 'ripper'
4
2
  require 'optparse'
3
+ require 'ruby-beautify'
5
4
 
6
5
  include RubyBeautify
7
6
 
@@ -10,6 +9,7 @@ Options = OptionParser.new do |opts|
10
9
  opts.on("-c", "--indent_count [COUNT]", Integer, "Count of characters to use for indenting. (default: 1)") { |count| @indent_count = count}
11
10
  opts.on("-t", "--tabs", "Use tabs for the indent character (default)") { @indent_token = "\t" }
12
11
  opts.on("-s", "--spaces", "Use spaces for the indent character") { @indent_token = " " }
12
+ opts.on("--overwrite", "Overwrite files as you go (won't touch files that faile a syntax check).") { @overwrite = true }
13
13
  opts.banner = "Usage: print ruby into a pretty format, or break trying."
14
14
  end
15
15
  Options.parse!
@@ -17,25 +17,44 @@ Options.parse!
17
17
  @indent_token = "\t" unless @indent_token
18
18
  @indent_count = 1 unless @indent_count
19
19
 
20
+ def print_or_die(content)
21
+ if content
22
+ if syntax_ok? content
23
+ puts pretty_string content, indent_token: @indent_token, indent_count: @indent_count
24
+ else
25
+ puts content
26
+ exit 127
27
+ end
28
+ end
29
+ end
30
+
20
31
  # no argument, assume we want to open STDIN.
21
32
  if ARGV.empty?
22
33
  content = $stdin.read
34
+ print_or_die content
23
35
  else
24
- file = ARGV[0]
25
-
26
- if File.exist? file
27
- content = open(file).read
28
- else
29
- puts "No such file: #{file}"
30
- exit
31
- end
32
- end
36
+ ARGV.each do |file|
37
+ if File.exist? file
38
+ fh = open(file)
39
+ content = fh.read
40
+ fh.sync
41
+ fh.close
42
+ else
43
+ puts "No such file: #{file}"
44
+ exit
45
+ end
33
46
 
34
- if content
35
- if syntax_ok? content
36
- pretty_string content, indent_token: @indent_token, indent_count: @indent_count
37
- else
38
- puts content
39
- exit 127
47
+ if @overwrite
48
+ if syntax_ok? content
49
+ fh = open(file, 'w')
50
+ fh.write pretty_string content
51
+ fh.sync
52
+ fh.close
53
+ else
54
+ next
55
+ end
56
+ else
57
+ print_or_die content
58
+ end
40
59
  end
41
60
  end
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
- require 'ruby-beautify'
3
- require 'ripper'
4
2
  require 'optparse'
3
+ require 'ruby-beautify'
5
4
 
6
5
  include RubyBeautify
7
6
 
@@ -10,6 +9,7 @@ Options = OptionParser.new do |opts|
10
9
  opts.on("-c", "--indent_count [COUNT]", Integer, "Count of characters to use for indenting. (default: 1)") { |count| @indent_count = count}
11
10
  opts.on("-t", "--tabs", "Use tabs for the indent character (default)") { @indent_token = "\t" }
12
11
  opts.on("-s", "--spaces", "Use spaces for the indent character") { @indent_token = " " }
12
+ opts.on("--overwrite", "Overwrite files as you go (won't touch files that faile a syntax check).") { @overwrite = true }
13
13
  opts.banner = "Usage: print ruby into a pretty format, or break trying."
14
14
  end
15
15
  Options.parse!
@@ -17,25 +17,44 @@ Options.parse!
17
17
  @indent_token = "\t" unless @indent_token
18
18
  @indent_count = 1 unless @indent_count
19
19
 
20
+ def print_or_die(content)
21
+ if content
22
+ if syntax_ok? content
23
+ puts pretty_string content, indent_token: @indent_token, indent_count: @indent_count
24
+ else
25
+ puts content
26
+ exit 127
27
+ end
28
+ end
29
+ end
30
+
20
31
  # no argument, assume we want to open STDIN.
21
32
  if ARGV.empty?
22
33
  content = $stdin.read
34
+ print_or_die content
23
35
  else
24
- file = ARGV[0]
25
-
26
- if File.exist? file
27
- content = open(file).read
28
- else
29
- puts "No such file: #{file}"
30
- exit
31
- end
32
- end
36
+ ARGV.each do |file|
37
+ if File.exist? file
38
+ fh = open(file)
39
+ content = fh.read
40
+ fh.sync
41
+ fh.close
42
+ else
43
+ puts "No such file: #{file}"
44
+ exit
45
+ end
33
46
 
34
- if content
35
- if syntax_ok? content
36
- pretty_string content, indent_token: @indent_token, indent_count: @indent_count
37
- else
38
- puts content
39
- exit 127
47
+ if @overwrite
48
+ if syntax_ok? content
49
+ fh = open(file, 'w')
50
+ fh.write pretty_string content
51
+ fh.sync
52
+ fh.close
53
+ else
54
+ next
55
+ end
56
+ else
57
+ print_or_die content
58
+ end
40
59
  end
41
60
  end
@@ -1,157 +1,159 @@
1
1
  require 'open3'
2
+ require 'ripper'
2
3
  require 'ruby-beautify/version'
3
4
 
4
5
  module RubyBeautify
5
6
  extend self
6
7
 
7
- OPEN_BLOCK_START = ["module", "class", "begin", "def", 'if', 'while', 'unless', 'case']
8
- BOTH_BLOCK = ["else", "elsif", 'rescue', 'when']
9
- OPEN_BLOCK_DO = ['do', '{']
10
- CLOSE_BLOCK = ['end', '}']
11
-
12
- OPEN_BRACKETS = [:on_lparen, :on_lbracket, :on_lbrace, :on_embexpr_beg]
13
- CLOSE_BRACKETS = [:on_rparen, :on_rbracket, :on_rbrace, :on_embexpr_end]
14
- NEW_LINES = [:on_nl, :on_ignored_nl, :on_comment, :on_embdoc_end]
15
-
16
- # print an indented line. Requires the leve, token, count, and string.
17
- def puts_indented_line(level, token = "\t", count = 1, string)
18
- if string =~ /^\n$/
19
- puts
20
- else
21
- indent = (token * count) * level
22
- puts "#{indent}#{string.lstrip}"
23
- end
24
- end
25
-
26
- def pretty_string(content, indent_token: "\t", indent_count: 1)
27
- begin
28
- lex = Ripper.lex(content)
29
- rescue
30
- exit 255
31
- end
32
-
33
- indent_level = 0
34
- line_lex = []
35
-
36
- # walk through line tokens
37
- lex.each do |token|
38
- line_lex << token
39
- if NEW_LINES.include? token[1] # if type of this token is a new line
40
-
41
- # did we just close something? if so, lets bring it down a level.
42
- if closing_block?(line_lex) || closing_assignment?(line_lex)
43
- indent_level -= 1 if indent_level > 0
44
- end
45
-
46
- # print our line, in place.
47
- line_string = line_lex.map {|l| l.last}.join
48
- puts_indented_line(indent_level, indent_token, indent_count, line_string)
49
-
50
- # oh, we opened something did we? lets indent for the next run.
51
- if opening_block?(line_lex) || opening_assignment?(line_lex)
52
- indent_level += 1
53
- end
54
-
55
- line_lex.clear
56
- end
57
- end
58
-
59
- return nil
60
- end
61
-
62
- # how many times do we open in this line?
63
- def opening_block_count(line_lex)
64
- line_lex.select {|l| l[1] == :on_kw && OPEN_BLOCK_DO.include?(l[2])}.count
65
- end
66
-
67
- # how many times do we close?
68
- def closing_block_count(line_lex)
69
- line_lex.select {|l| l[1] == :on_kw && CLOSE_BLOCK.include?(l[2])}.count
70
- end
71
-
72
- # count the amount of opening assignments.
73
- def opening_assignment_count(line_lex)
74
- line_lex.select {|l| OPEN_BRACKETS.include? l[1]}.count
75
- end
76
-
77
- # count the amount of closing assignments.
78
- def closing_assignment_count(line_lex)
79
- line_lex.select {|l| CLOSE_BRACKETS.include? l[1]}.count
80
- end
81
-
82
- # check the syntax of a string, will pipe it through the ruby bin to see if
83
- # it has a valid syntax.
8
+ OPEN_BLOCK_START = ["module", "class", "begin", "def", 'if', 'while', 'unless', 'case']
9
+ BOTH_BLOCK = ["else", "elsif", 'rescue', 'when']
10
+ OPEN_BLOCK_DO = ['do', '{']
11
+ CLOSE_BLOCK = ['end', '}']
12
+
13
+ OPEN_BRACKETS = [:on_lparen, :on_lbracket, :on_lbrace, :on_embexpr_beg]
14
+ CLOSE_BRACKETS = [:on_rparen, :on_rbracket, :on_rbrace, :on_embexpr_end]
15
+ NEW_LINES = [:on_nl, :on_ignored_nl, :on_comment, :on_embdoc_end]
16
+
17
+
18
+ def pretty_string(content, indent_token: "\t", indent_count: 1)
19
+ output_string = ""
20
+ raise "Bad Syntax" unless syntax_ok? content
21
+ lex = ::Ripper.lex(content)
22
+
23
+ indent_level = 0
24
+ line_lex = []
25
+
26
+ # walk through line tokens
27
+ lex.each do |token|
28
+ line_lex << token
29
+ if NEW_LINES.include? token[1] # if type of this token is a new line
30
+
31
+ # did we just close something? if so, lets bring it down a level.
32
+ if closing_block?(line_lex) || closing_assignment?(line_lex)
33
+ indent_level -= 1 if indent_level > 0
34
+ end
35
+
36
+ # print our line, in place.
37
+ line_string = line_lex.map {|l| l.last}.join
38
+ output_string += indented_line(indent_level, indent_token, indent_count, line_string)
39
+
40
+ # oh, we opened something did we? lets indent for the next run.
41
+ if opening_block?(line_lex) || opening_assignment?(line_lex)
42
+ indent_level += 1
43
+ end
44
+
45
+ line_lex.clear
46
+ end
47
+ end
48
+
49
+ return output_string
50
+ end
51
+
52
+ # check the syntax of a string, will pipe it through the ruby bin to see if
53
+ # it has a valid syntax.
84
54
  def syntax_ok?(string)
85
55
  out, err, status = Open3.capture3("ruby -c -", stdin_data:string )
86
56
  return false unless err.empty?
87
57
  return true
88
58
  end
89
59
 
90
- # same trick as opening_block
91
- def opening_assignment?(line_lex)
92
- opens = opening_assignment_count line_lex
93
- closes = closing_assignment_count line_lex
94
- return false if opens == closes
95
- return true if opens > closes
96
- end
97
-
98
- # ...
99
- def closing_assignment?(line_lex)
100
- opens = opening_assignment_count line_lex
101
- closes = closing_assignment_count line_lex
102
- return false if opens == closes
103
- return true if closes > opens
104
- end
105
-
106
- # test for assignment from a block
107
- def contains_block_assignment?(line_lex)
108
- compacted_line = line_lex.reject{|x| x[1] == :on_sp} #remove spaces
109
- idx = compacted_line.rindex{|x| ['=', '||='].include? x[2]} #find last equal
110
- if idx
111
- return OPEN_BLOCK_START.include?(compacted_line[idx+1][2]) #check for if/begin block
112
- end
113
- return false
114
- end
115
-
116
- # is the first word a key word?
117
- def starts_block?(line_lex)
118
- return true if contains_block_assignment? line_lex
119
- line_lex.each do |x|
120
- # search for a first non-space token
121
- if not x[1] == :on_sp
122
- return x[1] == :on_kw && OPEN_BLOCK_START.include?(x[2])
123
- end
124
- end
125
- end
126
-
127
- # is the first word one of our 'both' keywords?
128
- def both_block?(line_lex)
129
- line_lex.each do |x|
130
- # search for a first non-space token
131
- if not x[1] == :on_sp
132
- return x[1] == :on_kw && BOTH_BLOCK.include?(x[2])
133
- end
134
- end
135
- end
136
-
137
- # kinda complex, we count open/close to determine if we ultimately have a
138
- # hanging line. Always true if it's a both_block.
139
- def opening_block?(line_lex)
140
- opens = (starts_block?(line_lex) || both_block?(line_lex)) ? 1 : 0
141
- opens += opening_block_count line_lex
142
- closes = closing_block_count line_lex
143
- return false if opens == closes
144
- return true if opens > closes
145
- end
146
-
147
- # kinda complex, we count open/close to determine if we ultimately have close a
148
- # hanging line. Always true if it's a both_block.
149
- def closing_block?(line_lex)
150
- return true if both_block? line_lex
151
- opens = starts_block?(line_lex) ? 1 : 0
152
- opens += opening_block_count line_lex
153
- closes = closing_block_count line_lex
154
- return false if opens == closes
155
- return true if opens < closes
156
- end
60
+ # same trick as opening_block
61
+ def opening_assignment?(line_lex)
62
+ opens = opening_assignment_count line_lex
63
+ closes = closing_assignment_count line_lex
64
+ return false if opens == closes
65
+ return true if opens > closes
66
+ end
67
+
68
+ # ...
69
+ def closing_assignment?(line_lex)
70
+ opens = opening_assignment_count line_lex
71
+ closes = closing_assignment_count line_lex
72
+ return false if opens == closes
73
+ return true if closes > opens
74
+ end
75
+
76
+ # test for assignment from a block
77
+ def contains_block_assignment?(line_lex)
78
+ compacted_line = line_lex.reject{|x| x[1] == :on_sp} #remove spaces
79
+ idx = compacted_line.rindex{|x| ['=', '||='].include? x[2]} #find last equal
80
+ if idx
81
+ return OPEN_BLOCK_START.include?(compacted_line[idx+1][2]) #check for if/begin block
82
+ end
83
+ return false
84
+ end
85
+
86
+ # is the first word a key word?
87
+ def starts_block?(line_lex)
88
+ return true if contains_block_assignment? line_lex
89
+ line_lex.each do |x|
90
+ # search for a first non-space token
91
+ if not x[1] == :on_sp
92
+ return x[1] == :on_kw && OPEN_BLOCK_START.include?(x[2])
93
+ end
94
+ end
95
+ end
96
+
97
+ # is the first word one of our 'both' keywords?
98
+ def both_block?(line_lex)
99
+ line_lex.each do |x|
100
+ # search for a first non-space token
101
+ if not x[1] == :on_sp
102
+ return x[1] == :on_kw && BOTH_BLOCK.include?(x[2])
103
+ end
104
+ end
105
+ end
106
+
107
+ # kinda complex, we count open/close to determine if we ultimately have a
108
+ # hanging line. Always true if it's a both_block.
109
+ def opening_block?(line_lex)
110
+ opens = (starts_block?(line_lex) || both_block?(line_lex)) ? 1 : 0
111
+ opens += opening_block_count line_lex
112
+ closes = closing_block_count line_lex
113
+ return false if opens == closes
114
+ return true if opens > closes
115
+ end
116
+
117
+ # kinda complex, we count open/close to determine if we ultimately have close a
118
+ # hanging line. Always true if it's a both_block.
119
+ def closing_block?(line_lex)
120
+ return true if both_block? line_lex
121
+ opens = starts_block?(line_lex) ? 1 : 0
122
+ opens += opening_block_count line_lex
123
+ closes = closing_block_count line_lex
124
+ return false if opens == closes
125
+ return true if opens < closes
126
+ end
127
+
128
+ private
129
+ # how many times do we open in this line?
130
+ def opening_block_count(line_lex)
131
+ line_lex.select {|l| l[1] == :on_kw && OPEN_BLOCK_DO.include?(l[2])}.count
132
+ end
133
+
134
+ # how many times do we close?
135
+ def closing_block_count(line_lex)
136
+ line_lex.select {|l| l[1] == :on_kw && CLOSE_BLOCK.include?(l[2])}.count
137
+ end
138
+
139
+ # count the amount of opening assignments.
140
+ def opening_assignment_count(line_lex)
141
+ line_lex.select {|l| OPEN_BRACKETS.include? l[1]}.count
142
+ end
143
+
144
+ # count the amount of closing assignments.
145
+ def closing_assignment_count(line_lex)
146
+ line_lex.select {|l| CLOSE_BRACKETS.include? l[1]}.count
147
+ end
148
+
149
+ # print an indented line. Requires the leve, token, count, and string.
150
+ def indented_line(level, token = "\t", count = 1, string)
151
+ output_string = ""
152
+ if string =~ /^\n$/
153
+ output_string += "\n"
154
+ else
155
+ indent = (token * count) * level
156
+ output_string += "#{indent}#{string.lstrip}"
157
+ end
158
+ end
157
159
  end