summaryrefslogblamecommitdiffstats
path: root/indent/julia.vim
blob: 7fafe89cfb6a8028701d33676bbee1c42fba9664 (plain) (tree)
1
2

                                                                              





































































































































































































                                                                                                                                                                                        

     
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'julia') == -1
  
" Vim indent file
" Language:	Julia
" Maintainer:	Carlo Baldassi <carlobaldassi@gmail.com>
" Last Change:	2011 dec 11
" Notes:        based on Bram Moneaar's indent file for vim

setlocal autoindent

setlocal indentexpr=GetJuliaIndent()
setlocal indentkeys+==end,=else,=catch,=finally
setlocal indentkeys-=0#
setlocal indentkeys-=:
setlocal indentkeys-=0{
setlocal indentkeys-=0}
setlocal nosmartindent

" Only define the function once.
if exists("*GetJuliaIndent")
  finish
endif

let s:skipPatterns = '\<julia\%(Comment\)\>'

function JuliaMatch(lnum, str, regex, st)
  let s = a:st
  while 1
    let f = match(a:str, a:regex, s)
    if f >= 0
      let attr = synIDattr(synID(a:lnum,f+1,1),"name")
      if attr =~ s:skipPatterns
        let s = f+1
        continue
      endif
    endif
    break
  endwhile
  return f
endfunction

function GetJuliaNestingStruct(lnum)
  " Auxiliary function to inspect the block structure of a line
  let line = getline(a:lnum)
  let s = 0
  let blocks_stack = []
  let num_closed_blocks = 0
  while 1
    let fb = JuliaMatch(a:lnum, line, '@\@<!\<\%(if\|else\%(if\)\=\|while\|for\|try\|catch\|finally\|function\|macro\|begin\|type\|immutable\|let\|\%(bare\)\?module\|quote\|do\)\>', s)
    let fe = JuliaMatch(a:lnum, line, '@\@<!\<end\>', s)

    if fb < 0 && fe < 0
      " No blocks found
      break
    end

    if fb >= 0 && (fb < fe || fe < 0)
      " The first occurrence is an opening block keyword
      " Note: some keywords (elseif,else,catch,finally) are both
      "       closing blocks and opening new ones

      let i = JuliaMatch(a:lnum, line, '@\@<!\<if\>', s)
      if i >= 0 && i == fb
        let s = i+1
        call add(blocks_stack, 'if')
        continue
      endif
      let i = JuliaMatch(a:lnum, line, '@\@<!\<elseif\>', s)
      if i >= 0 && i == fb
        let s = i+1
        if len(blocks_stack) > 0 && blocks_stack[-1] == 'if'
          let blocks_stack[-1] = 'elseif'
        elseif (len(blocks_stack) > 0 && blocks_stack[-1] != 'elseif') || len(blocks_stack) == 0
          call add(blocks_stack, 'elseif')
          let num_closed_blocks += 1
        endif
        continue
      endif
      let i = JuliaMatch(a:lnum, line, '@\@<!\<else\>', s)
      if i >= 0 && i == fb
        let s = i+1
        if len(blocks_stack) > 0 && blocks_stack[-1] =~ '\<\%(else\)\=if\>'
          let blocks_stack[-1] = 'else'
        else
          call add(blocks_stack, 'else')
          let num_closed_blocks += 1
        endif
        continue
      endif

      let i = JuliaMatch(a:lnum, line, '@\@<!\<try\>', s)
      if i >= 0 && i == fb
        let s = i+1
        call add(blocks_stack, 'try')
        continue
      endif
      let i = JuliaMatch(a:lnum, line, '@\@<!\<catch\>', s)
      if i >= 0 && i == fb
        let s = i+1
        if len(blocks_stack) > 0 && blocks_stack[-1] == 'try'
          let blocks_stack[-1] = 'catch'
        else
          call add(blocks_stack, 'catch')
          let num_closed_blocks += 1
        endif
        continue
      endif
      let i = JuliaMatch(a:lnum, line, '@\@<!\<finally\>', s)
      if i >= 0 && i == fb
        let s = i+1
        if len(blocks_stack) > 0 && (blocks_stack[-1] == 'try' || blocks_stack[-1] == 'catch')
          let blocks_stack[-1] = 'finally'
        else
          call add(blocks_stack, 'finally')
          let num_closed_blocks += 1
        endif
        continue
      endif

      let i = JuliaMatch(a:lnum, line, '@\@<!\<\%(bare\)\?module\>', s)
      if i >= 0 && i == fb
        let s = i+1
        if i == 0
          call add(blocks_stack, 'col1module')
        else
          call add(blocks_stack, 'other')
        endif
        continue
      endif

      let i = JuliaMatch(a:lnum, line, '@\@<!\<\%(while\|for\|function\|macro\|begin\|type\|immutable\|let\|quote\|do\)\>', s)
      if i >= 0 && i == fb
        let s = i+1
        call add(blocks_stack, 'other')
        continue
      endif

      " Note: it should be impossible to get here
      break

    else
      " The first occurrence is an 'end'

      let s = fe+1
      if len(blocks_stack) == 0
        let num_closed_blocks += 1
      else
        call remove(blocks_stack, -1)
      endif
      continue

    endif

    " Note: it should be impossible to get here
    break
  endwhile
  let num_open_blocks = len(blocks_stack) - count(blocks_stack, 'col1module')
  return [num_open_blocks, num_closed_blocks]
endfunction

function GetJuliaIndent()
  let s:save_ignorecase = &ignorecase
  set noignorecase

  " Find a non-blank line above the current line.
  let lnum = prevnonblank(v:lnum - 1)

  " At the start of the file use zero indent.
  if lnum == 0
    let &ignorecase = s:save_ignorecase
    unlet s:save_ignorecase
    return 0
  endif

  let ind = indent(lnum)

  " Analyse previous line
  let [num_open_blocks, num_closed_blocks] = GetJuliaNestingStruct(lnum)

  " Increase indentation for each newly opened block
  " in the previous line
  while num_open_blocks > 0
    let ind += &sw
    let num_open_blocks -= 1
  endwhile

  " Analyse current line
  let [num_open_blocks, num_closed_blocks] = GetJuliaNestingStruct(v:lnum)

  " Decrease indentation for each closed block
  " in the current line
  while num_closed_blocks > 0
    let ind -= &sw
    let num_closed_blocks -= 1
  endwhile

  let &ignorecase = s:save_ignorecase
  unlet s:save_ignorecase
  return ind
endfunction

endif