1 ;;; make-mode.el --- makefile editing commands for Emacs
3 ;; Copyright (C) 1992, 1994, 1999, 2000 Free Software Foundation, Inc.
5 ;; Author: Thomas Neumann <tom@smart.bo.open.de>
6 ;; Eric S. Raymond <esr@snark.thyrsus.com>
7 ;; Maintainer: XEmacs Development Team <xemacs-beta@xemacs.org>
9 ;; Keywords: unix, tools
13 ;; Also, the doc strings need fixing: the first line doesn't stand alone,
14 ;; and other usage is not high quality. Symbol names don't have `...'.
16 ;; This file is part of XEmacs.
18 ;; XEmacs is free software; you can redistribute it and/or modify it
19 ;; under the terms of the GNU General Public License as published by
20 ;; the Free Software Foundation; either version 2, or (at your option)
23 ;; XEmacs is distributed in the hope that it will be useful, but
24 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
25 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 ;; General Public License for more details.
28 ;; You should have received a copy of the GNU General Public License
29 ;; along with XEmacs; see the file COPYING. If not, write to the Free
30 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
33 ;;; Synched up with: GNU Emacs 19.34, partially with 21.2.
37 ;; A major mode for editing makefiles. The mode knows about Makefile
38 ;; syntax and defines M-n and M-p to move to next and previous productions.
40 ;; The keys $, =, : and . are electric; they try to help you fill in a
41 ;; macro reference, macro definition, ordinary target name, or special
42 ;; target name, respectively. Such names are completed using a list of
43 ;; targets and macro names parsed out of the makefile. This list is
44 ;; automatically updated, if necessary, whenever you invoke one of
45 ;; these commands. You can force it to be updated with C-c C-p.
47 ;; The command C-c C-f adds certain filenames in the current directory
48 ;; as targets. You can filter out filenames by setting the variable
49 ;; makefile-ignored-files-in-pickup-regex.
51 ;; The command C-c C-u grinds for a bit, then pops up a report buffer
52 ;; showing which target names are up-to-date with respect to their
53 ;; prerequisites, which targets are out-of-date, and which have no
56 ;; The command C-c C-b pops up a browser window listing all target and
57 ;; macro names. You can mark or unmark items wit C-c SPC, and insert
58 ;; all marked items back in the Makefile with C-c TAB.
60 ;; The command C-c TAB in the makefile buffer inserts a GNU make builtin.
61 ;; You will be prompted for the builtin's args.
63 ;; There are numerous other customization variables.
68 ;; * makefile-backslash-region should be given better behavior.
69 ;; * Consider binding C-c C-c to comment-region (like cc-mode).
70 ;; * Eliminate electric stuff entirely.
71 ;; * It might be nice to highlight targets differently depending on
72 ;; whether they are up-to-date or not. Not sure how this would
73 ;; interact with font-lock.
74 ;; * Would be nice to edit the commands in ksh-mode and have
75 ;; indentation and slashification done automatically. Hard.
76 ;; * Consider removing browser mode. It seems useless.
77 ;; * ":" should notice when a new target is made and add it to the
78 ;; list (or at least set makefile-need-target-pickup).
79 ;; * Make browser into a major mode.
80 ;; * Clean up macro insertion stuff. It is a mess.
81 ;; * Browser entry and exit is weird. Normalize.
82 ;; * Browser needs to be rewritten. Right now it is kind of a crock.
84 ;; * Act more like dired/buffer menu/whatever.
85 ;; * Highlight as mouse traverses.
87 ;; * Update documentation above.
88 ;; * Update texinfo manual.
95 ;; Sadly we need this for a macro.
97 (unless (featurep 'xemacs)
102 ;; Used to generate some fancy regexps
103 (require 'regexp-opt)
105 ;;; ------------------------------------------------------------
106 ;;; Configurable stuff
107 ;;; ------------------------------------------------------------
109 (defgroup makefile nil
110 "Makefile editing commands for XEmacs."
114 (defface makefile-space-face
115 '((((class color)) (:background "hotpink"))
116 (t (:reverse-video t)))
117 "Face to use for highlighting leading spaces in Font-Lock mode."
121 (defcustom makefile-browser-buffer-name "*Macros and Targets*"
122 "*Name of the macro- and target browser buffer."
126 (defcustom makefile-target-colon ":"
127 "*String to append to all target names inserted by `makefile-insert-target'.
128 \":\" or \"::\" are common values."
132 (defcustom makefile-macro-assign " = "
133 "*String to append to all macro names inserted by `makefile-insert-macro'.
134 The normal value should be \" = \", since this is what
135 standard make expects. However, newer makes such as dmake
136 allow a larger variety of different macro assignments, so you
137 might prefer to use \" += \" or \" := \" ."
141 (defcustom makefile-electric-keys nil
142 "*If non-nil, Makefile mode should install electric keybindings.
147 (defcustom makefile-use-curly-braces-for-macros-p nil
148 "*Controls the style of generated macro references.
149 Non-nil means macro references should use curly braces, like `${this}'.
150 nil means use parentheses, like `$(this)'."
154 (defcustom makefile-tab-after-target-colon t
155 "*If non-nil, insert a TAB after a target colon.
156 Otherwise, a space is inserted.
161 (defcustom makefile-browser-leftmost-column 10
162 "*Number of blanks to the left of the browser selection mark."
166 (defcustom makefile-browser-cursor-column 10
167 "*Column the cursor goes to when it moves up or down in the Makefile browser."
171 (defcustom makefile-backslash-column 48
172 "*Column in which `makefile-backslash-region' inserts backslashes."
176 (defcustom makefile-browser-selected-mark "+ "
177 "*String used to mark selected entries in the Makefile browser."
181 (defcustom makefile-browser-unselected-mark " "
182 "*String used to mark unselected entries in the Makefile browser."
186 (defcustom makefile-browser-auto-advance-after-selection-p t
187 "*If non-nil, cursor will move after item is selected in Makefile browser."
191 (defcustom makefile-pickup-everything-picks-up-filenames-p nil
192 "*If non-nil, `makefile-pickup-everything' picks up filenames as targets.
193 This means it calls `makefile-pickup-filenames-as-targets'.
194 Otherwise filenames are omitted."
198 (defcustom makefile-cleanup-continuations-p t
199 "*If non-nil, automatically clean up continuation lines when saving.
200 A line is cleaned up by removing all whitespace following a trailing
201 backslash. This is done silently.
202 IMPORTANT: Please note that enabling this option causes Makefile mode
203 to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\"."
207 ;;; those suspicious line warnings are really annoying and
208 ;;; seem to be generated for every makefile I've ever seen.
209 ;;; add a simple mechanism to disable them. -gk
210 (defcustom makefile-warn-suspicious-lines-p t
211 "In non-nil, warn about suspicious lines when saving the makefile"
215 (defcustom makefile-browser-hook '()
216 "The hook to run when entering makefile browser."
221 ;; Special targets for DMake, Sun's make ...
223 (defcustom makefile-special-targets-list
224 '(("DEFAULT") ("DONE") ("ERROR") ("EXPORT")
225 ("FAILED") ("GROUPEPILOG") ("GROUPPROLOG") ("IGNORE")
226 ("IMPORT") ("INCLUDE") ("INCLUDEDIRS") ("INIT")
227 ("KEEP_STATE") ("MAKEFILES") ("MAKE_VERSION") ("NO_PARALLEL")
228 ("PARALLEL") ("PHONY") ("PRECIOUS") ("REMOVE")
229 ("SCCS_GET") ("SILENT") ("SOURCE") ("SUFFIXES")
230 ("WAIT") ("c.o") ("C.o") ("m.o")
231 ("el.elc") ("y.c") ("s.o"))
232 "*List of special targets.
233 You will be offered to complete on one of those in the minibuffer whenever
234 you enter a \".\" at the beginning of a line in `makefile-mode'."
235 :type '(repeat (list string))
238 (defcustom makefile-runtime-macros-list
239 '(("@") ("&") (">") ("<") ("*") ("^") ("+") ("?") ("%") ("$"))
240 "*List of macros that are resolved by make at runtime.
241 If you insert a macro reference using `makefile-insert-macro-ref', the name
242 of the macro is checked against this list. If it can be found its name will
243 not be enclosed in { } or ( )."
244 :type '(repeat (list string))
247 ;;; Some sample lines from one of the glibc makefiles:
249 ;; $(services:%=$(objpfx)libnss_%.so) $(objpfx)libnsl.so: $(common-objpfx)libc.so
250 ;; $(objpfx)libnss_compat.so: $(objpfx)libnsl.so$(libnsl.so-version)
251 ;; subdir-dirs = $(services:%=nss_%) ---> mustn't match.
252 ;; ordinary: blah blah
254 ;; Note that the first big subexpression (the only match capturing
255 ;; one) is used by font lock, imenu, and makefile-mode.
256 (defconst makefile-dependency-regex
260 ;;; "\\(?:vpath[ \t]\\)\\{0,0\\}" ; doesn't work as intended
261 ;;; I want it to NOT highlight lines like:
262 ;;;vpath %.h $(subst $(empty) ,:,$(strip $(common-objpfx) $(objpfx) \
263 ;;; $(+sysdep_dirs) $(..)))
264 ;;; ... where the colon between the two commas makes it look like a
265 ;;; target. The workaround is to write the line like:
267 ;;;vpath %.h $(subst $(empty) ,$(colon),$(strip $(common-objpfx) $(objpfx) \
268 ;;; $(+sysdep_dirs) $(..)))
269 ;;; ... putting a space before vpath works too, but I highlight vpath later,
270 ;;; and that expects it to be anchored left.
271 ;;; I wonder if the "zero length negative assertion" (the \\{0,0\\} is
272 ;;; moving the scan cursor forward? Bet that's it. I should look
273 ;;; into the regexp engine at some point and see if I can fix it.
274 ;;; The libpcre is not too shabby. Dunno if it's right for an Emacs.
278 "\\$[\(\{][^\)\}]+[\)\}][^ \n\t#=:]+"
285 "\\$[\(\}][^\)\}]+[\)\}][^ \n\t#=:]+"
290 "\\)" ; end match-string 1 (the only one we use.)
297 "Regex used to find dependency lines in a makefile.")
299 ;; Note that the first match capturing subexpression is used by font
300 ;; lock, Imenu, and makefile-mode.
301 (defconst makefile-macroassign-regex
302 "^ *\\(?:export[ \t]+\\)?\\([^# \t\n][^#=: \t\n]*\\)[ \t]*[*:+?]?:?="
303 "Regex used to find macro assignment lines in a makefile.")
305 (defconst makefile-imenu-generic-expression
306 `(("Targets" ,makefile-dependency-regex 1)
307 ("Macros" ,makefile-macroassign-regex 1)
308 ("Defines" "^define[ \t]+\\([-.a-zA-Z0-9_+]+\\)" 1)
309 ("Includes" "^[-s]?include[ \t]+\\([-.,/a-zA-Z0-9_+]+\\)" 1)
311 "See: `imenu-generic-expression'")
313 (defconst makefile-ignored-files-in-pickup-regex
314 "\\(^\\..*\\)\\|\\(.*~$\\)\\|\\(.*,v$\\)\\|\\(\\.[chy]\\)"
315 "Regex for filenames that will NOT be included in the target list.")
317 ;Older version of same.
318 ;(defconst makefile-font-lock-keywords (purecopy
320 ; '("^#.*$" . font-lock-comment-face)
321 ; '("[^$]#.*$" . font-lock-comment-face)
323 ; '("^\\([^ \t\n]*%?[^ \t\n]*[ \t]*::?\\)[ \t]" 1 font-lock-type-face t)
324 ; '("^\\(\\.[A-Za-z][A-Za-z]?\\..[ \t]*::?\\)" 1 font-lock-type-face t)
325 ; '("^[^ \t\n]+[ \t]*:;?\\(.*\\)$" 1 font-lock-doc-string-face t)
326 ; ;; variable definition
327 ; '("^[_A-Za-z0-9]+[ \t]*\+?=" . font-lock-function-name-face)
328 ; '("\\( \\|:=\\)[_A-Za-z0-9]+[ \t]*\\+=" . font-lock-function-name-face)
329 ; ;; variable references
330 ; '("\\(\\$\\$?\\([^ \t\n{(]\\|[{(][^ \t\n)}]+[)}]\\)\\)"
331 ; 1 font-lock-keyword-face t)
332 ; '("^include " . font-lock-string-face)
335 (defconst makefile-font-lock-keywords
337 ;; conditionals, vpath & include
341 (mapcar #'symbol-name
342 '(ifeq ifneq else endif endef include sinclude)))
343 "\\|-include\\)[ \t\n]+")
344 1 'font-lock-preprocessor-face)
346 '("^ *\\(ifn?def\\)[ \t]+\\(.*$\\)"
347 (1 font-lock-preprocessor-face) (2 font-lock-reference-face nil t))
350 '("^ *\\(define\\)[ \t]+\\(.*$\\)"
351 (1 font-lock-preprocessor-face) (2 font-lock-variable-name-face nil t))
353 ;; vpath export unexport override
357 (mapcar #'symbol-name
358 '(vpath export unexport override)))
359 "\\)[ \t]+") 1 'font-lock-keyword-face 'prepend)
361 ;; Do dependencies. These get the function name face.
362 (list makefile-dependency-regex 1 'font-lock-function-name-face 'prepend)
364 ;; Do macro assignments. These get the "variable-name" face rather
366 (list makefile-macroassign-regex 1 'font-lock-variable-name-face 'keep)
368 ;; Variable references even in targets/strings/comments:
370 (concat "\\$[\(\{][ \t]*"
371 ;;; Commented off because
372 ;;; $($(var)-ext) still doesn't work.
373 ;;; I want to highlight
374 ;;; ${${var}-ext} blah blah ${var2}
377 ;;; ${${var}-ext} blah blah ${var2}
378 ;;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
380 ;;; ${${var}-ext} blah blah ${var2}
388 "[-<@.a-zA-Z0-9+_]+" ; match-string 1
391 "[^-.a-zA-Z0-9+_]\\{0,0\\}"
396 1 'font-lock-reference-face 'prepend)
398 ;; and builtin special variable names
400 (concat "\\$" (regexp-opt (mapcar #'car makefile-runtime-macros-list)))
401 '(0 font-lock-reference-face t))
403 ;; Make $(functions ...)
408 (mapcar #'symbol-name
409 '(subst patsubst strip findstring filter filter-out sort
410 dir notdir suffix basename addsuffix addprefix join word words
411 wordlist firstword wildcard error warning shell origin foreach
413 "\\)[ \t\n]+:\\{0,0\\}")
414 1 'font-lock-keyword-face 'prepend)
416 ;; Todo:, Fixme,and ### through ###### in comments.
417 '("#.*?[ \t]+\\([Tt][Oo][Dd][Oo]:?\\)" (1 font-lock-warning-face t))
418 '("#.*?[ \t]+\\(#\\{3,6\\}\\)[ \t\n]+" (1 font-lock-warning-face t))
419 '("#.*?[ \t]+\\([Ff][Ii][Xx] *[Mm][Ee]:?\\)" (1 font-lock-warning-face t))
421 ;; Highlight lines that contain just whitespace.
422 ;; They can cause trouble, especially if they start with a tab.
423 '("^[ \t]+$" . makefile-space-face)
425 ;; Highlight shell comments that Make treats as commands,
426 ;; since these can fool people.
427 '("^\t+#" 0 makefile-space-face t)
429 ;; Highlight spaces that precede tabs.
430 ;; They can make a tab fail to be effective.
431 '("^\\( +\\)\t" 1 makefile-space-face))
432 "Additional expressions to highlight in makefiles")
434 (put 'makefile-mode 'font-lock-defaults '(makefile-font-lock-keywords))
436 ;;; ------------------------------------------------------------
437 ;;; The following configurable variables are used in the
438 ;;; up-to-date overview .
439 ;;; The standard configuration assumes that your `make' program
440 ;;; can be run in question/query mode using the `-q' option, this
441 ;;; means that the command
445 ;;; should return an exit status of zero if the target `foo' is
446 ;;; up to date and a nonzero exit status otherwise.
447 ;;; Many makes can do this although the docs/manpages do not mention
448 ;;; it. Try it with your favourite one. GNU make, System V make, and
449 ;;; Dennis Vadura's DMake have no problems.
450 ;;; Set the variable `makefile-brave-make' to the name of the
451 ;;; make utility that does this on your system.
452 ;;; To understand what this is all about see the function definition
453 ;;; of `makefile-query-by-make-minus-q' .
454 ;;; ------------------------------------------------------------
456 (defcustom makefile-brave-make "make"
457 "*How to invoke make, for `makefile-query-targets'.
458 This should identify a `make' command that can handle the `-q' option."
462 (defcustom makefile-query-one-target-method 'makefile-query-by-make-minus-q
463 "*Function to call to determine whether a make target is up to date.
464 The function must satisfy this calling convention:
466 * As its first argument, it must accept the name of the target to
467 be checked, as a string.
469 * As its second argument, it may accept the name of a makefile
470 as a string. Depending on what you're going to do you may
473 * It must return the integer value 0 (zero) if the given target
474 should be considered up-to-date in the context of the given
475 makefile, any nonzero integer value otherwise."
479 (defcustom makefile-up-to-date-buffer-name "*Makefile Up-to-date overview*"
480 "*Name of the Up-to-date overview buffer."
484 ;;; --- end of up-to-date-overview configuration ------------------
486 (defvar makefile-mode-abbrev-table nil
487 "Abbrev table in use in Makefile buffers.")
488 (if makefile-mode-abbrev-table
490 (define-abbrev-table 'makefile-mode-abbrev-table ()))
492 (defvar makefile-mode-map nil
493 "The keymap that is used in Makefile mode.")
495 (if makefile-mode-map
497 (setq makefile-mode-map (make-sparse-keymap 'makefile-mode-map))
499 (define-key makefile-mode-map "\C-c:" 'makefile-insert-target-ref)
500 (if makefile-electric-keys
502 (define-key makefile-mode-map "$" 'makefile-insert-macro-ref)
503 (define-key makefile-mode-map ":" 'makefile-electric-colon)
504 (define-key makefile-mode-map "=" 'makefile-electric-equal)
505 (define-key makefile-mode-map "." 'makefile-electric-dot)))
506 (define-key makefile-mode-map "\C-c\C-f" 'makefile-pickup-filenames-as-targets)
507 (define-key makefile-mode-map "\C-c\C-b" 'makefile-switch-to-browser)
508 (define-key makefile-mode-map "\C-c\C-c" 'comment-region)
509 (define-key makefile-mode-map "\C-c\C-p" 'makefile-pickup-everything)
510 (define-key makefile-mode-map "\C-c\C-u" 'makefile-create-up-to-date-overview)
511 (define-key makefile-mode-map "\C-c\C-i" 'makefile-insert-gmake-function)
512 (define-key makefile-mode-map "\C-c\C-\\" 'makefile-backslash-region)
513 (define-key makefile-mode-map "\M-p" 'makefile-previous-dependency)
514 (define-key makefile-mode-map "\M-n" 'makefile-next-dependency)
515 (define-key makefile-mode-map "\e\t" 'makefile-complete))
518 (defconst makefile-menubar-menu
520 ["Move to Next Dependency" makefile-next-dependency t]
521 ["Move to Previous Dependency" makefile-previous-dependency t]
523 ["Find Targets and Macros" makefile-pickup-everything t]
524 ["Complete Target or Macro" makefile-complete t]
525 ["Pop up Makefile Browser" makefile-switch-to-browser t]))
528 (defconst makefile-popup-menu
529 (cons "Makefile Mode Commands"
530 (cdr makefile-menubar-menu)))
532 (defvar makefile-browser-map nil
533 "The keymap that is used in the macro- and target browser.")
534 (if makefile-browser-map
536 (setq makefile-browser-map (make-sparse-keymap))
537 (define-key makefile-browser-map "n" 'makefile-browser-next-line)
538 (define-key makefile-browser-map "\C-n" 'makefile-browser-next-line)
539 (define-key makefile-browser-map "p" 'makefile-browser-previous-line)
540 (define-key makefile-browser-map "\C-p" 'makefile-browser-previous-line)
541 (define-key makefile-browser-map " " 'makefile-browser-toggle)
542 (define-key makefile-browser-map "i" 'makefile-browser-insert-selection)
543 (define-key makefile-browser-map "I" 'makefile-browser-insert-selection-and-quit)
544 (define-key makefile-browser-map "\C-c\C-m" 'makefile-browser-insert-continuation)
545 (define-key makefile-browser-map "q" 'makefile-browser-quit)
546 ;; disable horizontal movement
547 (define-key makefile-browser-map "\C-b" 'undefined)
548 (define-key makefile-browser-map "\C-f" 'undefined))
551 (defvar makefile-mode-syntax-table nil)
552 (if makefile-mode-syntax-table
554 (setq makefile-mode-syntax-table (make-syntax-table))
555 (modify-syntax-entry ?\( "() " makefile-mode-syntax-table)
556 (modify-syntax-entry ?\) ")( " makefile-mode-syntax-table)
557 (modify-syntax-entry ?\[ "(] " makefile-mode-syntax-table)
558 (modify-syntax-entry ?\] ")[ " makefile-mode-syntax-table)
559 (modify-syntax-entry ?\{ "(} " makefile-mode-syntax-table)
560 (modify-syntax-entry ?\} "){ " makefile-mode-syntax-table)
561 (modify-syntax-entry ?\' "\" " makefile-mode-syntax-table)
562 (modify-syntax-entry ?\` "\" " makefile-mode-syntax-table)
563 (modify-syntax-entry ?# "< " makefile-mode-syntax-table)
564 (modify-syntax-entry ?\n "> " makefile-mode-syntax-table))
567 ;;; ------------------------------------------------------------
568 ;;; Internal variables.
569 ;;; You don't need to configure below this line.
570 ;;; ------------------------------------------------------------
572 (defvar makefile-target-table nil
573 "Table of all target names known for this buffer.")
575 (defvar makefile-macro-table nil
576 "Table of all macro names known for this buffer.")
578 (defvar makefile-browser-client
579 "A buffer in Makefile mode that is currently using the browser.")
581 (defvar makefile-browser-selection-vector nil)
582 (defvar makefile-has-prereqs nil)
583 (defvar makefile-need-target-pickup t)
584 (defvar makefile-need-macro-pickup t)
586 (defvar makefile-mode-hook '())
588 ;; Each element looks like '("GNU MAKE FUNCTION" "ARG" "ARG" ... )
589 ;; Each "ARG" is used as a prompt for a required argument.
590 (defconst makefile-gnumake-functions-alist
593 ("subst" "From" "To" "In")
594 ("patsubst" "Pattern" "Replacement" "In")
596 ("findstring" "Find what" "In")
597 ("filter" "Pattern" "Text")
598 ("filter-out" "Pattern" "Text")
600 ;; Filename functions
605 ("addprefix" "Prefix" "Names")
606 ("addsuffix" "Suffix" "Names")
607 ("join" "List 1" "List 2")
608 ("word" "Index" "Text")
611 ("wildcard" "Pattern")
613 ("foreach" "Variable" "List" "Text")
614 ("origin" "Variable")
615 ("shell" "Command")))
618 ;;; ------------------------------------------------------------
619 ;;; The mode function itself.
620 ;;; ------------------------------------------------------------
623 (defun makefile-mode ()
624 "Major mode for editing Makefiles.
625 This function ends by invoking the function(s) `makefile-mode-hook'.
627 \\{makefile-mode-map}
629 In the browser, use the following keys:
631 \\{makefile-browser-map}
633 Makefile mode can be configured by modifying the following variables:
635 makefile-browser-buffer-name:
636 Name of the macro- and target browser buffer.
638 makefile-target-colon:
639 The string that gets appended to all target names
640 inserted by `makefile-insert-target'.
641 \":\" or \"::\" are quite common values.
643 makefile-macro-assign:
644 The string that gets appended to all macro names
645 inserted by `makefile-insert-macro'.
646 The normal value should be \" = \", since this is what
647 standard make expects. However, newer makes such as dmake
648 allow a larger variety of different macro assignments, so you
649 might prefer to use \" += \" or \" := \" .
651 makefile-tab-after-target-colon:
652 If you want a TAB (instead of a space) to be appended after the
653 target colon, then set this to a non-nil value.
655 makefile-browser-leftmost-column:
656 Number of blanks to the left of the browser selection mark.
658 makefile-browser-cursor-column:
659 Column in which the cursor is positioned when it moves
660 up or down in the browser.
662 makefile-browser-selected-mark:
663 String used to mark selected entries in the browser.
665 makefile-browser-unselected-mark:
666 String used to mark unselected entries in the browser.
668 makefile-browser-auto-advance-after-selection-p:
669 If this variable is set to a non-nil value the cursor
670 will automagically advance to the next line after an item
671 has been selected in the browser.
673 makefile-pickup-everything-picks-up-filenames-p:
674 If this variable is set to a non-nil value then
675 `makefile-pickup-everything' also picks up filenames as targets
676 (i.e. it calls `makefile-pickup-filenames-as-targets'), otherwise
677 filenames are omitted.
679 makefile-cleanup-continuations-p:
680 If this variable is set to a non-nil value then Makefile mode
681 will assure that no line in the file ends with a backslash
682 (the continuation character) followed by any whitespace.
683 This is done by silently removing the trailing whitespace, leaving
684 the backslash itself intact.
685 IMPORTANT: Please note that enabling this option causes Makefile mode
686 to MODIFY A FILE WITHOUT YOUR CONFIRMATION when \"it seems necessary\".
688 makefile-browser-hook:
689 A function or list of functions to be called just before the
690 browser is entered. This is executed in the makefile buffer.
692 makefile-special-targets-list:
693 List of special targets. You will be offered to complete
694 on one of those in the minibuffer whenever you enter a `.'.
695 at the beginning of a line in Makefile mode."
698 (kill-all-local-variables)
699 (make-local-variable 'local-write-file-hooks)
700 (setq local-write-file-hooks
701 '(makefile-cleanup-continuations makefile-warn-suspicious-lines))
702 (make-local-variable 'makefile-target-table)
703 (make-local-variable 'makefile-macro-table)
704 (make-local-variable 'makefile-has-prereqs)
705 (make-local-variable 'makefile-need-target-pickup)
706 (make-local-variable 'makefile-need-macro-pickup)
709 (make-local-variable 'font-lock-defaults)
710 (setq font-lock-defaults '(makefile-font-lock-keywords))
713 (make-local-variable 'add-log-current-defun-function)
714 (setq add-log-current-defun-function 'makefile-add-log-defun)
717 (make-local-variable 'imenu-generic-expression)
718 (setq imenu-generic-expression makefile-imenu-generic-expression)
721 (make-local-variable 'dabbrev-abbrev-skip-leading-regexp)
722 (setq dabbrev-abbrev-skip-leading-regexp "\\$")
725 (setq local-abbrev-table makefile-mode-abbrev-table)
728 (make-local-variable 'fill-paragraph-function)
729 (setq fill-paragraph-function 'makefile-fill-paragraph)
732 (make-local-variable 'comment-start)
733 (setq comment-start "#")
734 (make-local-variable 'comment-end)
735 (setq comment-end "")
736 (make-local-variable 'comment-start-skip)
737 (setq comment-start-skip "#+[ \t]*")
739 ;; become the current major mode
740 (setq major-mode 'makefile-mode)
741 (setq mode-name "Makefile")
743 ;; Activate keymap and syntax table.
744 (use-local-map makefile-mode-map)
745 (set-syntax-table makefile-mode-syntax-table)
749 (setq mode-popup-menu makefile-popup-menu)
750 (if (and (featurep 'menubar)
751 (or (not (featurep 'infodock))
752 (not (eq infodock-menubar-type 'menubar-infodock))))
754 ;; make a local copy of the menubar, so our modes don't
755 ;; change the global menubar
756 (set-buffer-menubar current-menubar)
757 (add-submenu nil makefile-menubar-menu)))
759 ;; Real TABs are important in makefiles
760 (setq indent-tabs-mode t)
761 (run-hooks 'makefile-mode-hook))
767 (defun makefile-next-dependency ()
768 "Move point to the beginning of the next dependency line."
770 (let ((here (point)))
772 (if (re-search-forward makefile-dependency-regex (point-max) t)
773 (progn (beginning-of-line) t) ; indicate success
774 (goto-char here) nil)))
776 (defun makefile-previous-dependency ()
777 "Move point to the beginning of the previous dependency line."
779 (let ((here (point)))
781 (if (re-search-backward makefile-dependency-regex (point-min) t)
782 (progn (beginning-of-line) t) ; indicate success
783 (goto-char here) nil)))
787 ;;; Electric keys. Blech.
789 (defun makefile-electric-dot (arg)
790 "Prompt for the name of a special target to insert.
791 Only does electric insertion at beginning of line.
792 Anywhere else just self-inserts."
795 (makefile-insert-special-target)
796 (self-insert-command arg)))
798 (defun makefile-insert-special-target ()
799 "Prompt for and insert a special target name.
800 Uses `makefile-special-targets' list."
802 (makefile-pickup-targets)
803 (let ((special-target
804 (completing-read "Special target: "
805 makefile-special-targets-list nil nil nil)))
806 (if (zerop (length special-target))
808 (insert "." special-target ":")
809 (makefile-forward-after-target-colon))))
811 (defun makefile-electric-equal (arg)
812 "Prompt for name of a macro to insert.
813 Only does prompting if point is at beginning of line.
814 Anywhere else just self-inserts."
816 (makefile-pickup-macros)
818 (call-interactively 'makefile-insert-macro)
819 (self-insert-command arg)
820 ;; from here down is new -- if they inserted a macro without using
821 ;; the electric behavior, pick it up anyway -gk
824 (if (looking-at makefile-macroassign-regex)
825 (makefile-add-this-line-macro)))))
827 (defun makefile-insert-macro (macro-name)
828 "Prepare definition of a new macro."
829 (interactive "sMacro Name: ")
830 (makefile-pickup-macros)
831 (if (not (zerop (length macro-name)))
834 (insert macro-name makefile-macro-assign)
835 (setq makefile-need-macro-pickup t)
836 (makefile-remember-macro macro-name))))
838 (defun makefile-insert-macro-ref (macro-name)
839 "Complete on a list of known macros, then insert complete ref at point."
843 (makefile-pickup-macros)
844 (completing-read "Refer to macro: " makefile-macro-table nil nil nil))))
845 (makefile-do-macro-insertion macro-name))
847 (defun makefile-insert-target (target-name)
848 "Prepare definition of a new target (dependency line)."
849 (interactive "sTarget: ")
850 (if (not (zerop (length target-name)))
853 (insert target-name makefile-target-colon)
854 (makefile-forward-after-target-colon)
856 (setq makefile-need-target-pickup t)
857 (makefile-remember-target target-name))))
859 (defun makefile-insert-target-ref (target-name)
860 "Complete on a list of known targets, then insert TARGET-NAME at point."
864 (makefile-pickup-targets)
865 (completing-read "Refer to target: " makefile-target-table nil nil nil))))
866 (if (not (zerop (length target-name)))
867 (insert target-name " ")))
869 (defun makefile-electric-colon (arg)
870 "Prompt for name of new target.
871 Prompting only happens at beginning of line.
872 Anywhere else just self-inserts."
875 (call-interactively 'makefile-insert-target)
876 (self-insert-command arg)))
880 ;;; ------------------------------------------------------------
881 ;;; Extracting targets and macros from an existing makefile
882 ;;; ------------------------------------------------------------
884 (defun makefile-pickup-targets ()
885 "Notice names of all target definitions in Makefile."
887 (if (not makefile-need-target-pickup)
889 (setq makefile-need-target-pickup nil)
890 (setq makefile-target-table nil)
891 (setq makefile-has-prereqs nil)
893 (goto-char (point-min))
894 (while (re-search-forward makefile-dependency-regex (point-max) t)
895 (makefile-add-this-line-targets)))
896 (message "Read targets OK.")))
898 (defun makefile-add-this-line-targets ()
901 (let ((done-with-line nil)
902 (line-number (1+ (count-lines (point-min) (point)))))
903 (while (not done-with-line)
904 (skip-chars-forward " \t")
905 (if (not (setq done-with-line (or (eolp)
906 (char-equal (char-after (point)) ?:))))
908 (let* ((start-of-target-name (point))
911 (skip-chars-forward "^ \t:#")
912 (buffer-substring start-of-target-name (point))))
914 (not (looking-at ":[ \t]*$"))))
915 (if (makefile-remember-target target-name has-prereqs)
916 (message "Picked up target \"%s\" from line %d"
917 target-name line-number)))))))))
919 (defun makefile-pickup-macros ()
920 "Notice names of all macro definitions in Makefile."
922 (if (not makefile-need-macro-pickup)
924 (setq makefile-need-macro-pickup nil)
925 ;; changed the nil in the next line to makefile-runtime-macros-list
926 ;; so you don't have to confirm on every runtime macro entered... -gk
927 (setq makefile-macro-table makefile-runtime-macros-list)
929 (goto-char (point-min))
930 (while (re-search-forward makefile-macroassign-regex (point-max) t)
931 (makefile-add-this-line-macro)
933 (message "Read macros OK.")))
935 (defun makefile-add-this-line-macro ()
938 (skip-chars-forward " \t")
940 (let* ((start-of-macro-name (point))
941 (line-number (1+ (count-lines (point-min) (point))))
943 (skip-chars-forward "^ \t:#=*")
944 (buffer-substring start-of-macro-name (point)))))
945 (if (makefile-remember-macro macro-name)
946 (message "Picked up macro \"%s\" from line %d"
947 macro-name line-number))))))
949 (defun makefile-pickup-everything (arg)
950 "Notice names of all macros and targets in Makefile.
951 Prefix arg means force pickups to be redone."
955 (setq makefile-need-target-pickup t)
956 (setq makefile-need-macro-pickup t)))
957 (makefile-pickup-macros)
958 (makefile-pickup-targets)
959 (if makefile-pickup-everything-picks-up-filenames-p
960 (makefile-pickup-filenames-as-targets)))
962 (defun makefile-pickup-filenames-as-targets ()
963 "Scan the current directory for filenames to use as targets.
964 Checks each filename against `makefile-ignored-files-in-pickup-regex'
965 and adds all qualifying names to the list of known targets."
967 (let* ((dir (file-name-directory (buffer-file-name)))
968 (raw-filename-list (if dir
969 (file-name-all-completions "" dir)
970 (file-name-all-completions "" ""))))
971 (mapcar '(lambda (name)
972 (if (and (not (file-directory-p name))
973 (not (string-match makefile-ignored-files-in-pickup-regex
975 (if (makefile-remember-target name)
976 (message "Picked up file \"%s\" as target" name))))
983 (defun makefile-complete ()
984 "Perform completion on Makefile construct preceding point.
985 Can complete variable and target names.
986 The context determines which are considered."
988 (let* ((beg (save-excursion
989 (skip-chars-backward "^$(){}:#= \t\n")
991 (try (buffer-substring beg (point)))
997 (let ((pc (preceding-char)))
999 ;; Beginning of line means anything.
1003 ;; Preceding "$" means macros only.
1007 ;; Preceding "$(" or "${" means macros only.
1014 (= (preceding-char) ?$))))
1015 (setq do-macros t)))))
1018 (let* ((table (append (if do-macros
1020 makefile-target-table)
1021 makefile-macro-table))
1022 (completion (try-completion try table)))
1024 ;; Exact match, so insert closing paren or colon.
1026 (insert (if do-macros
1038 (message "Can't find completion for \"%s\"" try)
1041 ;; Partial completion.
1042 ((not (string= try completion))
1043 ;; FIXME it would be nice to supply the closing paren if an
1044 ;; exact, unambiguous match were found. That is not possible
1045 ;; right now. Ditto closing ":" for targets.
1046 (delete-region beg (point))
1048 ;; DO-MACROS means doing macros only. If not that, then check
1049 ;; to see if this completion is a macro. Special insertion
1050 ;; must be done for macros.
1052 (assoc completion makefile-macro-table))
1053 (let ((makefile-use-curly-braces-for-macros-p
1055 makefile-use-curly-braces-for-macros-p)))
1056 (delete-backward-char 2)
1057 (makefile-do-macro-insertion completion)
1058 (delete-backward-char 1))
1060 ;; Just insert targets.
1061 (insert completion)))
1063 ;; Can't complete any more, so make completion list. FIXME
1064 ;; this doesn't do the right thing when the completion is
1065 ;; actually inserted. I don't think there is an easy way to do
1068 (message "Making completion list...")
1069 (let ((list (all-completions try table)))
1070 (with-output-to-temp-buffer "*Completions*"
1071 (display-completion-list list)))
1072 (message "Making completion list...done"))))))
1076 ;; Backslashification. Stolen from cc-mode.el.
1078 (defun makefile-backslashify-current-line (doit)
1081 (if (not (save-excursion
1083 (eq (char-after (point)) ?\\ )))
1085 (if (>= (current-column) makefile-backslash-column)
1087 (while (<= (current-column) makefile-backslash-column)
1091 (while (< (current-column) makefile-backslash-column)
1098 (if (eq (char-after (point)) ?\\ )
1099 (let ((saved (save-excursion
1102 (skip-chars-backward " \t")
1103 (delete-region (point) saved)))))))
1105 (defun makefile-backslash-region (beg end arg)
1106 "Insert backslashes at end of every line in region.
1107 Useful for defining multi-line rules.
1108 If called with a prefix argument, trailing backslashes are removed."
1109 (interactive "r\nP")
1111 (let ((do-lastline-p (progn (goto-char end) (not (bolp))))
1112 ;; dynamic binding relied on here.
1113 (makefile-backslash-column makefile-backslash-column))
1115 (narrow-to-region beg end)
1116 (goto-char (point-min))
1119 (and (> (current-column) (- makefile-backslash-column 1))
1120 (setq makefile-backslash-column (+ (current-column) 1)))
1122 (goto-char (point-min))
1123 (while (not (save-excursion
1126 (makefile-backslashify-current-line (null arg))
1129 (progn (goto-char end)
1130 (makefile-backslashify-current-line (null arg)))))))
1136 (defun makefile-fill-paragraph (arg)
1137 ;; Fill comments, backslashed lines, and variable definitions
1142 ((looking-at "^#+ ")
1143 ;; Found a comment. Set the fill prefix and then fill.
1144 (let ((fill-prefix (buffer-substring-no-properties (match-beginning 0)
1146 (fill-paragraph-function nil))
1147 (fill-paragraph nil)
1150 ;; Must look for backslashed-region before looking for variable
1155 (= (preceding-char) ?\\)
1158 (= (preceding-char) ?\\))))
1159 ;; A backslash region. Find beginning and end, remove
1160 ;; backslashes, fill, and then reapply backslahes.
1165 (while (= (preceding-char) ?\\)
1171 (while (= (preceding-char) ?\\)
1175 (narrow-to-region beginning end)
1176 (makefile-backslash-region (point-min) (point-max) t)
1177 (let ((fill-paragraph-function nil))
1178 (fill-paragraph nil))
1179 (makefile-backslash-region (point-min) (point-max) nil)
1180 (goto-char (point-max))
1181 (if (< (skip-chars-backward "\n") 0)
1182 (delete-region (point) (point-max))))))
1184 ((looking-at makefile-macroassign-regex)
1185 ;; Have a macro assign. Fill just this line, and then backslash
1186 ;; resulting region.
1188 (narrow-to-region (point) (save-excursion
1192 (let ((fill-paragraph-function nil))
1193 (fill-paragraph nil))
1194 (makefile-backslash-region (point-min) (point-max) nil)))))
1196 ;; Always return non-nil so we don't fill anything else.
1201 ;;; ------------------------------------------------------------
1203 ;;; ------------------------------------------------------------
1205 (defun makefile-browser-format-target-line (target selected)
1207 (concat (make-string makefile-browser-leftmost-column ?\ )
1209 makefile-browser-selected-mark
1210 makefile-browser-unselected-mark)
1212 target makefile-target-colon))
1214 (defun makefile-browser-format-macro-line (macro selected)
1215 (concat (make-string makefile-browser-leftmost-column ?\ )
1217 makefile-browser-selected-mark
1218 makefile-browser-unselected-mark)
1219 (makefile-format-macro-ref macro)))
1221 (defun makefile-browser-fill (targets macros)
1222 (let ((inhibit-read-only t))
1223 (goto-char (point-min))
1227 (lambda (item) (insert (makefile-browser-format-target-line (car item) nil) "\n")))
1232 (lambda (item) (insert (makefile-browser-format-macro-line (car item) nil) "\n")))
1235 (sort-lines nil (point-min) (point-max))
1236 (goto-char (1- (point-max)))
1237 (delete-char 1) ; remove unnecessary newline at eob
1238 (goto-char (point-min))
1239 (forward-char makefile-browser-cursor-column)))
1242 ;;; Moving up and down in the browser
1245 (defun makefile-browser-next-line ()
1246 "Move the browser selection cursor to the next line."
1248 (if (not (makefile-last-line-p))
1251 (forward-char makefile-browser-cursor-column))))
1253 (defun makefile-browser-previous-line ()
1254 "Move the browser selection cursor to the previous line."
1256 (if (not (makefile-first-line-p))
1259 (forward-char makefile-browser-cursor-column))))
1262 ;;; Quitting the browser (returns to client buffer)
1265 (defun makefile-browser-quit ()
1266 "Leave the browser and return to the makefile buffer."
1268 (let ((my-client makefile-browser-client))
1269 (setq makefile-browser-client nil) ; we quitted, so NO client!
1270 (set-buffer-modified-p nil)
1271 (kill-buffer (current-buffer))
1272 (pop-to-buffer my-client)))
1275 ;;; Toggle state of a browser item
1278 (defun makefile-browser-toggle ()
1279 "Toggle the selection state of the browser item at the cursor position."
1281 (let ((this-line (count-lines (point-min) (point))))
1282 (setq this-line (max 1 this-line))
1283 (makefile-browser-toggle-state-for-line this-line)
1284 (goto-line this-line)
1285 (let ((inhibit-read-only t))
1287 (if (makefile-browser-on-macro-line-p)
1288 (let ((macro-name (makefile-browser-this-line-macro-name)))
1289 (delete-region (point) (progn (end-of-line) (point)))
1291 (makefile-browser-format-macro-line
1293 (makefile-browser-get-state-for-line this-line))))
1294 (let ((target-name (makefile-browser-this-line-target-name)))
1295 (delete-region (point) (progn (end-of-line) (point)))
1297 (makefile-browser-format-target-line
1299 (makefile-browser-get-state-for-line this-line))))))
1301 (forward-char makefile-browser-cursor-column)
1302 (if makefile-browser-auto-advance-after-selection-p
1303 (makefile-browser-next-line))))
1306 ;;; Making insertions into the client buffer
1309 (defun makefile-browser-insert-continuation ()
1310 "Insert a makefile continuation.
1311 In the makefile buffer, go to (end-of-line), insert a \'\\\'
1312 character, insert a new blank line, go to that line and indent by one TAB.
1313 This is most useful in the process of creating continued lines when copying
1314 large dependencies from the browser to the client buffer.
1315 \(point) advances accordingly in the client buffer."
1318 (set-buffer makefile-browser-client)
1322 (defun makefile-browser-insert-selection ()
1323 "Insert all selected targets and/or macros in the makefile buffer.
1324 Insertion takes place at point."
1328 (let ((current-line 1))
1330 (if (makefile-browser-get-state-for-line current-line)
1331 (makefile-browser-send-this-line-item))
1333 (setq current-line (1+ current-line))))))
1335 (defun makefile-browser-insert-selection-and-quit ()
1337 (makefile-browser-insert-selection)
1338 (makefile-browser-quit))
1340 (defun makefile-browser-send-this-line-item ()
1341 (if (makefile-browser-on-macro-line-p)
1343 (let ((macro-name (makefile-browser-this-line-macro-name)))
1344 (set-buffer makefile-browser-client)
1345 (insert (makefile-format-macro-ref macro-name) " ")))
1347 (let ((target-name (makefile-browser-this-line-target-name)))
1348 (set-buffer makefile-browser-client)
1349 (insert target-name " ")))))
1351 (defun makefile-browser-start-interaction ()
1352 (use-local-map makefile-browser-map)
1353 (setq buffer-read-only t))
1355 (defun makefile-browse (targets macros)
1356 (if (zerop (+ (length targets) (length macros)))
1359 (message "No macros or targets to browse! Consider running 'makefile-pickup-everything\'"))
1360 (let ((browser-buffer (get-buffer-create makefile-browser-buffer-name)))
1361 (pop-to-buffer browser-buffer)
1362 (make-variable-buffer-local 'makefile-browser-selection-vector)
1363 (makefile-browser-fill targets macros)
1364 (shrink-window-if-larger-than-buffer)
1365 (setq makefile-browser-selection-vector
1366 (make-vector (+ (length targets) (length macros)) nil))
1367 (makefile-browser-start-interaction))))
1369 (defun makefile-switch-to-browser ()
1371 (run-hooks 'makefile-browser-hook)
1372 (setq makefile-browser-client (current-buffer))
1373 (makefile-pickup-targets)
1374 (makefile-pickup-macros)
1375 (makefile-browse makefile-target-table
1376 ;; take out the runtime macros which were added for completion sake -gk
1377 (set-difference makefile-macro-table makefile-runtime-macros-list)))
1381 ;;; ------------------------------------------------------------
1382 ;;; Up-to-date overview buffer
1383 ;;; ------------------------------------------------------------
1385 (defun makefile-create-up-to-date-overview ()
1386 "Create a buffer containing an overview of the state of all known targets.
1387 Known targets are targets that are explicitly defined in that makefile;
1388 in other words, all targets that appear on the left hand side of a
1389 dependency in the makefile."
1391 (if (y-or-n-p "Are you sure that the makefile being edited is consistent? ")
1393 ;; The rest of this function operates on a temporary makefile, created by
1394 ;; writing the current contents of the makefile buffer.
1396 (let ((saved-target-table makefile-target-table)
1397 (this-buffer (current-buffer))
1398 (makefile-up-to-date-buffer
1399 (get-buffer-create makefile-up-to-date-buffer-name))
1400 (filename (makefile-save-temporary))
1402 ;; Forget the target table because it may contain picked-up filenames
1403 ;; that are not really targets in the current makefile.
1404 ;; We don't want to query these, so get a new target-table with just the
1405 ;; targets that can be found in the makefile buffer.
1406 ;; The 'old' target table will be restored later.
1408 (real-targets (progn
1409 (makefile-pickup-targets)
1410 makefile-target-table))
1411 (prereqs makefile-has-prereqs)
1414 (set-buffer makefile-up-to-date-buffer)
1415 (setq buffer-read-only nil)
1417 (makefile-query-targets filename real-targets prereqs)
1418 (if (zerop (buffer-size)) ; if it did not get us anything
1420 (kill-buffer (current-buffer))
1421 (message "No overview created!")))
1422 (set-buffer this-buffer)
1423 (setq makefile-target-table saved-target-table)
1424 (if (get-buffer makefile-up-to-date-buffer-name)
1426 (pop-to-buffer (get-buffer makefile-up-to-date-buffer-name))
1427 (shrink-window-if-larger-than-buffer)
1428 (sort-lines nil (point-min) (point-max))
1429 (setq buffer-read-only t))))))
1431 (defun makefile-save-temporary ()
1432 "Create a temporary file from the current makefile buffer."
1433 (let ((filename (makefile-generate-temporary-filename)))
1434 (write-region (point-min) (point-max) filename nil 0)
1435 filename)) ; return the filename
1437 (defun makefile-generate-temporary-filename ()
1438 "Create a filename suitable for use in `makefile-save-temporary'.
1439 Be careful to allow brain-dead file systems (DOS, SYSV ...) to cope
1440 with the generated name!"
1441 (let ((my-name (user-login-name))
1442 (my-uid (int-to-string (user-uid))))
1444 (if (> (length my-name) 3)
1445 (substring my-name 0 3)
1448 (if (> (length my-uid) 3)
1449 (substring my-uid 0 3)
1452 (defun makefile-query-targets (filename target-table prereq-list)
1453 "Fill the up-to-date overview buffer.
1454 Checks each target in TARGET-TABLE using `makefile-query-one-target-method'
1455 and generates the overview, one line per target name."
1458 (function (lambda (item)
1459 (let* ((target-name (car item))
1460 (no-prereqs (not (member target-name prereq-list)))
1461 (needs-rebuild (or no-prereqs
1463 makefile-query-one-target-method
1468 (cond (no-prereqs " .. has no prerequisites")
1469 (needs-rebuild " .. NEEDS REBUILD")
1470 (t " .. is up to date"))))
1473 (goto-char (point-min))
1474 (delete-file filename)) ; remove the tmpfile
1476 (defun makefile-query-by-make-minus-q (target &optional filename)
1478 (call-process makefile-brave-make nil nil nil
1479 "-f" filename "-q" target))))
1483 ;;; ------------------------------------------------------------
1484 ;;; Continuation cleanup
1485 ;;; ------------------------------------------------------------
1487 (defun makefile-cleanup-continuations ()
1488 (if (eq major-mode 'makefile-mode)
1489 (if (and makefile-cleanup-continuations-p
1490 (not buffer-read-only))
1492 (goto-char (point-min))
1493 (while (re-search-forward "\\\\[ \t]+$" (point-max) t)
1494 (replace-match "\\" t t))))))
1497 ;;; ------------------------------------------------------------
1498 ;;; Warn of suspicious lines
1499 ;;; ------------------------------------------------------------
1501 (defun makefile-warn-suspicious-lines ()
1502 (let ((dont-save nil))
1503 (if (and (eq major-mode 'makefile-mode)
1504 makefile-warn-suspicious-lines-p) ; -gk
1507 (goto-char (point-min))
1509 "\\(^[\t]+$\\)\\|\\(^[ ]+[\t]\\)" (point-max) t))))
1511 (let ((line-nr (count-lines (point-min) suspicious)))
1514 (format "Suspicious line %d. Save anyway "
1520 ;;; ------------------------------------------------------------
1521 ;;; GNU make function support
1522 ;;; ------------------------------------------------------------
1524 (defun makefile-insert-gmake-function ()
1525 "Insert a GNU make function call.
1526 Asks for the name of the function to use (with completion).
1527 Then prompts for all required parameters."
1529 (let* ((gm-function-name (completing-read
1531 makefile-gnumake-functions-alist
1533 (gm-function-prompts
1534 (cdr (assoc gm-function-name makefile-gnumake-functions-alist))))
1535 (if (not (zerop (length gm-function-name)))
1536 (insert (makefile-format-macro-ref
1537 (concat gm-function-name " "
1538 (makefile-prompt-for-gmake-funargs
1539 gm-function-name gm-function-prompts)))
1542 (defun makefile-prompt-for-gmake-funargs (function-name prompt-list)
1544 (function (lambda (one-prompt)
1545 (read-string (format "[%s] %s: " function-name one-prompt)
1552 ;;; ------------------------------------------------------------
1553 ;;; Utility functions
1554 ;;; ------------------------------------------------------------
1556 (defun makefile-do-macro-insertion (macro-name)
1557 "Insert a macro reference."
1558 (if (not (zerop (length macro-name)))
1559 (if (assoc macro-name makefile-runtime-macros-list)
1560 (insert "$" macro-name)
1561 (insert (makefile-format-macro-ref macro-name)))))
1563 (defun makefile-remember-target (target-name &optional has-prereqs)
1564 "Remember a given target if it is not already remembered for this buffer."
1565 (if (not (zerop (length target-name)))
1567 (if (not (assoc target-name makefile-target-table))
1568 (setq makefile-target-table
1569 (cons (list target-name) makefile-target-table)))
1571 (setq makefile-has-prereqs
1572 (cons target-name makefile-has-prereqs))))))
1574 (defun makefile-remember-macro (macro-name)
1575 "Remember a given macro if it is not already remembered for this buffer."
1576 (if (not (zerop (length macro-name)))
1577 (if (not (assoc macro-name makefile-macro-table))
1578 (setq makefile-macro-table
1579 (cons (list macro-name) makefile-macro-table)))))
1581 (defun makefile-forward-after-target-colon ()
1582 "Move point forward after inserting the terminating colon of a target.
1583 This acts according to the value of `makefile-tab-after-target-colon'."
1584 (if makefile-tab-after-target-colon
1588 (defun makefile-browser-on-macro-line-p ()
1589 "Determine if point is on a macro line in the browser."
1592 (re-search-forward "\\$[{(]" (makefile-end-of-line-point) t)))
1594 (defun makefile-browser-this-line-target-name ()
1595 "Extract the target name from a line in the browser."
1598 (skip-chars-backward "^ \t")
1599 (buffer-substring (point) (1- (makefile-end-of-line-point)))))
1601 (defun makefile-browser-this-line-macro-name ()
1602 "Extract the macro name from a line in the browser."
1605 (re-search-forward "\\$[{(]" (makefile-end-of-line-point) t)
1606 (let ((macro-start (point)))
1607 (skip-chars-forward "^})")
1608 (buffer-substring macro-start (point)))))
1610 (defun makefile-format-macro-ref (macro-name)
1611 "Format a macro reference.
1612 Uses `makefile-use-curly-braces-for-macros-p'."
1613 (if (or (char-equal ?\( (string-to-char macro-name))
1614 (char-equal ?\{ (string-to-char macro-name)))
1615 (format "$%s" macro-name)
1616 (if makefile-use-curly-braces-for-macros-p
1617 (format "${%s}" macro-name)
1618 (format "$(%s)" macro-name))))
1620 (defun makefile-browser-get-state-for-line (n)
1621 (aref makefile-browser-selection-vector (1- n)))
1623 (defun makefile-browser-set-state-for-line (n to-state)
1624 (aset makefile-browser-selection-vector (1- n) to-state))
1626 (defun makefile-browser-toggle-state-for-line (n)
1627 (makefile-browser-set-state-for-line n (not (makefile-browser-get-state-for-line n))))
1629 (defun makefile-beginning-of-line-point ()
1634 (defun makefile-end-of-line-point ()
1639 (defun makefile-last-line-p ()
1640 (= (makefile-end-of-line-point) (point-max)))
1642 (defun makefile-first-line-p ()
1643 (= (makefile-beginning-of-line-point) (point-min)))
1647 ;;; Support for other packages, like add-log and imenu.
1649 (defun makefile-add-log-defun ()
1650 "Return name of target or variable assignment that point is in.
1651 If it isn't in one, return nil."
1655 ;; Scan back line by line, noticing when we come to a
1656 ;; variable or rule definition, and giving up when we see
1657 ;; a line that is not part of either of those.
1660 ((looking-at makefile-macroassign-regex)
1661 (setq found (buffer-substring-no-properties (match-beginning 1)
1663 ((looking-at makefile-dependency-regex)
1664 (setq found (buffer-substring-no-properties (match-beginning 1)
1666 ;; Don't keep looking across a blank line or comment. Give up.
1667 ((looking-at "$\\|#")
1670 (setq found 'bobp)))
1673 (if (stringp found) found))))
1676 ;;;###autoload(add-to-list 'auto-mode-alist '("\\.ma?ke?\\'" . makefile-mode))
1677 ;;;###autoload(add-to-list 'auto-mode-alist '("\\(GNU\\)?[Mm]akefile\\(\\.in\\)*\\'" . makefile-mode))
1678 ;;;###autoload(add-to-list 'auto-mode-alist '("\\.am\\'" . makefile-mode))
1679 ;;;###autoload(add-to-list 'interpreter-mode-alist '("make" . makefile-mode))
1681 ;; provide 'makefile for bug-compatibility
1683 (provide 'make-mode)
1684 ;;; make-mode.el ends here