comparison lisp/modes/make-mode.el @ 0:376386a54a3c r19-14

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