summaryrefslogtreecommitdiff
path: root/.config/vim/indent/matlab.vim
blob: 936ac7ce2409209b6afae94d2e06506f78d307e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
" Matlab indent file
" Language:	Matlab
" Maintainer:	Fabrice Guy <fabrice.guy at gmail dot com>
" Last Change:	2008 Oct 15 

" Only load this indent file when no other was loaded.
if exists("b:did_indent")
  finish
endif
let b:did_indent = 1
let s:onlySubfunctionExists = 0

setlocal indentexpr=GetMatlabIndent()
setlocal indentkeys=!,o,O=end,=case,=else,=elseif,=otherwise,=catch

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

function! s:IsMatlabContinuationLine(lnum)
  let continuationLine = 0
  if a:lnum > 0
    let pnbline = getline(prevnonblank(a:lnum))
    " if we have the line continuation operator (... at the end of a line or
    " ... followed by a comment) it may be a line continuation
    if pnbline =~ '\.\.\.\s*$' || pnbline =~ '\.\.\.\s*%.*$'
      let continuationLine = 1
      " but if the ... are part of a string or a comment, it is not a
      " continuation line
      let col = match(pnbline, '\.\.\.\s*$')
      if col == -1
	let col = match(pnbline, '\.\.\.\s*%.*$')
      endif
      if has('syntax_items')
	if synIDattr(synID(prevnonblank(a:lnum), col + 1, 1), "name") =~ "matlabString" ||
	      \ synIDattr(synID(prevnonblank(a:lnum), col + 1, 1), "name") =~ "matlabComment" 
	  let continuationLine = 0
	endif
      endif
    endif
  endif
  return continuationLine
endfunction

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

  " If the previous line is a continuation line, get the beginning of the block to 
  " use the indent of that line
  if s:IsMatlabContinuationLine(plnum - 1)
    while s:IsMatlabContinuationLine(plnum - 1)
      let plnum = plnum - 1
    endwhile
  endif

  " At the start of the file use zero indent.
  if plnum == 0
    return 0
  endif

  let curind = indent(plnum)
  if s:IsMatlabContinuationLine(v:lnum - 1) 
    let curind = curind + &sw
  endif
  " Add a 'shiftwidth' after classdef, properties, switch, methods, events,
  " function, if, while, for, otherwise, case, tic, try, catch, else, elseif
  if getline(plnum) =~ '^\s*\(classdef\|properties\|switch\|methods\|events\|function\|if\|while\|for\|otherwise\|case\|tic\|try\|catch\|else\|elseif\)\>'
    let curind = curind + &sw
    " In Matlab we have different kind of functions
    " - the main function (the function with the same name than the filename)
    " - the nested functions
    " - the functions defined in methods (for classes)
    " - subfunctions
    " For the moment the main function (located line 1) doesn't produce any indentation in the
    " code (default behavior in the Matlab editor) and the other kind of
    " functions indent the code
    if getline(plnum)  =~ '^\s*\function\>'
      " If it is the main function
      if plnum == 1
	" look for a matching end : 
	" - if we find a matching end everything is fine
	" - if not, then all other functions are subfunctions
	normal %
	if getline(line('.')) =~ '^\s*end'
	  let s:onlySubfunctionExists = 0
	else
	  let s:onlySubfunctionExists = 1
	endif
	normal %
	let curind = curind - &sw
      else
	" it is a subfunction without matching end : dedent
	if s:onlySubfunctionExists
	  let curind = curind - &sw
	endif
      endif
    endif
  endif

  " Subtract a 'shiftwidth' on a else, elseif, end, catch, otherwise, case,
  " toc
  if getline(v:lnum) =~ '^\s*\(else\|elseif\|end\|catch\|otherwise\|case\|toc\)\>'
    let curind = curind - &sw
  endif
  " No indentation in a subfunction
  if getline(v:lnum)  =~ '^\s*\function\>' && s:onlySubfunctionExists
    let curind = curind - &sw
  endif

  " First case after a switch : indent
  if getline(v:lnum) =~ '^\s*case'
    while plnum > 0 && (getline(plnum) =~ '^\s*%' || getline(plnum) =~ '^\s*$')
      let plnum = plnum - 1
    endwhile
    if getline(plnum) =~ '^\s*switch'
      let curind = indent(plnum) + &sw
    endif
  endif

  " end in a switch / end block : dedent twice
  " we use the matchit script to know if this end is the end of a switch block
  if exists("b:match_words")
    if getline(v:lnum) =~ '^\s*end'
      normal %
      if getline(line('.')) =~ "switch"
	let curind = curind - &sw
      endif
      normal %
    end
  end
  return curind
endfunction

" vim:sw=2