1
#!/usr/bin/ruby -w
2
3
# Ruby beautifier, version 2.1, 09/11/2006
4
# Copyright (c) 2006, P. Lutus
5
# Released under the GPL
6
7
$tabSize = 2
8
$tabStr = " "
9
10
# indent regexp tests
11
12
$indentExp = [
13
   /^module\b/,
14
   /^if\b/,
15
   /(=\s*|^)until\b/,
16
   /(=\s*|^)for\b/,
17
   /^unless\b/,
18
   /(=\s*|^)while\b/,
19
   /(=\s*|^)begin\b/,
20
   /(^| )case\b/,
21
   /\bthen\b/,
22
   /^class\b/,
23
   /^rescue\b/,
24
   /^def\b/,
25
   /\bdo\b/,
26
   /^else\b/,
27
   /^elsif\b/,
28
   /^ensure\b/,
29
   /\bwhen\b/,
30
   /\{[^\}]*$/,
31
   /\[[^\]]*$/
32
]
33
34
# outdent regexp tests
35
36
$outdentExp = [
37
   /^rescue\b/,
38
   /^ensure\b/,
39
   /^elsif\b/,
40
   /^end\b/,
41
   /^else\b/,
42
   /\bwhen\b/,
43
   /^[^\{]*\}/,
44
   /^[^\[]*\]/
45
]
46
47
def makeTab(tab)
48
   return (tab < 0)?"":$tabStr * $tabSize * tab
49
end
50
51
def addLine(line,tab)
52
   line.strip!
53
   line = makeTab(tab)+line if line.length > 0
54
   return line + "\n"
55
end
56
57
def beautifyRuby(path)
58
   commentBlock = false
59
   programEnd = false
60
   multiLineArray = Array.new
61
   multiLineStr = ""
62
   tab = 0
63
   source = File.read(path)
64
   dest = ""
65
   source.split("\n").each do |line|
66
      if(!programEnd)
67
         # detect program end mark
68
         if(line =~ /^__END__$/)
69
            programEnd = true
70
         else
71
            # combine continuing lines
72
            if(!(line =~ /^\s*#/) && line =~ /[^\\]\\\s*$/)
73
               multiLineArray.push line
74
               multiLineStr += line.sub(/^(.*)\\\s*$/,"\\1")
75
               next
76
            end
77
78
            # add final line
79
            if(multiLineStr.length > 0)
80
               multiLineArray.push line
81
               multiLineStr += line.sub(/^(.*)\\\s*$/,"\\1")
82
            end
83
84
            tline = ((multiLineStr.length > 0)?multiLineStr:line).strip
85
            if(tline =~ /^=begin/)
86
               commentBlock = true
87
            end
88
         end
89
      end
90
      if(commentBlock || programEnd)
91
         # add the line unchanged
92
         dest += line + "\n"
93
      else
94
         commentLine = (tline =~ /^#/)
95
         if(!commentLine)
96
            # throw out sequences that will
97
            # only sow confusion
98
            while tline.gsub!(/'.*?'/,"")
99
            end
100
            while tline.gsub!(/".*?"/,"")
101
            end
102
            while tline.gsub!(/\`.*?\`/,"")
103
            end
104
            while tline.gsub!(/\{[^\{]*?\}/,"")
105
            end
106
            while tline.gsub!(/\([^\(]*?\)/,"")
107
            end
108
            while tline.gsub!(/\/.*?\//,"")
109
            end
110
            while tline.gsub!(/%r(.).*?\1/,"")
111
            end
112
            tline.gsub!(/\\\"/,"'")
113
            $outdentExp.each do |re|
114
               if(tline =~ re)
115
                  tab -= 1
116
                  break
117
               end
118
            end
119
         end
120
         if (multiLineArray.length > 0)
121
            multiLineArray.each do |ml|
122
               dest += addLine(ml,tab)
123
            end
124
            multiLineArray.clear
125
            multiLineStr = ""
126
         else
127
            dest += addLine(line,tab)
128
         end
129
         if(!commentLine)
130
            $indentExp.each do |re|
131
               if(tline =~ re && !(tline =~ /\s+end\s*$/))
132
                  tab += 1
133
                  break
134
               end
135
            end
136
         end
137
      end
138
      if(tline =~ /^=end/)
139
         commentBlock = false
140
      end
141
   end
142
   if(source != dest)
143
      # make a backup copy
144
      File.open(path + "~","w") { |f| f.write(source) }
145
      # overwrite the original
146
      File.open(path,"w") { |f| f.write(dest) }
147
   end
148
   if(tab != 0)
149
      STDERR.puts "#{path}: Indentation error: #{tab}"
150
   end
151
end
152
153
if(!ARGV[0])
154
   STDERR.puts "usage: Ruby filenames to beautify."
155
   exit 0
156
end
157
158
ARGV.each do |path|
159
   beautifyRuby(path)
160
end