blob: 1aea4f809c16e4b89e8b0ec638f7cdf2bae6725c [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" MetaPost indent file
2" Language: MetaPost
3" Maintainer: Eugene Minkovskii <emin@mccme.ru>
4" Last Change: 2003 Nov 21
5" Version: 0.1
6" ==========================================================================
7
8" Identation Rules: {{{1
9" First of all, MetaPost language don't expect any identation rules.
10" This screept need for you only if you (not MetaPost) need to do
11" exactly code. If you don't need to use indentation, see
12" :help filetype-indent-off
13"
14" Note: Every rules of identation in MetaPost or TeX languages (and in some
15" other of course) is very subjective. I can release only my vision of this
16" promlem.
17"
18" ..........................................................................
19" Example of correct (by me) identation {{{2
20" shiftwidth=4
21" ==========================================================================
22" for i=0 upto 99:
23" z[i] = (0,1u) rotated (i*360/100);
24" endfor
25" draw z0 -- z10 -- z20
26" withpen ... % <- 2sw because breaked line
27" withcolor ...; % <- same as previous
28" draw z0 for i=1 upto 99:
29" -- z[i] % <- 1sw from left end of 'for' satement
30" endfor withpen ... % <- 0sw from left end of 'for' satement
31" withcolor ...; % <- 2sw because breaked line
32" draw if One: % <- This is internal if (like 'for' above)
33" one
34" elsif Other:
35" other
36" fi withpen ...;
37" if one: % <- This is external if
38" draw one;
39" elseif other:
40" draw other;
41" fi
42" draw z0; draw z1;
43" }}}
44" }}}
45
46" Only load this indent file when no other was loaded.
47if exists("b:did_indent")
48 finish
49endif
50let b:did_indent = 1
51
52setlocal indentexpr=GetMetaPostIndent()
53setlocal indentkeys+=;,<:>,=if,=for,=def,=end,=else,=fi
54
55" Only define the function once.
56if exists("*GetMetaPostIndent")
57 finish
58endif
59
60" Auxiliary Definitions: {{{1
61function! MetaNextNonblankNoncomment(pos)
62 " Like nextnonblank() but ignore comment lines
63 let tmp = nextnonblank(a:pos)
64 while tmp && getline(tmp) =~ '^\s*%'
65 let tmp = nextnonblank(tmp+1)
66 endwhile
67 return tmp
68endfunction
69
70function! MetaPrevNonblankNoncomment(pos)
71 " Like prevnonblank() but ignore comment lines
72 let tmp = prevnonblank(a:pos)
73 while tmp && getline(tmp) =~ '^\s*%'
74 let tmp = prevnonblank(tmp-1)
75 endwhile
76 return tmp
77endfunction
78
79function! MetaSearchNoncomment(pattern, ...)
80 " Like search() but ignore commented areas
81 if a:0
82 let flags = a:1
83 elseif &wrapscan
84 let flags = "w"
85 else
86 let flags = "W"
87 endif
88 let cl = line(".")
89 let cc = col(".")
90 let tmp = search(a:pattern, flags)
91 while tmp && synIDattr(synID(line("."), col("."), 1), "name") =~
92 \ 'm[fp]\(Comment\|TeXinsert\|String\)'
93 let tmp = search(a:pattern, flags)
94 endwhile
95 if !tmp
96 call cursor(cl,cc)
97 endif
98 return tmp
99endfunction
100" }}}
101
102function! GetMetaPostIndent()
103 " not indent in comment ???
104 if synIDattr(synID(line("."), col("."), 1), "name") =~
105 \ 'm[fp]\(Comment\|TeXinsert\|String\)'
106 return -1
107 endif
108 " Some RegExps: {{{1
109 " end_of_item: all of end by ';'
110 " + all of end by :endfor, :enddef, :endfig, :endgroup, :fi
111 " + all of start by :beginfig(num), :begingroup
112 " + all of start by :for, :if, :else, :elseif and end by ':'
113 " + all of start by :def, :vardef and end by '='
114 let end_of_item = '\(' .
115 \ ';\|' .
116 \ '\<\(end\(for\|def\|fig\|group\)\|fi\)\>\|' .
117 \ '\<begin\(group\>\|fig\s*(\s*\d\+\s*)\)\|' .
118 \ '\<\(for\|if\|else\(if\)\=\)\>.\+:\|' .
119 \ '\<\(var\)\=def\>.\+=' . '\)'
120 " }}}
121 " Save: current position {{{1
122 let cl = line (".")
123 let cc = col (".")
124 let cs = getline(".")
125 " if it is :beginfig or :endfig use zero indent
126 if cs =~ '^\s*\(begin\|end\)fig\>'
127 return 0
128 endif
129 " }}}
130 " Initialise: ind variable {{{1
131 " search previous item not in current line
132 let p_semicol_l = MetaSearchNoncomment(end_of_item,"bW")
133 while p_semicol_l == cl
134 let p_semicol_l = MetaSearchNoncomment(end_of_item,"bW")
135 endwhile
136 " if this is first item in program use zero indent
137 if !p_semicol_l
138 return 0
139 endif
140 " if this is multiline item, remember first indent
141 if MetaNextNonblankNoncomment(p_semicol_l+1) < cl
142 let ind = indent(MetaNextNonblankNoncomment(p_semicol_l+1))
143 " else --- search pre-previous item for search first line in previous item
144 else
145 " search pre-previous item not in current line
146 let pp_semicol_l = MetaSearchNoncomment(end_of_item,"bW")
147 while pp_semicol_l == p_semicol_l
148 let pp_semicol_l = MetaSearchNoncomment(end_of_item,"bW")
149 endwhile
150 " if we find pre-previous item, remember indent of previous item
151 " else --- remember zero
152 if pp_semicol_l
153 let ind = indent(MetaNextNonblankNoncomment(line(".")+1))
154 else
155 let ind = 0
156 endif
157 endif
158 " }}}
159 " Increase Indent: {{{1
160 " if it is an internal/external :for or :if statements {{{2
161 let pnn_s = getline(MetaPrevNonblankNoncomment(cl-1))
162 if pnn_s =~ '\<\(for\|if\)\>.\+:\s*\($\|%\)'
163 let ind = match(pnn_s, '\<\(for\|if\)\>.\+:\s*\($\|%\)') + &sw
164 " }}}
165 " if it is a :def, :vardef, :beginfig, :begingroup, :else, :elseif {{{2
166 elseif pnn_s =~ '^\s*\(' .
167 \ '\(var\)\=def\|' .
168 \ 'begin\(group\|fig\s*(\s*\d\+\s*)\)\|' .
169 \ 'else\(if\)\=' . '\)\>'
170 let ind = ind + &sw
171 " }}}
172 " if it is a broken line {{{2
173 elseif pnn_s !~ end_of_item.'\s*\($\|%\)'
174 let ind = ind + (2 * &sw)
175 endif
176 " }}}
177 " }}}
178 " Decrease Indent: {{{1
179 " if this is :endfor or :enddef statements {{{2
180 " this is correct because :def cannot be inside :for
181 if cs =~ '\<end\(for\|def\)\=\>'
182 call MetaSearchNoncomment('\<for\>.\+:\s*\($\|%\)' . '\|' .
183 \ '^\s*\(var\)\=def\>',"bW")
184 if col(".") > 1
185 let ind = col(".") - 1
186 else
187 let ind = indent(".")
188 endif
189 " }}}
190 " if this is :fi, :else, :elseif statements {{{2
191 elseif cs =~ '\<\(else\(if\)\=\|fi\)\>'
192 call MetaSearchNoncomment('\<if\>.\+:\s*\($\|%\)',"bW")
193 let ind = col(".") - 1
194 " }}}
195 " if this is :endgroup statement {{{2
196 elseif cs =~ '^\s*endgroup\>'
197 let ind = ind - &sw
198 endif
199 " }}}
200 " }}}
201
202 return ind
203endfunction
204"
205
206" vim:sw=2:fdm=marker