1" Vim indent file 2" Language: Makefile 3" Maintainer: Doug Kearns <[email protected]> 4" Previous Maintainer: Nikolai Weibull <[email protected]> 5" Last Change: 24 Sep 2021 6 7if exists("b:did_indent") 8 finish 9endif 10let b:did_indent = 1 11 12setlocal indentexpr=GetMakeIndent() 13setlocal indentkeys=!^F,o,O,<:>,=else,=endif 14setlocal nosmartindent 15 16let b:undo_indent = "setl ai< inde< indk<" 17 18if exists("*GetMakeIndent") 19 finish 20endif 21 22let s:comment_rx = '^\s*#' 23let s:rule_rx = '^[^ \t#:][^#:]*:\{1,2}\%([^=:]\|$\)' 24let s:continued_rule_rx = '^[^#:]*:\{1,2}\%([^=:]\|$\)' 25let s:continuation_rx = '\\$' 26let s:assignment_rx = '^\s*\h\w*\s*[+:?]\==\s*\zs.*\\$' 27let s:folded_assignment_rx = '^\s*\h\w*\s*[+:?]\==' 28" TODO: This needs to be a lot more restrictive in what it matches. 29let s:just_inserted_rule_rx = '^\s*[^#:]\+:\{1,2}$' 30let s:conditional_directive_rx = '^ *\%(ifn\=\%(eq\|def\)\|else\)\>' 31let s:end_conditional_directive_rx = '^\s*\%(else\|endif\)\>' 32 33function s:remove_continuation(line) 34 return substitute(a:line, s:continuation_rx, "", "") 35endfunction 36 37function GetMakeIndent() 38 " TODO: Should this perhaps be v:lnum -1? 39" let prev_lnum = prevnonblank(v:lnum - 1) 40 let prev_lnum = v:lnum - 1 41 if prev_lnum == 0 42 return 0 43 endif 44 let prev_line = getline(prev_lnum) 45 46 let prev_prev_lnum = prev_lnum - 1 47 let prev_prev_line = prev_prev_lnum != 0 ? getline(prev_prev_lnum) : "" 48 49 " TODO: Deal with comments. In comments, continuations aren't interesting. 50 if prev_line =~ s:continuation_rx 51 if prev_prev_line =~ s:continuation_rx 52 return indent(prev_lnum) 53 elseif prev_line =~ s:rule_rx 54 return shiftwidth() 55 elseif prev_line =~ s:assignment_rx 56 call cursor(prev_lnum, 1) 57 if search(s:assignment_rx, 'W') != 0 58 return virtcol('.') - 1 59 else 60 " TODO: ? 61 return shiftwidth() 62 endif 63 else 64 " TODO: OK, this might be a continued shell command, so perhaps indent 65 " properly here? Leave this out for now, but in the next release this 66 " should be using indent/sh.vim somehow. 67 "if prev_line =~ '^\t' " s:rule_command_rx 68 " if prev_line =~ '^\s\+[@-]\%(if\)\>' 69 " return indent(prev_lnum) + 2 70 " endif 71 "endif 72 return indent(prev_lnum) + shiftwidth() 73 endif 74 elseif prev_prev_line =~ s:continuation_rx 75 let folded_line = s:remove_continuation(prev_prev_line) . ' ' . s:remove_continuation(prev_line) 76 let lnum = prev_prev_lnum - 1 77 let line = getline(lnum) 78 while line =~ s:continuation_rx 79 let folded_line = s:remove_continuation(line) . ' ' . folded_line 80 let lnum -= 1 81 let line = getline(lnum) 82 endwhile 83 let folded_lnum = lnum + 1 84 if folded_line =~ s:rule_rx 85 if getline(v:lnum) =~ s:rule_rx 86 return 0 87 else 88 return &ts 89 endif 90 else 91" elseif folded_line =~ s:folded_assignment_rx 92 if getline(v:lnum) =~ s:rule_rx 93 return 0 94 else 95 return indent(folded_lnum) 96 endif 97" else 98" " TODO: ? 99" return indent(prev_lnum) 100 endif 101 elseif prev_line =~ s:rule_rx 102 if getline(v:lnum) =~ s:rule_rx 103 return 0 104 else 105 return &ts 106 endif 107 elseif prev_line =~ s:conditional_directive_rx 108 return shiftwidth() 109 else 110 let line = getline(v:lnum) 111 if line =~ s:just_inserted_rule_rx 112 return 0 113 elseif line =~ s:end_conditional_directive_rx 114 return v:lnum - 1 == 0 ? 0 : indent(v:lnum - 1) - shiftwidth() 115 else 116 return v:lnum - 1 == 0 ? 0 : indent(v:lnum - 1) 117 endif 118 endif 119endfunction 120