Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 1 | " Vim indent file |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 2 | " Language: Makefile |
| 3 | " Maintainer: Nikolai Weibull <now@bitwi.se> |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 4 | " Latest Revision: 2006-04-26 |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 5 | |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 6 | if exists("b:did_indent") |
| 7 | finish |
| 8 | endif |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 9 | let b:did_indent = 1 |
| 10 | |
| 11 | setlocal indentexpr=GetMakeIndent() |
| 12 | setlocal indentkeys=!^F,o,O |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 13 | setlocal nosmartindent |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 14 | |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 15 | if exists("*GetMakeIndent") |
| 16 | finish |
| 17 | endif |
| 18 | |
Bram Moolenaar | 57657d8 | 2006-04-21 22:12:41 +0000 | [diff] [blame] | 19 | let s:rule_rx = '^[^ \t#:][^#:]*:\{1,2}\%([^=:]\|$\)' |
| 20 | let s:continuation_rx = '\\$' |
| 21 | let s:assignment_rx = '^\s*\h\w*\s*+\==\s*\zs.*\\$' |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 22 | |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 23 | " TODO: Deal with comments, string, and all kinds of other crap, e.g., defines. |
| 24 | " TODO: Unwrap the whole logic of this function into something that requires a |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 25 | " lot less 'return's. |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 26 | function GetMakeIndent() |
Bram Moolenaar | 42eeac3 | 2005-06-29 22:40:58 +0000 | [diff] [blame] | 27 | let lnum = v:lnum - 1 |
| 28 | if lnum == 0 |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 29 | return 0 |
| 30 | endif |
| 31 | |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 32 | " Figure out if the previous line is part of a rule or not. If it is, then |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 33 | " we more or less just indent by a 'tabstop', the previous' lines indent, or |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 34 | " remove all indent if the current line is itself a rule. Also, if the line |
| 35 | " in question is part of a continuation-line set constituting the rule line |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 36 | " itself, we indent by either a 'shiftwidth', if the line is the first in the |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 37 | " continuation, or use the indent of the previous line, if not. |
| 38 | while lnum > 0 |
| 39 | let line = getline(lnum) |
| 40 | if line[0] != "\t" |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 41 | " We found a non-shell-command line, i.e., one that doesn't have a |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 42 | " leading tab. |
| 43 | if line =~ s:rule_rx |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 44 | " The line looks like a rule line, so we must therefore either be inside a |
| 45 | " rule or we are a continuation line to that rule line. |
| 46 | if line =~ s:continuation_rx |
| 47 | " Ah, the rule line was continued, so look up the last continuation |
| 48 | " line that's above the current line. |
| 49 | while line =~ s:continuation_rx && lnum < v:lnum |
| 50 | let lnum += 1 |
| 51 | let line = getline(lnum) |
| 52 | endwhile |
| 53 | let lnum -= 1 |
| 54 | let line = getline(lnum) |
| 55 | endif |
Bram Moolenaar | 57657d8 | 2006-04-21 22:12:41 +0000 | [diff] [blame] | 56 | |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 57 | " If the line that we've found is right above the current line, deal |
| 58 | " with it specifically. |
| 59 | if lnum == v:lnum - 1 |
| 60 | " If it was continued, indent the current line by a shiftwidth, as it |
| 61 | " is the first to follow it. Otherwise, depending on if the current |
| 62 | " line is a rule line, i.e, a rule line following another rule line, |
| 63 | " then indent to the left margin. Otherwise, the current line is the |
| 64 | " first shell-command line in the rule, so indent by a 'tabstop' |
| 65 | if line =~ s:continuation_rx |
| 66 | return &sw |
| 67 | else |
| 68 | return getline(v:lnum) =~ s:rule_rx ? 0 : &ts |
| 69 | endif |
| 70 | else |
| 71 | " If the previous line was a continuation line, then unless it was |
| 72 | " itself a part of a continuation line, add a 'shiftwidth''s worth of |
| 73 | " indent. Otherwise, just use the indent of the previous line. |
| 74 | " Otherwise, if the previous line wasn't a continuation line, check |
| 75 | " if the one above it was. If it was then indent to whatever level |
| 76 | " the 'owning' line had. Otherwise, indent to the previous line's |
| 77 | " level. |
| 78 | let lnum = v:lnum - 1 |
| 79 | let line = getline(lnum) |
| 80 | if line =~ s:continuation_rx |
| 81 | let pnum = v:lnum - 2 |
| 82 | let pine = getline(pnum) |
| 83 | if pine =~ s:continuation_rx |
| 84 | return indent(lnum) |
| 85 | else |
| 86 | return indent(lnum) + &sw |
| 87 | endif |
| 88 | else |
| 89 | let lnum = v:lnum - 2 |
| 90 | let line = getline(lnum) |
| 91 | if line =~ s:continuation_rx |
| 92 | while lnum > 0 |
| 93 | if line !~ s:continuation_rx |
| 94 | let lnum += 1 |
| 95 | let line = getline(lnum) |
| 96 | break |
| 97 | endif |
| 98 | let lnum -= 1 |
| 99 | let line = getline(lnum) |
| 100 | endwhile |
| 101 | " We've found the owning line. Indent to it's level. |
| 102 | return indent(lnum) |
| 103 | else |
| 104 | return indent(v:lnum - 1) |
| 105 | endif |
| 106 | endif |
| 107 | endif |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 108 | endif |
| 109 | |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 110 | " The line wasn't a rule line, so the current line is part of a series |
| 111 | " of tab-indented lines that don't belong to any rule. |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 112 | break |
| 113 | endif |
| 114 | let lnum -= 1 |
| 115 | endwhile |
| 116 | |
| 117 | " If the line before the one we are currently indenting ended with a |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 118 | " continuation, then try to figure out what 'owns' that line and indent |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 119 | " appropriately. |
| 120 | let lnum = v:lnum - 1 |
| 121 | let line = getline(lnum) |
| 122 | if line =~ s:continuation_rx |
| 123 | let indent = indent(lnum) |
| 124 | if line =~ s:assignment_rx |
| 125 | " The previous line is a continuation line that begins a variable- |
| 126 | " assignment expression, so set the indent to just beyond the whitespace |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 127 | " following the assignment operator ('='). |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 128 | call cursor(lnum, 1) |
| 129 | if search(s:assignment_rx, 'W') != 0 |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 130 | let indent = virtcol('.') - 1 |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 131 | endif |
| 132 | endif |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 133 | |
| 134 | " The previous line didn't constitute an assignment, so just indent to |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 135 | " whatever level it had. |
| 136 | return indent |
| 137 | endif |
| 138 | |
| 139 | " If the line above the line above the current line ended was continued, |
| 140 | " then the line above the current line was part of a continued line. Find |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 141 | " the 'owning' line and indent to its level. |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 142 | let lnum = v:lnum - 2 |
| 143 | let line = getline(lnum) |
| 144 | if line =~ s:continuation_rx |
| 145 | while lnum > 0 |
| 146 | if line !~ s:continuation_rx |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 147 | let lnum += 1 |
| 148 | let line = getline(lnum) |
| 149 | break |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 150 | endif |
Bram Moolenaar | 57657d8 | 2006-04-21 22:12:41 +0000 | [diff] [blame] | 151 | let lnum -= 1 |
| 152 | let line = getline(lnum) |
| 153 | endwhile |
Bram Moolenaar | c9b4b05 | 2006-04-30 18:54:39 +0000 | [diff] [blame] | 154 | " We've found the owning line. Indent to it's level. |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 155 | return indent(lnum) |
| 156 | endif |
Bram Moolenaar | 57657d8 | 2006-04-21 22:12:41 +0000 | [diff] [blame] | 157 | |
Bram Moolenaar | f193fff | 2006-04-27 00:02:13 +0000 | [diff] [blame] | 158 | " If nothing else caught on, then check if this line is a rule line. If it |
| 159 | " is, indent it to the left margin. Otherwise, simply use the indent of the |
| 160 | " previous line. |
| 161 | let line = getline(v:lnum) |
| 162 | if line =~ s:rule_rx |
| 163 | return 0 |
| 164 | else |
| 165 | return indent(v:lnum - 1) |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 166 | endif |
Bram Moolenaar | 071d427 | 2004-06-13 20:20:40 +0000 | [diff] [blame] | 167 | endfunction |