]> code.delx.au - gnu-emacs/blob - lisp/progmodes/make-mode.el
(makefile-gnumake-functions-alist): Add `addprefix'.
[gnu-emacs] / lisp / progmodes / make-mode.el
1 ;;; make-mode.el --- makefile editing commands for Emacs
2
3 ;; Copyright (C) 1992, 1994 Free Software Foundation, Inc.
4
5 ;; Author: Thomas Neumann <tom@smart.bo.open.de>
6 ;; Eric S. Raymond <esr@snark.thyrsus.com>
7 ;; Adapted-By: ESR
8 ;; Keywords: unix, tools
9
10 ;; RMS:
11 ;; This needs work.
12 ;; Also, the doc strings need fixing: the first line doesn't stand alone,
13 ;; and other usage is not high quality. Symbol names don't have `...'.
14
15 ;; This file is part of GNU Emacs.
16
17 ;; GNU Emacs is free software; you can redistribute it and/or modify
18 ;; it under the terms of the GNU General Public License as published by
19 ;; the Free Software Foundation; either version 2, or (at your option)
20 ;; any later version.
21
22 ;; GNU Emacs is distributed in the hope that it will be useful,
23 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 ;; GNU General Public License for more details.
26
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with GNU Emacs; see the file COPYING. If not, write to the
29 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
30 ;; Boston, MA 02111-1307, USA.
31
32 ;;; Commentary:
33
34 ;; A major mode for editing makefiles. The mode knows about Makefile
35 ;; syntax and defines M-n and M-p to move to next and previous productions.
36 ;;
37 ;; The keys $, =, : and . are electric; they try to help you fill in a
38 ;; macro reference, macro definition, ordinary target name, or special
39 ;; target name, respectively. Such names are completed using a list of
40 ;; targets and macro names parsed out of the makefile. This list is
41 ;; automatically updated, if necessary, whenever you invoke one of
42 ;; these commands. You can force it to be updated with C-c C-p.
43 ;;
44 ;; The command C-c C-f adds certain filenames in the current directory
45 ;; as targets. You can filter out filenames by setting the variable
46 ;; makefile-ignored-files-in-pickup-regex.
47 ;;
48 ;; The command C-c C-u grinds for a bit, then pops up a report buffer
49 ;; showing which target names are up-to-date with respect to their
50 ;; prerequisites, which targets are out-of-date, and which have no
51 ;; prerequisites.
52 ;;
53 ;; The command C-c C-b pops up a browser window listing all target and
54 ;; macro names. You can mark or unmark items wit C-c SPC, and insert
55 ;; all marked items back in the Makefile with C-c TAB.
56 ;;
57 ;; The command C-c TAB in the makefile buffer inserts a GNU make builtin.
58 ;; You will be prompted for the builtin's args.
59 ;;
60 ;; There are numerous other customization variables.
61
62 ;;
63 ;; To Do:
64 ;;
65 ;; * makefile-backslash-region should be given better behavior.
66 ;; * Consider binding C-c C-c to comment-region (like cc-mode).
67 ;; * Eliminate electric stuff entirely.
68 ;; * It might be nice to highlight targets differently depending on
69 ;; whether they are up-to-date or not. Not sure how this would
70 ;; interact with font-lock.
71 ;; * Would be nice to edit the commands in ksh-mode and have
72 ;; indentation and slashification done automatically. Hard.
73 ;; * Consider removing browser mode. It seems useless.
74 ;; * ":" should notice when a new target is made and add it to the
75 ;; list (or at least set makefile-need-target-pickup).
76 ;; * Make browser into a major mode.
77 ;; * Clean up macro insertion stuff. It is a mess.
78 ;; * Browser entry and exit is weird. Normalize.
79 ;; * Browser needs to be rewritten. Right now it is kind of a crock.
80 ;; Should at least:
81 ;; * Act more like dired/buffer menu/whatever.
82 ;; * Highlight as mouse traverses.
83 ;; * B2 inserts.
84 ;; * Update documentation above.
85 ;; * Update texinfo manual.
86 ;; * Update files.el.
87
88 \f
89
90 ;;; Code:
91
92 (provide 'makefile)
93
94 ;; Sadly we need this for a macro.
95 (eval-when-compile
96 (require 'imenu))
97
98 ;;; ------------------------------------------------------------
99 ;;; Configurable stuff
100 ;;; ------------------------------------------------------------
101
102 (defvar makefile-browser-buffer-name "*Macros and Targets*"
103 "Name of the macro- and target browser buffer.")
104
105 (defvar makefile-target-colon ":"
106 "String to append to all target names inserted by `makefile-insert-target'.
107 \":\" or \"::\" are common values.")
108
109 (defvar makefile-macro-assign " = "
110 "String to append to all macro names inserted by `makefile-insert-macro'.
111 The normal value should be \" = \", since this is what
112 standard make expects. However, newer makes such as dmake
113 allow a larger variety of different macro assignments, so you
114 might prefer to use \" += \" or \" := \" .")
115
116 (defvar makefile-electric-keys nil
117 "If non-nil, install electric keybindings.
118 Default is nil.")
119
120 (defvar makefile-use-curly-braces-for-macros-p nil
121 "Controls the style of generated macro references.
122 t (actually non-nil) means macro references should use curly braces,
123 like `${this}'.
124 nil means use parentheses, like `$(this)'.")
125
126 (defvar makefile-tab-after-target-colon t
127 "If non-nil, insert a TAB after a target colon.
128 Otherwise, a space is inserted.
129 The default is t.")
130
131 (defvar makefile-browser-leftmost-column 10
132 "Number of blanks to the left of the browser selection mark.")
133
134 (defvar makefile-browser-cursor-column 10
135 "Column in which the cursor is positioned when it moves
136 up or down in the browser.")
137
138 (defvar makefile-backslash-column 48
139 "*Column in which `makefile-backslash-region' inserts backslashes.")
140
141 (defvar makefile-browser-selected-mark "+ "
142 "String used to mark selected entries in the browser.")
143
144 (defvar makefile-browser-unselected-mark " "
145 "String used to mark unselected entries in the browser.")
146
147 (defvar makefile-browser-auto-advance-after-selection-p t
148 "If non-nil, cursor will move after item is selected in browser.")
149
150 (defvar makefile-pickup-everything-picks-up-filenames-p nil
151 "If non-nil, `makefile-pickup-everything' picks up filenames as targets.
152 \(i.e. it calls `makefile-find-filenames-as-targets').
153 Otherwise filenames are omitted.")
154
155 (defvar makefile-cleanup-continuations-p t
156 "If non-nil, automatically clean up continuation lines when saving.
157 A line is cleaned up by removing all whitespace following a trailing
158 backslash. This is done silently.
159 IMPORTANT: Please note that enabling this option causes makefile-mode
160 to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \'it seems necessary\'.")
161
162 (defvar makefile-browser-hook '())
163
164 ;;
165 ;; Special targets for DMake, Sun's make ...
166 ;;
167 (defvar makefile-special-targets-list
168 '(("DEFAULT") ("DONE") ("ERROR") ("EXPORT")
169 ("FAILED") ("GROUPEPILOG") ("GROUPPROLOG") ("IGNORE")
170 ("IMPORT") ("INCLUDE") ("INCLUDEDIRS") ("INIT")
171 ("KEEP_STATE") ("MAKEFILES") ("MAKE_VERSION") ("NO_PARALLEL")
172 ("PARALLEL") ("PHONY") ("PRECIOUS") ("REMOVE")
173 ("SCCS_GET") ("SILENT") ("SOURCE") ("SUFFIXES")
174 ("WAIT") ("c.o") ("C.o") ("m.o")
175 ("el.elc") ("y.c") ("s.o"))
176 "List of special targets.
177 You will be offered to complete on one of those in the minibuffer whenever
178 you enter a \".\" at the beginning of a line in makefile-mode.")
179
180 (defvar makefile-runtime-macros-list
181 '(("@") ("&") (">") ("<") ("*") ("^") ("+") ("?") ("%") ("$"))
182 "List of macros that are resolved by make at runtime.
183 If you insert a macro reference using makefile-insert-macro-ref, the name
184 of the macro is checked against this list. If it can be found its name will
185 not be enclosed in { } or ( ).")
186
187 ;; Note that the first big subexpression is used by font lock. Note
188 ;; that if you change this regexp you must fix the imenu index
189 ;; function defined at the end of the file.
190 (defconst makefile-dependency-regex
191 "^\\([^ \n\t#:]+\\([ \t]+[^ \t\n#:]+\\)*\\)[ \t]*:\\([ \t]*$\\|\\([^=\n].*$\\)\\)"
192 "Regex used to find dependency lines in a makefile.")
193
194 ;; Note that the first subexpression is used by font lock. Note that
195 ;; if you change this regexp you must fix the imenu index function
196 ;; defined at the end of the file.
197 (defconst makefile-macroassign-regex
198 "^\\([^ \n\t][^:#= \t\n]*\\)[ \t]*[*:+]?:?="
199 "Regex used to find macro assignment lines in a makefile.")
200
201 (defconst makefile-ignored-files-in-pickup-regex
202 "\\(^\\..*\\)\\|\\(.*~$\\)\\|\\(.*,v$\\)\\|\\(\\.[chy]\\)"
203 "Regex for filenames that will NOT be included in the target list.")
204
205 (if (fboundp 'facemenu-unlisted-faces)
206 (add-to-list 'facemenu-unlisted-faces 'makefile-space-face))
207 (defvar makefile-space-face 'makefile-space-face
208 "Face to use for highlighting leading spaces in Font-Lock mode.")
209
210 (defconst makefile-font-lock-keywords
211 (list
212 ;; Do macro assignments. These get the "variable-name" face rather
213 ;; arbitrarily.
214 (list makefile-macroassign-regex 1 'font-lock-variable-name-face)
215 ;;
216 ;; Variable references even in targets/strings/comments:
217 '("\\$[({]\\([a-zA-Z0-9_]+\\)[})]" 1 font-lock-reference-face prepend)
218 ;;
219 ;; Do dependencies. These get the function name face.
220 (list makefile-dependency-regex 1 'font-lock-function-name-face 'prepend)
221
222 ;; Highlight lines that contain just whitespace.
223 ;; They can cause trouble, especially if they start with a tab.
224 '("^[ \t]+$" . makefile-space-face)
225
226 ;; Highlight shell comments that Make treats as commands,
227 ;; since these can fool people.
228 '("^\t+#" 0 makefile-space-face t)
229
230 ;; Highlight spaces that precede tabs.
231 ;; They can make a tab fail to be effective.
232 '("^\\( +\\)\t" 1 makefile-space-face)))
233
234 ;;; ------------------------------------------------------------
235 ;;; The following configurable variables are used in the
236 ;;; up-to-date overview .
237 ;;; The standard configuration assumes that your `make' program
238 ;;; can be run in question/query mode using the `-q' option, this
239 ;;; means that the command
240 ;;;
241 ;;; make -q foo
242 ;;;
243 ;;; should return an exit status of zero if the target `foo' is
244 ;;; up to date and a nonzero exit status otherwise.
245 ;;; Many makes can do this although the docs/manpages do not mention
246 ;;; it. Try it with your favourite one. GNU make, System V make, and
247 ;;; Dennis Vadura's DMake have no problems.
248 ;;; Set the variable `makefile-brave-make' to the name of the
249 ;;; make utility that does this on your system.
250 ;;; To understand what this is all about see the function definition
251 ;;; of `makefile-query-by-make-minus-q' .
252 ;;; ------------------------------------------------------------
253
254 (defvar makefile-brave-make "make"
255 "A make that can handle the `-q' option.")
256
257 (defvar makefile-query-one-target-method 'makefile-query-by-make-minus-q
258 "Function to call to determine whether a make target is up to date.
259 The function must satisfy this calling convention:
260
261 * As its first argument, it must accept the name of the target to
262 be checked, as a string.
263
264 * As its second argument, it may accept the name of a makefile
265 as a string. Depending on what you're going to do you may
266 not need this.
267
268 * It must return the integer value 0 (zero) if the given target
269 should be considered up-to-date in the context of the given
270 makefile, any nonzero integer value otherwise.")
271
272 (defvar makefile-up-to-date-buffer-name "*Makefile Up-to-date overview*"
273 "Name of the Up-to-date overview buffer.")
274
275 ;;; --- end of up-to-date-overview configuration ------------------
276
277 (defvar makefile-mode-map nil
278 "The keymap that is used in Makefile mode.")
279
280 (if makefile-mode-map
281 ()
282 (setq makefile-mode-map (make-sparse-keymap))
283 ;; set up the keymap
284 (define-key makefile-mode-map "\C-c:" 'makefile-insert-target-ref)
285 (if makefile-electric-keys
286 (progn
287 (define-key makefile-mode-map "$" 'makefile-insert-macro-ref)
288 (define-key makefile-mode-map ":" 'makefile-electric-colon)
289 (define-key makefile-mode-map "=" 'makefile-electric-equal)
290 (define-key makefile-mode-map "." 'makefile-electric-dot)))
291 (define-key makefile-mode-map "\C-c\C-f" 'makefile-pickup-filenames-as-targets)
292 (define-key makefile-mode-map "\C-c\C-b" 'makefile-switch-to-browser)
293 (define-key makefile-mode-map "\C-c\C-p" 'makefile-pickup-everything)
294 (define-key makefile-mode-map "\C-c\C-u" 'makefile-create-up-to-date-overview)
295 (define-key makefile-mode-map "\C-c\C-i" 'makefile-insert-gmake-function)
296 (define-key makefile-mode-map "\C-c\C-\\" 'makefile-backslash-region)
297 (define-key makefile-mode-map "\M-p" 'makefile-previous-dependency)
298 (define-key makefile-mode-map "\M-n" 'makefile-next-dependency)
299 (define-key makefile-mode-map "\e\t" 'makefile-complete)
300
301 ;; Make menus.
302 (define-key makefile-mode-map [menu-bar makefile-mode]
303 (cons "Makefile" (make-sparse-keymap "Makefile")))
304
305 (define-key makefile-mode-map [menu-bar makefile-mode browse]
306 '("Pop up Makefile Browser" . makefile-switch-to-browser))
307 (define-key makefile-mode-map [menu-bar makefile-mode complete]
308 '("Complete Target or Macro" . makefile-complete))
309 (define-key makefile-mode-map [menu-bar makefile-mode pickup]
310 '("Find Targets and Macros" . makefile-pickup-everything))
311
312 (define-key makefile-mode-map [menu-bar makefile-mode prev]
313 '("Move to Previous Dependency" . makefile-previous-dependency))
314 (define-key makefile-mode-map [menu-bar makefile-mode next]
315 '("Move to Next Dependency" . makefile-next-dependency)))
316
317 (defvar makefile-browser-map nil
318 "The keymap that is used in the macro- and target browser.")
319 (if makefile-browser-map
320 ()
321 (setq makefile-browser-map (make-sparse-keymap))
322 (define-key makefile-browser-map "n" 'makefile-browser-next-line)
323 (define-key makefile-browser-map "\C-n" 'makefile-browser-next-line)
324 (define-key makefile-browser-map "p" 'makefile-browser-previous-line)
325 (define-key makefile-browser-map "\C-p" 'makefile-browser-previous-line)
326 (define-key makefile-browser-map " " 'makefile-browser-toggle)
327 (define-key makefile-browser-map "i" 'makefile-browser-insert-selection)
328 (define-key makefile-browser-map "I" 'makefile-browser-insert-selection-and-quit)
329 (define-key makefile-browser-map "\C-c\C-m" 'makefile-browser-insert-continuation)
330 (define-key makefile-browser-map "q" 'makefile-browser-quit)
331 ;; disable horizontal movement
332 (define-key makefile-browser-map "\C-b" 'undefined)
333 (define-key makefile-browser-map "\C-f" 'undefined))
334
335
336 (defvar makefile-mode-syntax-table nil)
337 (if makefile-mode-syntax-table
338 ()
339 (setq makefile-mode-syntax-table (make-syntax-table))
340 (modify-syntax-entry ?\( "() " makefile-mode-syntax-table)
341 (modify-syntax-entry ?\) ")( " makefile-mode-syntax-table)
342 (modify-syntax-entry ?\[ "(] " makefile-mode-syntax-table)
343 (modify-syntax-entry ?\] ")[ " makefile-mode-syntax-table)
344 (modify-syntax-entry ?\{ "(} " makefile-mode-syntax-table)
345 (modify-syntax-entry ?\} "){ " makefile-mode-syntax-table)
346 (modify-syntax-entry ?\' "\" " makefile-mode-syntax-table)
347 (modify-syntax-entry ?\` "\" " makefile-mode-syntax-table)
348 (modify-syntax-entry ?# "< " makefile-mode-syntax-table)
349 (modify-syntax-entry ?\n "> " makefile-mode-syntax-table))
350
351
352 ;;; ------------------------------------------------------------
353 ;;; Internal variables.
354 ;;; You don't need to configure below this line.
355 ;;; ------------------------------------------------------------
356
357 (defvar makefile-target-table nil
358 "Table of all target names known for this buffer.")
359
360 (defvar makefile-macro-table nil
361 "Table of all macro names known for this buffer.")
362
363 (defvar makefile-browser-client
364 "A buffer in Makefile mode that is currently using the browser.")
365
366 (defvar makefile-browser-selection-vector nil)
367 (defvar makefile-has-prereqs nil)
368 (defvar makefile-need-target-pickup t)
369 (defvar makefile-need-macro-pickup t)
370
371 (defvar makefile-mode-hook '())
372
373 ;; Each element looks like '("GNU MAKE FUNCTION" "ARG" "ARG" ... )
374 ;; Each "ARG" is used as a prompt for a required argument.
375 (defconst makefile-gnumake-functions-alist
376 '(
377 ;; Text functions
378 ("subst" "From" "To" "In")
379 ("patsubst" "Pattern" "Replacement" "In")
380 ("strip" "Text")
381 ("findstring" "Find what" "In")
382 ("filter" "Pattern" "Text")
383 ("filter-out" "Pattern" "Text")
384 ("sort" "List")
385 ;; Filename functions
386 ("dir" "Names")
387 ("notdir" "Names")
388 ("suffix" "Names")
389 ("basename" "Names")
390 ("addprefix" "Prefix" "Names")
391 ("addsuffix" "Suffix" "Names")
392 ("join" "List 1" "List 2")
393 ("word" "Index" "Text")
394 ("words" "Text")
395 ("firstword" "Text")
396 ("wildcard" "Pattern")
397 ;; Misc functions
398 ("foreach" "Variable" "List" "Text")
399 ("origin" "Variable")
400 ("shell" "Command")))
401
402
403 ;;; ------------------------------------------------------------
404 ;;; The mode function itself.
405 ;;; ------------------------------------------------------------
406
407 ;;;###autoload
408 (defun makefile-mode ()
409 "Major mode for editing Makefiles.
410 This function ends by invoking the function(s) `makefile-mode-hook'.
411
412 \\{makefile-mode-map}
413
414 In the browser, use the following keys:
415
416 \\{makefile-browser-map}
417
418 Makefile mode can be configured by modifying the following variables:
419
420 makefile-browser-buffer-name:
421 Name of the macro- and target browser buffer.
422
423 makefile-target-colon:
424 The string that gets appended to all target names
425 inserted by `makefile-insert-target'.
426 \":\" or \"::\" are quite common values.
427
428 makefile-macro-assign:
429 The string that gets appended to all macro names
430 inserted by `makefile-insert-macro'.
431 The normal value should be \" = \", since this is what
432 standard make expects. However, newer makes such as dmake
433 allow a larger variety of different macro assignments, so you
434 might prefer to use \" += \" or \" := \" .
435
436 makefile-tab-after-target-colon:
437 If you want a TAB (instead of a space) to be appended after the
438 target colon, then set this to a non-nil value.
439
440 makefile-browser-leftmost-column:
441 Number of blanks to the left of the browser selection mark.
442
443 makefile-browser-cursor-column:
444 Column in which the cursor is positioned when it moves
445 up or down in the browser.
446
447 makefile-browser-selected-mark:
448 String used to mark selected entries in the browser.
449
450 makefile-browser-unselected-mark:
451 String used to mark unselected entries in the browser.
452
453 makefile-browser-auto-advance-after-selection-p:
454 If this variable is set to a non-nil value the cursor
455 will automagically advance to the next line after an item
456 has been selected in the browser.
457
458 makefile-pickup-everything-picks-up-filenames-p:
459 If this variable is set to a non-nil value then
460 `makefile-pickup-everything' also picks up filenames as targets
461 (i.e. it calls `makefile-find-filenames-as-targets'), otherwise
462 filenames are omitted.
463
464 makefile-cleanup-continuations-p:
465 If this variable is set to a non-nil value then makefile-mode
466 will assure that no line in the file ends with a backslash
467 (the continuation character) followed by any whitespace.
468 This is done by silently removing the trailing whitespace, leaving
469 the backslash itself intact.
470 IMPORTANT: Please note that enabling this option causes makefile-mode
471 to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\".
472
473 makefile-browser-hook:
474 A function or list of functions to be called just before the
475 browser is entered. This is executed in the makefile buffer.
476
477 makefile-special-targets-list:
478 List of special targets. You will be offered to complete
479 on one of those in the minibuffer whenever you enter a `.'.
480 at the beginning of a line in Makefile mode."
481
482 (interactive)
483 (kill-all-local-variables)
484 (make-local-variable 'local-write-file-hooks)
485 (setq local-write-file-hooks
486 '(makefile-cleanup-continuations makefile-warn-suspicious-lines))
487 (make-local-variable 'makefile-target-table)
488 (make-local-variable 'makefile-macro-table)
489 (make-local-variable 'makefile-has-prereqs)
490 (make-local-variable 'makefile-need-target-pickup)
491 (make-local-variable 'makefile-need-macro-pickup)
492
493 ;; Font lock.
494 (if (fboundp 'make-face)
495 (makefile-define-space-face))
496 (make-local-variable 'font-lock-defaults)
497 (setq font-lock-defaults '(makefile-font-lock-keywords))
498
499 ;; Add-log.
500 (make-local-variable 'add-log-current-defun-function)
501 (setq add-log-current-defun-function 'makefile-add-log-defun)
502
503 ;; Imenu.
504 (make-local-variable 'imenu-create-index-function)
505 (setq imenu-create-index-function 'makefile-menu-index-function)
506
507 ;; Dabbrev.
508 (make-local-variable 'dabbrev-abbrev-skip-leading-regexp)
509 (setq dabbrev-abbrev-skip-leading-regexp "\\$")
510
511 ;; Comment stuff.
512 (make-local-variable 'comment-start)
513 (setq comment-start "#")
514 (make-local-variable 'comment-end)
515 (setq comment-end "")
516 (make-local-variable 'comment-start-skip)
517 (setq comment-start-skip "#+[ \t]*")
518
519 ;; become the current major mode
520 (setq major-mode 'makefile-mode)
521 (setq mode-name "Makefile")
522
523 ;; Activate keymap and syntax table.
524 (use-local-map makefile-mode-map)
525 (set-syntax-table makefile-mode-syntax-table)
526
527 ;; Real TABs are important in makefiles
528 (setq indent-tabs-mode t)
529 (run-hooks 'makefile-mode-hook))
530
531 \f
532
533 ;;; Motion code.
534
535 (defun makefile-next-dependency ()
536 "Move point to the beginning of the next dependency line."
537 (interactive)
538 (let ((here (point)))
539 (end-of-line)
540 (if (re-search-forward makefile-dependency-regex (point-max) t)
541 (progn (beginning-of-line) t) ; indicate success
542 (goto-char here) nil)))
543
544 (defun makefile-previous-dependency ()
545 "Move point to the beginning of the previous dependency line."
546 (interactive)
547 (let ((here (point)))
548 (beginning-of-line)
549 (if (re-search-backward makefile-dependency-regex (point-min) t)
550 (progn (beginning-of-line) t) ; indicate success
551 (goto-char here) nil)))
552
553 \f
554
555 ;;; Electric keys. Blech.
556
557 (defun makefile-electric-dot (arg)
558 "Prompt for the name of a special target to insert.
559 Only does electric insertion at beginning of line.
560 Anywhere else just self-inserts."
561 (interactive "p")
562 (if (bolp)
563 (makefile-insert-special-target)
564 (self-insert-command arg)))
565
566 (defun makefile-insert-special-target ()
567 "Prompt for and insert a special target name.
568 Uses `makefile-special-targets' list."
569 (interactive)
570 (makefile-pickup-targets)
571 (let ((special-target
572 (completing-read "Special target: "
573 makefile-special-targets-list nil nil nil)))
574 (if (zerop (length special-target))
575 ()
576 (insert "." special-target ":")
577 (makefile-forward-after-target-colon))))
578
579 (defun makefile-electric-equal (arg)
580 "Prompt for name of a macro to insert.
581 Only does prompting if point is at beginning of line.
582 Anywhere else just self-inserts."
583 (interactive "p")
584 (makefile-pickup-macros)
585 (if (bolp)
586 (call-interactively 'makefile-insert-macro)
587 (self-insert-command arg)))
588
589 (defun makefile-insert-macro (macro-name)
590 "Prepare definition of a new macro."
591 (interactive "sMacro Name: ")
592 (makefile-pickup-macros)
593 (if (not (zerop (length macro-name)))
594 (progn
595 (beginning-of-line)
596 (insert macro-name makefile-macro-assign)
597 (setq makefile-need-macro-pickup t)
598 (makefile-remember-macro macro-name))))
599
600 (defun makefile-insert-macro-ref (macro-name)
601 "Complete on a list of known macros, then insert complete ref at point."
602 (interactive
603 (list
604 (progn
605 (makefile-pickup-macros)
606 (completing-read "Refer to macro: " makefile-macro-table nil nil nil))))
607 (makefile-do-macro-insertion macro-name))
608
609 (defun makefile-insert-target (target-name)
610 "Prepare definition of a new target (dependency line)."
611 (interactive "sTarget: ")
612 (if (not (zerop (length target-name)))
613 (progn
614 (beginning-of-line)
615 (insert target-name makefile-target-colon)
616 (makefile-forward-after-target-colon)
617 (end-of-line)
618 (setq makefile-need-target-pickup t)
619 (makefile-remember-target target-name))))
620
621 (defun makefile-insert-target-ref (target-name)
622 "Complete on a list of known targets, then insert target-ref at point."
623 (interactive
624 (list
625 (progn
626 (makefile-pickup-targets)
627 (completing-read "Refer to target: " makefile-target-table nil nil nil))))
628 (if (not (zerop (length target-name)))
629 (insert target-name " ")))
630
631 (defun makefile-electric-colon (arg)
632 "Prompt for name of new target.
633 Prompting only happens at beginning of line.
634 Anywhere else just self-inserts."
635 (interactive "p")
636 (if (bolp)
637 (call-interactively 'makefile-insert-target)
638 (self-insert-command arg)))
639
640 \f
641
642 ;;; ------------------------------------------------------------
643 ;;; Extracting targets and macros from an existing makefile
644 ;;; ------------------------------------------------------------
645
646 (defun makefile-pickup-targets ()
647 "Notice names of all target definitions in Makefile."
648 (interactive)
649 (if (not makefile-need-target-pickup)
650 nil
651 (setq makefile-need-target-pickup nil)
652 (setq makefile-target-table nil)
653 (setq makefile-has-prereqs nil)
654 (save-excursion
655 (goto-char (point-min))
656 (while (re-search-forward makefile-dependency-regex (point-max) t)
657 (makefile-add-this-line-targets)))
658 (message "Read targets OK.")))
659
660 (defun makefile-add-this-line-targets ()
661 (save-excursion
662 (beginning-of-line)
663 (let ((done-with-line nil)
664 (line-number (1+ (count-lines (point-min) (point)))))
665 (while (not done-with-line)
666 (skip-chars-forward " \t")
667 (if (not (setq done-with-line (or (eolp)
668 (char-equal (char-after (point)) ?:))))
669 (progn
670 (let* ((start-of-target-name (point))
671 (target-name
672 (progn
673 (skip-chars-forward "^ \t:#")
674 (buffer-substring start-of-target-name (point))))
675 (has-prereqs
676 (not (looking-at ":[ \t]*$"))))
677 (if (makefile-remember-target target-name has-prereqs)
678 (message "Picked up target \"%s\" from line %d"
679 target-name line-number)))))))))
680
681 (defun makefile-pickup-macros ()
682 "Notice names of all macro definitions in Makefile."
683 (interactive)
684 (if (not makefile-need-macro-pickup)
685 nil
686 (setq makefile-need-macro-pickup nil)
687 (setq makefile-macro-table nil)
688 (save-excursion
689 (goto-char (point-min))
690 (while (re-search-forward makefile-macroassign-regex (point-max) t)
691 (makefile-add-this-line-macro)
692 (forward-line 1)))
693 (message "Read macros OK.")))
694
695 (defun makefile-add-this-line-macro ()
696 (save-excursion
697 (beginning-of-line)
698 (skip-chars-forward " \t")
699 (if (not (eolp))
700 (let* ((start-of-macro-name (point))
701 (line-number (1+ (count-lines (point-min) (point))))
702 (macro-name (progn
703 (skip-chars-forward "^ \t:#=*")
704 (buffer-substring start-of-macro-name (point)))))
705 (if (makefile-remember-macro macro-name)
706 (message "Picked up macro \"%s\" from line %d"
707 macro-name line-number))))))
708
709 (defun makefile-pickup-everything (arg)
710 "Notice names of all macros and targets in Makefile.
711 Prefix arg means force pickups to be redone."
712 (interactive "P")
713 (if arg
714 (progn
715 (setq makefile-need-target-pickup t)
716 (setq makefile-need-macro-pickup t)))
717 (makefile-pickup-macros)
718 (makefile-pickup-targets)
719 (if makefile-pickup-everything-picks-up-filenames-p
720 (makefile-pickup-filenames-as-targets)))
721
722 (defun makefile-pickup-filenames-as-targets ()
723 "Scan the current directory for filenames to use as targets.
724 Checks each filename against `makefile-ignored-files-in-pickup-regex'
725 and adds all qualifying names to the list of known targets."
726 (interactive)
727 (let* ((dir (file-name-directory (buffer-file-name)))
728 (raw-filename-list (if dir
729 (file-name-all-completions "" dir)
730 (file-name-all-completions "" ""))))
731 (mapcar '(lambda (name)
732 (if (and (not (file-directory-p name))
733 (not (string-match makefile-ignored-files-in-pickup-regex
734 name)))
735 (if (makefile-remember-target name)
736 (message "Picked up file \"%s\" as target" name))))
737 raw-filename-list)))
738
739 \f
740
741 ;;; Completion.
742
743 (defun makefile-complete ()
744 "Perform completion on Makefile construct preceding point.
745 Can complete variable and target names.
746 The context determines which are considered."
747 (interactive)
748 (let* ((beg (save-excursion
749 (skip-chars-backward "^$(){}:#= \t\n")
750 (point)))
751 (try (buffer-substring beg (point)))
752 (do-macros nil)
753 (paren nil))
754
755 (save-excursion
756 (goto-char beg)
757 (let ((pc (preceding-char)))
758 (cond
759 ;; Beginning of line means anything.
760 ((bolp)
761 ())
762
763 ;; Preceding "$" means macros only.
764 ((= pc ?$)
765 (setq do-macros t))
766
767 ;; Preceding "$(" or "${" means macros only.
768 ((and (or (= pc ?{)
769 (= pc ?\())
770 (progn
771 (setq paren pc)
772 (backward-char)
773 (and (not (bolp))
774 (= (preceding-char) ?$))))
775 (setq do-macros t)))))
776
777 ;; Try completion.
778 (let* ((table (append (if do-macros
779 '()
780 makefile-target-table)
781 makefile-macro-table))
782 (completion (try-completion try table)))
783 (cond
784 ;; Exact match, so insert closing paren or colon.
785 ((eq completion t)
786 (insert (if do-macros
787 (if (eq paren ?{)
788 ?}
789 ?\))
790 (if (save-excursion
791 (goto-char beg)
792 (bolp))
793 ":"
794 " "))))
795
796 ;; No match.
797 ((null completion)
798 (message "Can't find completion for \"%s\"" try)
799 (ding))
800
801 ;; Partial completion.
802 ((not (string= try completion))
803 ;; FIXME it would be nice to supply the closing paren if an
804 ;; exact, unambiguous match were found. That is not possible
805 ;; right now. Ditto closing ":" for targets.
806 (delete-region beg (point))
807
808 ;; DO-MACROS means doing macros only. If not that, then check
809 ;; to see if this completion is a macro. Special insertion
810 ;; must be done for macros.
811 (if (or do-macros
812 (assoc completion makefile-macro-table))
813 (let ((makefile-use-curly-braces-for-macros-p
814 (or (eq paren ?{)
815 makefile-use-curly-braces-for-macros-p)))
816 (delete-backward-char 2)
817 (makefile-do-macro-insertion completion)
818 (delete-backward-char 1))
819
820 ;; Just insert targets.
821 (insert completion)))
822
823 ;; Can't complete any more, so make completion list. FIXME
824 ;; this doesn't do the right thing when the completion is
825 ;; actually inserted. I don't think there is an easy way to do
826 ;; that.
827 (t
828 (message "Making completion list...")
829 (let ((list (all-completions try table)))
830 (with-output-to-temp-buffer "*Completions*"
831 (display-completion-list list)))
832 (message "Making completion list...done"))))))
833
834 \f
835
836 ;; Backslashification. Stolen from cc-mode.el.
837
838 (defun makefile-backslashify-current-line (doit)
839 (end-of-line)
840 (if doit
841 (if (not (save-excursion
842 (forward-char -1)
843 (eq (char-after (point)) ?\\ )))
844 (progn
845 (if (>= (current-column) makefile-backslash-column)
846 (insert " \\")
847 (while (<= (current-column) makefile-backslash-column)
848 (insert "\t")
849 (end-of-line))
850 (delete-char -1)
851 (while (< (current-column) makefile-backslash-column)
852 (insert " ")
853 (end-of-line))
854 (insert "\\"))))
855 (if (not (bolp))
856 (progn
857 (forward-char -1)
858 (if (eq (char-after (point)) ?\\ )
859 (let ((saved (save-excursion
860 (end-of-line)
861 (point))))
862 (skip-chars-backward " \t")
863 (delete-region (point) saved)))))))
864
865 (defun makefile-backslash-region (beg end arg)
866 "Insert backslashes at end of every line in region.
867 Useful for defining multi-line rules.
868 If called with a prefix argument, trailing backslashes are removed."
869 (interactive "r\nP")
870 (save-excursion
871 (let ((do-lastline-p (progn (goto-char end) (not (bolp)))))
872 (save-restriction
873 (narrow-to-region beg end)
874 (goto-char (point-min))
875 (while (not (save-excursion
876 (forward-line 1)
877 (eobp)))
878 (makefile-backslashify-current-line (null arg))
879 (forward-line 1)))
880 (and do-lastline-p
881 (progn (goto-char end)
882 (makefile-backslashify-current-line (null arg)))))))
883
884 \f
885
886 ;;; ------------------------------------------------------------
887 ;;; Browser mode.
888 ;;; ------------------------------------------------------------
889
890 (defun makefile-browser-format-target-line (target selected)
891 (format
892 (concat (make-string makefile-browser-leftmost-column ?\ )
893 (if selected
894 makefile-browser-selected-mark
895 makefile-browser-unselected-mark)
896 "%s%s")
897 target makefile-target-colon))
898
899 (defun makefile-browser-format-macro-line (macro selected)
900 (format
901 (concat (make-string makefile-browser-leftmost-column ?\ )
902 (if selected
903 makefile-browser-selected-mark
904 makefile-browser-unselected-mark)
905 (makefile-format-macro-ref macro))))
906
907 (defun makefile-browser-fill (targets macros)
908 (let ((inhibit-read-only t))
909 (goto-char (point-min))
910 (erase-buffer)
911 (mapconcat
912 (function
913 (lambda (item) (insert (makefile-browser-format-target-line (car item) nil) "\n")))
914 targets
915 "")
916 (mapconcat
917 (function
918 (lambda (item) (insert (makefile-browser-format-macro-line (car item) nil) "\n")))
919 macros
920 "")
921 (sort-lines nil (point-min) (point-max))
922 (goto-char (1- (point-max)))
923 (delete-char 1) ; remove unnecessary newline at eob
924 (goto-char (point-min))
925 (forward-char makefile-browser-cursor-column)))
926
927 ;;;
928 ;;; Moving up and down in the browser
929 ;;;
930
931 (defun makefile-browser-next-line ()
932 "Move the browser selection cursor to the next line."
933 (interactive)
934 (if (not (makefile-last-line-p))
935 (progn
936 (forward-line 1)
937 (forward-char makefile-browser-cursor-column))))
938
939 (defun makefile-browser-previous-line ()
940 "Move the browser selection cursor to the previous line."
941 (interactive)
942 (if (not (makefile-first-line-p))
943 (progn
944 (forward-line -1)
945 (forward-char makefile-browser-cursor-column))))
946
947 ;;;
948 ;;; Quitting the browser (returns to client buffer)
949 ;;;
950
951 (defun makefile-browser-quit ()
952 "Leave the browser and return to the makefile buffer."
953 (interactive)
954 (let ((my-client makefile-browser-client))
955 (setq makefile-browser-client nil) ; we quitted, so NO client!
956 (set-buffer-modified-p nil)
957 (kill-buffer (current-buffer))
958 (pop-to-buffer my-client)))
959
960 ;;;
961 ;;; Toggle state of a browser item
962 ;;;
963
964 (defun makefile-browser-toggle ()
965 "Toggle the selection state of the browser item at the cursor position."
966 (interactive)
967 (let ((this-line (count-lines (point-min) (point))))
968 (setq this-line (max 1 this-line))
969 (makefile-browser-toggle-state-for-line this-line)
970 (goto-line this-line)
971 (let ((inhibit-read-only t))
972 (beginning-of-line)
973 (if (makefile-browser-on-macro-line-p)
974 (let ((macro-name (makefile-browser-this-line-macro-name)))
975 (delete-region (point) (progn (end-of-line) (point)))
976 (insert
977 (makefile-browser-format-macro-line
978 macro-name
979 (makefile-browser-get-state-for-line this-line))))
980 (let ((target-name (makefile-browser-this-line-target-name)))
981 (delete-region (point) (progn (end-of-line) (point)))
982 (insert
983 (makefile-browser-format-target-line
984 target-name
985 (makefile-browser-get-state-for-line this-line))))))
986 (beginning-of-line)
987 (forward-char makefile-browser-cursor-column)
988 (if makefile-browser-auto-advance-after-selection-p
989 (makefile-browser-next-line))))
990
991 ;;;
992 ;;; Making insertions into the client buffer
993 ;;;
994
995 (defun makefile-browser-insert-continuation ()
996 "Insert a makefile continuation.
997 In the makefile buffer, go to (end-of-line), insert a \'\\\'
998 character, insert a new blank line, go to that line and indent by one TAB.
999 This is most useful in the process of creating continued lines when copying
1000 large dependencies from the browser to the client buffer.
1001 \(point) advances accordingly in the client buffer."
1002 (interactive)
1003 (save-excursion
1004 (set-buffer makefile-browser-client)
1005 (end-of-line)
1006 (insert "\\\n\t")))
1007
1008 (defun makefile-browser-insert-selection ()
1009 "Insert all selected targets and/or macros in the makefile buffer.
1010 Insertion takes place at point."
1011 (interactive)
1012 (save-excursion
1013 (goto-line 1)
1014 (let ((current-line 1))
1015 (while (not (eobp))
1016 (if (makefile-browser-get-state-for-line current-line)
1017 (makefile-browser-send-this-line-item))
1018 (forward-line 1)
1019 (setq current-line (1+ current-line))))))
1020
1021 (defun makefile-browser-insert-selection-and-quit ()
1022 (interactive)
1023 (makefile-browser-insert-selection)
1024 (makefile-browser-quit))
1025
1026 (defun makefile-browser-send-this-line-item ()
1027 (if (makefile-browser-on-macro-line-p)
1028 (save-excursion
1029 (let ((macro-name (makefile-browser-this-line-macro-name)))
1030 (set-buffer makefile-browser-client)
1031 (insert (makefile-format-macro-ref macro-name) " ")))
1032 (save-excursion
1033 (let ((target-name (makefile-browser-this-line-target-name)))
1034 (set-buffer makefile-browser-client)
1035 (insert target-name " ")))))
1036
1037 (defun makefile-browser-start-interaction ()
1038 (use-local-map makefile-browser-map)
1039 (setq buffer-read-only t))
1040
1041 (defun makefile-browse (targets macros)
1042 (interactive)
1043 (if (zerop (+ (length targets) (length macros)))
1044 (progn
1045 (beep)
1046 (message "No macros or targets to browse! Consider running 'makefile-pickup-everything\'"))
1047 (let ((browser-buffer (get-buffer-create makefile-browser-buffer-name)))
1048 (pop-to-buffer browser-buffer)
1049 (make-variable-buffer-local 'makefile-browser-selection-vector)
1050 (makefile-browser-fill targets macros)
1051 (shrink-window-if-larger-than-buffer)
1052 (setq makefile-browser-selection-vector
1053 (make-vector (+ (length targets) (length macros)) nil))
1054 (makefile-browser-start-interaction))))
1055
1056 (defun makefile-switch-to-browser ()
1057 (interactive)
1058 (run-hooks 'makefile-browser-hook)
1059 (setq makefile-browser-client (current-buffer))
1060 (makefile-pickup-targets)
1061 (makefile-pickup-macros)
1062 (makefile-browse makefile-target-table makefile-macro-table))
1063
1064 \f
1065
1066 ;;; ------------------------------------------------------------
1067 ;;; Up-to-date overview buffer
1068 ;;; ------------------------------------------------------------
1069
1070 (defun makefile-create-up-to-date-overview ()
1071 "Create a buffer containing an overview of the state of all known targets.
1072 Known targets are targets that are explicitly defined in that makefile;
1073 in other words, all targets that appear on the left hand side of a
1074 dependency in the makefile."
1075 (interactive)
1076 (if (y-or-n-p "Are you sure that the makefile being edited is consistent? ")
1077 ;;
1078 ;; The rest of this function operates on a temporary makefile, created by
1079 ;; writing the current contents of the makefile buffer.
1080 ;;
1081 (let ((saved-target-table makefile-target-table)
1082 (this-buffer (current-buffer))
1083 (makefile-up-to-date-buffer
1084 (get-buffer-create makefile-up-to-date-buffer-name))
1085 (filename (makefile-save-temporary))
1086 ;;
1087 ;; Forget the target table because it may contain picked-up filenames
1088 ;; that are not really targets in the current makefile.
1089 ;; We don't want to query these, so get a new target-table with just the
1090 ;; targets that can be found in the makefile buffer.
1091 ;; The 'old' target table will be restored later.
1092 ;;
1093 (real-targets (progn
1094 (makefile-pickup-targets)
1095 makefile-target-table))
1096 (prereqs makefile-has-prereqs)
1097 )
1098
1099 (set-buffer makefile-up-to-date-buffer)
1100 (setq buffer-read-only nil)
1101 (erase-buffer)
1102 (makefile-query-targets filename real-targets prereqs)
1103 (if (zerop (buffer-size)) ; if it did not get us anything
1104 (progn
1105 (kill-buffer (current-buffer))
1106 (message "No overview created!")))
1107 (set-buffer this-buffer)
1108 (setq makefile-target-table saved-target-table)
1109 (if (get-buffer makefile-up-to-date-buffer-name)
1110 (progn
1111 (pop-to-buffer (get-buffer makefile-up-to-date-buffer-name))
1112 (shrink-window-if-larger-than-buffer)
1113 (sort-lines nil (point-min) (point-max))
1114 (setq buffer-read-only t))))))
1115
1116 (defun makefile-save-temporary ()
1117 "Create a temporary file from the current makefile buffer."
1118 (let ((filename (makefile-generate-temporary-filename)))
1119 (write-region (point-min) (point-max) filename nil 0)
1120 filename)) ; return the filename
1121
1122 (defun makefile-generate-temporary-filename ()
1123 "Create a filename suitable for use in `makefile-save-temporary'.
1124 Be careful to allow brain-dead file systems (DOS, SYSV ...) to cope
1125 with the generated name!"
1126 (let ((my-name (user-login-name))
1127 (my-uid (int-to-string (user-uid))))
1128 (concat "mktmp"
1129 (if (> (length my-name) 3)
1130 (substring my-name 0 3)
1131 my-name)
1132 "."
1133 (if (> (length my-uid) 3)
1134 (substring my-uid 0 3)
1135 my-uid))))
1136
1137 (defun makefile-query-targets (filename target-table prereq-list)
1138 "Fill the up-to-date overview buffer.
1139 Checks each target in TARGET-TABLE using `makefile-query-one-target-method'
1140 and generates the overview, one line per target name."
1141 (insert
1142 (mapconcat
1143 (function (lambda (item)
1144 (let* ((target-name (car item))
1145 (no-prereqs (not (member target-name prereq-list)))
1146 (needs-rebuild (or no-prereqs
1147 (funcall
1148 makefile-query-one-target-method
1149 target-name
1150 filename))))
1151 (format "\t%s%s"
1152 target-name
1153 (cond (no-prereqs " .. has no prerequisites")
1154 (needs-rebuild " .. NEEDS REBUILD")
1155 (t " .. is up to date"))))
1156 ))
1157 target-table "\n"))
1158 (goto-char (point-min))
1159 (delete-file filename)) ; remove the tmpfile
1160
1161 (defun makefile-query-by-make-minus-q (target &optional filename)
1162 (not (zerop
1163 (call-process makefile-brave-make nil nil nil
1164 "-f" filename "-q" target))))
1165
1166 \f
1167
1168 ;;; ------------------------------------------------------------
1169 ;;; Continuation cleanup
1170 ;;; ------------------------------------------------------------
1171
1172 (defun makefile-cleanup-continuations ()
1173 (if (eq major-mode 'makefile-mode)
1174 (if (and makefile-cleanup-continuations-p
1175 (not buffer-read-only))
1176 (save-excursion
1177 (goto-char (point-min))
1178 (while (re-search-forward "\\\\[ \t]+$" (point-max) t)
1179 (replace-match "\\" t t))))))
1180
1181
1182 ;;; ------------------------------------------------------------
1183 ;;; Warn of suspicious lines
1184 ;;; ------------------------------------------------------------
1185
1186 (defun makefile-warn-suspicious-lines ()
1187 (let ((dont-save nil))
1188 (if (eq major-mode 'makefile-mode)
1189 (let ((suspicious
1190 (save-excursion
1191 (goto-char (point-min))
1192 (re-search-forward
1193 "\\(^[\t]+$\\)\\|\\(^[ ]+[\t]\\)" (point-max) t))))
1194 (if suspicious
1195 (let ((line-nr (count-lines (point-min) suspicious)))
1196 (setq dont-save
1197 (not (y-or-n-p
1198 (format "Suspicious line %d. Save anyway "
1199 line-nr))))))))
1200 dont-save))
1201
1202 \f
1203
1204 ;;; ------------------------------------------------------------
1205 ;;; GNU make function support
1206 ;;; ------------------------------------------------------------
1207
1208 (defun makefile-insert-gmake-function ()
1209 "Insert a GNU make function call.
1210 Asks for the name of the function to use (with completion).
1211 Then prompts for all required parameters."
1212 (interactive)
1213 (let* ((gm-function-name (completing-read
1214 "Function: "
1215 makefile-gnumake-functions-alist
1216 nil t nil))
1217 (gm-function-prompts
1218 (cdr (assoc gm-function-name makefile-gnumake-functions-alist))))
1219 (if (not (zerop (length gm-function-name)))
1220 (insert (makefile-format-macro-ref
1221 (concat gm-function-name " "
1222 (makefile-prompt-for-gmake-funargs
1223 gm-function-name gm-function-prompts)))
1224 " "))))
1225
1226 (defun makefile-prompt-for-gmake-funargs (function-name prompt-list)
1227 (mapconcat
1228 (function (lambda (one-prompt)
1229 (read-string (format "[%s] %s: " function-name one-prompt)
1230 nil)))
1231 prompt-list
1232 ","))
1233
1234 \f
1235
1236 ;;; ------------------------------------------------------------
1237 ;;; Utility functions
1238 ;;; ------------------------------------------------------------
1239
1240 (defun makefile-do-macro-insertion (macro-name)
1241 "Insert a macro reference."
1242 (if (not (zerop (length macro-name)))
1243 (if (assoc macro-name makefile-runtime-macros-list)
1244 (insert "$" macro-name)
1245 (insert (makefile-format-macro-ref macro-name)))))
1246
1247 (defun makefile-remember-target (target-name &optional has-prereqs)
1248 "Remember a given target if it is not already remembered for this buffer."
1249 (if (not (zerop (length target-name)))
1250 (progn
1251 (if (not (assoc target-name makefile-target-table))
1252 (setq makefile-target-table
1253 (cons (list target-name) makefile-target-table)))
1254 (if has-prereqs
1255 (setq makefile-has-prereqs
1256 (cons target-name makefile-has-prereqs))))))
1257
1258 (defun makefile-remember-macro (macro-name)
1259 "Remember a given macro if it is not already remembered for this buffer."
1260 (if (not (zerop (length macro-name)))
1261 (if (not (assoc macro-name makefile-macro-table))
1262 (setq makefile-macro-table
1263 (cons (list macro-name) makefile-macro-table)))))
1264
1265 (defun makefile-forward-after-target-colon ()
1266 "Move point forward after inserting the terminating colon of a target.
1267 This acts according to the value of `makefile-tab-after-target-colon'."
1268 (if makefile-tab-after-target-colon
1269 (insert "\t")
1270 (insert " ")))
1271
1272 (defun makefile-browser-on-macro-line-p ()
1273 "Determine if point is on a macro line in the browser."
1274 (save-excursion
1275 (beginning-of-line)
1276 (re-search-forward "\\$[{(]" (makefile-end-of-line-point) t)))
1277
1278 (defun makefile-browser-this-line-target-name ()
1279 "Extract the target name from a line in the browser."
1280 (save-excursion
1281 (end-of-line)
1282 (skip-chars-backward "^ \t")
1283 (buffer-substring (point) (1- (makefile-end-of-line-point)))))
1284
1285 (defun makefile-browser-this-line-macro-name ()
1286 "Extract the macro name from a line in the browser."
1287 (save-excursion
1288 (beginning-of-line)
1289 (re-search-forward "\\$[{(]" (makefile-end-of-line-point) t)
1290 (let ((macro-start (point)))
1291 (skip-chars-forward "^})")
1292 (buffer-substring macro-start (point)))))
1293
1294 (defun makefile-format-macro-ref (macro-name)
1295 "Format a macro reference.
1296 Uses `makefile-use-curly-braces-for-macros-p'."
1297 (if (or (char-equal ?\( (string-to-char macro-name))
1298 (char-equal ?\{ (string-to-char macro-name)))
1299 (format "$%s" macro-name)
1300 (if makefile-use-curly-braces-for-macros-p
1301 (format "${%s}" macro-name)
1302 (format "$(%s)" macro-name))))
1303
1304 (defun makefile-browser-get-state-for-line (n)
1305 (aref makefile-browser-selection-vector (1- n)))
1306
1307 (defun makefile-browser-set-state-for-line (n to-state)
1308 (aset makefile-browser-selection-vector (1- n) to-state))
1309
1310 (defun makefile-browser-toggle-state-for-line (n)
1311 (makefile-browser-set-state-for-line n (not (makefile-browser-get-state-for-line n))))
1312
1313 (defun makefile-beginning-of-line-point ()
1314 (save-excursion
1315 (beginning-of-line)
1316 (point)))
1317
1318 (defun makefile-end-of-line-point ()
1319 (save-excursion
1320 (end-of-line)
1321 (point)))
1322
1323 (defun makefile-last-line-p ()
1324 (= (makefile-end-of-line-point) (point-max)))
1325
1326 (defun makefile-first-line-p ()
1327 (= (makefile-beginning-of-line-point) (point-min)))
1328
1329 \f
1330
1331 ;;; Support for other packages, like add-log and imenu.
1332
1333 (defun makefile-add-log-defun ()
1334 "Return name of target or variable assignment that point is in.
1335 If it isn't in one, return nil."
1336 (save-excursion
1337 (let (found)
1338 (beginning-of-line)
1339 ;; Scan back line by line, noticing when we come to a
1340 ;; variable or rule definition, and giving up when we see
1341 ;; a line that is not part of either of those.
1342 (while (not found)
1343 (cond
1344 ((looking-at makefile-macroassign-regex)
1345 (setq found (buffer-substring-no-properties (match-beginning 1)
1346 (match-end 1))))
1347 ((looking-at makefile-dependency-regex)
1348 (setq found (buffer-substring-no-properties (match-beginning 1)
1349 (match-end 1))))
1350 ;; Don't keep looking across a blank line or comment. Give up.
1351 ((looking-at "$\\|#")
1352 (setq found 'bobp))
1353 ((bobp)
1354 (setq found 'bobp)))
1355 (or found
1356 (forward-line -1)))
1357 (if (stringp found) found))))
1358
1359 ;; FIXME it might be nice to have them separated by macro vs target.
1360 (defun makefile-menu-index-function ()
1361 ;; "Generate alist of indices for imenu."
1362 (let (alist
1363 stupid
1364 (re (concat makefile-dependency-regex
1365 "\\|"
1366 makefile-macroassign-regex)))
1367 (imenu-progress-message stupid 0)
1368 (goto-char (point-min))
1369 (while (re-search-forward re nil t)
1370 (imenu-progress-message stupid)
1371 (let ((n (if (match-beginning 1) 1 5)))
1372 (setq alist (cons
1373 (cons (buffer-substring (match-beginning n)
1374 (match-end n))
1375 (match-beginning n))
1376 alist))))
1377 (imenu-progress-message stupid 100)
1378 (nreverse alist)))
1379
1380 (defun makefile-define-space-face ()
1381 (make-face 'makefile-space-face)
1382 (or (not (eq window-system 'x))
1383 (face-differs-from-default-p 'makefile-space-face)
1384 (let* ((params (frame-parameters))
1385 (light-bg (cdr (assq 'background-mode params)))
1386 (bg-color (cond ((eq (cdr (assq 'display-type params)) 'mono)
1387 (if light-bg "black" "white"))
1388 ((eq (cdr (assq 'display-type params)) 'grayscale)
1389 (if light-bg "black" "white"))
1390 (light-bg ; Light color background.
1391 "hotpink")
1392 (t ; Dark color background.
1393 "hotpink"))))
1394 (set-face-background 'makefile-space-face bg-color))))
1395
1396 ;;; make-mode.el ends here