cobol.vim 9.2 KB

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