| 
									
										
										
										
											2004-06-13 20:20:40 +00:00
										 |  |  | " Vim indent file | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  | " Language:	    Makefile | 
					
						
							|  |  |  | " Maintainer:	    Nikolai Weibull <now@bitwi.se> | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  | " Latest Revision:  2006-04-26 | 
					
						
							| 
									
										
										
										
											2004-06-13 20:20:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if exists("b:did_indent") | 
					
						
							|  |  |  |   finish | 
					
						
							|  |  |  | endif | 
					
						
							|  |  |  | let b:did_indent = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | setlocal indentexpr=GetMakeIndent() | 
					
						
							|  |  |  | setlocal indentkeys=!^F,o,O | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  | setlocal nosmartindent | 
					
						
							| 
									
										
										
										
											2004-06-13 20:20:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if exists("*GetMakeIndent") | 
					
						
							|  |  |  |   finish | 
					
						
							|  |  |  | endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-21 22:12:41 +00:00
										 |  |  | let s:rule_rx = '^[^ \t#:][^#:]*:\{1,2}\%([^=:]\|$\)' | 
					
						
							|  |  |  | let s:continuation_rx = '\\$' | 
					
						
							|  |  |  | let s:assignment_rx = '^\s*\h\w*\s*+\==\s*\zs.*\\$' | 
					
						
							| 
									
										
										
										
											2004-06-13 20:20:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  | " TODO: Deal with comments, string, and all kinds of other crap, e.g., defines. | 
					
						
							|  |  |  | " TODO: Unwrap the whole logic of this function into something that requires a | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  | " lot less 'return's. | 
					
						
							| 
									
										
										
										
											2004-06-13 20:20:40 +00:00
										 |  |  | function GetMakeIndent() | 
					
						
							| 
									
										
										
										
											2005-06-29 22:40:58 +00:00
										 |  |  |   let lnum = v:lnum - 1 | 
					
						
							|  |  |  |   if lnum == 0 | 
					
						
							| 
									
										
										
										
											2004-06-13 20:20:40 +00:00
										 |  |  |     return 0 | 
					
						
							|  |  |  |   endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |   " Figure out if the previous line is part of a rule or not.  If it is, then | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  |   " we more or less just indent by a 'tabstop', the previous' lines indent, or | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |   " remove all indent if the current line is itself a rule.  Also, if the line | 
					
						
							|  |  |  |   " in question is part of a continuation-line set constituting the rule line | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  |   " itself, we indent by either a 'shiftwidth', if the line is the first in the | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |   " continuation, or use the indent of the previous line, if not. | 
					
						
							|  |  |  |   while lnum > 0 | 
					
						
							|  |  |  |     let line = getline(lnum) | 
					
						
							|  |  |  |     if line[0] != "\t" | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  |       " We found a non-shell-command line, i.e., one that doesn't have a | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |       " leading tab. | 
					
						
							|  |  |  |       if line =~ s:rule_rx | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  | 	" The line looks like a rule line, so we must therefore either be inside a | 
					
						
							|  |  |  | 	" rule or we are a continuation line to that rule line. | 
					
						
							|  |  |  | 	if line =~ s:continuation_rx | 
					
						
							|  |  |  | 	  " Ah, the rule line was continued, so look up the last continuation | 
					
						
							|  |  |  | 	  " line that's above the current line. | 
					
						
							|  |  |  | 	  while line =~ s:continuation_rx && lnum < v:lnum | 
					
						
							|  |  |  | 	    let lnum += 1 | 
					
						
							|  |  |  | 	    let line = getline(lnum) | 
					
						
							|  |  |  | 	  endwhile | 
					
						
							|  |  |  | 	  let lnum -= 1 | 
					
						
							|  |  |  | 	  let line = getline(lnum) | 
					
						
							|  |  |  | 	endif | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  | 	" If the line that we've found is right above the current line, deal | 
					
						
							|  |  |  | 	" with it specifically. | 
					
						
							|  |  |  | 	if lnum == v:lnum - 1 | 
					
						
							|  |  |  | 	  " If it was continued, indent the current line by a shiftwidth, as it | 
					
						
							|  |  |  | 	  " is the first to follow it.  Otherwise, depending on if the current | 
					
						
							|  |  |  | 	  " line is a rule line, i.e, a rule line following another rule line, | 
					
						
							|  |  |  | 	  " then indent to the left margin.  Otherwise, the current line is the | 
					
						
							|  |  |  | 	  " first shell-command line in the rule, so indent by a 'tabstop' | 
					
						
							|  |  |  | 	  if line =~ s:continuation_rx | 
					
						
							|  |  |  | 	    return &sw | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    return getline(v:lnum) =~ s:rule_rx ? 0 : &ts | 
					
						
							|  |  |  | 	  endif | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	  " If the previous line was a continuation line, then unless it was | 
					
						
							|  |  |  | 	  " itself a part of a continuation line, add a 'shiftwidth''s worth of | 
					
						
							|  |  |  | 	  " indent.  Otherwise, just use the indent of the previous line. | 
					
						
							|  |  |  | 	  " Otherwise, if the previous line wasn't a continuation line, check | 
					
						
							|  |  |  | 	  " if the one above it was.  If it was then indent to whatever level | 
					
						
							|  |  |  | 	  " the 'owning' line had.  Otherwise, indent to the previous line's | 
					
						
							|  |  |  | 	  " level. | 
					
						
							|  |  |  | 	  let lnum = v:lnum - 1 | 
					
						
							|  |  |  | 	  let line = getline(lnum) | 
					
						
							|  |  |  | 	  if line =~ s:continuation_rx | 
					
						
							|  |  |  | 	    let pnum = v:lnum - 2 | 
					
						
							|  |  |  | 	    let pine = getline(pnum) | 
					
						
							|  |  |  | 	    if pine =~ s:continuation_rx | 
					
						
							|  |  |  | 	      return indent(lnum) | 
					
						
							|  |  |  | 	    else | 
					
						
							|  |  |  | 	      return indent(lnum) + &sw | 
					
						
							|  |  |  | 	    endif | 
					
						
							|  |  |  | 	  else | 
					
						
							|  |  |  | 	    let lnum = v:lnum - 2 | 
					
						
							|  |  |  | 	    let line = getline(lnum) | 
					
						
							|  |  |  | 	    if line =~ s:continuation_rx | 
					
						
							|  |  |  | 	      while lnum > 0 | 
					
						
							|  |  |  | 		if line !~ s:continuation_rx | 
					
						
							|  |  |  | 		  let lnum += 1 | 
					
						
							|  |  |  | 		  let line = getline(lnum) | 
					
						
							|  |  |  | 		  break | 
					
						
							|  |  |  | 		endif | 
					
						
							|  |  |  | 		let lnum -= 1 | 
					
						
							|  |  |  | 		let line = getline(lnum) | 
					
						
							|  |  |  | 	      endwhile | 
					
						
							|  |  |  | 	      " We've found the owning line.  Indent to it's level. | 
					
						
							|  |  |  | 	      return indent(lnum) | 
					
						
							|  |  |  | 	    else | 
					
						
							|  |  |  | 	      return indent(v:lnum - 1) | 
					
						
							|  |  |  | 	    endif | 
					
						
							|  |  |  | 	  endif | 
					
						
							|  |  |  | 	endif | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |       endif | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  |       " The line wasn't a rule line, so the current line is part of a series | 
					
						
							|  |  |  |       " of tab-indented lines that don't belong to any rule. | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |       break | 
					
						
							|  |  |  |     endif | 
					
						
							|  |  |  |     let lnum -= 1 | 
					
						
							|  |  |  |   endwhile | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   " If the line before the one we are currently indenting ended with a | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  |   " continuation, then try to figure out what 'owns' that line and indent | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |   " appropriately. | 
					
						
							|  |  |  |   let lnum = v:lnum - 1 | 
					
						
							| 
									
										
										
										
											2005-06-29 22:40:58 +00:00
										 |  |  |   let line = getline(lnum) | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |   if line =~ s:continuation_rx | 
					
						
							|  |  |  |     let indent = indent(lnum) | 
					
						
							|  |  |  |     if line =~ s:assignment_rx | 
					
						
							|  |  |  |       " The previous line is a continuation line that begins a variable- | 
					
						
							|  |  |  |       " assignment expression, so set the indent to just beyond the whitespace | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  |       " following the assignment operator ('='). | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |       call cursor(lnum, 1) | 
					
						
							|  |  |  |       if search(s:assignment_rx, 'W') != 0 | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  | 	let indent = virtcol('.') - 1 | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |       endif | 
					
						
							|  |  |  |     endif | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     " The previous line didn't constitute an assignment, so just indent to | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |     " whatever level it had. | 
					
						
							|  |  |  |     return indent | 
					
						
							|  |  |  |   endif | 
					
						
							| 
									
										
										
										
											2006-04-21 22:12:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |   " If the line above the line above the current line ended was continued, | 
					
						
							|  |  |  |   " then the line above the current line was part of a continued line.  Find | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  |   " the 'owning' line and indent to its level. | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |   let lnum = v:lnum - 2 | 
					
						
							|  |  |  |   let line = getline(lnum) | 
					
						
							|  |  |  |   if line =~ s:continuation_rx | 
					
						
							|  |  |  |     while lnum > 0 | 
					
						
							|  |  |  |       if line !~ s:continuation_rx | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  | 	let lnum += 1 | 
					
						
							|  |  |  | 	let line = getline(lnum) | 
					
						
							|  |  |  | 	break | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |       endif | 
					
						
							| 
									
										
										
										
											2006-04-21 22:12:41 +00:00
										 |  |  |       let lnum -= 1 | 
					
						
							|  |  |  |       let line = getline(lnum) | 
					
						
							|  |  |  |     endwhile | 
					
						
							| 
									
										
										
										
											2006-04-30 18:54:39 +00:00
										 |  |  |     " We've found the owning line.  Indent to it's level. | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |     return indent(lnum) | 
					
						
							|  |  |  |   endif | 
					
						
							| 
									
										
										
										
											2006-04-21 22:12:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-27 00:02:13 +00:00
										 |  |  |   " If nothing else caught on, then check if this line is a rule line.  If it | 
					
						
							|  |  |  |   " is, indent it to the left margin.  Otherwise, simply use the indent of the | 
					
						
							|  |  |  |   " previous line. | 
					
						
							|  |  |  |   let line = getline(v:lnum) | 
					
						
							|  |  |  |   if line =~ s:rule_rx | 
					
						
							|  |  |  |     return 0 | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return indent(v:lnum - 1) | 
					
						
							| 
									
										
										
										
											2004-06-13 20:20:40 +00:00
										 |  |  |   endif | 
					
						
							|  |  |  | endfunction |