cobol.vim 9.3 KB

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