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