;;; make-mode.el --- makefile editing commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1992, 1994, 1999-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1994, 1999-2013 Free Software Foundation, Inc.
;; Author: Thomas Neumann <tom@smart.bo.open.de>
;; Eric S. Raymond <esr@snark.thyrsus.com>
:version "22.1")
(defcustom makefile-browser-buffer-name "*Macros and Targets*"
- "*Name of the macro- and target browser buffer."
+ "Name of the macro- and target browser buffer."
:type 'string
:group 'makefile)
(defcustom makefile-target-colon ":"
- "*String to append to all target names inserted by `makefile-insert-target'.
+ "String to append to all target names inserted by `makefile-insert-target'.
\":\" or \"::\" are common values."
:type 'string
:group 'makefile)
(defcustom makefile-macro-assign " = "
- "*String to append to all macro names inserted by `makefile-insert-macro'.
+ "String to append to all macro names inserted by `makefile-insert-macro'.
The normal value should be \" = \", since this is what
standard make expects. However, newer makes such as dmake
allow a larger variety of different macro assignments, so you
:group 'makefile)
(defcustom makefile-electric-keys nil
- "*If non-nil, Makefile mode should install electric keybindings.
+ "If non-nil, Makefile mode should install electric keybindings.
Default is nil."
:type 'boolean
:group 'makefile)
(defcustom makefile-use-curly-braces-for-macros-p nil
- "*Controls the style of generated macro references.
+ "Controls the style of generated macro references.
Non-nil means macro references should use curly braces, like `${this}'.
nil means use parentheses, like `$(this)'."
:type 'boolean
:group 'makefile)
(defcustom makefile-tab-after-target-colon t
- "*If non-nil, insert a TAB after a target colon.
+ "If non-nil, insert a TAB after a target colon.
Otherwise, a space is inserted.
The default is t."
:type 'boolean
:group 'makefile)
(defcustom makefile-browser-leftmost-column 10
- "*Number of blanks to the left of the browser selection mark."
+ "Number of blanks to the left of the browser selection mark."
:type 'integer
:group 'makefile)
(defcustom makefile-browser-cursor-column 10
- "*Column the cursor goes to when it moves up or down in the Makefile browser."
+ "Column the cursor goes to when it moves up or down in the Makefile browser."
:type 'integer
:group 'makefile)
(defcustom makefile-backslash-column 48
- "*Column in which `makefile-backslash-region' inserts backslashes."
+ "Column in which `makefile-backslash-region' inserts backslashes."
:type 'integer
:group 'makefile)
(defcustom makefile-backslash-align t
- "*If non-nil, `makefile-backslash-region' will align backslashes."
+ "If non-nil, `makefile-backslash-region' will align backslashes."
:type 'boolean
:group 'makefile)
(defcustom makefile-browser-selected-mark "+ "
- "*String used to mark selected entries in the Makefile browser."
+ "String used to mark selected entries in the Makefile browser."
:type 'string
:group 'makefile)
(defcustom makefile-browser-unselected-mark " "
- "*String used to mark unselected entries in the Makefile browser."
+ "String used to mark unselected entries in the Makefile browser."
:type 'string
:group 'makefile)
(defcustom makefile-browser-auto-advance-after-selection-p t
- "*If non-nil, cursor will move after item is selected in Makefile browser."
+ "If non-nil, cursor will move after item is selected in Makefile browser."
:type 'boolean
:group 'makefile)
(defcustom makefile-pickup-everything-picks-up-filenames-p nil
- "*If non-nil, `makefile-pickup-everything' picks up filenames as targets.
+ "If non-nil, `makefile-pickup-everything' picks up filenames as targets.
This means it calls `makefile-pickup-filenames-as-targets'.
Otherwise filenames are omitted."
:type 'boolean
:group 'makefile)
(defcustom makefile-cleanup-continuations nil
- "*If non-nil, automatically clean up continuation lines when saving.
+ "If non-nil, automatically clean up continuation lines when saving.
A line is cleaned up by removing all whitespace following a trailing
backslash. This is done silently.
IMPORTANT: Please note that enabling this option causes Makefile mode
:group 'makefile)
(defcustom makefile-mode-hook nil
- "*Normal hook run by `makefile-mode'."
+ "Normal hook run by `makefile-mode'."
:type 'hook
:group 'makefile)
(defcustom makefile-runtime-macros-list
'(("@") ("&") (">") ("<") ("*") ("^") ("+") ("?") ("%") ("$"))
- "*List of macros that are resolved by make at runtime.
+ "List of macros that are resolved by make at runtime.
If you insert a macro reference using `makefile-insert-macro-ref', the name
of the macro is checked against this list. If it can be found its name will
not be enclosed in { } or ( )."
"List of keywords understood by automake.")
(defconst makefile-gmake-statements
- `("-sinclude" "sinclude" "vpath" ; makefile-makepp-statements takes rest
+ `("-sinclude" "sinclude" ; makefile-makepp-statements takes rest
"ifdef" "ifndef" "ifeq" "ifneq" "-include" "define" "endef" "export"
- "override define" "override" "unexport"
+ "override define" "override" "unexport" "vpath"
,@(cdr makefile-automake-statements))
"List of keywords understood by gmake.")
-;; These are even more silly, because you can have more spaces in between.
(defconst makefile-makepp-statements
- `("and ifdef" "and ifndef" "and ifeq" "and ifneq" "and ifperl"
- "and ifmakeperl" "and ifsys" "and ifnsys" "build_cache" "build_check"
+ `(t ; - alternately means _
+ ;; todo: take if* out of these lists, and let the negation regexp do it all
+ "ifperl" "ifmakeperl" "ifsys" "ifnsys" "iftrue" "ifntrue"
+ "and ifdef" "and ifndef" "and ifeq" "and ifneq" "and ifperl"
+ "and ifmakeperl" "and ifsys" "and ifnsys" "and iftrue" "and ifntrue"
"else ifdef" "else ifndef" "else ifeq" "else ifneq" "else ifperl"
- "else ifmakeperl" "else ifsys" "else ifnsys" "enddef" "global"
- "load_makefile" "ifperl" "ifmakeperl" "ifsys" "ifnsys" "_include"
- "makeperl" "makesub" "no_implicit_load" "perl" "perl-begin" "perl_begin"
- "perl-end" "perl_end" "prebuild" "or ifdef" "or ifndef" "or ifeq"
- "or ifneq" "or ifperl" "or ifmakeperl" "or ifsys" "or ifnsys"
- "override export" "override global" "register_command_parser"
- "register_scanner" "repository" "runtime" "signature" "sub"
- ,@(nthcdr 3 makefile-gmake-statements))
+ "else ifmakeperl" "else ifsys" "else ifnsys" "else iftrue" "else ifntrue"
+ "or ifdef" "or ifndef" "or ifeq" "or ifneq" "or ifperl"
+ "or ifmakeperl" "or ifsys" "or ifnsys" "or iftrue" "or ifntrue"
+
+ "autoload" "build-cache" "build-check" "enddef" "export define"
+ "global" "global build-cache" "global build-check" "global define"
+ "global signature" "global override signature" "load-makefile"
+ "make" "makeperl" "makesub" "no-implicit-load" "perl" "perl-begin"
+ "perl-end" "prebuild" "override export" "override global" "register-parser"
+ "register-command-parser" "register-input-suffix"
+ "register-scanner" "repository" "runtime" "signature" "sub"
+
+ ,@(nthcdr 2 makefile-gmake-statements))
"List of keywords understood by gmake.")
(defconst makefile-bsdmake-statements
;; Fontify conditionals and includes.
(,(concat "^\\(?: [ \t]*\\)?"
- (regexp-opt keywords t)
+ (replace-regexp-in-string
+ " " "[ \t]+"
+ (if (eq (car keywords) t)
+ (replace-regexp-in-string "-" "[_-]"
+ (regexp-opt (cdr keywords) t))
+ (regexp-opt keywords t)))
"\\>[ \t]*\\([^: \t\n#]*\\)")
(1 font-lock-keyword-face) (2 font-lock-variable-name-face))
makefile-var-use-regex
makefile-makepp-statements
nil
- "^\\(?: [ \t]*\\)?\\(?:and[ \t]+\\|else[ \t]+\\|or[ \t]+\\)?if\\(n\\)\\(?:def\\|eq\\|sys\\)\\>"
+ "^\\(?: [ \t]*\\)?\\(?:and[ \t]+\\|else[ \t]+\\|or[ \t]+\\)?if\\(n\\)\\(?:def\\|eq\\|sys\\|true\\)\\>"
'("[^$]\\(\\$[({]\\(?:output\\|stem\\|target\\)s?\\_>.*?[})]\\)"
1 'makefile-targets append)
(2 font-lock-keyword-face t)
(3 font-lock-variable-name-face t))
- ;; $(function ...) $((function ...)) ${function ...} ${{function ...}}
- '("[^$]\\$\\(?:((?\\|{{?\\)\\([-a-zA-Z0-9_.]+\\s \\)"
+ ;; $(function ...) $((function ...)) ${...} ${{...}} $[...] $[[...]]
+ '("[^$]\\$\\(?:((?\\|{{?\\|\\[\\[?\\)\\([-a-zA-Z0-9_.]+\\s \\)"
1 font-lock-function-name-face prepend)
- ;; $(shell ...) $((shell ...)) ${shell ...} ${{shell ...}}
- '("[^$]\\$\\(((?\\|{{?\\)shell\\(?:[-_]\\(?:global[-_]\\)?once\\)?[ \t]+"
+ ;; $(shell ...) $((shell ...)) ${...} ${{...}} $[...] $[[...]]
+ '("[^$]\\$\\(((?\\|{{?\\|\\[\\[?\\)shell\\(?:[-_]\\(?:global[-_]\\)?once\\)?[ \t]+"
makefile-match-function-end nil nil
(1 'makefile-shell prepend t))
- ;; $(perl ...) $((perl ...)) ${perl ...} ${{perl ...}}
- '("[^$]\\$\\(((?\\|{{?\\)makeperl[ \t]+"
+ ;; $(perl ...) $((perl ...)) ${...} ${{...}} $[...] $[[...]]
+ '("[^$]\\$\\(((?\\|{{?\\|\\[\\[?\\)makeperl[ \t]+"
makefile-match-function-end nil nil
(1 'makefile-makepp-perl prepend t))
'("[^$]\\$\\(((?\\|{{?\\)perl[ \t]+"
;; should return an exit status of zero if the target `foo' is
;; up to date and a nonzero exit status otherwise.
;; Many makes can do this although the docs/manpages do not mention
-;; it. Try it with your favourite one. GNU make, System V make, and
+;; it. Try it with your favorite one. GNU make, System V make, and
;; Dennis Vadura's DMake have no problems.
;; Set the variable `makefile-brave-make' to the name of the
;; make utility that does this on your system.
;; ------------------------------------------------------------
(defcustom makefile-brave-make "make"
- "*How to invoke make, for `makefile-query-targets'.
+ "How to invoke make, for `makefile-query-targets'.
This should identify a `make' command that can handle the `-q' option."
:type 'string
:group 'makefile)
(defcustom makefile-query-one-target-method-function
'makefile-query-by-make-minus-q
- "*Function to call to determine whether a make target is up to date.
+ "Function to call to determine whether a make target is up to date.
The function must satisfy this calling convention:
* As its first argument, it must accept the name of the target to
'makefile-query-one-target-method-function)
(defcustom makefile-up-to-date-buffer-name "*Makefile Up-to-date overview*"
- "*Name of the Up-to-date overview buffer."
+ "Name of the Up-to-date overview buffer."
:type 'string
:group 'makefile)
(make-local-variable 'makefile-need-macro-pickup)
;; Font lock.
- (set (make-local-variable 'font-lock-defaults)
- ;; SYNTAX-BEGIN set to backward-paragraph to avoid slow-down
- ;; near the end of a large buffer, due to parse-partial-sexp's
- ;; trying to parse all the way till the beginning of buffer.
- '(makefile-font-lock-keywords
- nil nil
- ((?$ . "."))
- backward-paragraph))
- (set (make-local-variable 'syntax-propertize-function)
- makefile-syntax-propertize-function)
+ (setq-local font-lock-defaults
+ ;; Set SYNTAX-BEGIN to backward-paragraph to avoid
+ ;; slow-down near the end of a large buffer, due to
+ ;; `parse-partial-sexp' trying to parse all the way till
+ ;; the beginning of buffer.
+ '(makefile-font-lock-keywords
+ nil nil
+ ((?$ . "."))
+ backward-paragraph))
+ (setq-local syntax-propertize-function
+ makefile-syntax-propertize-function)
;; Add-log.
- (set (make-local-variable 'add-log-current-defun-function)
- 'makefile-add-log-defun)
+ (setq-local add-log-current-defun-function
+ 'makefile-add-log-defun)
;; Imenu.
- (set (make-local-variable 'imenu-generic-expression)
- makefile-imenu-generic-expression)
+ (setq-local imenu-generic-expression
+ makefile-imenu-generic-expression)
;; Dabbrev.
- (set (make-local-variable 'dabbrev-abbrev-skip-leading-regexp) "\\$")
+ (setq-local dabbrev-abbrev-skip-leading-regexp "\\$")
;; Other abbrevs.
(setq local-abbrev-table makefile-mode-abbrev-table)
;; Filling.
- (set (make-local-variable 'fill-paragraph-function) 'makefile-fill-paragraph)
+ (setq-local fill-paragraph-function 'makefile-fill-paragraph)
;; Comment stuff.
- (set (make-local-variable 'comment-start) "#")
- (set (make-local-variable 'comment-end) "")
- (set (make-local-variable 'comment-start-skip) "#+[ \t]*")
+ (setq-local comment-start "#")
+ (setq-local comment-end "")
+ (setq-local comment-start-skip "#+[ \t]*")
;; Make sure TAB really inserts \t.
- (set (make-local-variable 'indent-line-function) 'indent-to-left-margin)
+ (setq-local indent-line-function 'indent-to-left-margin)
;; Real TABs are important in makefiles
(setq indent-tabs-mode t))
;;;###autoload
(define-derived-mode makefile-makepp-mode makefile-mode "Makeppfile"
"An adapted `makefile-mode' that knows about makepp."
- (set (make-local-variable 'makefile-rule-action-regex)
- makefile-makepp-rule-action-regex)
+ (setq-local makefile-rule-action-regex makefile-makepp-rule-action-regex)
(setq font-lock-defaults
`(makefile-makepp-font-lock-keywords ,@(cdr font-lock-defaults))
imenu-generic-expression
;;;###autoload
(define-derived-mode makefile-bsdmake-mode makefile-mode "BSDmakefile"
"An adapted `makefile-mode' that knows about BSD make."
- (set (make-local-variable 'makefile-dependency-regex)
- makefile-bsdmake-dependency-regex)
- (set (make-local-variable 'makefile-dependency-skip) "^:!")
- (set (make-local-variable 'makefile-rule-action-regex)
- makefile-bsdmake-rule-action-regex)
+ (setq-local makefile-dependency-regex makefile-bsdmake-dependency-regex)
+ (setq-local makefile-dependency-skip "^:!")
+ (setq-local makefile-rule-action-regex makefile-bsdmake-rule-action-regex)
(setq font-lock-defaults
`(makefile-bsdmake-font-lock-keywords ,@(cdr font-lock-defaults))))
(define-derived-mode makefile-imake-mode makefile-mode "Imakefile"
"An adapted `makefile-mode' that knows about imake."
:syntax-table makefile-imake-mode-syntax-table
- (set (make-local-variable 'syntax-propertize-function) nil)
+ (setq-local syntax-propertize-function nil)
(setq font-lock-defaults
`(makefile-imake-font-lock-keywords ,@(cdr font-lock-defaults))))
(save-excursion
(goto-char from)
(let ((column makefile-backslash-column)
- (endmark (make-marker)))
- (move-marker endmark to)
+ (endmark (copy-marker to)))
;; Compute the smallest column number past the ends of all the lines.
- (if makefile-backslash-align
- (progn
- (if (not delete-flag)
- (while (< (point) to)
- (end-of-line)
- (if (= (preceding-char) ?\\)
- (progn (forward-char -1)
- (skip-chars-backward " \t")))
- (setq column (max column (1+ (current-column))))
- (forward-line 1)))
- ;; Adjust upward to a tab column, if that doesn't push
- ;; past the margin.
- (if (> (% column tab-width) 0)
- (let ((adjusted (* (/ (+ column tab-width -1) tab-width)
- tab-width)))
- (if (< adjusted (window-width))
- (setq column adjusted))))))
+ (when (and makefile-backslash-align (not delete-flag))
+ (while (< (point) to)
+ (end-of-line)
+ (if (= (preceding-char) ?\\)
+ (progn (forward-char -1)
+ (skip-chars-backward " \t")))
+ (setq column (max column (1+ (current-column))))
+ (forward-line 1))
+ ;; Adjust upward to a tab column, if that doesn't push
+ ;; past the margin.
+ (if (> (% column tab-width) 0)
+ (let ((adjusted (* (/ (+ column tab-width -1) tab-width)
+ tab-width)))
+ (if (< adjusted (window-width))
+ (setq column adjusted)))))
;; Don't modify blank lines at start of region.
(goto-char from)
(while (and (< (point) endmark) (eolp))
;; Filling
-(defun makefile-fill-paragraph (_arg)
- ;; Fill comments, backslashed lines, and variable definitions
- ;; specially.
+(defun makefile-fill-paragraph (_justify)
+ "Function used for `fill-paragraph-function' in Makefile mode.
+Fill comments, backslashed lines, and variable definitions specially."
(save-excursion
(beginning-of-line)
(cond
((or (eq (char-before (line-end-position 1)) ?\\)
(eq (char-before (line-end-position 0)) ?\\))
;; A backslash region. Find beginning and end, remove
- ;; backslashes, fill, and then reapply backslahes.
+ ;; backslashes, fill, and then reapply backslashes.
(end-of-line)
(let ((beginning
(save-excursion
(end-of-line 0)
(while (= (preceding-char) ?\\)
(end-of-line 0))
- (forward-char)
- (point)))
+ ;; Maybe we hit bobp, in which case we are not at EOL.
+ (if (eolp)
+ (1+ (point))
+ (point))))
(end
(save-excursion
(while (= (preceding-char) ?\\)
(save-restriction
(narrow-to-region beginning end)
(makefile-backslash-region (point-min) (point-max) t)
+ ;; Backslashed newlines are marked as punctuation, so when
+ ;; fill-delete-newlines turns the LF into SPC, we end up with spaces
+ ;; which back-to-indentation (called via fill-newline ->
+ ;; fill-indent-to-left-margin -> indent-line-to) thinks are real code
+ ;; (bug#13179).
+ (remove-text-properties (point-min) (point-max) '(syntax-table))
(let ((fill-paragraph-function nil)
;; Adjust fill-column to allow space for the backslash.
(fill-column (- fill-column 1)))
(setq buffer-read-only t))
(defun makefile-browse (targets macros)
- (interactive)
(if (zerop (+ (length targets) (length macros)))
(progn
(beep)
(pop-to-buffer browser-buffer)
(makefile-browser-fill targets macros)
(shrink-window-if-larger-than-buffer)
- (set (make-local-variable 'makefile-browser-selection-vector)
- (make-vector (+ (length targets) (length macros)) nil))
+ (setq-local makefile-browser-selection-vector
+ (make-vector (+ (length targets) (length macros)) nil))
(makefile-browser-start-interaction))))
(defun makefile-switch-to-browser ()
;; FIXME forward-sexp or somesuch would be better?
(if (setq s (cond ((string= s "(") ")")
((string= s "{") "}")
+ ((string= s "[") "]")
((string= s "((") "))")
- ((string= s "{{") "}}")))
+ ((string= s "{{") "}}")
+ ((string= s "[[") "]]")))
(re-search-forward (concat "\\(.*\\)[ \t]*" s) (line-end-position) t))))
(defun makefile-match-dependency (bound)