Indentinator 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/indentinator +87 -25
- data/lib/indentinator.rb +33 -29
- data/test/tests.rb +139 -9
- metadata +33 -6
data/bin/indentinator
CHANGED
@@ -1,50 +1,112 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
|
+
$:.unshift(File.expand_path('../../lib', __FILE__)) if $0 == __FILE__
|
2
3
|
require 'getopt/std'
|
3
4
|
require 'indentinator'
|
4
5
|
include Indentinator
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
def parse_amount(val)
|
8
|
+
return nil if val.nil?
|
9
|
+
if val.to_i.to_s == val # is a number
|
10
|
+
' ' * val.to_i
|
11
|
+
elsif val.downcase == 'tab'
|
12
|
+
"\t"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
opts = Getopt::Std.getopts('ic:a:vVr')
|
17
|
+
@from_stdin = opts['i']
|
18
|
+
@amount = parse_amount(opts['a'])
|
19
|
+
@to_amount = parse_amount(opts['c'])
|
8
20
|
@very_verbose = opts['V']
|
9
|
-
@verbose = opts['v']
|
21
|
+
@verbose = opts['v'] || @very_verbose
|
22
|
+
@replace = opts['r'] && !@from_stdin
|
10
23
|
@files = ARGV
|
11
|
-
|
24
|
+
|
25
|
+
if @files.size == 0 and not @from_stdin
|
12
26
|
puts "Usage:
|
13
27
|
|
14
28
|
indentinator [-c INDENT_AMOUNT] <file> [<file2>...]
|
15
29
|
|
16
30
|
Options:
|
17
31
|
|
18
|
-
-c
|
32
|
+
-c INDENT_AMOUNT
|
33
|
+
Modify the indentation amount to INDENT_AMOUNT. The value is either
|
34
|
+
a number - in which case it indicates the number of spaces to use;
|
35
|
+
or TAB - which indicates to use tabs.
|
36
|
+
|
37
|
+
-a AMOUNT
|
38
|
+
Tell me the original AMOUNT of indentation to use
|
39
|
+
when converting the file's indentation.
|
40
|
+
Normally, this value is inferred by looking at the input.
|
41
|
+
This option takes the same values as -c.
|
42
|
+
|
43
|
+
-i Read input from stdin. This will ignore any file arguments.
|
44
|
+
|
45
|
+
-r Replace the original file. Please back up your file or make sure you
|
46
|
+
are using version control. Indentinator is not responsible for
|
47
|
+
any damages; it just indents.
|
48
|
+
|
19
49
|
-v Verbose output
|
50
|
+
|
20
51
|
-V Very verbose output
|
21
52
|
|
22
53
|
"
|
23
54
|
exit(0)
|
24
55
|
end
|
25
56
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
57
|
+
def process_input(text, path)
|
58
|
+
lines = text.split("\n")
|
59
|
+
if @to_amount.nil? or @amount.nil?
|
60
|
+
@amount = indent_amount(lines)
|
61
|
+
end
|
62
|
+
if @to_amount.nil?
|
63
|
+
if @amount == ''
|
64
|
+
puts "#{path} has no indentation."
|
65
|
+
elsif @amount.match(/^ *$/)
|
66
|
+
puts "#{path} uses #{@amount.size} spaces."
|
67
|
+
elsif @amount == "\t"
|
68
|
+
puts "#{path} uses tabs."
|
69
|
+
else
|
70
|
+
puts "#{path} uses #{@amount.gsub(' ', 'SPACE ').gsub("\t", 'TAB ').strip}. WTF?"
|
71
|
+
end
|
72
|
+
else
|
73
|
+
output = convert_lines(lines, @amount, @to_amount).join("\n")
|
74
|
+
if @replace
|
75
|
+
write_file(path, output)
|
76
|
+
else
|
77
|
+
puts output
|
31
78
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def read_file(path)
|
83
|
+
f = open(path, 'r')
|
84
|
+
text = f.read
|
85
|
+
f.close
|
86
|
+
text
|
87
|
+
end
|
88
|
+
|
89
|
+
def write_file(path, text)
|
90
|
+
f = open(path, 'w')
|
91
|
+
f.write(text)
|
92
|
+
f.close
|
93
|
+
end
|
94
|
+
|
95
|
+
if @from_stdin
|
96
|
+
process_file(STDIN, 'Input')
|
97
|
+
else
|
98
|
+
@files.each do |path|
|
99
|
+
begin
|
100
|
+
if File.directory?(path)
|
101
|
+
puts "#{path} is a directory."
|
102
|
+
next
|
43
103
|
end
|
104
|
+
text = read_file(path)
|
105
|
+
process_input(text, path)
|
106
|
+
rescue Errno::ENOENT
|
107
|
+
puts "Can't open #{path}"
|
108
|
+
rescue ArgumentError
|
109
|
+
puts "Failed for #{path}. Is it binary?"
|
44
110
|
end
|
45
|
-
rescue Errno::ENOENT
|
46
|
-
puts "Can't open #{path}"
|
47
|
-
rescue ArgumentError
|
48
|
-
puts "Failed for #{path}. Is it binary?"
|
49
111
|
end
|
50
112
|
end
|
data/lib/indentinator.rb
CHANGED
@@ -1,28 +1,37 @@
|
|
1
|
+
class String
|
2
|
+
def -(other)
|
3
|
+
self.index(other) == 0 ? self[other.size..self.size] : nil
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
1
7
|
module Indentinator
|
2
8
|
|
3
9
|
def indent_amount(lines)
|
4
|
-
curr =
|
10
|
+
curr = ''
|
5
11
|
diffs = {}
|
12
|
+
# loop through the lines and count each indent difference
|
13
|
+
# between prev and current line in `diffs`
|
6
14
|
lines.each_with_index do |line, idx|
|
7
|
-
|
8
|
-
diff =
|
15
|
+
whites = line.match(/^([ \t]*)/)[0]
|
16
|
+
diff = whites - curr
|
9
17
|
if @very_verbose
|
10
|
-
puts "#{'%- 5d' % (idx + 1)}: #{diff}"
|
18
|
+
puts "#{'%- 5d' % (idx + 1)}: #{diff.size}" if diff
|
11
19
|
end
|
12
|
-
if diff > 0
|
20
|
+
if diff and diff.size > 0
|
13
21
|
diffs[diff] ||= 0
|
14
22
|
diffs[diff] = diffs[diff] + 1
|
15
23
|
end
|
16
|
-
curr =
|
24
|
+
curr = whites
|
17
25
|
end
|
26
|
+
# sort and pick the one w highest frequency
|
18
27
|
if diffs.size > 0
|
19
28
|
sorted = diffs.sort{|a, b| b[1] - a[1]}
|
20
29
|
if @verbose
|
21
|
-
puts sorted.map{|p| ('%- 5d=> ' % p[0]) + p[1].to_s}.join("\n")
|
30
|
+
puts sorted.map{|p| ('%- 5d=> ' % p[0].size) + p[1].to_s}.join("\n")
|
22
31
|
end
|
23
32
|
sorted[0][0]
|
24
33
|
else
|
25
|
-
|
34
|
+
''
|
26
35
|
end
|
27
36
|
end
|
28
37
|
|
@@ -31,30 +40,25 @@ def convert_indentation(text, from, to)
|
|
31
40
|
end
|
32
41
|
|
33
42
|
def convert_lines(lines, from, to)
|
34
|
-
|
35
|
-
|
36
|
-
curr_indent = 0
|
43
|
+
indents = [] # indentation stack
|
44
|
+
# loop through and convert line by line
|
37
45
|
lines.map do |line|
|
38
|
-
if line.empty?
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
indent
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
elsif indent == 0 # no indent
|
51
|
-
|
52
|
-
else # de-indent
|
53
|
-
# reset back to use original indentation
|
54
|
-
curr_indent = (curr_indent_org * ratio).round
|
46
|
+
next line if line.strip.empty?
|
47
|
+
m = line.match(/^([ \t]*)(.*)$/)
|
48
|
+
whites = m[1]
|
49
|
+
rest = m[2]
|
50
|
+
diff = whites - indents.join
|
51
|
+
if diff.nil?
|
52
|
+
# no match indent, could be a de-indent or a different indent pattern
|
53
|
+
# find longest matching indent in stack, and pop till that point
|
54
|
+
indents.pop
|
55
|
+
while indents.size > 0 and diff.nil?
|
56
|
+
indents.pop
|
57
|
+
diff = whites - indents.join
|
55
58
|
end
|
56
|
-
' ' * curr_indent + rest
|
57
59
|
end
|
60
|
+
indents.push(diff)
|
61
|
+
indents.map{|i| (i == from or i == "\t") ? to : i }.join + rest
|
58
62
|
end
|
59
63
|
end
|
60
64
|
|
data/test/tests.rb
CHANGED
@@ -1,5 +1,61 @@
|
|
1
1
|
require 'rspec'
|
2
|
-
require 'indentinator
|
2
|
+
require 'indentinator'
|
3
|
+
include Indentinator
|
4
|
+
|
5
|
+
describe 'indent_amount' do
|
6
|
+
it "sniffs indent amount 2" do
|
7
|
+
text = "
|
8
|
+
line 1
|
9
|
+
line 2"
|
10
|
+
indent_amount(text.split("\n")).should == " " * 2
|
11
|
+
text = "
|
12
|
+
line 1
|
13
|
+
line 2"
|
14
|
+
indent_amount(text.split("\n")).should == " " * 4
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should pick most frequent indentation" do
|
18
|
+
text = "
|
19
|
+
line 1
|
20
|
+
line 2
|
21
|
+
line 3
|
22
|
+
line 4"
|
23
|
+
indent_amount(text.split("\n")).should == " " * 4
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should support tabs" do
|
27
|
+
lines = [
|
28
|
+
"line 1",
|
29
|
+
"\tline 2",
|
30
|
+
"\t\tline 3"
|
31
|
+
]
|
32
|
+
indent_amount(lines).should == "\t"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should support tabs - adheres to frequency principle" do
|
36
|
+
lines = [
|
37
|
+
"line 1",
|
38
|
+
"\tline 2",
|
39
|
+
"\t\tline 3",
|
40
|
+
" line 4"
|
41
|
+
]
|
42
|
+
indent_amount(lines).should == "\t"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should support tabs - adheres to frequency principle(2)" do
|
46
|
+
lines = [
|
47
|
+
"line 1",
|
48
|
+
"\tline 2",
|
49
|
+
"\t\tline 3",
|
50
|
+
"line 4",
|
51
|
+
" line 5",
|
52
|
+
" line 6",
|
53
|
+
" line 7"
|
54
|
+
]
|
55
|
+
indent_amount(lines).should == " "
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
3
59
|
describe 'convert_file' do
|
4
60
|
it "converts basic indentation" do
|
5
61
|
text = "
|
@@ -7,7 +63,7 @@ line 1
|
|
7
63
|
line 2
|
8
64
|
line 3
|
9
65
|
line 4"
|
10
|
-
convert_indentation(text, 2, 4).should == "
|
66
|
+
convert_indentation(text, ' ' * 2, ' ' * 4).should == "
|
11
67
|
line 1
|
12
68
|
line 2
|
13
69
|
line 3
|
@@ -19,7 +75,7 @@ line 4"
|
|
19
75
|
text = "
|
20
76
|
line 1
|
21
77
|
line 2"
|
22
|
-
convert_indentation(text, 2, 4).should == text
|
78
|
+
convert_indentation(text, ' ' * 2, ' ' * 4).should == text
|
23
79
|
end
|
24
80
|
|
25
81
|
it "retains non-standard indentation even when is
|
@@ -29,7 +85,7 @@ line 1
|
|
29
85
|
line 2
|
30
86
|
line 3
|
31
87
|
line 2"
|
32
|
-
convert_indentation(text, 2, 4).should == "
|
88
|
+
convert_indentation(text, ' ' * 2, ' ' * 4).should == "
|
33
89
|
line 1
|
34
90
|
line 2
|
35
91
|
line 3
|
@@ -42,7 +98,7 @@ line 1
|
|
42
98
|
line 2
|
43
99
|
line 3
|
44
100
|
line 4"
|
45
|
-
convert_indentation(text, 4, 2).should == "
|
101
|
+
convert_indentation(text, ' ' * 4, ' ' * 2).should == "
|
46
102
|
line 1
|
47
103
|
line 2
|
48
104
|
line 3
|
@@ -56,7 +112,7 @@ line 0
|
|
56
112
|
line 2
|
57
113
|
line 3
|
58
114
|
line 4"
|
59
|
-
convert_indentation(text, 4, 2).should == "
|
115
|
+
convert_indentation(text, ' ' * 4, ' ' * 2).should == "
|
60
116
|
line 0
|
61
117
|
line 1
|
62
118
|
line 2
|
@@ -70,7 +126,7 @@ line 0
|
|
70
126
|
line 2
|
71
127
|
line 3
|
72
128
|
line 4"
|
73
|
-
convert_indentation(text, 2, 4).should == "
|
129
|
+
convert_indentation(text, ' ' * 2, ' ' * 4).should == "
|
74
130
|
line 0
|
75
131
|
line 2
|
76
132
|
line 3
|
@@ -85,7 +141,7 @@ line 0
|
|
85
141
|
line 3
|
86
142
|
|
87
143
|
line 4"
|
88
|
-
convert_indentation(text, 4, 2).should == "
|
144
|
+
convert_indentation(text, ' ' * 4, ' ' * 2).should == "
|
89
145
|
line 0
|
90
146
|
line 1
|
91
147
|
line 2
|
@@ -101,11 +157,85 @@ line 1
|
|
101
157
|
line 3
|
102
158
|
|
103
159
|
line 4"
|
104
|
-
convert_indentation(text, 4, 2).should == "
|
160
|
+
convert_indentation(text, ' ' * 4, ' ' * 2).should == "
|
105
161
|
line 1
|
106
162
|
line 2
|
107
163
|
line 3
|
108
164
|
|
109
165
|
line 4"
|
110
166
|
end
|
167
|
+
|
168
|
+
it "should de-indent property(ex 3)" do
|
169
|
+
text = "
|
170
|
+
line 2
|
171
|
+
line 3
|
172
|
+
line 4
|
173
|
+
line 5"
|
174
|
+
convert_indentation(text, ' ' * 2, ' ' * 4).should == "
|
175
|
+
line 2
|
176
|
+
line 3
|
177
|
+
line 4
|
178
|
+
line 5"
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should de-indent property(ex 4)" do
|
182
|
+
text = "
|
183
|
+
line 2
|
184
|
+
line 3
|
185
|
+
line 4
|
186
|
+
line 5"
|
187
|
+
convert_indentation(text, ' ' * 2, ' ' * 4).should == text
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should de-indent property(ex 5)" do
|
191
|
+
text = "
|
192
|
+
line 1
|
193
|
+
line 2
|
194
|
+
line 3
|
195
|
+
line 4
|
196
|
+
line 5
|
197
|
+
line 6"
|
198
|
+
convert_indentation(text, ' ' * 2, ' ' * 4).should == text
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should support tabs" do
|
202
|
+
lines = [
|
203
|
+
"line 1",
|
204
|
+
"\tline 2",
|
205
|
+
"\tline 3",
|
206
|
+
"\t\tline 4"
|
207
|
+
]
|
208
|
+
convert_lines(lines, "\t", " " * 4).should == [
|
209
|
+
"line 1",
|
210
|
+
" line 2",
|
211
|
+
" line 3",
|
212
|
+
" line 4"
|
213
|
+
]
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should support tabs (ex 2)" do
|
217
|
+
text = "
|
218
|
+
line 1
|
219
|
+
line 2
|
220
|
+
line 3
|
221
|
+
line 4"
|
222
|
+
convert_indentation(text, ' ' * 2, "\t").should == "
|
223
|
+
line 1
|
224
|
+
\tline 2
|
225
|
+
\t\tline 3
|
226
|
+
line 4"
|
227
|
+
end
|
228
|
+
|
229
|
+
it "tabs should be converted always" do
|
230
|
+
lines = [
|
231
|
+
"line 1",
|
232
|
+
" line 2",
|
233
|
+
"\tline 3"
|
234
|
+
]
|
235
|
+
convert_lines(lines, ' ' * 2, ' ' * 4).should == [
|
236
|
+
"line 1",
|
237
|
+
" line 2",
|
238
|
+
" line 3"
|
239
|
+
]
|
240
|
+
end
|
111
241
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Indentinator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Toby Ho
|
@@ -15,10 +15,37 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-03-
|
18
|
+
date: 2011-03-26 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: getopt
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rspec
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
22
49
|
description:
|
23
50
|
email: airportyh@gmail.com
|
24
51
|
executables:
|