sponsor Vim development Vim logo Vim Book Ad

intermediate Tip #1368: Beautify Ruby code

 tip karma   Rating 75/24, Viewed by 2423 

Read and edit this tip on the Vim tip wiki. The wiki may have a more recent version of this tip.

created:   October 24, 2006 7:32      complexity:   intermediate
author:   lemsx1      as of Vim:  

Open your .vimrc file and add a function like:

fun BenIndent()
    let oldLine=line('.')
    " our text (whole file) is passed via STDIN (%) to script name, and the output is
    " placed in current buffer (STDOUT)
    if g:IndentStyle == "C"
        :%!indent --gnu-style --no-tabs --indent-level 8 --case-indentation 0 --brace-indent 0 --comment-delimiters-on-blank-lines --start-left-side-of-comments --format-all-comments --format-first-column-comments
    elseif g:IndentStyle == "perl"
        :%!perltidy -gnu
    elseif g:IndentStyle == "html"
        :%!tidy -quiet -utf8 -indent -clean -asxhtml
    elseif g:IndentStyle == "php"
        :%!tidy -quiet -utf8 -indent -clean
    elseif g:IndentStyle == "ruby"
        :%!~/.vim/rubybeautifier.rb
    endif
    exe ':' . oldLine
endfun
map -- :call BenIndent()<CR>

Pay attention to the "ruby" portion if that's all you care

Then in the same file add a group like:

augroup ruby
    if !exists("autocommands_ruby_loaded")
        let autocommands_ruby_loaded = 1
        au BufReadPre *.rb set sw=3 sts=3 nu | let IndentStyle = "ruby"
        
        au BufNewFile *.rb 0r ~/.vim/skeleton.rb | let IndentStyle = "ruby"
    endif
augroup END

Last, create a script called ~/.vim/rubybeautifier.rb

#!/usr/bin/env ruby

# http://blog.neontology.com/articles/2006/05/10/beautiful-ruby-in-textmate

#

# Ruby beautifier, version 1.3, 04/03/2006

# Copyright (c) 2006, P. Lutus

# TextMate modifications by T. Burks

# Vim modifications by Luis Mondesi

# Released under the GPL



$tabSize = 3

$tabStr = " "



# indent regexp tests



$indentExp = [

   /^module\b/,

   /(=\s*|^)if\b/,

   /(=\s*|^)until\b/,

   /(=\s*|^)for\b/,

   /(=\s*|^)unless\b/,

   /(=\s*|^)while\b/,

   /(=\s*|^)begin\b/,

   /(=\s*|^)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

   commentBlock = false

   multiLineArray = Array.new

   multiLineStr = ""

   tab = 0

   source = STDIN.read

   dest = ""

   source.split("\n").each do |line|

      # 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

      if(commentBlock)

         # add the line unchanged

         dest += line + "\n"

      else

         commentLine = (tline =~ /^#/)

         if(!commentLine)

            # throw out sequences that will

            # only sow confusion

            tline.gsub!(/\/.*?\//,"")

            tline.gsub!(/%r\{.*?\}/,"")

            tline.gsub!(/%r(.).*?\1/,"")

            tline.gsub!(/\\\"/,"'")

            tline.gsub!(/".*?"/,"\"\"")

            tline.gsub!(/'.*?'/,"''")

            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

   STDOUT.write(dest)

   # uncomment this to complain about mismatched blocks

   #if(tab != 0)

   #  STDERR.puts "Indentation error: #{tab}"

   #end

end



beautifyRuby

Now, whenever you open a file called foo.rb, you can simply press -- to have the whole file beautified for you. If you create a ~/.vim/skeleton.rb file, you can type things like: vim non_existent.rb. And it will create a new ruby script using your skeleton.

You can grab a tarball with all this already in place from:

http://lems.kiskeyix.org/vimrc.tar.bz2

 rate this tip  Life Changing Helpful Unfulfilling 

<< Pretty-formatting XML | save file that had missing-trailing-end-of-line automatically without trailing-end-of-line >>

Additional Notes

If you have questions or remarks about this site, visit the vimonline development pages. Please use this site responsibly.
Questions about Vim should go to the maillist. Help Bram help Uganda.
   
Sponsored by Web Concept Group Inc. SourceForge.net Logo