]> git.r.bdr.sh - rbdr/dotfiles/blob - vim/ftplugin/puppet.vim
Add universal ctags config
[rbdr/dotfiles] / vim / ftplugin / puppet.vim
1 " Vim filetype plugin
2 " Language: Puppet
3 " Maintainer: Todd Zullinger <tmz@pobox.com>
4 " Last Change: 2009 Aug 19
5 " vim: set sw=4 sts=4:
6
7 if exists("b:did_ftplugin")
8 finish
9 endif
10 let b:did_ftplugin = 1
11
12 if !exists("no_plugin_maps") && !exists("no_puppet_maps")
13 if !hasmapto("<Plug>AlignRange")
14 map <buffer> <LocalLeader>= <Plug>AlignRange
15 endif
16 endif
17
18 noremap <buffer> <unique> <script> <Plug>AlignArrows :call <SID>AlignArrows()<CR>
19 noremap <buffer> <unique> <script> <Plug>AlignRange :call <SID>AlignRange()<CR>
20
21 iabbrev => =><C-R>=<SID>AlignArrows('=>')<CR>
22 iabbrev +> +><C-R>=<SID>AlignArrows('+>')<CR>
23
24 if exists('*s:AlignArrows')
25 finish
26 endif
27
28 let s:arrow_re = '[=+]>'
29 let s:selector_re = '[=+]>\s*\$.*\s*?\s*{\s*$'
30
31 " set keywordprg to 'pi' (alias for puppet describe)
32 " this lets K invoke pi for word under cursor
33 setlocal keywordprg=puppet\ describe
34
35 function! s:AlignArrows(op)
36 let cursor_pos = getpos('.')
37 let lnum = line('.')
38 let line = getline(lnum)
39 if line !~ s:arrow_re
40 return
41 endif
42 let pos = stridx(line, a:op)
43 let start = lnum
44 let end = lnum
45 let pnum = lnum - 1
46 while 1
47 let pline = getline(pnum)
48 if pline !~ s:arrow_re || pline =~ s:selector_re
49 break
50 endif
51 let start = pnum
52 let pnum -= 1
53 endwhile
54 let cnum = end
55 while 1
56 let cline = getline(cnum)
57 if cline !~ s:arrow_re ||
58 \ (indent(cnum) != indent(cnum+1) && getline(cnum+1) !~ '\s*}')
59 break
60 endif
61 let end = cnum
62 let cnum += 1
63 endwhile
64 call s:AlignSection(start, end)
65 let cursor_pos[2] = stridx(getline('.'), a:op) + strlen(a:op) + 1
66 call setpos('.', cursor_pos)
67 return ''
68 endfunction
69
70 function! s:AlignRange() range
71 call s:AlignSection(a:firstline, a:lastline)
72 endfunction
73
74 " AlignSection and AlignLine are from the vim wiki:
75 " http://vim.wikia.com/wiki/Regex-based_text_alignment
76 function! s:AlignSection(start, end)
77 let extra = 1
78 let sep = s:arrow_re
79 let maxpos = 0
80 let section = getline(a:start, a:end)
81 for line in section
82 let pos = match(line, ' *'.sep)
83 if maxpos < pos
84 let maxpos = pos
85 endif
86 endfor
87 call map(section, 's:AlignLine(v:val, sep, maxpos, extra)')
88 call setline(a:start, section)
89 endfunction
90
91 function! s:AlignLine(line, sep, maxpos, extra)
92 let m = matchlist(a:line, '\(.\{-}\) \{-}\('.a:sep.'.*\)')
93 if empty(m)
94 return a:line
95 endif
96 let spaces = repeat(' ', a:maxpos - strlen(m[1]) + a:extra)
97 return m[1] . spaces . m[2]
98 endfunction
99
100 " detect if we are in a module and set variables for classpath (autoloader),
101 " modulename, modulepath, and classname
102 " useful to use in templates
103 function! s:SetModuleVars()
104
105 " set these to any dirs you want to stop searching on
106 " useful to stop vim from spinning disk looking all over for init.pp
107 " probably only a macosx problem with /tmp since it's really /private/tmp
108 " but it's here if you find vim spinning on new files in certain places
109 if !exists("g:puppet_stop_dirs")
110 let g:puppet_stop_dirs = '/tmp;/private/tmp'
111 endif
112
113 " search path for init.pp
114 let b:search_path = './**'
115 let b:search_path = b:search_path . ';' . getcwd() . ';' . g:puppet_stop_dirs
116
117 " find what we assume to be our module dir
118 let b:initpp = findfile("init.pp", b:search_path) " find an init.pp up or down
119 let b:module_path = fnamemodify(b:initpp, ":p:h:h") " full path to module name
120 let b:module_name = fnamemodify(b:module_path, ":t") " just the module name
121
122 " sub out the full path to the module with the name and replace slashes with ::
123 let b:classpath = fnamemodify(expand("%:p:r"), ':s#' . b:module_path . '/manifests#' . b:module_name . '#'. ":gs?/?::?")
124 let b:classname = expand("%:t:r")
125
126 " if we don't start with a word we didn't replace the module_path
127 " probably b/c we couldn't find an init.pp / not a module
128 " so we assume that root of the filename is the class (sane for throwaway
129 " manifests
130 if b:classpath =~ '^::'
131 let b:classpath = b:classname
132 endif
133 endfunction
134
135 if exists("g:puppet_module_detect")
136 call s:SetModuleVars()
137 endif