Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 1 | " MetaPost indent file |
| 2 | " Language: MetaPost |
| 3 | " Maintainer: Eugene Minkovskii <emin@mccme.ru> |
Bram Moolenaar | 8e52a59 | 2012-05-18 21:49:28 +0200 | [diff] [blame] | 4 | " Last Change: 2012 May 18 |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 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. |
| 47 | if exists("b:did_indent") |
| 48 | finish |
| 49 | endif |
| 50 | let b:did_indent = 1 |
| 51 | |
| 52 | setlocal indentexpr=GetMetaPostIndent() |
| 53 | setlocal indentkeys+=;,<:>,=if,=for,=def,=end,=else,=fi |
| 54 | |
| 55 | " Only define the function once. |
| 56 | if exists("*GetMetaPostIndent") |
| 57 | finish |
| 58 | endif |
Bram Moolenaar | 8e52a59 | 2012-05-18 21:49:28 +0200 | [diff] [blame] | 59 | let s:keepcpo= &cpo |
| 60 | set cpo&vim |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 61 | |
| 62 | " Auxiliary Definitions: {{{1 |
| 63 | function! 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 |
| 70 | endfunction |
| 71 | |
| 72 | function! 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 |
| 79 | endfunction |
| 80 | |
| 81 | function! 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 |
| 101 | endfunction |
| 102 | " }}} |
| 103 | |
| 104 | function! 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 |
| 205 | endfunction |
| 206 | " |
| 207 | |
Bram Moolenaar | 8e52a59 | 2012-05-18 21:49:28 +0200 | [diff] [blame] | 208 | let &cpo = s:keepcpo |
| 209 | unlet s:keepcpo |
| 210 | |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 211 | " vim:sw=2:fdm=marker |