Permalink
Browse files

Optionally indent private/protected methods

  • Loading branch information...
AndrewRadev committed Oct 19, 2013
1 parent 934f157 commit 244ab1989fe27da7a87cc3daf2baa96b87fe3d17
Showing with 106 additions and 0 deletions.
  1. +50 −0 indent/ruby.vim
  2. +56 −0 spec/indent/private_protected_spec.rb
View
@@ -13,6 +13,11 @@ if exists("b:did_indent")
endif
let b:did_indent = 1
+if !exists('g:ruby_indent_private_protected_style')
+ " Possible values: "normal", "indent"
+ let g:ruby_indent_private_protected_style = 'normal'
+endif
+
setlocal nosmartindent
" Now, set up our indentation expression and keys that trigger it.
@@ -89,9 +94,17 @@ let s:continuation_regex =
" Regex that defines bracket continuations
let s:bracket_continuation_regex = '%\@<!\%([({[]\)\s*\%(#.*\)\=$'
+" Regex that matches a class/module definition
+let s:class_regex =
+ \ '\C\%(^\s*\|[=,*/%+\-|;{]\|<<\|>>\|:\s\)\s*\zs' .
+ \ '\<\%(module\|class\):\@!\>'
+
" Regex that defines the first part of a splat pattern
let s:splat_regex = '[[,(]\s*\*\s*\%(#.*\)\=$'
+" Regex that describes a private/protected access modifier
+let s:private_protected_regex = '\C^\s*\%(private\|protected\)\s*\%(#.*\)\=$'
+
" Regex that defines blocks.
"
" Note that there's a slight problem with this regex and s:continuation_regex.
@@ -315,6 +328,25 @@ function s:Match(lnum, regex)
endif
endfunction
+" Search for a pattern match with search(), ignoring strings or comments.
+"
+" Note that you should NOT use the "n" or "c" flags here, since it may loop
+" indefinitely. You should use the "W" flag for the same reason.
+"
+function s:SearchCode(pattern, flags)
+ let saved_position = getpos('.')
+
+ let [lnum, col] = searchpos(a:pattern, a:flags)
+
+ while lnum > 0 && s:IsInStringOrComment(lnum, col)
+ let [lnum, col] = searchpos(a:pattern, a:flags)
+ endwhile
+
+ call setpos('.', saved_position)
+
+ return lnum
+endfunction
+
" 3. GetRubyIndent Function {{{1
" =========================
@@ -335,6 +367,17 @@ function GetRubyIndent(...)
let line = getline(clnum)
let ind = -1
+ if g:ruby_indent_private_protected_style == 'indent'
+ " If this line is a private/protected keyword, align according to the
+ " closest class declaration.
+ if s:Match(clnum, s:private_protected_regex)
+ let class_line = s:SearchCode(s:class_regex, 'Wb')
+ if class_line > 0
+ return indent(class_line) + &sw
+ endif
+ endif
+ endif
+
" If we got a closing bracket on an empty line, find its match and indent
" according to it. For parentheses we indent to its column - 1, for the
" others we indent to the containing line's MSL's level. Return -1 if fail.
@@ -411,6 +454,13 @@ function GetRubyIndent(...)
let line = getline(lnum)
let ind = indent(lnum)
+ if g:ruby_indent_private_protected_style == 'indent'
+ " If the previous line was a private/protected keyword, add a level of indent
+ if s:Match(lnum, s:private_protected_regex)
+ return indent(s:GetMSL(lnum)) + &sw
+ endif
+ endif
+
" If the previous line ended with a block opening, add a level of indent.
if s:Match(lnum, s:block_regex)
return indent(s:GetMSL(lnum)) + &sw
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+describe "Indenting" do
+ specify "default public/private indenting" do
+ assert_correct_indenting <<-EOF
+ class One
+ def two
+ end
+
+ protected
+
+ def three
+ end
+
+ private
+
+ def four
+ end
+ end
+ EOF
+ end
+
+ specify "indented public/private" do
+ vim.command 'let g:ruby_indent_private_protected_style = "indent"'
+
+ assert_correct_indenting <<-EOF
+ class One
+ def two
+ end
+
+ protected
+
+ def three
+ end
+
+ private
+
+ def four
+ end
+ end
+ EOF
+
+ assert_correct_indenting <<-EOF
+ class One
+ def two
+ end
+
+ private :two
+ protected :two
+
+ def three
+ end
+ end
+ EOF
+ end
+end

0 comments on commit 244ab19

Please sign in to comment.