Mercurial > hg > RemoteEditor > vim7
annotate runtime/indent/cobol.vim @ 34:e170173ecb68 current-release
before ack base protocol.
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 26 Nov 2008 15:02:10 +0900 |
parents | 76efa0be13f1 |
children | c16898406ff2 |
rev | line source |
---|---|
0 | 1 " Vim indent file |
2 " Language: cobol | |
3 " Author: Tim Pope <vimNOSPAM@tpope.info> | |
34
e170173ecb68
before ack base protocol.
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
4 " $Id: cobol.vim,v 1.2 2008/08/29 06:41:29 axmo Exp $ |
0 | 5 |
6 if exists("b:did_indent") | |
7 finish | |
8 endif | |
9 let b:did_indent = 1 | |
10 | |
11 setlocal expandtab | |
12 setlocal indentexpr=GetCobolIndent(v:lnum) | |
13 setlocal indentkeys& | |
14 setlocal indentkeys+=0<*>,0/,0$,0=01,=~division,=~section,0=~end,0=~then,0=~else,0=~when,*<Return>,. | |
15 | |
16 " Only define the function once. | |
17 if exists("*GetCobolIndent") | |
18 finish | |
19 endif | |
20 | |
21 let s:skip = 'getline(".") =~ "^.\\{6\\}[*/$-]\\|\"[^\"]*\""' | |
22 | |
23 function! s:prevgood(lnum) | |
24 " Find a non-blank line above the current line. | |
25 " Skip over comments. | |
26 let lnum = a:lnum | |
27 while lnum > 0 | |
28 let lnum = prevnonblank(lnum - 1) | |
29 let line = getline(lnum) | |
30 if line !~? '^\s*[*/$-]' && line !~? '^.\{6\}[*/$CD-]' | |
31 break | |
32 endif | |
33 endwhile | |
34 return lnum | |
35 endfunction | |
36 | |
37 function! s:stripped(lnum) | |
38 return substitute(strpart(getline(a:lnum),0,72),'^\s*','','') | |
39 endfunction | |
40 | |
41 function! s:optionalblock(lnum,ind,blocks,clauses) | |
42 let ind = a:ind | |
43 let clauses = '\c\<\%(\<NOT\s\+\)\@<!\%(NOT\s\+\)\=\%('.a:clauses.'\)' | |
44 let begin = '\c-\@<!\<\%('.a:blocks.'\)\>' | |
45 let beginfull = begin.'\ze.*\%(\n\%(\s*\%([*/$-].*\)\=\n\)*\)\=\s*\%('.clauses.'\)' | |
46 let end = '\c\<end-\%('.a:blocks.'\)\>\|\%(\.\%( \|$\)\)\@=' | |
47 let cline = s:stripped(a:lnum) | |
48 let line = s:stripped(s:prevgood(a:lnum)) | |
49 if cline =~? clauses "&& line !~? '^search\>' | |
50 call cursor(a:lnum,1) | |
51 let lastclause = searchpair(beginfull,clauses,end,'bWr',s:skip) | |
52 if getline(lastclause) =~? clauses && s:stripped(lastclause) !~? '^'.begin | |
53 let ind = indent(lastclause) | |
54 elseif lastclause > 0 | |
55 let ind = indent(lastclause) + &sw | |
56 "let ind = ind + &sw | |
57 endif | |
58 elseif line =~? clauses && cline !~? end | |
59 let ind = ind + &sw | |
60 endif | |
61 return ind | |
62 endfunction | |
63 | |
64 function! GetCobolIndent(lnum) abort | |
65 let minshft = 6 | |
66 let ashft = minshft + 1 | |
67 let bshft = ashft + 4 | |
68 " (Obsolete) numbered lines | |
69 if getline(a:lnum) =~? '^\s*\d\{6\}\%($\|[ */$CD-]\)' | |
70 return 0 | |
71 endif | |
72 let cline = s:stripped(a:lnum) | |
73 " Comments, etc. must start in the 7th column | |
74 if cline =~? '^[*/$-]' | |
75 return minshft | |
76 elseif cline =~# '^[CD]' && indent(a:lnum) == minshft | |
77 return minshft | |
78 endif | |
79 " Divisions, sections, and file descriptions start in area A | |
80 if cline =~? '\<\(DIVISION\|SECTION\)\%($\|\.\)' || cline =~? '^[FS]D\>' | |
81 return ashft | |
82 endif | |
83 " Fields | |
84 if cline =~? '^0*\(1\|77\)\>' | |
85 return ashft | |
86 endif | |
87 if cline =~? '^\d\+\>' | |
88 let cnum = matchstr(cline,'^\d\+\>') | |
89 let default = 0 | |
90 let step = -1 | |
91 while step < 2 | |
92 let lnum = a:lnum | |
93 while lnum > 0 && lnum < line('$') && lnum > a:lnum - 500 && lnum < a:lnum + 500 | |
94 let lnum = step > 0 ? nextnonblank(lnum + step) : prevnonblank(lnum + step) | |
95 let line = getline(lnum) | |
96 let lindent = indent(lnum) | |
97 if line =~? '^\s*\d\+\>' | |
98 let num = matchstr(line,'^\s*\zs\d\+\>') | |
99 if 0+cnum == num | |
100 return lindent | |
101 elseif 0+cnum > num && default < lindent + &sw | |
102 let default = lindent + &sw | |
103 endif | |
104 elseif lindent < bshft && lindent >= ashft | |
105 break | |
106 endif | |
107 endwhile | |
108 let step = step + 2 | |
109 endwhile | |
110 return default ? default : bshft | |
111 endif | |
112 let lnum = s:prevgood(a:lnum) | |
113 " Hit the start of the file, use "zero" indent. | |
114 if lnum == 0 | |
115 return ashft | |
116 endif | |
117 " Initial spaces are ignored | |
118 let line = s:stripped(lnum) | |
119 let ind = indent(lnum) | |
120 " Paragraphs. There may be some false positives. | |
121 if cline =~? '^\(\a[A-Z0-9-]*[A-Z0-9]\|\d[A-Z0-9-]*\a\)\.' "\s*$' | |
122 if cline !~? '^EXIT\s*\.' && line =~? '\.\s*$' | |
123 return ashft | |
124 endif | |
125 endif | |
126 " Paragraphs in the identification division. | |
127 "if cline =~? '^\(PROGRAM-ID\|AUTHOR\|INSTALLATION\|' . | |
128 "\ 'DATE-WRITTEN\|DATE-COMPILED\|SECURITY\)\>' | |
129 "return ashft | |
130 "endif | |
131 if line =~? '\.$' | |
132 " XXX | |
133 return bshft | |
134 endif | |
135 if line =~? '^PERFORM\>' | |
136 let perfline = substitute(line, '\c^PERFORM\s*', "", "") | |
137 if perfline =~? '^\%(\k\+\s\+TIMES\)\=\s*$' | |
138 let ind = ind + &sw | |
139 elseif perfline =~? '^\%(WITH\s\+TEST\|VARYING\|UNTIL\)\>.*[^.]$' | |
140 let ind = ind + &sw | |
141 endif | |
142 endif | |
143 if line =~? '^\%(IF\|THEN\|ELSE\|READ\|EVALUATE\|SEARCH\|SELECT\)\>' | |
144 let ind = ind + &sw | |
145 endif | |
146 let ind = s:optionalblock(a:lnum,ind,'ADD\|COMPUTE\|DIVIDE\|MULTIPLY\|SUBTRACT','ON\s\+SIZE\s\+ERROR') | |
147 let ind = s:optionalblock(a:lnum,ind,'STRING\|UNSTRING\|ACCEPT\|DISPLAY\|CALL','ON\s\+OVERFLOW\|ON\s\+EXCEPTION') | |
148 if cline !~? '^AT\s\+END\>' || line !~? '^SEARCH\>' | |
149 let ind = s:optionalblock(a:lnum,ind,'DELETE\|REWRITE\|START\|WRITE\|READ','INVALID\s\+KEY\|AT\s\+END\|NO\s\+DATA\|AT\s\+END-OF-PAGE') | |
150 endif | |
151 if cline =~? '^WHEN\>' | |
152 call cursor(a:lnum,1) | |
153 " We also search for READ so that contained AT ENDs are skipped | |
154 let lastclause = searchpair('\c-\@<!\<\%(SEARCH\|EVALUATE\|READ\)\>','\c\<\%(WHEN\|AT\s\+END\)\>','\c\<END-\%(SEARCH\|EVALUATE\|READ\)\>','bW',s:skip) | |
155 let g:foo = s:stripped(lastclause) | |
156 if s:stripped(lastclause) =~? '\c\<\%(WHEN\|AT\s\+END\)\>' | |
157 "&& s:stripped(lastclause) !~? '^\%(SEARCH\|EVALUATE\|READ\)\>' | |
158 let ind = indent(lastclause) | |
159 elseif lastclause > 0 | |
160 let ind = indent(lastclause) + &sw | |
161 endif | |
162 elseif line =~? '^WHEN\>' | |
163 let ind = ind + &sw | |
164 endif | |
165 "I'm not sure why I had this | |
166 "if line =~? '^ELSE\>-\@!' && line !~? '\.$' | |
167 "let ind = indent(s:prevgood(lnum)) | |
168 "endif | |
169 if cline =~? '^\(END\)\>-\@!' | |
170 " On lines with just END, 'guess' a simple shift left | |
171 let ind = ind - &sw | |
172 elseif cline =~? '^\(END-IF\|THEN\|ELSE\)\>-\@!' | |
173 call cursor(a:lnum,indent(a:lnum)) | |
174 let match = searchpair('\c-\@<!\<IF\>','\c-\@<!\%(THEN\|ELSE\)\>','\c-\@<!\<END-IF\>\zs','bnW',s:skip) | |
175 if match > 0 | |
176 let ind = indent(match) | |
177 endif | |
178 elseif cline =~? '^END-[A-Z]' | |
179 let beginword = matchstr(cline,'\c\<END-\zs[A-Z0-9-]\+') | |
180 let endword = 'END-'.beginword | |
181 let first = 0 | |
182 let suffix = '.*\%(\n\%(\%(\s*\|.\{6\}\)[*/].*\n\)*\)\=\s*' | |
183 if beginword =~? '^\%(ADD\|COMPUTE\|DIVIDE\|MULTIPLY\|SUBTRACT\)$' | |
184 let beginword = beginword . suffix . '\<\%(NOT\s\+\)\=ON\s\+SIZE\s\+ERROR' | |
185 let g:beginword = beginword | |
186 let first = 1 | |
187 elseif beginword =~? '^\%(STRING\|UNSTRING\)$' | |
188 let beginword = beginword . suffix . '\<\%(NOT\s\+\)\=ON\s\+OVERFLOW' | |
189 let first = 1 | |
190 elseif beginword =~? '^\%(ACCEPT\|DISPLAY\)$' | |
191 let beginword = beginword . suffix . '\<\%(NOT\s\+\)\=ON\s\+EXCEPTION' | |
192 let first = 1 | |
193 elseif beginword ==? 'CALL' | |
194 let beginword = beginword . suffix . '\<\%(NOT\s\+\)\=ON\s\+\%(EXCEPTION\|OVERFLOW\)' | |
195 let first = 1 | |
196 elseif beginword =~? '^\%(DELETE\|REWRITE\|START\|READ\|WRITE\)$' | |
197 let first = 1 | |
198 let beginword = beginword . suffix . '\<\%(NOT\s\+\)\=\(INVALID\s\+KEY' | |
199 if beginword =~? '^READ' | |
200 let first = 0 | |
201 let beginword = beginword . '\|AT\s\+END\|NO\s\+DATA' | |
202 elseif beginword =~? '^WRITE' | |
203 let beginword = beginword . '\|AT\s\+END-OF-PAGE' | |
204 endif | |
205 let beginword = beginword . '\)' | |
206 endif | |
207 call cursor(a:lnum,indent(a:lnum)) | |
208 let match = searchpair('\c-\@<!\<'.beginword.'\>','','\c\<'.endword.'\>\zs','bnW'.(first? 'r' : ''),s:skip) | |
209 if match > 0 | |
210 let ind = indent(match) | |
211 elseif cline =~? '^\(END-\(READ\|EVALUATE\|SEARCH\|PERFORM\)\)\>' | |
212 let ind = ind - &sw | |
213 endif | |
214 endif | |
215 return ind < bshft ? bshft : ind | |
216 endfunction |