Vim 7.2b ready for testing.
[MacVim.git] / runtime / ftplugin / cobol.vim
blob28c94d4fe72157fc3e96e3a8f4f393998d0eb113
1 " Vim filetype plugin file
2 " Language:     cobol
3 " Author:       Tim Pope <vimNOSPAM@tpope.info>
4 " $Id: cobol.vim,v 1.7 2008/07/13 17:21:56 vimboss Exp $
6 " Insert mode mappings: <C-T> <C-D> <Tab>
7 " Normal mode mappings: < > << >> [[ ]] [] ][
8 " Visual mode mappings: < >
10 if exists("b:did_ftplugin")
11     finish
12 endif
13 let b:did_ftplugin = 1
15 let s:cpo_save = &cpo
16 set cpo&vim
18 setlocal commentstring=\ \ \ \ \ \ *%s
19 setlocal comments=:*
20 setlocal fo+=croqlt
21 setlocal expandtab
22 setlocal textwidth=72
24 " matchit support
25 if exists("loaded_matchit")
26     let s:ordot = '\|\ze\.\%( \@=\|$\)'
27     let b:match_ignorecase=1
28     "let b:match_skip = 'getline(".") =~ "^.\\{6\\}[*/C]"'
29     let b:match_words=
30     \ '\$if\>:$else\>:\$endif\>,' .
31     \ '[$-]\@<!\<if\>:\<\%(then\|else\)\>:\<end-if\>'.s:ordot.',' .
32     \ '-\@<!\<perform\s\+\%(\d\+\s\+times\|until\|varying\|with\s\+test\)\>:\<end-perform\>'.s:ordot . ',' .
33     \ '-\@<!\<\%(search\|evaluate\)\>:\<\%(when\)\>:\<end-\%(search\|evaluate\)\>' .s:ordot . ',' .
34     \ '-\@<!\<\%(add\|compute\|divide\|multiply\|subtract\)\>\%(.*\(\%$\|\%(\n\%(\%(\s*\|.\{6\}\)[*/].*\n\)*\)\=\s*\%(not\s\+\)\=on\s\+size\s\+error\>\)\)\@=:\%(\<not\s\+\)\@<!\<\%(not\s\+\)\=on\s\+size\s\+error\>:\<end-\%(add\|compute\|divide\|multiply\|subtract\)\>' .s:ordot . ',' .
35     \ '-\@<!\<\%(string\|unstring\|accept\|display\|call\)\>\%(.*\(\%$\|\%(\n\%(\%(\s*\|.\{6\}\)[*/].*\n\)*\)\=\s*\%(not\s\+\)\=on\s\+\%(overflow\|exception\)\>\)\)\@=:\%(\<not\s\+\)\@<!\<\%(not\s\+\)\=on\s\+\%(overflow\|exception\)\>:\<end-\%(string\|unstring\|accept\|display\|call\)\>' .s:ordot . ',' .
36     \ '-\@<!\<\%(delete\|rewrite\|start\|write\|read\)\>\%(.*\(\%$\|\%(\n\%(\%(\s*\|.\{6\}\)[*/].*\n\)*\)\=\s*\%(invalid\s\+key\|at\s\+end\|no\s\+data\|at\s\+end-of-page\)\>\)\)\@=:\%(\<not\s\+\)\@<!\<\%(not\s\+\)\=\%(invalid\s\+key\|at\s\+end\|no\s\+data\|at\s\+end-of-page\)\>:\<end-\%(delete\|rewrite\|start\|write\|read\)\>' .s:ordot
37 endif
39 if has("gui_win32") && !exists("b:browsefilter")
40   let b:browsefilter = "COBOL Source Files (*.cbl, *.cob)\t*.cbl;*.cob;*.lib\n".
41                      \ "All Files (*.*)\t*.*\n"
42 endif
44 let b:undo_ftplugin = "setlocal com< cms< fo< et< tw<" .
45             \ " | unlet! b:browsefilter b:match_words b:match_ignorecase b:match_skip"
46 if !exists("g:no_plugin_maps") && !exists("g:no_cobol_maps")
47     let b:undo_ftplugin = b:undo_ftplugin .
48             \ " | sil! exe 'nunmap <buffer> <'" .
49             \ " | sil! exe 'nunmap <buffer> >'" .
50             \ " | sil! exe 'nunmap <buffer> <<'" .
51             \ " | sil! exe 'nunmap <buffer> >>'" .
52             \ " | sil! exe 'vunmap <buffer> <'" .
53             \ " | sil! exe 'vunmap <buffer> >'" .
54             \ " | sil! exe 'iunmap <buffer> <C-D>'" .
55             \ " | sil! exe 'iunmap <buffer> <C-T>'" .
56             \ " | sil! exe 'iunmap <buffer> <Tab>'" .
57             \ " | sil! exe 'nunmap <buffer> <Plug>Traditional'" .
58             \ " | sil! exe 'nunmap <buffer> <Plug>Comment'" .
59             \ " | sil! exe 'nunmap <buffer> <Plug>DeComment'" .
60             \ " | sil! exe 'vunmap <buffer> <Plug>VisualTraditional'" .
61             \ " | sil! exe 'vunmap <buffer> <Plug>VisualComment'" .
62             \ " | sil! exe 'iunmap <buffer> <Plug>VisualDeComment'" .
63             \ " | sil! exe 'unmap  <buffer> [['" .
64             \ " | sil! exe 'unmap  <buffer> ]]'" .
65             \ " | sil! exe 'unmap  <buffer> []'" .
66             \ " | sil! exe 'unmap  <buffer> ]['"
67 endif
69 if !exists("g:no_plugin_maps") && !exists("g:no_cobol_maps")
70     if version >= 700
71         nnoremap <silent> <buffer> > :set opfunc=<SID>IncreaseFunc<CR>g@
72         nnoremap <silent> <buffer> < :set opfunc=<SID>DecreaseFunc<CR>g@
73     endif
74     nnoremap <silent> <buffer> >> :call CobolIndentBlock(1)<CR>
75     nnoremap <silent> <buffer> << :call CobolIndentBlock(-1)<CR>
76     vnoremap <silent> <buffer> > :call CobolIndentBlock(v:count1)<CR>
77     vnoremap <silent> <buffer> < :call CobolIndentBlock(-v:count1)<CR>
78     inoremap <silent> <buffer> <C-T> <C-R>=<SID>IncreaseIndent()<CR><C-R>=<SID>RestoreShiftwidth()<CR>
79     inoremap <silent> <buffer> <C-D> <C-R>=<SID>DecreaseIndent()<CR><C-R>=<SID>RestoreShiftwidth()<CR>
80     if !maparg("<Tab>","i")
81         inoremap <silent> <buffer> <Tab> <C-R>=<SID>Tab()<CR><C-R>=<SID>RestoreShiftwidth()<CR>
82     endif
83     noremap <silent> <buffer> [[ m':call search('\c^\%(\s*\<Bar>.\{6\}\s\+\)\zs[A-Za-z0-9-]\+\s\+\%(division\<Bar>section\)\s*\.','bW')<CR>
84     noremap <silent> <buffer> ]] m':call search('\c^\%(\s*\<Bar>.\{6\}\s\+\)\zs[A-Za-z0-9-]\+\s\+\%(division\<Bar>section\)\.','W')<CR>
85     noremap <silent> <buffer> [] m':call <SID>toend('b')<CR>
86     noremap <silent> <buffer> ][ m':call <SID>toend('')<CR>
87     " For EnhancedCommentify
88     noremap <silent> <buffer> <Plug>Traditional      :call <SID>Comment('t')<CR>
89     noremap <silent> <buffer> <Plug>Comment          :call <SID>Comment('c')<CR>
90     noremap <silent> <buffer> <Plug>DeComment        :call <SID>Comment('u')<CR>
91     noremap <silent> <buffer> <Plug>VisualTraditional :'<,'>call <SID>Comment('t')<CR>
92     noremap <silent> <buffer> <Plug>VisualComment     :'<,'>call <SID>Comment('c')<CR>
93     noremap <silent> <buffer> <Plug>VisualDeComment   :'<,'>call <SID>Comment('u')<CR>
94 endif
96 let &cpo = s:cpo_save
97 unlet s:cpo_save
99 if exists("g:did_cobol_ftplugin_functions")
100     finish
101 endif
102 let g:did_cobol_ftplugin_functions = 1
104 function! s:repeat(str,count)
105     let i = 0
106     let ret = ""
107     while i < a:count
108         let ret = ret . a:str
109         let i = i + 1
110     endwhile
111     return ret
112 endfunction
114 function! s:increase(...)
115     let lnum = '.'
116     let sw = &shiftwidth
117     let i = a:0 ? a:1 : indent(lnum)
118     if i >= 11
119         return sw - (i - 11) % sw
120     elseif i >= 7
121         return 11-i
122     elseif i == 6
123         return 1
124     else
125         return 6-i
126     endif
127 endfunction
129 function! s:decrease(...)
130     let lnum = '.'
131     let sw = &shiftwidth
132     let i = indent(a:0 ? a:1 : lnum)
133     if i >= 11 + sw
134         return 1 + (i + 12) % sw
135     elseif i > 11
136         return i-11
137     elseif i > 7
138         return i-7
139     elseif i == 7
140         return 1
141     else
142         return i
143     endif
144 endfunction
146 function! CobolIndentBlock(shift)
147     let head = strpart(getline('.'),0,7)
148     let tail = strpart(getline('.'),7)
149     let indent = match(tail,'[^ ]')
150     let sw = &shiftwidth
151     let shift = a:shift
152     if shift > 0
153         if indent < 4
154             let tail = s:repeat(" ",4-indent).tail
155             let shift = shift - 1
156         endif
157         let tail = s:repeat(" ",shift*sw).tail
158         let shift = 0
159     elseif shift < 0
160         if (indent-4) > -shift * sw
161             let tail = strpart(tail,-shift * sw)
162         elseif (indent-4) > (-shift-1) * sw
163             let tail = strpart(tail,indent - 4)
164         else
165             let tail = strpart(tail,indent)
166         endif
167     endif
168     call setline('.',head.tail)
169 endfunction
171 function! s:IncreaseFunc(type)
172     '[,']call CobolIndentBlock(1)
173 endfunction
175 function! s:DecreaseFunc(type)
176     '[,']call CobolIndentBlock(-1)
177 endfunction
179 function! s:IncreaseIndent()
180     let c = "\<C-T>"
181     if exists("*InsertCtrlTWrapper")
182         let key = InsertCtrlTWrapper()
183         if key != c
184             return key
185         endif
186     endif
187     let interval = s:increase()
188     let b:cobol_shiftwidth = &shiftwidth
189     let &shiftwidth = 1
190     let lastchar = strpart(getline('.'),col('.')-2,1)
191     if lastchar == '0' || lastchar == '^'
192         return "\<BS>".lastchar.c
193     else
194         return s:repeat(c,interval)
195     endif
196 endfunction
198 function! s:DecreaseIndent()
199     let c = "\<C-D>"
200     if exists("*InsertCtrlDWrapper")
201         " I hack Ctrl-D to delete when not at the end of the line.
202         let key = InsertCtrlDWrapper()
203         if key != c
204             return key
205         endif
206     endif
207     let interval = s:decrease()
208     let b:cobol_shiftwidth = &shiftwidth
209     let &shiftwidth = 1
210     return s:repeat(c,interval)
211 endfunction
213 function! s:RestoreShiftwidth()
214     if exists("b:cobol_shiftwidth")
215         let &shiftwidth=b:cobol_shiftwidth
216         unlet b:cobol_shiftwidth
217     endif
218     return ""
219 endfunction
221 function! s:Tab()
222     if (strpart(getline('.'),0,col('.')-1) =~ '^\s*$' && &sta)
223         return s:IncreaseIndent()
224     elseif &sts == &sw && &sts != 8 && &et
225         return s:repeat(" ",s:increase(col('.')-1))
226     else
227         return "\<Tab>"
228     endif
229 endfunction
231 function! s:Comment(arg)
232     " For EnhancedCommentify
233     let line = getline('.')
234     if (line =~ '^.\{6\}[*/C]' || a:arg == 'c') && a:arg != 'u'
235         let line = substitute(line,'^.\{6\}\zs.',' ','')
236     else
237         let line = substitute(line,'^.\{6\}\zs.','*','')
238     endif
239     call setline('.',line)
240 endfunction
242 function! s:toend(direction)
243     let ignore = '^\(\s*\|.\{6\}\)\%([*/]\|\s*$\)'
244     let keep = line('.')
245     keepjumps +
246     while line('.') < line('$') && getline('.') =~ ignore
247         keepjumps +
248     endwhile
249     let res = search('\c^\%(\s*\|.\{6\}\s\+\)\zs[A-Za-z0-9-]\+\s\+\%(division\|section\)\s*\.',a:direction.'W')
250     if a:direction != 'b' && !res
251         let res = line('$')
252         keepjumps $
253     elseif res
254         keepjumps -
255     endif
256     if res
257         while line('.') > 1 && getline('.') =~ ignore
258             keepjumps -
259         endwhile
260         if line('.') == 1 && getline('.') =~ ignore
261             exe "keepjumps ".keep
262         endif
263     else
264         exe "keepjumps ".keep
265     endif
266 endfunction