Mercurial > hg > forks > UniversalIndentGUI
changeset 487:99383b949316
Added support for two (rather simple) Ruby beautifiers.
git-svn-id: svn://svn.code.sf.net/p/universalindent/code/trunk@727 59b1889a-e5ac-428c-b0c7-476e01d41282
author | thomas_-_s <thomas_-_s@59b1889a-e5ac-428c-b0c7-476e01d41282> |
---|---|
date | Fri, 13 Jun 2008 12:05:39 +0000 |
parents | 4946039b2c16 |
children | 0745e5a3a9df |
files | indenters/example.rb indenters/rbeautify.rb indenters/ruby_formatter.rb indenters/uigui_rbeautify.ini indenters/uigui_rubyformatter.ini |
diffstat | 5 files changed, 514 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/indenters/example.rb Fri Jun 13 12:05:39 2008 +0000 @@ -0,0 +1,1 @@ +#!/usr/bin/env ruby #odd assignments BEGIN { puts "a block i have never seen used" } entry = Post.update(params["id"],{:title => params["title"],:post => params['post'],:context => params["context"],:creator => session[:creator]}) moo = if false "Sdf" elsif true "df" end defintion = "moo" puts moo moo = case 3 when 2 "unless proceeding to 3" when 3 "right" when 4 "one to many" when 5 "three sir" end puts moo def pointless_call if false "Sdf" elsif true "df" end end puts pointless_call if true puts "moo" end i = 5 def title doc = load_page title = doc.search("h1").first.inner_html clean_html_tags(title) clean_9_0(title) title end if i if true puts "moo" elsif i < 3 * 23 "sdf" else "df" end end class Tested def sadf "asdf" end end module Moo def t434t "352" end#comments at the end end #comments again debug_if =begin block comments should have no formatting done ever =end #java formatter test parts ping(argument) {|block| } if (moo) cow; else dog; end x = 5 x = 5 x = 5 x = 5 IN_OUTS_RX = /^(def|class|module|begin|case|if|unless|loop|while|until|for)/ #end java formatter test parts here_doc = <<-EOX This should not loose its formatting EOX dsfffffffff=[2, 3, 4, 5] print <<-STRING1, <<-STRING2 Concat STRING1 enate STRING2 unless false "4" else "5" end x = 2 while x > 0 x -= 1 if x == 1 "p" else "3" end end x = 2 until x < 0 x -= 1 end a = 3 a *= 2 while a < 100 a -= 10 until a < 100 print "Hello\n" while false print "Goodbye\n" while false 3.times do print "Ho! " end 0.upto(9) do | x| print x, " " end 0.step(12, 3) {|x | print x, " " } x = 0 loop { if x == 5 break end x += 1 } (1..4).each {|x| puts x } (1..4).each do | x| puts x end for i in (1..4) puts i end i = 0 loop do i += 1 next if i < 3 print i break if i > 4 end string = "x+1" begin eval string rescue SyntaxError, NameError => boom print "String doesn't compile: " + boom rescue StandardError => bang print "Error running script: " + bang ensure print "thank you pick axe" end a = "Fats ' ' \\\" do Waller" a =~ /\/a/ if true then print "a" end x = 3 unless true then print "a" end x = 3 begin raise "cow" rescue Exception => e end x = 3 puts i += 1 while i < 3 # ruby x = 3 klass = Fixnum #its like a do while loop begin print klass klass = klass.superclass print " < " if klass end while klass puts p Fixnum.ancestors boom = %q / this is a spinal tap/ boom = %q - string- boom =%q(a (nested) string) x = "done with string" puts "In parent,term = #{ENV['TERM']}" cow = if true "moot" else "woot" end fork do puts "Start of child 1,term=#{ENV['TERM']}" ENV['TERM'] = "ansi" fork do puts "Start of child 2, term=#{ENV['TERM']}" begin if moo < 3 p "asdf4" elsif 9 * 0 p "asde" else puts cow end end while x > 3 end Process.wait puts "End of child 1, term=#{ENV['TERM']}" end Process.wait puts "Back in parent, term=#{ENV['TERM']}" OPENOFFICE = true # do Openoffice - Spreadsheet Tests? EXCEL = true # do Excel Tests? GOOGLE = true # do Google - Spreadsheet Tests? OPENOFFICEWRITE = false # experimental: END{ puts "another block i have never seen" } \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/indenters/rbeautify.rb Fri Jun 13 12:05:39 2008 +0000 @@ -0,0 +1,186 @@ +#!/usr/bin/ruby -w + +# NEED_SYMLINK + +=begin +/*************************************************************************** + * Copyright (C) 2006, Paul Lutus * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +=end + +PVERSION = "Version 2.2, 10/29/2007" + +$tabSize = 3 +$tabStr = " " + +# indent regexp tests + +$indentExp = [ + /^module\b/, + /^if\b/, + /(=\s*|^)until\b/, + /(=\s*|^)for\b/, + /^unless\b/, + /(=\s*|^)while\b/, + /(=\s*|^)begin\b/, + /(^| )case\b/, + /\bthen\b/, + /^class\b/, + /^rescue\b/, + /^def\b/, + /\bdo\b/, + /^else\b/, + /^elsif\b/, + /^ensure\b/, + /\bwhen\b/, + /\{[^\}]*$/, + /\[[^\]]*$/ +] + +# outdent regexp tests + +$outdentExp = [ + /^rescue\b/, + /^ensure\b/, + /^elsif\b/, + /^end\b/, + /^else\b/, + /\bwhen\b/, + /^[^\{]*\}/, + /^[^\[]*\]/ +] + +def makeTab(tab) + return (tab < 0)?"":$tabStr * $tabSize * tab +end + +def addLine(line,tab) + line.strip! + line = makeTab(tab)+line if line.length > 0 + return line + "\n" +end + +def beautifyRuby(path) + commentBlock = false + programEnd = false + multiLineArray = Array.new + multiLineStr = "" + tab = 0 + source = File.read(path) + dest = "" + source.split("\n").each do |line| + if(!programEnd) + # detect program end mark + if(line =~ /^__END__$/) + programEnd = true + else + # combine continuing lines + if(!(line =~ /^\s*#/) && line =~ /[^\\]\\\s*$/) + multiLineArray.push line + multiLineStr += line.sub(/^(.*)\\\s*$/,"\\1") + next + end + + # add final line + if(multiLineStr.length > 0) + multiLineArray.push line + multiLineStr += line.sub(/^(.*)\\\s*$/,"\\1") + end + + tline = ((multiLineStr.length > 0)?multiLineStr:line).strip + if(tline =~ /^=begin/) + commentBlock = true + end + end + end + if(commentBlock || programEnd) + # add the line unchanged + dest += line + "\n" + else + commentLine = (tline =~ /^#/) + if(!commentLine) + # throw out sequences that will + # only sow confusion + while tline.gsub!(/\{[^\{]*?\}/,"") + end + while tline.gsub!(/\[[^\[]*?\]/,"") + end + while tline.gsub!(/'.*?'/,"") + end + while tline.gsub!(/".*?"/,"") + end + while tline.gsub!(/\`.*?\`/,"") + end + while tline.gsub!(/\([^\(]*?\)/,"") + end + while tline.gsub!(/\/.*?\//,"") + end + while tline.gsub!(/%r(.).*?\1/,"") + end + # delete end-of-line comments + tline.sub!(/#[^\"]+$/,"") + # convert quotes + tline.gsub!(/\\\"/,"'") + $outdentExp.each do |re| + if(tline =~ re) + tab -= 1 + break + end + end + end + if (multiLineArray.length > 0) + multiLineArray.each do |ml| + dest += addLine(ml,tab) + end + multiLineArray.clear + multiLineStr = "" + else + dest += addLine(line,tab) + end + if(!commentLine) + $indentExp.each do |re| + if(tline =~ re && !(tline =~ /\s+end\s*$/)) + tab += 1 + break + end + end + end + end + if(tline =~ /^=end/) + commentBlock = false + end + end + if(source != dest) + # make a backup copy + File.open(path + "~","w") { |f| f.write(source) } + # overwrite the original + File.open(path,"w") { |f| f.write(dest) } + end + if(tab != 0) + STDERR.puts "#{path}: Indentation error: #{tab}" + end +end + +if(!ARGV[0]) + STDERR.puts "usage: Ruby filenames to beautify." + exit 0 +end + +ARGV.each do |path| + beautifyRuby(path) +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/indenters/ruby_formatter.rb Fri Jun 13 12:05:39 2008 +0000 @@ -0,0 +1,283 @@ +#!/usr/bin/ruby -w +# +# == Synopsis +# +# Simple Ruby Formatter +# +# Created by: Stephen Becker IV +# Contributions: Andrew Nutter-Upham +# Contact: sbeckeriv@gmail.com +# SVN: http://svn.stephenbeckeriv.com/code/ruby_formatter/ +# +# Its been done before RadRails did, +# http://vim.sourceforge.net/tips/tip.php?tip_id = 1368 that guy did it, but I did +# not look for a ruby formatter until i was done. +# +# It is called simple formatting because it is. I have the concept of 3 differnt +# indent actions In, Out and Both. I have mixed the concept of indenting and +# outdenting. Out means you have added white space and in means you remove a layer +# of white space. +# +# Basic logic +# Decrease current depth if +# ((the it is not a one line if unless statment +# (need to lookfor more oneline blocks) and it ends with end +# or if the } count is larger then {) +# or +# the first word is in the both list) +# +# and +# depth is larger then zero +# +# Increase current depth if +# It is not a one liner +# and +# (the word is in the out list +# or +# the word is in the both list +# or +# it looks like a start block) +# and +# temp_depth is nil (used for = comment blocks) +# +# +# Sure there are some regx's and a crap load of gsubs, but it still simple. Its +# not like its a pychecker (http://www.metaslash.com/brochure/ipc10.html) +# +# == Usage +# +# ruby [options] filelist +# +# options: +# -s # will change the indent to a space count of # per level +# by default we space with 1 tab per level +# -b # create a backup file +# +# examples: +# ruby simple_formatter.rb -s 3 -b /moo/cluck/cow.rb +# runs with the indent of 3 spaces,creates a backup file, and formats moo/cluck/cow.rb +# +# +# Tested with random files off of koders.com +# +# +::DEBUG_ME = false +require 'getoptlong' +require "fileutils" +require "pp" +$escape_strings = {:regex=>"EsCaPedReGex",:string=>"EsCaPeDStRiNg"} +begin + require 'rdoc/usage' +rescue Exception => e + #eat the no load of rdocs? +end +opts = GetoptLong.new( +[ '--help', '-h', GetoptLong::NO_ARGUMENT ], +[ '--spaces', '-s', GetoptLong::OPTIONAL_ARGUMENT ], +[ '--debug', '-d', GetoptLong::NO_ARGUMENT ], +[ '--backup', '-b', GetoptLong::NO_ARGUMENT ] +) +space_count = nil +backup = false +files = [] +opts.each do | opt, arg| + case opt + when '--help' + begin + RDoc::usage + rescue Exception =>e + puts "If you want to use rdocs you need to install it" + exit(-1) + end + when '--spaces' + space_count = arg.to_i + when '--backup' + backup = true + when '--debug' + ::DEBUG_ME = true + end +end +require "profile" if ::DEBUG_ME +if ARGV.length < 1 + puts "Missing filelist argument (try --help)" + exit 0 +end +array_loc = ARGV +#find if the string is a start block +#return true if it is +#rules +# does not include end at the end +# and ( { out number the } or it includes do +DO_RX = /\sdo\s*$/ +def start_block?(string) + return true if string.gsub(/\|.*\|/, "").match(DO_RX) || (string.scan(/\{/).size > string.scan(/\}/).size) + false +end +#is this an end block? +#rules +#its not a one liner +#and it ends with end +#or } out number { +CHECK_ENDS_RX = /end$|end\s+while/ +def check_ends?(string) + #check for one liners end and } + #string = just_the_string_please(string) + return true if (string.scan(/\{/).size < string.scan(/\}/).size) || string.match(CHECK_ENDS_RX) + false +end +IN_OUTS_RX = /^(def|class|module|begin|case|if|unless|loop|while|until|for)/ +#look at first work does it start with one of the out works +def in_outs?(string) + string.sub!(/\(.*\)/, "") + return true if string.lstrip.match(IN_OUTS_RX) && string.strip.size == $1.strip.size + false +end +IN_BOTH_RX = /^(elsif|else|when|rescue|ensure)/ +#look at first work does it start with one of the both words? +def in_both?(string) + return true if string.lstrip.match(IN_BOTH_RX) && string.strip.size == $1.strip.size + false +end +#extra formatting for the line +#we wrap = with spaces +#JUST_STRING_PLEASE_RX = /^#.*|\/.*\/|"([^"])*"|'([^'])*'/ +LINE_CLEAN_UP_RX = /[a-zA-Z\]\'\"{\d]+=[a-zA-Z\[\'\"{\d]+/ +def line_clean_up(x) + #this formatts strings and regexs remove and add in replacement works + + x.gsub!(/\\\//,$escape_strings[:regex]) + strings = x.scan(/#.*|["'\/].*?["'\/]/) + strings.each { | str | + x.sub!(str, $escape_strings[:string]) + } + #lofted code from java formatter #{add in link} + # replace "){" with ") {" + x.sub!(/\)\s*\{/, ") {") + # replace "return(" with "return (" + # replace "if(" with "if (" + # replace "while(" with "while (" + # replace "switch(" with "switch (" ruby does not have a switch + # replace "catch(" with "catch (" + x.sub!(/\b(return|if|elsif|while|case|catch)\s*\(/, '\1 (') + # replace " ;" with ";" + # replace " ," with "," + x.gsub!(/\s+([\;\,])/, '\1') + #replace ",abc" with ", abc" + x.gsub!(/\,(\w+)/, ', \1') + + x.gsub!(/(\)|"|\w)\s*([\+\-\*\/\&\|\^\%]|\&\&|\|\||[\>\<]|\>\=|\<\=|\=\=|\!\=|\<\<|\>\>|\>\>\>)\s*(?=(\w | "))/, '\1 \2 ') + # a space before and after AssignmentOperator + x.gsub!(/(\w)\s*(\+\=|\-\=|\*\=|\/\=|\&\=|\|\=|\^\=|\%\=|\<\<\=|\>\>\=|\>\>\>\=)\s*(?=(\w))/, '\1 \2 ') + # do not trim spaces + x.gsub!(/(\w)\=\s*(?=(\w|"))/, '\1 = ') + x.gsub!(/(\w)\s*\=(?=(\w|"))/, '\1 = ') + #becker format + #not complete list but alot of the common ones. + x.sub!(/(\.each|\.collect[!]*|\.map[!]*|\.delete_if|\.sort[!]*|\.each_[pair|key|value|byte|with_index|line|option]|\.reject[!]*|\.reverse_each|\.detect|\.find[_all]*|\.select|\.module_eval|\.all_waits|loop|proc|lambda|fork|at_exit)\s*\{/, '\1 {') + x.sub!(/def\s(\w*)?(\(.*?\))/, 'def \1\2') if x.match(/def\s+?(\w*)?\(.*?\)/) + x.sub!(/^for\s+(\w*)?\s+in\s+?(.*)$/, 'for \1 in \2') if x.match(/^for\s+(\w*)?\s*?in\s*?(.*)$/) + x.gsub!(/(\w)\=>\s*(?=(\w|"|:))/, '\1 => ') + x.gsub!(/(\w)\s*\=>(?=(\w|"|:))/, '\1 => ') + x.strip! + x.gsub!($escape_strings[:string]) { + strings.shift + } + x.gsub!($escape_strings[:regex], "\\\/") + return x +end + +JUST_STRING_PLEASE_RX = /\/.*\/|"([^"])*" | '([^']) * '|#.*/ +def just_the_string_please(org_string) + string = String.new(org_string) + #remove escaped chars + string.gsub!(/\\\/|\\"|\\'/, "") + string.gsub!(JUST_STRING_PLEASE_RX, "") + string = string.strip + string.sub!(/\b(return|if|while|case|catch)\s*\(/, '\1 (') + puts "clean string: #{string}" if ::DEBUG_ME + string +end +ONE_LINER_RX = /(unless|if).*(then).*end|(begin).*(rescue|ensure|else).*end/ +def one_liner?(string) + return true if string.match(ONE_LINER_RX) + false +end + +array_loc.each {|file_loc| + f = File.open(file_loc, "r") + text = f.read + f.close + if File.expand_path(file_loc) == File.expand_path($0) + $escape_strings = {:regex=>"EsCaPedReGex#{rand(200)}",:string=>"EsCaPeDStRiNg#{rand(200)}"} + end + new_text = "" + current_depth = 0 + spaces = " " * space_count if space_count + here_doc_ending = nil + indenter = spaces || "\t" + temp_depth = nil + line_count = 1 + + text.split("\n").each { |x| + #comments + #The first idea was to leave them alone. + #after running a few test i did not like the way it looked + if temp_depth + puts "In temp_depth #{x} line ♯ #{line_count} here:#{here_doc_ending}" if ::DEBUG_ME + new_text << x << "\n" + #block comments, its going to get ugly + if !x.lstrip.scan(/^\=end/).empty? || (here_doc_ending && x.strip == here_doc_ending.strip) + #swap and set + puts "swap and set #{x} line # #{line_count}" if ::DEBUG_ME + current_depth = temp_depth + temp_depth = nil + here_doc_ending = nil + end + line_count += 1 + next + end + #block will always be 0 depth + #block comments, its going to get ugly + unless x.lstrip.scan(/^\=begin/).empty? + #swap and set + puts "Looking for begin #{x} #{line_count}" if ::DEBUG_ME + temp_depth = current_depth + current_depth = 0 + end + #here docs have same type of logic for block comments + unless x.lstrip.scan(/<<-/).empty? + #swap and set + here_doc_ending = x.lstrip.split(/<<-/).last.strip + temp_depth = current_depth + end + #whats the first word? + text_node = x.split.first || "" + just_string = just_the_string_please(x) + in_both = in_both?(text_node) + one_liner = one_liner?(just_string) + #check if its in end or both and that the current_depth is >0 + #maybe i should raise if it goes negative ? + puts "minus one #{line_count} #{x} statement:#{(check_ends?(just_string) || in_both) && current_depth > 0} check_ends:#{check_ends?(just_string)} in_both:#{in_both} current_depth:#{ current_depth }" if ::DEBUG_ME + if (check_ends?(just_string) || in_both) && !one_liner + puts "We have a Negative depth count. This was caused around line:#{line_count}\nCheck for if( it should be if (" if current_depth == 0 + current_depth -= 1 unless current_depth == 0 + end + clean_string = line_clean_up(x) + current_indent = clean_string.size>0 ? indenter*current_depth : "" + new_text << current_indent << clean_string << "\n" + #we want to kick the indent out one + # x.match(/(unless|if).*(then).*end/): we use this match one liners for if statements not one-line blocks + # in_outs? returns true if the first work is in the out array + # in_both? does the same for the both array + # start_block looks for to not have an end at the end and {.count > }.count and if the word do is in there + # temp_depth is used when we hit the = comments should be nil unless you are in a comment + puts "plus one match:#{line_count} #{x} not a one liner:#{!(one_liner)} or statements:#{(in_outs?(text_node) || in_both?(text_node) || start_block?(x))} in_outs#{in_outs?(text_node)} in_both:#{ in_both?(text_node)} start_block:#{ start_block?(x)} temp_depth:#{temp_depth}" if ::DEBUG_ME + current_depth += 1 if ((in_outs?(text_node) || start_block?(just_string) || in_both || x.lstrip.slice(/\w*\s=\s(unless|if|case)/)) && !one_liner && !temp_depth) + line_count += 1 + } + FileUtils.cp("#{file_loc}","#{file_loc}.bk.#{Time.now.to_s.gsub(/\s|:/,"_")}") if backup + f = File.open("#{file_loc}","w+") + f.puts new_text + f.close + puts "Done!" +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/indenters/uigui_rbeautify.ini Fri Jun 13 12:05:39 2008 +0000 @@ -0,0 +1,17 @@ +[header] +categories= +cfgFileParameterEnding=" " +configFilename= +fileTypes=*.rb +indenterFileName=rbeautify.rb +indenterName=Ruby Script Beautifier (Ruby) +inputFileName=indentinput +inputFileParameter= +manual=http://www.arachnoid.com/ruby/rubyBeautifier.html +outputFileName=indentinput +outputFileParameter=none +parameterOrder=pio +showHelpParameter= +stringparaminquotes=false +useCfgFileParameter= +version=2.2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/indenters/uigui_rubyformatter.ini Fri Jun 13 12:05:39 2008 +0000 @@ -0,0 +1,27 @@ +[header] +categories=General +cfgFileParameterEnding=" " +configFilename= +fileTypes=*.rb +indenterFileName=ruby_formatter.rb +indenterName=Simple Ruby Formatter (Ruby) +inputFileName=indentinput +inputFileParameter= +manual=http://raa.ruby-lang.org/project/ruby_formatter/ +outputFileName=indentinput +outputFileParameter=none +parameterOrder=pio +showHelpParameter= +stringparaminquotes=false +useCfgFileParameter= +version=Rev 0.6.1 + +[indent spaces] +CallName="-s " +Category=0 +Description=<html>Indent using # spaces per indent</html> +EditorType=numeric +Enabled=false +MaxVal=20 +MinVal=2 +ValueDefault=4 \ No newline at end of file