xref: /vim-8.2.3635/runtime/indent/mp.vim (revision cf2d8dee)
1" MetaPost indent file
2" Language:	MetaPost
3" Maintainer:	Eugene Minkovskii <[email protected]>
4" Last Change:	2012 May 18
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
59let s:keepcpo= &cpo
60set cpo&vim
61
62" Auxiliary Definitions: {{{1
63function! MetaNextNonblankNoncomment(pos)
64  " Like nextnonblank() but ignore comment lines
65  let tmp = nextnonblank(a:pos)
66  while tmp && getline(tmp) =~ '^\s*%'
67    let tmp = nextnonblank(tmp+1)
68  endwhile
69  return tmp
70endfunction
71
72function! MetaPrevNonblankNoncomment(pos)
73  " Like prevnonblank() but ignore comment lines
74  let tmp = prevnonblank(a:pos)
75  while tmp && getline(tmp) =~ '^\s*%'
76    let tmp = prevnonblank(tmp-1)
77  endwhile
78  return tmp
79endfunction
80
81function! MetaSearchNoncomment(pattern, ...)
82  " Like search() but ignore commented areas
83  if a:0
84    let flags = a:1
85  elseif &wrapscan
86    let flags = "w"
87  else
88    let flags = "W"
89  endif
90  let cl  = line(".")
91  let cc  = col(".")
92  let tmp = search(a:pattern, flags)
93  while tmp && synIDattr(synID(line("."), col("."), 1), "name") =~
94        \ 'm[fp]\(Comment\|TeXinsert\|String\)'
95    let tmp = search(a:pattern, flags)
96  endwhile
97  if !tmp
98    call cursor(cl,cc)
99  endif
100  return tmp
101endfunction
102" }}}
103
104function! GetMetaPostIndent()
105  " not indent in comment ???
106  if synIDattr(synID(line("."), col("."), 1), "name") =~
107        \ 'm[fp]\(Comment\|TeXinsert\|String\)'
108    return -1
109  endif
110  " Some RegExps: {{{1
111  " end_of_item: all of end by ';'
112  "            + all of end by :endfor, :enddef, :endfig, :endgroup, :fi
113  "            + all of start by :beginfig(num), :begingroup
114  "            + all of start by :for, :if, :else, :elseif and end by ':'
115  "            + all of start by :def, :vardef             and end by '='
116  let end_of_item = '\('                              .
117        \ ';\|'                                       .
118        \ '\<\(end\(for\|def\|fig\|group\)\|fi\)\>\|' .
119        \ '\<begin\(group\>\|fig\s*(\s*\d\+\s*)\)\|'  .
120        \ '\<\(for\|if\|else\(if\)\=\)\>.\+:\|'       .
121        \ '\<\(var\)\=def\>.\+='                      . '\)'
122  " }}}
123  " Save: current position {{{1
124  let cl = line   (".")
125  let cc = col    (".")
126  let cs = getline(".")
127  " if it is :beginfig or :endfig use zero indent
128  if  cs =~ '^\s*\(begin\|end\)fig\>'
129    return 0
130  endif
131  " }}}
132  " Initialise: ind variable {{{1
133  " search previous item not in current line
134  let p_semicol_l = MetaSearchNoncomment(end_of_item,"bW")
135  while p_semicol_l == cl
136    let p_semicol_l = MetaSearchNoncomment(end_of_item,"bW")
137  endwhile
138  " if this is first item in program use zero indent
139  if !p_semicol_l
140    return 0
141  endif
142  " if this is multiline item, remember first indent
143  if MetaNextNonblankNoncomment(p_semicol_l+1) < cl
144    let ind = indent(MetaNextNonblankNoncomment(p_semicol_l+1))
145  " else --- search pre-previous item for search first line in previous item
146  else
147    " search pre-previous item not in current line
148    let pp_semicol_l = MetaSearchNoncomment(end_of_item,"bW")
149    while pp_semicol_l == p_semicol_l
150      let pp_semicol_l = MetaSearchNoncomment(end_of_item,"bW")
151    endwhile
152    " if we find pre-previous item, remember indent of previous item
153    " else --- remember zero
154    if pp_semicol_l
155      let ind = indent(MetaNextNonblankNoncomment(line(".")+1))
156    else
157      let ind = 0
158    endif
159  endif
160  " }}}
161  " Increase Indent: {{{1
162  " if it is an internal/external :for or :if statements {{{2
163  let pnn_s = getline(MetaPrevNonblankNoncomment(cl-1))
164  if  pnn_s =~ '\<\(for\|if\)\>.\+:\s*\($\|%\)'
165    let ind = match(pnn_s, '\<\(for\|if\)\>.\+:\s*\($\|%\)') + &sw
166  " }}}
167  " if it is a :def, :vardef, :beginfig, :begingroup, :else, :elseif {{{2
168  elseif pnn_s =~ '^\s*\('                       .
169        \ '\(var\)\=def\|'                       .
170        \ 'begin\(group\|fig\s*(\s*\d\+\s*)\)\|' .
171        \ 'else\(if\)\='                         . '\)\>'
172    let ind = ind + &sw
173  " }}}
174  " if it is a broken line {{{2
175  elseif pnn_s !~ end_of_item.'\s*\($\|%\)'
176    let ind = ind + (2 * &sw)
177  endif
178  " }}}
179  " }}}
180  " Decrease Indent: {{{1
181  " if this is :endfor or :enddef statements {{{2
182  " this is correct because :def cannot be inside :for
183  if  cs  =~ '\<end\(for\|def\)\=\>'
184    call MetaSearchNoncomment('\<for\>.\+:\s*\($\|%\)' . '\|' .
185                            \ '^\s*\(var\)\=def\>',"bW")
186    if col(".") > 1
187      let ind = col(".") - 1
188    else
189      let ind = indent(".")
190    endif
191  " }}}
192  " if this is :fi, :else, :elseif statements {{{2
193  elseif cs =~ '\<\(else\(if\)\=\|fi\)\>'
194    call MetaSearchNoncomment('\<if\>.\+:\s*\($\|%\)',"bW")
195    let ind = col(".") - 1
196  " }}}
197  " if this is :endgroup statement {{{2
198  elseif cs =~ '^\s*endgroup\>'
199    let ind = ind - &sw
200  endif
201  " }}}
202  " }}}
203
204  return ind
205endfunction
206"
207
208let &cpo = s:keepcpo
209unlet s:keepcpo
210
211" vim:sw=2:fdm=marker
212