comparison lisp/progmodes/make-mode.el @ 2559:5f2c2994cbca

Rewritten and simplified, commentary added. It now will usually detect when the makefile target or macro lists need to be rebuilt and do it automatically; in particular, this means you no longer have to deal with an annoying wait at find-time.
author Eric S. Raymond <esr@snark.thyrsus.com>
date Wed, 21 Apr 1993 03:47:05 +0000
parents 0099d6be2b11
children 09647458cad9
comparison
equal deleted inserted replaced
2558:78a9cebdb22c 2559:5f2c2994cbca
1 ;;; makefile.el --- makefile editing commands for Emacs 1 ;;; makefile.el --- makefile editing commands for Emacs
2 2
3 ;; Copyright (C) 1992 Free Software Foundation, Inc. 3 ;; Copyright (C) 1992 Free Software Foundation, Inc.
4 4
5 ;; Author: Thomas Neumann <tom@smart.bo.open.de> 5 ;; Author: Thomas Neumann <tom@smart.bo.open.de>
6 ;; Eric S. Raymond <esr@snark.thyrsus.com>
6 ;; Adapted-By: ESR 7 ;; Adapted-By: ESR
7 ;; Keywords: unix, tools 8 ;; Keywords: unix, tools
8 9
9 ;; $Id: makefile.el,v 1.5 1993/03/28 06:24:54 eric Exp rms $ 10 ;; $Id: makefile.el,v 1.3 1993/04/20 20:01:16 esr Exp $
10 11
11 ;; This file is part of GNU Emacs. 12 ;; This file is part of GNU Emacs.
12 13
13 ;; GNU Emacs is free software; you can redistribute it and/or modify 14 ;; GNU Emacs is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by 15 ;; it under the terms of the GNU General Public License as published by
24 ;; along with GNU Emacs; see the file COPYING. If not, write to 25 ;; along with GNU Emacs; see the file COPYING. If not, write to
25 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 26 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26 27
27 ;;; Commentary: 28 ;;; Commentary:
28 29
29 ;; A major mode for editing Makefiles. Hairy. Needs more documentation. 30 ;; A major mode for editing makefiles. The mode knows about Makefile
30 ;; If you get familiar with it, please write some and send it to the GNU 31 ;; syntax and defines M-n and M-p to move to next and previous productions.
31 ;; Emacs maintainers. 32 ;;
33 ;; The keys $, =, : and . are electric; they try to help you fill in a
34 ;; macro reference, macro definition, ordinary target name, or special
35 ;; target name, respectively. Such names are completed using a list of
36 ;; targets and macro names parsed out of the makefile. This list is
37 ;; automatically updated, if necessary, whenever you invoke one of
38 ;; these commands. You can force it to be updated with C-c C-p.
39 ;;
40 ;; The command C-c f adds certain filenames in the current directory
41 ;; as targets. You can filter out filenames by setting the variable
42 ;; makefile-ignored-files-in-pickup-regex.
43 ;;
44 ;; The command C-c C-u grinds for a bit, then pops up a report buffer
45 ;; showing which target names are up-to-date with respect to their
46 ;; prerequisites, which targets are out-of-date, and which have no
47 ;; prerequisites.
48 ;;
49 ;; The command C-c b pops up a browser window listing all target and
50 ;; macro names. You can mark or unmark items wit C-c SPC, and insert
51 ;; all marked items back in the Makefile with C-c TAB.
52 ;;
53 ;; The command C-c TAB in the makefile buffer inserts a GNU make builtin.
54 ;; You will be prompted for the builtin's args.
55 ;;
56 ;; There are numerous other customization variables.
32 57
33 ;;; Code: 58 ;;; Code:
34 59
35 (provide 'makefile) 60 (provide 'makefile)
36 61
37 ;;; ------------------------------------------------------------ 62 ;;; ------------------------------------------------------------
38 ;;; Configureable stuff 63 ;;; Configureable stuff
39 ;;; ------------------------------------------------------------ 64 ;;; ------------------------------------------------------------
40 65
41 (defvar makefile-mode-name "makefile" 66 (defconst makefile-mode-name "makefile"
42 "The \"pretty name\" of makefile-mode, as it 67 "The \"pretty name\" of makefile-mode, as it appears in the modeline.")
43 appears in the modeline.")
44 68
45 (defvar makefile-browser-buffer-name "*Macros and Targets*" 69 (defvar makefile-browser-buffer-name "*Macros and Targets*"
46 "Name of the macro- and target browser buffer.") 70 "Name of the macro- and target browser buffer.")
47 71
48 (defvar makefile-target-colon ":" 72 (defvar makefile-target-colon ":"
57 standard make expects. However, newer makes such as dmake 81 standard make expects. However, newer makes such as dmake
58 allow a larger variety of different macro assignments, so you 82 allow a larger variety of different macro assignments, so you
59 might prefer to use \" += \" or \" := \" .") 83 might prefer to use \" += \" or \" := \" .")
60 84
61 (defvar makefile-use-curly-braces-for-macros-p nil 85 (defvar makefile-use-curly-braces-for-macros-p nil
62 "Set this variable to a non-nil value if you prefer curly braces 86 "Controls the style of generated macro references.
63 in macro-references, so it looks like ${this}. A value of nil 87 Set this variable to a non-nil value if you prefer curly braces
88 in macro-references, so it looks like ${this}. A value of nil
64 will cause makefile-mode to use parantheses, making macro references 89 will cause makefile-mode to use parantheses, making macro references
65 look like $(this) .") 90 look like $(this) .")
66 91
67 (defvar makefile-tab-after-target-colon t 92 (defvar makefile-tab-after-target-colon t
68 "If you want a TAB (instead of a space) to be appended after the 93 "If you want a TAB (instead of a space) to be appended after the
80 105
81 (defvar makefile-browser-unselected-mark " " 106 (defvar makefile-browser-unselected-mark " "
82 "String used to mark unselected entries in the browser.") 107 "String used to mark unselected entries in the browser.")
83 108
84 (defvar makefile-browser-auto-advance-after-selection-p t 109 (defvar makefile-browser-auto-advance-after-selection-p t
85 "If this variable is set to a non-nil value the cursor 110 "If non-nil, the cursor will automagically advance to the next line after
86 will automagically advance to the next line after an item 111 an item has been selected in the browser.")
87 has been selected in the browser.")
88
89 (defvar makefile-find-file-autopickup-p t
90 "If this variable is set to a non-nil value then finding a file in
91 a makefile-mode buffer will cause an automatic initial pickup of
92 all macros and targets from the found file.")
93 112
94 (defvar makefile-pickup-everything-picks-up-filenames-p nil 113 (defvar makefile-pickup-everything-picks-up-filenames-p nil
95 "If this variable is set to a non-nil value then 114 "If non-nil, makefile-pickup-everything also picks up filenames as targets
96 makefile-pickup-everything also picks up filenames as targets 115 (i.e. it calls makefile-find-filenames-as-targets), otherwise filenames are
97 (i.e. it calls makefile-find-filenames-as-targets), otherwise 116 omitted.")
98 filenames are omitted.")
99 117
100 (defvar makefile-cleanup-continuations-p t 118 (defvar makefile-cleanup-continuations-p t
101 "If this variable is set to a non-nil value then makefile-mode 119 "If non-nil, makefile-mode will assure that no line in the file ends with a
102 will assure that no line in the file ends with a backslash 120 backslash (the continuation character) followed by any whitespace. This is
103 (the continuation character) followed by any whitespace. 121 done by silently removing the trailing whitespace, leaving the backslash itself
104 This is done by silently removing the trailing whitespace, leaving 122 intact. IMPORTANT: Please note that enabling this option causes makefile-mode
105 the backslash itself intact.
106 IMPORTANT: Please note that enabling this option causes makefile-mode
107 to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \'it seems necessary\'.") 123 to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \'it seems necessary\'.")
108 124
109 (defvar makefile-browser-hook '() 125 (defvar makefile-browser-hook '()
110 "A function or list of functions to be called just before the 126 "A function or list of functions to be called just before the
111 browser is entered. This is executed in the makefile buffer, so 127 browser is entered. This is executed in the makefile buffer.")
112 you can for example run a makefile-pickup-everything automatically.")
113 128
114 ;; 129 ;;
115 ;; Special targets for DMake, Sun's make ... 130 ;; Special targets for DMake, Sun's make ...
116 ;; 131 ;;
117 (defvar makefile-special-targets-list 132 (defvar makefile-special-targets-list
133 If you insert a macro reference using makefile-insert-macro-ref, the name 148 If you insert a macro reference using makefile-insert-macro-ref, the name
134 of the macro is checked against this list. If it can be found its name will 149 of the macro is checked against this list. If it can be found its name will
135 not be enclosed in { } or ( ).") 150 not be enclosed in { } or ( ).")
136 151
137 (defconst makefile-dependency-regex 152 (defconst makefile-dependency-regex
138 "^[^ \t#:]+\\([ \t]+[^ \t#:]+\\)*[ \t]*:\\($\\|\\([^=].*$\\)\\)" 153 "^[^ \t#:]+\\([ \t]+[^ \t#:]+\\)*[ \t]*:\\([ \t]*$\\|\\([^=\n].*$\\)\\)"
139 "Regex used to find dependency lines in a makefile.") 154 "Regex used to find dependency lines in a makefile.")
140 155
141 (defconst makefile-macroassign-regex 156 (defconst makefile-macroassign-regex
142 "^[^ \t][^:#=]*[\\*:\\+]?:?=.*$" 157 "^[^ \t][^:#=]*[\\*:\\+]?:?=.*$"
143 "Regex used to find macro assignment lines in a makefile.") 158 "Regex used to find macro assignment lines in a makefile.")
144 159
145 (defconst makefile-ignored-files-in-pickup-regex 160 (defconst makefile-ignored-files-in-pickup-regex
146 "\\(^\\..*\\)\\|\\(.*~$\\)\\|\\(.*,v$\\)" 161 "\\(^\\..*\\)\\|\\(.*~$\\)\\|\\(.*,v$\\)\\|(\\.[chy]\\)"
147 "Regex for filenames that will NOT be included in the target list.") 162 "Regex for filenames that will NOT be included in the target list.")
148 163
149 ;;; ------------------------------------------------------------ 164 ;;; ------------------------------------------------------------
150 ;;; The following configurable variables are used in the 165 ;;; The following configurable variables are used in the
151 ;;; up-to-date overview . 166 ;;; up-to-date overview .
156 ;;; make -q foo 171 ;;; make -q foo
157 ;;; 172 ;;;
158 ;;; should return an exit status of zero if the target `foo' is 173 ;;; should return an exit status of zero if the target `foo' is
159 ;;; up to date and a nonzero exit status otherwise. 174 ;;; up to date and a nonzero exit status otherwise.
160 ;;; Many makes can do this although the docs/manpages do not mention 175 ;;; Many makes can do this although the docs/manpages do not mention
161 ;;; it. Try it with your favourite one. GNU make and Dennis Vaduras 176 ;;; it. Try it with your favourite one. GNU make, System V make, and
162 ;;; DMake have no problems. 177 ;;; Dennis Vadura's DMake have no problems.
163 ;;; Set the variable `makefile-brave-make' to the name of the 178 ;;; Set the variable `makefile-brave-make' to the name of the
164 ;;; make utility that does this on your system. 179 ;;; make utility that does this on your system.
165 ;;; To understand what this is all about see the function defintion 180 ;;; To understand what this is all about see the function defintion
166 ;;; of `makefile-query-by-make-minus-q' . 181 ;;; of `makefile-query-by-make-minus-q' .
167 ;;; ------------------------------------------------------------ 182 ;;; ------------------------------------------------------------
168 183
169 (defvar makefile-brave-make "gmake" 184 (defvar makefile-brave-make "make"
170 "A make that can handle the \'-q\' option.") 185 "A make that can handle the \'-q\' option.")
171 186
172 (defvar makefile-query-one-target-method 'makefile-query-by-make-minus-q 187 (defvar makefile-query-one-target-method 'makefile-query-by-make-minus-q
173 "A function symbol [one that can be used as the first argument to 188 "A function symbol [one that can be used as the first argument to
174 funcall] that provides a function that must conform to the following 189 funcall] that provides a function that must conform to the following
176 191
177 * As its first argument, it must accept the name of the target to 192 * As its first argument, it must accept the name of the target to
178 be checked, as a string. 193 be checked, as a string.
179 194
180 * As its second argument, it may accept the name of a makefile 195 * As its second argument, it may accept the name of a makefile
181 as a string. Depending on what you\'re going to do you may 196 as a string. Depending on what you're going to do you may
182 not need this. 197 not need this.
183 198
184 * It must return the integer value 0 (zero) if the given target 199 * It must return the integer value 0 (zero) if the given target
185 should be considered up-to-date in the context of the given 200 should be considered up-to-date in the context of the given
186 makefile, any nonzero integer value otherwise.") 201 makefile, any nonzero integer value otherwise.")
187 202
188 (defvar makefile-up-to-date-buffer-name "*Makefile Up-to-date overview*" 203 (defvar makefile-up-to-date-buffer-name "*Makefile Up-to-date overview*"
189 "Name of the Up-to-date overview buffer.") 204 "Name of the Up-to-date overview buffer.")
190 205
191 (defvar makefile-target-needs-rebuild-mark " .. NEEDS REBUILD"
192 "A string that is appended to the target name in the up-to-date
193 overview if that target is considered to require a rebuild.")
194
195 (defvar makefile-target-up-to-date-mark " .. is up to date"
196 "A string that is appenden to the target name in the up-to-date
197 overview if that target is considered up-to-date.")
198
199 ;;; --- end of up-to-date-overview configuration ------------------ 206 ;;; --- end of up-to-date-overview configuration ------------------
200
201 207
202 (defvar makefile-mode-map nil 208 (defvar makefile-mode-map nil
203 "The keymap that is used in makefile-mode.") 209 "The keymap that is used in makefile-mode.")
204 (if makefile-mode-map 210 (if makefile-mode-map
205 () 211 ()
208 (define-key makefile-mode-map "$" 'makefile-insert-macro-ref) 214 (define-key makefile-mode-map "$" 'makefile-insert-macro-ref)
209 (define-key makefile-mode-map "\C-c:" 'makefile-insert-target-ref) 215 (define-key makefile-mode-map "\C-c:" 'makefile-insert-target-ref)
210 (define-key makefile-mode-map ":" 'makefile-electric-colon) 216 (define-key makefile-mode-map ":" 'makefile-electric-colon)
211 (define-key makefile-mode-map "=" 'makefile-electric-equal) 217 (define-key makefile-mode-map "=" 'makefile-electric-equal)
212 (define-key makefile-mode-map "." 'makefile-electric-dot) 218 (define-key makefile-mode-map "." 'makefile-electric-dot)
213 (define-key makefile-mode-map "\C-c\C-t" 'makefile-pickup-targets)
214 (define-key makefile-mode-map "\C-c\C-m" 'makefile-pickup-macros)
215 (define-key makefile-mode-map "\C-c\C-f" 'makefile-pickup-filenames-as-targets) 219 (define-key makefile-mode-map "\C-c\C-f" 'makefile-pickup-filenames-as-targets)
216 (define-key makefile-mode-map "\C-c\C-0" 'makefile-forget-everything)
217 (define-key makefile-mode-map "\C-c0" 'makefile-forget-everything)
218 (define-key makefile-mode-map "\C-c\C-b" 'makefile-switch-to-browser) 220 (define-key makefile-mode-map "\C-c\C-b" 'makefile-switch-to-browser)
219 (define-key makefile-mode-map "\C-c\C-p" 'makefile-pickup-everything) 221 (define-key makefile-mode-map "\C-c\C-p" 'makefile-pickup-everything)
220 (define-key makefile-mode-map "\C-c\C-u" 'makefile-create-up-to-date-overview) 222 (define-key makefile-mode-map "\C-c\C-u" 'makefile-create-up-to-date-overview)
221 (define-key makefile-mode-map "\C-c\C-i" 'makefile-insert-gmake-function) 223 (define-key makefile-mode-map "\C-c\C-i" 'makefile-insert-gmake-function)
222 (define-key makefile-mode-map "\M-p" 'makefile-previous-dependency) 224 (define-key makefile-mode-map "\M-p" 'makefile-previous-dependency)
273 275
274 (defvar makefile-browser-client 276 (defvar makefile-browser-client
275 "A buffer in makefile-mode that is currently using the browser.") 277 "A buffer in makefile-mode that is currently using the browser.")
276 278
277 (defvar makefile-browser-selection-vector nil) 279 (defvar makefile-browser-selection-vector nil)
280 (defvar makefile-has-prereqs nil)
281 (defvar makefile-need-target-pickup t)
282 (defvar makefile-need-macro-pickup t)
278 283
279 (defvar makefile-mode-hook '()) 284 (defvar makefile-mode-hook '())
280 285
281 (defconst makefile-gnumake-functions-alist 286 (defconst makefile-gnumake-functions-alist
282
283 '( 287 '(
284 ;; Text functions 288 ;; Text functions
285 ("subst" "From" "To" "In") 289 ("subst" "From" "To" "In")
286 ("patsubst" "Pattern" "Replacement" "In") 290 ("patsubst" "Pattern" "Replacement" "In")
287 ("strip" "Text") 291 ("strip" "Text")
368 makefile-browser-auto-advance-after-selection-p: 372 makefile-browser-auto-advance-after-selection-p:
369 If this variable is set to a non-nil value the cursor 373 If this variable is set to a non-nil value the cursor
370 will automagically advance to the next line after an item 374 will automagically advance to the next line after an item
371 has been selected in the browser. 375 has been selected in the browser.
372 376
373 makefile-find-file-autopickup-p:
374 If this variable is set to a non-nil value then finding a file in
375 a makefile-mode buffer will cause an automatic initial pickup of
376 all macros and targets from the found file.
377
378 makefile-pickup-everything-picks-up-filenames-p: 377 makefile-pickup-everything-picks-up-filenames-p:
379 If this variable is set to a non-nil value then 378 If this variable is set to a non-nil value then
380 makefile-pickup-everything also picks up filenames as targets 379 makefile-pickup-everything also picks up filenames as targets
381 (i.e. it calls makefile-find-filenames-as-targets), otherwise 380 (i.e. it calls makefile-find-filenames-as-targets), otherwise
382 filenames are omitted. 381 filenames are omitted.
390 IMPORTANT: Please note that enabling this option causes makefile-mode 389 IMPORTANT: Please note that enabling this option causes makefile-mode
391 to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \'it seems necessary\'. 390 to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \'it seems necessary\'.
392 391
393 makefile-browser-hook: 392 makefile-browser-hook:
394 A function or list of functions to be called just before the 393 A function or list of functions to be called just before the
395 browser is entered. This is executed in the makefile buffer, so 394 browser is entered. This is executed in the makefile buffer.
396 you can for example run a makefile-pickup-everything automatically.
397 395
398 makefile-special-targets-list: 396 makefile-special-targets-list:
399 List of special targets. You will be offered to complete 397 List of special targets. You will be offered to complete
400 on one of those in the minibuffer whenever you enter a \".\" 398 on one of those in the minibuffer whenever you enter a \".\"
401 at the beginning of a line in makefile-mode." 399 at the beginning of a line in makefile-mode."
402 (interactive) 400 (interactive)
403 (kill-all-local-variables) 401 (kill-all-local-variables)
404 (if (not (memq 'makefile-find-file-autopickup find-file-hooks))
405 (setq find-file-hooks
406 (append find-file-hooks (list 'makefile-find-file-autopickup))))
407 (if (not (memq 'makefile-cleanup-continuations write-file-hooks)) 402 (if (not (memq 'makefile-cleanup-continuations write-file-hooks))
408 (setq write-file-hooks 403 (setq write-file-hooks
409 (append write-file-hooks (list 'makefile-cleanup-continuations)))) 404 (append write-file-hooks (list 'makefile-cleanup-continuations))))
410 (make-variable-buffer-local 'makefile-target-table) 405 (make-variable-buffer-local 'makefile-target-table)
411 (make-variable-buffer-local 'makefile-macro-table) 406 (make-variable-buffer-local 'makefile-macro-table)
412 (makefile-forget-all-macros) 407 (make-variable-buffer-local 'makefile-has-prereqs)
413 (makefile-forget-all-targets) 408 (make-variable-buffer-local 'makefile-need-target-pickup)
409 (make-variable-buffer-local 'makefile-need-macro-pickup)
414 (setq comment-start "#") 410 (setq comment-start "#")
415 (setq comment-end "") 411 (setq comment-end "")
416 (setq comment-start-skip "#[ \t]*") 412 (setq comment-start-skip "#[ \t]*")
417 ;; become the current major mode 413 ;; become the current major mode
418 (setq major-mode 'makefile-mode) 414 (setq major-mode 'makefile-mode)
420 ;; activate keymap 416 ;; activate keymap
421 (use-local-map makefile-mode-map) 417 (use-local-map makefile-mode-map)
422 (set-syntax-table makefile-mode-syntax-table) 418 (set-syntax-table makefile-mode-syntax-table)
423 (run-hooks 'makefile-mode-hook)) 419 (run-hooks 'makefile-mode-hook))
424 420
425
426 (defun makefile-find-file-autopickup ()
427 (if (eq major-mode 'makefile-mode)
428 (if makefile-find-file-autopickup-p
429 (makefile-pickup-everything))))
430
431 (defun makefile-next-dependency () 421 (defun makefile-next-dependency ()
432 "Move (point) to the beginning of the next dependency line 422 "Move (point) to the beginning of the next dependency line below (point)."
433 below the current position of (point)."
434 (interactive) 423 (interactive)
435 (let ((here (point))) 424 (let ((here (point)))
436 (end-of-line) 425 (end-of-line)
437 (if (re-search-forward makefile-dependency-regex (point-max) t) 426 (if (re-search-forward makefile-dependency-regex (point-max) t)
438 (progn (beginning-of-line) t) ; indicate success 427 (progn (beginning-of-line) t) ; indicate success
439 (goto-char here) nil))) 428 (goto-char here) nil)))
440 429
441 (defun makefile-previous-dependency () 430 (defun makefile-previous-dependency ()
442 "Move (point) to the beginning of the next dependency line 431 "Move (point) to the beginning of the next dependency line above (point)."
443 above the current position of (point)."
444 (interactive) 432 (interactive)
445 (let ((here (point))) 433 (let ((here (point)))
446 (beginning-of-line) 434 (beginning-of-line)
447 (if (re-search-backward makefile-dependency-regex (point-min) t) 435 (if (re-search-backward makefile-dependency-regex (point-min) t)
448 (progn (beginning-of-line) t) ; indicate success 436 (progn (beginning-of-line) t) ; indicate success
449 (goto-char here) nil))) 437 (goto-char here) nil)))
450 438
451 439
440 ;;; Stuff below here depends on the pickup state
441
452 (defun makefile-electric-dot () 442 (defun makefile-electric-dot ()
453 "At (bol), offer completion on makefile-special-targets-list. 443 "At (bol), offer completion on makefile-special-targets-list.
454 Anywhere else just insert a dot." 444 Anywhere else just insert a dot."
455 (interactive) 445 (interactive)
456 (if (bolp) 446 (if (bolp)
457 (makefile-insert-special-target) 447 (makefile-insert-special-target)
458 (insert "."))) 448 (insert ".")))
459 449
460
461 (defun makefile-insert-special-target () 450 (defun makefile-insert-special-target ()
462 "Offer completion on makefile-special-targets-list and insert 451 "Complete on makefile-special-targets-list, insert result at (point)."
463 the result at (point)." 452 (interactive)
464 (interactive) 453 (makefile-pickup-targets)
465 (let 454 (let
466 ((special-target 455 ((special-target
467 (completing-read "Special target: " 456 (completing-read "Special target: "
468 makefile-special-targets-list nil nil nil))) 457 makefile-special-targets-list nil nil nil)))
469 (if (zerop (length special-target)) 458 (if (zerop (length special-target))
470 () 459 ()
471 (insert (format ".%s:" special-target)) 460 (insert (format ".%s:" special-target))
472 (makefile-forward-after-target-colon)))) 461 (makefile-forward-after-target-colon))))
473 462
474
475 (defun makefile-electric-equal () 463 (defun makefile-electric-equal ()
476 "At (bol) do makefile-insert-macro. Anywhere else just 464 "At (bol) do makefile-insert-macro. Anywhere else just self-insert."
477 self-insert." 465 (interactive)
478 (interactive) 466 (makefile-pickup-macros)
479 (if (bolp) 467 (if (bolp)
480 (call-interactively 'makefile-insert-macro) 468 (call-interactively 'makefile-insert-macro)
481 (insert "="))) 469 (insert "=")))
482 470
483 (defun makefile-insert-macro (macro-name) 471 (defun makefile-insert-macro (macro-name)
484 "Prepare definition of a new macro." 472 "Prepare definition of a new macro."
485 (interactive "sMacro Name: ") 473 (interactive "sMacro Name: ")
474 (makefile-pickup-macros)
486 (if (not (zerop (length macro-name))) 475 (if (not (zerop (length macro-name)))
487 (progn 476 (progn
488 (beginning-of-line) 477 (beginning-of-line)
489 (insert (format "%s%s" macro-name makefile-macro-assign)) 478 (insert (format "%s%s" macro-name makefile-macro-assign))
479 (setq makefile-need-macro-pickup t)
490 (makefile-remember-macro macro-name)))) 480 (makefile-remember-macro macro-name))))
491 481
492
493 (defun makefile-insert-macro-ref (macro-name) 482 (defun makefile-insert-macro-ref (macro-name)
494 "Offer completion on a list of known macros, then 483 "Complete on a list of known macros, then insert complete ref at (point)."
495 insert complete macro-ref at (point) ."
496 (interactive 484 (interactive
497 (list 485 (list
498 (completing-read "Refer to macro: " makefile-macro-table nil nil nil))) 486 (progn
487 (makefile-pickup-macros)
488 (completing-read "Refer to macro: " makefile-macro-table nil nil nil))))
499 (if (not (zerop (length macro-name))) 489 (if (not (zerop (length macro-name)))
500 (if (assoc macro-name makefile-runtime-macros-list) 490 (if (assoc macro-name makefile-runtime-macros-list)
501 (insert (format "$%s " macro-name)) 491 (insert (format "$%s " macro-name))
502 (insert (makefile-format-macro-ref macro-name) " ")))) 492 (insert (makefile-format-macro-ref macro-name) " "))))
503
504 493
505 (defun makefile-insert-target (target-name) 494 (defun makefile-insert-target (target-name)
506 "Prepare definition of a new target (dependency line)." 495 "Prepare definition of a new target (dependency line)."
507 (interactive "sTarget: ") 496 (interactive "sTarget: ")
508 (if (not (zerop (length target-name))) 497 (if (not (zerop (length target-name)))
509 (progn 498 (progn
510 (beginning-of-line) 499 (beginning-of-line)
511 (insert (format "%s%s" target-name makefile-target-colon)) 500 (insert (format "%s%s" target-name makefile-target-colon))
512 (makefile-forward-after-target-colon) 501 (makefile-forward-after-target-colon)
513 (end-of-line) 502 (end-of-line)
503 (setq makefile-need-target-pickup t)
514 (makefile-remember-target target-name)))) 504 (makefile-remember-target target-name))))
515 505
516
517 (defun makefile-insert-target-ref (target-name) 506 (defun makefile-insert-target-ref (target-name)
518 "Offer completion on a list of known targets, then 507 "Complete on a list of known targets, then insert target-ref at (point) ."
519 insert complete target-ref at (point) ."
520 (interactive 508 (interactive
521 (list 509 (list
522 (completing-read "Refer to target: " makefile-target-table nil nil nil))) 510 (pogn
511 (makefile-pickup-targets)
512 (completing-read "Refer to target: " makefile-target-table nil nil nil))))
523 (if (not (zerop (length target-name))) 513 (if (not (zerop (length target-name)))
524 (progn 514 (progn
525 (insert (format "%s " target-name))))) 515 (insert (format "%s " target-name)))))
526 516
527 (defun makefile-electric-colon () 517 (defun makefile-electric-colon ()
529 (interactive) 519 (interactive)
530 (if (bolp) 520 (if (bolp)
531 (call-interactively 'makefile-insert-target) 521 (call-interactively 'makefile-insert-target)
532 (insert ":"))) 522 (insert ":")))
533 523
534
535 ;;; ------------------------------------------------------------ 524 ;;; ------------------------------------------------------------
536 ;;; Extracting targets and macros from an existing makefile 525 ;;; Extracting targets and macros from an existing makefile
537 ;;; ------------------------------------------------------------ 526 ;;; ------------------------------------------------------------
538 527
539 (defun makefile-pickup-targets () 528 (defun makefile-pickup-targets ()
540 "Scan a buffer that contains a makefile for target definitions (dependencies) 529 "Scan a buffer that contains a makefile for target definitions (dependencies)
541 and add them to the list of known targets." 530 and add them to the list of known targets."
542 (interactive) 531 (interactive)
543 (save-excursion 532 (if (not makefile-need-target-pickup)
544 (goto-char (point-min)) 533 nil
545 (while (re-search-forward makefile-dependency-regex (point-max) t) 534 (setq makefile-need-target-pickup nil)
546 (makefile-add-this-line-targets)))) 535 (setq makefile-target-table nil)
547 ; (forward-line 1)))) 536 (setq makefile-has-prereqs nil)
537 (save-excursion
538 (goto-char (point-min))
539 (while (re-search-forward makefile-dependency-regex (point-max) t)
540 (makefile-add-this-line-targets)))
541 (message "Read targets OK.")))
548 542
549 (defun makefile-add-this-line-targets () 543 (defun makefile-add-this-line-targets ()
550 (save-excursion 544 (save-excursion
551 (beginning-of-line) 545 (beginning-of-line)
552 (let ((done-with-line nil)) 546 (let ((done-with-line nil)
547 (line-number (1+ (count-lines (point-min) (point)))))
553 (while (not done-with-line) 548 (while (not done-with-line)
554 (skip-chars-forward " \t") 549 (skip-chars-forward " \t")
555 (if (not (setq done-with-line (or (eolp) 550 (if (not (setq done-with-line (or (eolp)
556 (char-equal (char-after (point)) ?:)))) 551 (char-equal (char-after (point)) ?:))))
557 (progn 552 (progn
558 (let* ((start-of-target-name (point)) 553 (let* ((start-of-target-name (point))
559 (target-name 554 (target-name
560 (progn 555 (progn
561 (skip-chars-forward "^ \t:#") 556 (skip-chars-forward "^ \t:#")
562 (buffer-substring start-of-target-name (point))))) 557 (buffer-substring start-of-target-name (point))))
563 (if (makefile-remember-target target-name) 558 (has-prereqs
564 (message "Picked up target \"%s\"" target-name))))))))) 559 (not (looking-at ":[ \t]*$"))))
560 (if (makefile-remember-target target-name has-prereqs)
561 (message "Picked up target \"%s\" from line %d"
562 target-name line-number)))))))))
565 563
566 564
567 (defun makefile-pickup-macros () 565 (defun makefile-pickup-macros ()
568 "Scan a buffer that contains a makefile for macro definitions 566 "Scan a buffer that contains a makefile for macro definitions
569 and add them to the list of known macros." 567 and add them to the list of known macros."
570 (interactive) 568 (interactive)
571 (save-excursion 569 (if (not makefile-need-macro-pickup)
572 (goto-char (point-min)) 570 nil
573 (while (re-search-forward makefile-macroassign-regex (point-max) t) 571 (setq makefile-need-macro-pickup nil)
574 (makefile-add-this-line-macro) 572 (setq makefile-macro-table nil)
575 (forward-line 1)))) 573 (save-excursion
574 (goto-char (point-min))
575 (while (re-search-forward makefile-macroassign-regex (point-max) t)
576 (makefile-add-this-line-macro)
577 (forward-line 1)))
578 (message "Read macros OK.")))
576 579
577 (defun makefile-add-this-line-macro () 580 (defun makefile-add-this-line-macro ()
578 (save-excursion 581 (save-excursion
579 (beginning-of-line) 582 (beginning-of-line)
580 (skip-chars-forward " \t") 583 (skip-chars-forward " \t")
581 (if (not (eolp)) 584 (if (not (eolp))
582 (let* ((start-of-macro-name (point)) 585 (let* ((start-of-macro-name (point))
586 (line-number (1+ (count-lines (point-min) (point))))
583 (macro-name (progn 587 (macro-name (progn
584 (skip-chars-forward "^ \t:#=*") 588 (skip-chars-forward "^ \t:#=*")
585 (buffer-substring start-of-macro-name (point))))) 589 (buffer-substring start-of-macro-name (point)))))
586 (if (makefile-remember-macro macro-name) 590 (if (makefile-remember-macro macro-name)
587 (message "Picked up macro \"%s\"" macro-name)))))) 591 (message "Picked up macro \"%s\" from line %d"
588 592 macro-name line-number))))))
589 593
590 (defun makefile-pickup-everything () 594 (defun makefile-pickup-everything ()
591 "Calls makefile-pickup-targets and makefile-pickup-macros. 595 "Calls makefile-pickup-targets and makefile-pickup-macros.
592 See their documentation for what they do." 596 See their documentation for what they do."
593 (interactive) 597 (interactive)
615 raw-filename-list))) 619 raw-filename-list)))
616 620
617 ;;; ------------------------------------------------------------ 621 ;;; ------------------------------------------------------------
618 ;;; The browser window 622 ;;; The browser window
619 ;;; ------------------------------------------------------------ 623 ;;; ------------------------------------------------------------
620
621 624
622 (defun makefile-browser-format-target-line (target selected) 625 (defun makefile-browser-format-target-line (target selected)
623 (format 626 (format
624 (concat (make-string makefile-browser-leftmost-column ?\ ) 627 (concat (make-string makefile-browser-leftmost-column ?\ )
625 (if selected 628 (if selected
654 (goto-char (1- (point-max))) 657 (goto-char (1- (point-max)))
655 (delete-char 1) ; remove unnecessary newline at eob 658 (delete-char 1) ; remove unnecessary newline at eob
656 (goto-char (point-min)) 659 (goto-char (point-min))
657 (forward-char makefile-browser-cursor-column) 660 (forward-char makefile-browser-cursor-column)
658 (setq buffer-read-only t)) 661 (setq buffer-read-only t))
659
660 662
661 ;;; 663 ;;;
662 ;;; Moving up and down in the browser 664 ;;; Moving up and down in the browser
663 ;;; 665 ;;;
664 666
727 ;;; 729 ;;;
728 ;;; Making insertions into the client buffer 730 ;;; Making insertions into the client buffer
729 ;;; 731 ;;;
730 732
731 (defun makefile-browser-insert-continuation () 733 (defun makefile-browser-insert-continuation ()
732 "In the browser\'s client buffer, go to (end-of-line), insert a \'\\\' 734 "Insert a makefile continuation.
735 In the browser\'s client buffer, go to (end-of-line), insert a \'\\\'
733 character, insert a new blank line, go to that line and indent by one TAB. 736 character, insert a new blank line, go to that line and indent by one TAB.
734 This is most useful in the process of creating continued lines when 'sending' large 737 This is most useful in the process of creating continued lines when copying
735 dependencies from the browser to the client buffer. 738 large dependencies from the browser to the client buffer.
736 (point) advances accordingly in the client buffer." 739 (point) advances accordingly in the client buffer."
737 (interactive) 740 (interactive)
738 (save-excursion 741 (save-excursion
739 (set-buffer makefile-browser-client) 742 (set-buffer makefile-browser-client)
740 (end-of-line) 743 (end-of-line)
768 (save-excursion 771 (save-excursion
769 (let ((target-name (makefile-browser-this-line-target-name))) 772 (let ((target-name (makefile-browser-this-line-target-name)))
770 (set-buffer makefile-browser-client) 773 (set-buffer makefile-browser-client)
771 (insert target-name " "))))) 774 (insert target-name " ")))))
772 775
773
774 (defun makefile-browser-start-interaction () 776 (defun makefile-browser-start-interaction ()
775 (use-local-map makefile-browser-map) 777 (use-local-map makefile-browser-map)
776 (setq buffer-read-only t)) 778 (setq buffer-read-only t))
777
778 779
779 (defun makefile-browse (targets macros) 780 (defun makefile-browse (targets macros)
780 (interactive) 781 (interactive)
781 (if (zerop (+ (length targets) (length macros))) 782 (if (zerop (+ (length targets) (length macros)))
782 (progn 783 (progn
784 (message "No macros or targets to browse! Consider running 'makefile-pickup-everything\'")) 785 (message "No macros or targets to browse! Consider running 'makefile-pickup-everything\'"))
785 (let ((browser-buffer (get-buffer-create makefile-browser-buffer-name))) 786 (let ((browser-buffer (get-buffer-create makefile-browser-buffer-name)))
786 (pop-to-buffer browser-buffer) 787 (pop-to-buffer browser-buffer)
787 (make-variable-buffer-local 'makefile-browser-selection-vector) 788 (make-variable-buffer-local 'makefile-browser-selection-vector)
788 (makefile-browser-fill targets macros) 789 (makefile-browser-fill targets macros)
790 (shrink-window-if-larger-than-buffer)
789 (setq makefile-browser-selection-vector 791 (setq makefile-browser-selection-vector
790 (make-vector (+ (length targets) (length macros)) nil)) 792 (make-vector (+ (length targets) (length macros)) nil))
791 (makefile-browser-start-interaction)))) 793 (makefile-browser-start-interaction))))
792
793 794
794 (defun makefile-switch-to-browser () 795 (defun makefile-switch-to-browser ()
795 (interactive) 796 (interactive)
796 (run-hooks 'makefile-browser-hook) 797 (run-hooks 'makefile-browser-hook)
797 (setq makefile-browser-client (current-buffer)) 798 (setq makefile-browser-client (current-buffer))
799 (makefile-pickup-targets)
800 (makefile-pickup-macros)
798 (makefile-browse makefile-target-table makefile-macro-table)) 801 (makefile-browse makefile-target-table makefile-macro-table))
799 802
800 803
801 ;;; ------------------------------------------------------------ 804 ;;; ------------------------------------------------------------
802 ;;; Up-to-date overview buffer 805 ;;; Up-to-date overview buffer
803 ;;; ------------------------------------------------------------ 806 ;;; ------------------------------------------------------------
804 807
805 (defun makefile-create-up-to-date-overview () 808 (defun makefile-create-up-to-date-overview ()
806 "Create a buffer containing an overview of the state of all 809 "Create a buffer containing an overview of the state of all known targets.
807 known targets from the makefile that is currently being edited.
808 Known targets are targets that are explicitly defined in that makefile; 810 Known targets are targets that are explicitly defined in that makefile;
809 in other words, all targets that appear on the left hand side of a 811 in other words, all targets that appear on the left hand side of a
810 dependency in the makefile." 812 dependency in the makefile."
811 (interactive) 813 (interactive)
812 (if (y-or-n-p "Are you sure that the makefile being edited is consistent? ") 814 (if (y-or-n-p "Are you sure that the makefile being edited is consistent? ")
825 ;; We don't want to query these, so get a new target-table with just the 827 ;; We don't want to query these, so get a new target-table with just the
826 ;; targets that can be found in the makefile buffer. 828 ;; targets that can be found in the makefile buffer.
827 ;; The 'old' target table will be restored later. 829 ;; The 'old' target table will be restored later.
828 ;; 830 ;;
829 (real-targets (progn 831 (real-targets (progn
830 (makefile-forget-all-targets)
831 (makefile-pickup-targets) 832 (makefile-pickup-targets)
832 makefile-target-table))) 833 makefile-target-table))
834 (prereqs makefile-has-prereqs)
835 )
833 836
834 (set-buffer makefile-up-to-date-buffer) 837 (set-buffer makefile-up-to-date-buffer)
835 (setq buffer-read-only nil) 838 (setq buffer-read-only nil)
836 (erase-buffer) 839 (erase-buffer)
837 (makefile-query-targets filename real-targets) 840 (makefile-query-targets filename real-targets prereqs)
838 (if (zerop (buffer-size)) ; if it did not get us anything 841 (if (zerop (buffer-size)) ; if it did not get us anything
839 (progn 842 (progn
840 (kill-buffer (current-buffer)) 843 (kill-buffer (current-buffer))
841 (message "No overview created!"))) 844 (message "No overview created!")))
842 (set-buffer this-buffer) 845 (set-buffer this-buffer)
843 (setq makefile-target-table saved-target-table) 846 (setq makefile-target-table saved-target-table)
844 (if (get-buffer makefile-up-to-date-buffer-name) 847 (if (get-buffer makefile-up-to-date-buffer-name)
845 (progn 848 (progn
846 (pop-to-buffer (get-buffer makefile-up-to-date-buffer-name)) 849 (pop-to-buffer (get-buffer makefile-up-to-date-buffer-name))
850 (shrink-window-if-larger-than-buffer)
847 (sort-lines nil (point-min) (point-max)) 851 (sort-lines nil (point-min) (point-max))
848 (setq buffer-read-only t)))))) 852 (setq buffer-read-only t))))))
849
850
851 853
852 (defun makefile-save-temporary () 854 (defun makefile-save-temporary ()
853 "Create a temporary file from the current makefile buffer." 855 "Create a temporary file from the current makefile buffer."
854 (let ((filename (makefile-generate-temporary-filename))) 856 (let ((filename (makefile-generate-temporary-filename)))
855 (write-region (point-min) (point-max) filename nil 0) 857 (write-region (point-min) (point-max) filename nil 0)
868 "." 870 "."
869 (if (> (length my-uid) 3) 871 (if (> (length my-uid) 3)
870 (substring my-uid 0 3) 872 (substring my-uid 0 3)
871 my-uid)))) 873 my-uid))))
872 874
873 (defun makefile-query-targets (filename target-table) 875 (defun makefile-query-targets (filename target-table prereq-list)
874 "This function fills the up-to-date-overview-buffer. 876 "This function fills the up-to-date-overview-buffer.
875 It checks each target in target-table using makefile-query-one-target-method 877 It checks each target in target-table using makefile-query-one-target-method
876 and generates the overview, one line per target name." 878 and generates the overview, one line per target name."
877 (insert 879 (insert
878 (mapconcat '(lambda (item) 880 (mapconcat
879 (let ((target-name (car item))) 881 (function (lambda (item)
880 (makefile-format-up-to-date-buffer-entry 882 (let* ((target-name (car item))
881 (funcall makefile-query-one-target-method 883 (no-prereqs (not (member target-name prereq-list)))
882 target-name filename) target-name))) 884 (needs-rebuild (or no-prereqs
883 target-table "\n")) 885 (funcall
886 makefile-query-one-target-method
887 target-name
888 filename))))
889 (format "\t%s%s"
890 target-name
891 (cond (no-prereqs " .. has no prerequisites")
892 (needs-rebuild " .. NEEDS REBUILD")
893 (t " .. is up to date"))))
894 ))
895 target-table "\n"))
884 (goto-char (point-min)) 896 (goto-char (point-min))
885 (delete-file filename)) ; remove the tmpfile 897 (delete-file filename)) ; remove the tmpfile
886 898
887 (defun makefile-query-by-make-minus-q (target &optional filename) 899 (defun makefile-query-by-make-minus-q (target &optional filename)
888 (not (zerop (call-process makefile-brave-make nil nil nil "-f" filename "-q" target)))) 900 (not (zerop (call-process makefile-brave-make nil nil nil "-f" filename "-q" target))))
889
890 (defun makefile-format-up-to-date-buffer-entry (needs-rebuild target)
891 (format "\t%s%s"
892 target
893 (if needs-rebuild
894 makefile-target-needs-rebuild-mark
895 makefile-target-up-to-date-mark)))
896
897 901
898 ;;; ------------------------------------------------------------ 902 ;;; ------------------------------------------------------------
899 ;;; Continuation cleanup 903 ;;; Continuation cleanup
900 ;;; ------------------------------------------------------------ 904 ;;; ------------------------------------------------------------
901 905
947 951
948 ;;; ------------------------------------------------------------ 952 ;;; ------------------------------------------------------------
949 ;;; Utility functions 953 ;;; Utility functions
950 ;;; ------------------------------------------------------------ 954 ;;; ------------------------------------------------------------
951 955
952 (defun makefile-forget-all-targets () 956 (defun makefile-remember-target (target-name &optional has-prereqs)
953 "Clear the target-table for this buffer."
954 (interactive)
955 (setq makefile-target-table '()))
956
957 (defun makefile-forget-all-macros ()
958 "Clear the macro-table for this buffer."
959 (interactive)
960 (setq makefile-macro-table '()))
961
962
963 (defun makefile-forget-everything ()
964 "Clear the macro-table AND the target-table for this buffer."
965 (interactive)
966 (if (y-or-n-p "Really forget all macro- and target information ? ")
967 (progn
968 (makefile-forget-all-targets)
969 (makefile-forget-all-macros)
970 (if (get-buffer makefile-browser-buffer-name)
971 (kill-buffer makefile-browser-buffer-name))
972 (message "Cleared macro- and target tables."))))
973
974 (defun makefile-remember-target (target-name)
975 "Remember a given target if it is not already remembered for this buffer." 957 "Remember a given target if it is not already remembered for this buffer."
976 (if (not (zerop (length target-name))) 958 (if (not (zerop (length target-name)))
959 (progn
977 (if (not (assoc target-name makefile-target-table)) 960 (if (not (assoc target-name makefile-target-table))
978 (setq makefile-target-table 961 (setq makefile-target-table
979 (cons (list target-name) makefile-target-table))))) 962 (cons (list target-name) makefile-target-table)))
963 (if has-prereqs
964 (setq makefile-has-prereqs
965 (cons target-name makefile-has-prereqs))))))
980 966
981 (defun makefile-remember-macro (macro-name) 967 (defun makefile-remember-macro (macro-name)
982 "Remember a given macro if it is not already remembered for this buffer." 968 "Remember a given macro if it is not already remembered for this buffer."
983 (if (not (zerop (length macro-name))) 969 (if (not (zerop (length macro-name)))
984 (if (not (assoc macro-name makefile-macro-table)) 970 (if (not (assoc macro-name makefile-macro-table))