home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / runtime / dos / indent / ocaml.vim < prev    next >
Encoding:
Text File  |  2012-05-31  |  9.0 KB  |  268 lines

  1. " Vim indent file
  2. " Language:     OCaml
  3. " Maintainers:  Jean-Francois Yuen   <jfyuen@happycoders.org>
  4. "               Mike Leary           <leary@nwlink.com>
  5. "               Markus Mottl         <markus.mottl@gmail.com>
  6. " URL:          http://www.ocaml.info/vim/indent/ocaml.vim
  7. " Last Change:  2010 Sep 04 - Added an indentation improvement by Mark Weber
  8. "               2005 Jun 25 - Fixed multiple bugs due to 'else\nreturn ind' working
  9. "               2005 May 09 - Added an option to not indent OCaml-indents specially (MM)
  10.  
  11. " Only load this indent file when no other was loaded.
  12. if exists("b:did_indent")
  13.  finish
  14. endif
  15. let b:did_indent = 1
  16.  
  17. setlocal expandtab
  18. setlocal indentexpr=GetOCamlIndent()
  19. setlocal indentkeys+=0=and,0=class,0=constraint,0=done,0=else,0=end,0=exception,0=external,0=if,0=in,0=include,0=inherit,0=initializer,0=let,0=method,0=open,0=then,0=type,0=val,0=with,0;;,0>\],0\|\],0>},0\|,0},0\],0)
  20. setlocal nolisp
  21. setlocal nosmartindent
  22. setlocal textwidth=80
  23.  
  24. " Comment formatting
  25. if !exists("no_ocaml_comments")
  26.  if (has("comments"))
  27.    setlocal comments=sr:(*,mb:*,ex:*)
  28.    setlocal fo=cqort
  29.  endif
  30. endif
  31.  
  32. " Only define the function once.
  33. if exists("*GetOCamlIndent")
  34.  finish
  35. endif
  36.  
  37. " Define some patterns:
  38. let s:beflet = '^\s*\(initializer\|method\|try\)\|\(\<\(begin\|do\|else\|in\|then\|try\)\|->\|<-\|=\|;\|(\)\s*$'
  39. let s:letpat = '^\s*\(let\|type\|module\|class\|open\|exception\|val\|include\|external\)\>'
  40. let s:letlim = '\(\<\(sig\|struct\)\|;;\)\s*$'
  41. let s:lim = '^\s*\(exception\|external\|include\|let\|module\|open\|type\|val\)\>'
  42. let s:module = '\<\%(begin\|sig\|struct\|object\)\>'
  43. let s:obj = '^\s*\(constraint\|inherit\|initializer\|method\|val\)\>\|\<\(object\|object\s*(.*)\)\s*$'
  44. let s:type = '^\s*\%(class\|let\|type\)\>.*='
  45.  
  46. " Skipping pattern, for comments
  47. function! s:GetLineWithoutFullComment(lnum)
  48.  let lnum = prevnonblank(a:lnum - 1)
  49.  let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '')
  50.  while lline =~ '^\s*$' && lnum > 0
  51.    let lnum = prevnonblank(lnum - 1)
  52.    let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '')
  53.  endwhile
  54.  return lnum
  55. endfunction
  56.  
  57. " Indent for ';;' to match multiple 'let'
  58. function! s:GetInd(lnum, pat, lim)
  59.  let llet = search(a:pat, 'bW')
  60.  let old = indent(a:lnum)
  61.  while llet > 0
  62.    let old = indent(llet)
  63.    let nb = s:GetLineWithoutFullComment(llet)
  64.    if getline(nb) =~ a:lim
  65.      return old
  66.    endif
  67.    let llet = search(a:pat, 'bW')
  68.  endwhile
  69.  return old
  70. endfunction
  71.  
  72. " Indent pairs
  73. function! s:FindPair(pstart, pmid, pend)
  74.  call search(a:pend, 'bW')
  75.  return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment"'))
  76. endfunction
  77.  
  78. " Indent 'let'
  79. function! s:FindLet(pstart, pmid, pend)
  80.  call search(a:pend, 'bW')
  81.  return indent(searchpair(a:pstart, a:pmid, a:pend, 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment" || getline(".") =~ "^\\s*let\\>.*=.*\\<in\\s*$" || getline(prevnonblank(".") - 1) =~ s:beflet'))
  82. endfunction
  83.  
  84. function! GetOCamlIndent()
  85.  " Find a non-commented line above the current line.
  86.  let lnum = s:GetLineWithoutFullComment(v:lnum)
  87.  
  88.  " At the start of the file use zero indent.
  89.  if lnum == 0
  90.    return 0
  91.  endif
  92.  
  93.  let ind = indent(lnum)
  94.  let lline = substitute(getline(lnum), '(\*.*\*)\s*$', '', '')
  95.  
  96.  " Return double 'shiftwidth' after lines matching:
  97.  if lline =~ '^\s*|.*->\s*$'
  98.    return ind + &sw + &sw
  99.  endif
  100.  
  101.  let line = getline(v:lnum)
  102.  
  103.  " Indent if current line begins with 'end':
  104.  if line =~ '^\s*end\>'
  105.    return s:FindPair(s:module, '','\<end\>')
  106.  
  107.  " Indent if current line begins with 'done' for 'do':
  108.  elseif line =~ '^\s*done\>'
  109.    return s:FindPair('\<do\>', '','\<done\>')
  110.  
  111.  " Indent if current line begins with '}' or '>}':
  112.  elseif line =~ '^\s*\(\|>\)}'
  113.    return s:FindPair('{', '','}')
  114.  
  115.  " Indent if current line begins with ']', '|]' or '>]':
  116.  elseif line =~ '^\s*\(\||\|>\)\]'
  117.    return s:FindPair('\[', '','\]')
  118.  
  119.  " Indent if current line begins with ')':
  120.  elseif line =~ '^\s*)'
  121.    return s:FindPair('(', '',')')
  122.  
  123.  " Indent if current line begins with 'let':
  124.  elseif line =~ '^\s*let\>'
  125.    if lline !~ s:lim . '\|' . s:letlim . '\|' . s:beflet
  126.      return s:FindLet(s:type, '','\<let\s*$')
  127.    endif
  128.  
  129.  " Indent if current line begins with 'class' or 'type':
  130.  elseif line =~ '^\s*\(class\|type\)\>'
  131.    if lline !~ s:lim . '\|\<and\s*$\|' . s:letlim
  132.      return s:FindLet(s:type, '','\<\(class\|type\)\s*$')
  133.    endif
  134.  
  135.  " Indent for pattern matching:
  136.  elseif line =~ '^\s*|'
  137.    if lline !~ '^\s*\(|[^\]]\|\(match\|type\|with\)\>\)\|\<\(function\|parser\|private\|with\)\s*$'
  138.      call search('|', 'bW')
  139.      return indent(searchpair('^\s*\(match\|type\)\>\|\<\(function\|parser\|private\|with\)\s*$', '', '^\s*|', 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string\\|comment" || getline(".") !~ "^\\s*|.*->"'))
  140.    endif
  141.  
  142.  " Indent if current line begins with ';;':
  143.  elseif line =~ '^\s*;;'
  144.    if lline !~ ';;\s*$'
  145.      return s:GetInd(v:lnum, s:letpat, s:letlim)
  146.    endif
  147.  
  148.  " Indent if current line begins with 'in':
  149.  elseif line =~ '^\s*in\>'
  150.    if lline !~ '^\s*\(let\|and\)\>'
  151.      return s:FindPair('\<let\>', '', '\<in\>')
  152.    endif
  153.  
  154.  " Indent if current line begins with 'else':
  155.  elseif line =~ '^\s*else\>'
  156.    if lline !~ '^\s*\(if\|then\)\>'
  157.      return s:FindPair('\<if\>', '', '\<else\>')
  158.    endif
  159.  
  160.  " Indent if current line begins with 'then':
  161.  elseif line =~ '^\s*then\>'
  162.    if lline !~ '^\s*\(if\|else\)\>'
  163.      return s:FindPair('\<if\>', '', '\<then\>')
  164.    endif
  165.  
  166.  " Indent if current line begins with 'and':
  167.  elseif line =~ '^\s*and\>'
  168.    if lline !~ '^\s*\(and\|let\|type\)\>\|\<end\s*$'
  169.      return ind - &sw
  170.    endif
  171.  
  172.  " Indent if current line begins with 'with':
  173.  elseif line =~ '^\s*with\>'
  174.    if lline !~ '^\s*\(match\|try\)\>'
  175.      return s:FindPair('\<\%(match\|try\)\>', '','\<with\>')
  176.    endif
  177.  
  178.  " Indent if current line begins with 'exception', 'external', 'include' or
  179.  " 'open':
  180.  elseif line =~ '^\s*\(exception\|external\|include\|open\)\>'
  181.    if lline !~ s:lim . '\|' . s:letlim
  182.      call search(line)
  183.      return indent(search('^\s*\(\(exception\|external\|include\|open\|type\)\>\|val\>.*:\)', 'bW'))
  184.    endif
  185.  
  186.  " Indent if current line begins with 'val':
  187.  elseif line =~ '^\s*val\>'
  188.    if lline !~ '^\s*\(exception\|external\|include\|open\)\>\|' . s:obj . '\|' . s:letlim
  189.      return indent(search('^\s*\(\(exception\|include\|initializer\|method\|open\|type\|val\)\>\|external\>.*:\)', 'bW'))
  190.    endif
  191.  
  192.  " Indent if current line begins with 'constraint', 'inherit', 'initializer'
  193.  " or 'method':
  194.  elseif line =~ '^\s*\(constraint\|inherit\|initializer\|method\)\>'
  195.    if lline !~ s:obj
  196.      return indent(search('\<\(object\|object\s*(.*)\)\s*$', 'bW')) + &sw
  197.    endif
  198.  
  199.  endif
  200.  
  201.  " Add a 'shiftwidth' after lines ending with:
  202.  if lline =~ '\(:\|=\|->\|<-\|(\|\[\|{\|{<\|\[|\|\[<\|\<\(begin\|do\|else\|fun\|function\|functor\|if\|initializer\|object\|parser\|private\|sig\|struct\|then\|try\)\|\<object\s*(.*)\)\s*$'
  203.    let ind = ind + &sw
  204.  
  205.  " Back to normal indent after lines ending with ';;':
  206.  elseif lline =~ ';;\s*$' && lline !~ '^\s*;;'
  207.    let ind = s:GetInd(v:lnum, s:letpat, s:letlim)
  208.  
  209.  " Back to normal indent after lines ending with 'end':
  210.  elseif lline =~ '\<end\s*$'
  211.    let ind = s:FindPair(s:module, '','\<end\>')
  212.  
  213.  " Back to normal indent after lines ending with 'in':
  214.  elseif lline =~ '\<in\s*$' && lline !~ '^\s*in\>'
  215.    let ind = s:FindPair('\<let\>', '', '\<in\>')
  216.  
  217.  " Back to normal indent after lines ending with 'done':
  218.  elseif lline =~ '\<done\s*$'
  219.    let ind = s:FindPair('\<do\>', '','\<done\>')
  220.  
  221.  " Back to normal indent after lines ending with '}' or '>}':
  222.  elseif lline =~ '\(\|>\)}\s*$'
  223.    let ind = s:FindPair('{', '','}')
  224.  
  225.  " Back to normal indent after lines ending with ']', '|]' or '>]':
  226.  elseif lline =~ '\(\||\|>\)\]\s*$'
  227.    let ind = s:FindPair('\[', '','\]')
  228.  
  229.  " Back to normal indent after comments:
  230.  elseif lline =~ '\*)\s*$'
  231.    call search('\*)', 'bW')
  232.    let ind = indent(searchpair('(\*', '', '\*)', 'bWn', 'synIDattr(synID(line("."), col("."), 0), "name") =~? "string"'))
  233.  
  234.  " Back to normal indent after lines ending with ')':
  235.  elseif lline =~ ')\s*$'
  236.    let ind = s:FindPair('(', '',')')
  237.  
  238.  " If this is a multiline comment then align '*':
  239.  elseif lline =~ '^\s*(\*' && line =~ '^\s*\*'
  240.    let ind = ind + 1
  241.  
  242.  else
  243.  " Don't change indentation of this line
  244.  " for new lines (indent==0) use indentation of previous line
  245.  
  246.  " This is for preventing removing indentation of these args:
  247.  "   let f x =
  248.  "     let y = x + 1 in
  249.  "     Printf.printf
  250.  "       "o"           << here
  251.  "       "oeuth"       << don't touch indentation
  252.  
  253.    let i = indent(v:lnum)
  254.    return i == 0 ? ind : i
  255.  
  256.  endif
  257.  
  258.  " Subtract a 'shiftwidth' after lines matching 'match ... with parser':
  259.  if lline =~ '\<match\>.*\<with\>\s*\<parser\s*$'
  260.    let ind = ind - &sw
  261.  endif
  262.  
  263.  return ind
  264.  
  265. endfunction
  266.  
  267. " vim:sw=2
  268.