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