cobol.vim 9.5 KB

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