;;; make-mode.el --- makefile editing commands for Emacs
-;; Copyright (C) 1992, 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1992, 1994, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+;; 2006, 2007, 2008 Free Software Foundation, Inc.
;; Author: Thomas Neumann <tom@smart.bo.open.de>
;; Eric S. Raymond <esr@snark.thyrsus.com>
;; This file is part of GNU Emacs.
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; that if you change this regexp you might have to fix the imenu index in
;; makefile-imenu-generic-expression.
(defconst makefile-macroassign-regex
- "^ *\\([^ \n\t][^:#= \t\n]*\\)[ \t]*\\(?:!=\\|[*:+]?[:?]?=\\)"
+ ;; We used to match not just the varname but also the whole value
+ ;; (spanning potentially several lines).
+ ;; "^ *\\([^ \n\t][^:#= \t\n]*\\)[ \t]*\\(?:!=[ \t]*\\(\\(?:.+\\\\\n\\)*.+\\)\\|[*:+]?[:?]?=[ \t]*\\(\\(?:.*\\\\\n\\)*.*\\)\\)"
+ ;; What about the define statement? What about differentiating this for makepp?
+ "\\(?:^\\|^export\\|^override\\|:\\|: *override\\) *\\([^ \n\t][^:#= \t\n]*\\)[ \t]*\\(?:!=\\|[*:+]?[:?]?=\\)"
"Regex used to find macro assignment lines in a makefile.")
(defconst makefile-var-use-regex
"\\(^\\..*\\)\\|\\(.*~$\\)\\|\\(.*,v$\\)\\|\\(\\.[chy]\\)"
"Regex for filenames that will NOT be included in the target list.")
-(if (fboundp 'facemenu-unlisted-faces)
- (add-to-list 'facemenu-unlisted-faces 'makefile-space))
(defvar makefile-space 'makefile-space
"Face to use for highlighting leading spaces in Font-Lock mode.")
"List of keywords understood by automake.")
(defconst makefile-gmake-statements
- `("-sinclude" "sinclude" "override" "vpath"
+ `("-sinclude" "sinclude" "vpath" ; makefile-makepp-statements takes rest
"ifdef" "ifndef" "ifeq" "ifneq" "-include" "define" "endef" "export"
- "unexport"
+ "override define" "override" "unexport"
,@(cdr makefile-automake-statements))
"List of keywords understood by gmake.")
`("and ifdef" "and ifndef" "and ifeq" "and ifneq" "and ifperl"
"and ifmakeperl" "and ifsys" "and ifnsys" "build_cache" "build_check"
"else ifdef" "else ifndef" "else ifeq" "else ifneq" "else ifperl"
- "else ifmakeperl" "else ifsys" "else ifnsys" "enddef" "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" "register_command_parser"
+ "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 4 makefile-gmake-statements))
+ ,@(nthcdr 3 makefile-gmake-statements))
"List of keywords understood by gmake.")
(defconst makefile-bsdmake-statements
:type 'string
:group 'makefile)
-(defcustom makefile-query-one-target-method 'makefile-query-by-make-minus-q
+(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.
The function must satisfy this calling convention:
makefile, any nonzero integer value otherwise."
:type 'function
:group 'makefile)
+(defvaralias 'makefile-query-one-target-method
+ '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."
(define-abbrev-table 'makefile-mode-abbrev-table ()))
(defvar makefile-mode-map
- (let ((map (make-sparse-keymap)))
+ (let ((map (make-sparse-keymap))
+ (opt-map (make-sparse-keymap)))
;; set up the keymap
(define-key map "\C-c:" 'makefile-insert-target-ref)
(if makefile-electric-keys
(define-key map [menu-bar makefile-mode]
(cons "Makefile" (make-sparse-keymap "Makefile")))
+ (define-key map [menu-bar makefile-mode makefile-type]
+ (cons "Switch Makefile Type" opt-map))
+ (define-key opt-map [makefile-makepp-mode]
+ '(menu-item "Makepp" makefile-makepp-mode
+ :help "An adapted `makefile-mode' that knows about makepp"
+ :button (:radio . (eq major-mode 'makefile-makepp-mode))))
+ (define-key opt-map [makefile-imake-mode]
+ '(menu-item "Imake" makefile-imake-mode
+ :help "An adapted `makefile-mode' that knows about imake"
+ :button (:radio . (eq major-mode 'makefile-imake-mode))))
+ (define-key opt-map [makefile-mode]
+ '(menu-item "Classic" makefile-mode
+ :help "`makefile-mode' with no special functionality"
+ :button (:radio . (eq major-mode 'makefile-mode))))
+ (define-key opt-map [makefile-bsdmake-mode]
+ '(menu-item "BSD" makefile-bsdmake-mode
+ :help "An adapted `makefile-mode' that knows about BSD make"
+ :button (:radio . (eq major-mode 'makefile-bsdmake-mode))))
+ (define-key opt-map [makefile-automake-mode]
+ '(menu-item "Automake" makefile-automake-mode
+ :help "An adapted `makefile-mode' that knows about automake"
+ :button (:radio . (eq major-mode 'makefile-automake-mode))))
+ (define-key opt-map [makefile-gmake-mode]
+ '(menu-item "GNU make" makefile-gmake-mode
+ :help "An adapted `makefile-mode' that knows about GNU make"
+ :button (:radio . (eq major-mode 'makefile-gmake-mode))))
(define-key map [menu-bar makefile-mode browse]
- '("Pop up Makefile Browser" . makefile-switch-to-browser))
- (define-key map [menu-bar makefile-mode complete]
- '("Complete Target or Macro" . makefile-complete))
+ '(menu-item "Pop up Makefile Browser" makefile-switch-to-browser
+ ;; XXX: this needs a better string, the function is not documented...
+ :help "Pop up Makefile Browser"))
+ (define-key map [menu-bar makefile-mode overview]
+ '(menu-item "Up To Date Overview" makefile-create-up-to-date-overview
+ :help "Create a buffer containing an overview of the state of all known targets"))
+ ;; Target related
+ (define-key map [menu-bar makefile-mode separator1] '("----"))
+ (define-key map [menu-bar makefile-mode pickup-file]
+ '(menu-item "Pick File Name as Target" makefile-pickup-filenames-as-targets
+ :help "Scan the current directory for filenames to use as targets"))
+ (define-key map [menu-bar makefile-mode function]
+ '(menu-item "Insert GNU make function" makefile-insert-gmake-function
+ :help "Insert a GNU make function call"))
(define-key map [menu-bar makefile-mode pickup]
- '("Find Targets and Macros" . makefile-pickup-everything))
-
+ '(menu-item "Find Targets and Macros" makefile-pickup-everything
+ :help "Notice names of all macros and targets in Makefile"))
+ (define-key map [menu-bar makefile-mode complete]
+ '(menu-item "Complete Target or Macro" makefile-complete
+ :help "Perform completion on Makefile construct preceding point"))
+ (define-key map [menu-bar makefile-mode backslash]
+ '(menu-item "Backslash Region" makefile-backslash-region
+ :help "Insert, align, or delete end-of-line backslashes on the lines in the region"))
+ ;; Motion
+ (define-key map [menu-bar makefile-mode separator] '("----"))
(define-key map [menu-bar makefile-mode prev]
- '("Move to Previous Dependency" . makefile-previous-dependency))
+ '(menu-item "Move to Previous Dependency" makefile-previous-dependency
+ :help "Move point to the beginning of the previous dependency line"))
(define-key map [menu-bar makefile-mode next]
- '("Move to Next Dependency" . makefile-next-dependency))
+ '(menu-item "Move to Next Dependency" makefile-next-dependency
+ :help "Move point to the beginning of the next dependency line"))
map)
"The keymap that is used in Makefile mode.")
-(defvar makefile-browser-map nil
+
+(defvar makefile-browser-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "n" 'makefile-browser-next-line)
+ (define-key map "\C-n" 'makefile-browser-next-line)
+ (define-key map "p" 'makefile-browser-previous-line)
+ (define-key map "\C-p" 'makefile-browser-previous-line)
+ (define-key map " " 'makefile-browser-toggle)
+ (define-key map "i" 'makefile-browser-insert-selection)
+ (define-key map "I" 'makefile-browser-insert-selection-and-quit)
+ (define-key map "\C-c\C-m" 'makefile-browser-insert-continuation)
+ (define-key map "q" 'makefile-browser-quit)
+ ;; disable horizontal movement
+ (define-key map "\C-b" 'undefined)
+ (define-key map "\C-f" 'undefined)
+ map)
"The keymap that is used in the macro- and target browser.")
-(if makefile-browser-map
- ()
- (setq makefile-browser-map (make-sparse-keymap))
- (define-key makefile-browser-map "n" 'makefile-browser-next-line)
- (define-key makefile-browser-map "\C-n" 'makefile-browser-next-line)
- (define-key makefile-browser-map "p" 'makefile-browser-previous-line)
- (define-key makefile-browser-map "\C-p" 'makefile-browser-previous-line)
- (define-key makefile-browser-map " " 'makefile-browser-toggle)
- (define-key makefile-browser-map "i" 'makefile-browser-insert-selection)
- (define-key makefile-browser-map "I" 'makefile-browser-insert-selection-and-quit)
- (define-key makefile-browser-map "\C-c\C-m" 'makefile-browser-insert-continuation)
- (define-key makefile-browser-map "q" 'makefile-browser-quit)
- ;; disable horizontal movement
- (define-key makefile-browser-map "\C-b" 'undefined)
- (define-key makefile-browser-map "\C-f" 'undefined))
-
-
-(defvar makefile-mode-syntax-table nil)
-(if makefile-mode-syntax-table
- ()
- (setq makefile-mode-syntax-table (make-syntax-table))
- (modify-syntax-entry ?\( "() " makefile-mode-syntax-table)
- (modify-syntax-entry ?\) ")( " makefile-mode-syntax-table)
- (modify-syntax-entry ?\[ "(] " makefile-mode-syntax-table)
- (modify-syntax-entry ?\] ")[ " makefile-mode-syntax-table)
- (modify-syntax-entry ?\{ "(} " makefile-mode-syntax-table)
- (modify-syntax-entry ?\} "){ " makefile-mode-syntax-table)
- (modify-syntax-entry ?\' "\" " makefile-mode-syntax-table)
- (modify-syntax-entry ?\` "\" " makefile-mode-syntax-table)
- (modify-syntax-entry ?# "< " makefile-mode-syntax-table)
- (modify-syntax-entry ?\n "> " makefile-mode-syntax-table))
+
+
+(defvar makefile-mode-syntax-table
+ (let ((st (make-syntax-table)))
+ (modify-syntax-entry ?\( "() " st)
+ (modify-syntax-entry ?\) ")( " st)
+ (modify-syntax-entry ?\[ "(] " st)
+ (modify-syntax-entry ?\] ")[ " st)
+ (modify-syntax-entry ?\{ "(} " st)
+ (modify-syntax-entry ?\} "){ " st)
+ (modify-syntax-entry ?\' "\" " st)
+ (modify-syntax-entry ?\` "\" " st)
+ (modify-syntax-entry ?# "< " st)
+ (modify-syntax-entry ?\n "> " st)
+ st))
(defvar makefile-imake-mode-syntax-table (copy-syntax-table
makefile-mode-syntax-table))
nil nil
((?$ . "."))
backward-paragraph
- (font-lock-syntactic-keywords . makefile-font-lock-syntactic-keywords)
- (font-lock-support-mode))) ; JIT breaks on long series of continuation lines.
+ (font-lock-syntactic-keywords
+ . makefile-font-lock-syntactic-keywords)))
;; Add-log.
(make-local-variable 'add-log-current-defun-function)
(save-excursion
(beginning-of-line)
(cond
- ((looking-at "^#+")
- ;; Found a comment. Set the fill prefix, and find the paragraph
- ;; boundaries by searching for lines that look like comment-only
- ;; lines.
- (let ((fill-prefix (match-string-no-properties 0))
- (fill-paragraph-function nil))
- (save-excursion
- (save-restriction
- (narrow-to-region
- ;; Search backwards.
- (save-excursion
- (while (and (zerop (forward-line -1))
- (looking-at "^#")))
- ;; We may have gone too far. Go forward again.
- (or (looking-at "^#")
- (forward-line 1))
- (point))
- ;; Search forwards.
- (save-excursion
- (while (looking-at "^#")
- (forward-line))
- (point)))
- (fill-paragraph nil)
- t))))
+ ((looking-at "^[ \t]*#+\\s-*")
+ ;; Found a comment. Return nil to let normal filling take place.
+ nil)
;; Must look for backslashed-region before looking for variable
;; assignment.
(makefile-backslash-region (point-min) (point-max) nil)
(goto-char (point-max))
(if (< (skip-chars-backward "\n") 0)
- (delete-region (point) (point-max))))))
+ (delete-region (point) (point-max)))))
+ ;; Return non-nil to indicate it's been filled.
+ t)
((looking-at makefile-macroassign-regex)
;; Have a macro assign. Fill just this line, and then backslash
(narrow-to-region (point) (line-beginning-position 2))
(let ((fill-paragraph-function nil))
(fill-paragraph nil))
- (makefile-backslash-region (point-min) (point-max) nil)))))
+ (makefile-backslash-region (point-min) (point-max) nil))
+ ;; Return non-nil to indicate it's been filled.
+ t)
- ;; Always return non-nil so we don't fill anything else.
- t)
+ (t
+ ;; Return non-nil so we don't fill anything else.
+ t))))
\f
(defun makefile-query-targets (filename target-table prereq-list)
"Fill the up-to-date overview buffer.
-Checks each target in TARGET-TABLE using `makefile-query-one-target-method'
+Checks each target in TARGET-TABLE using
+`makefile-query-one-target-method-function'
and generates the overview, one line per target name."
(insert
(mapconcat
(no-prereqs (not (member target-name prereq-list)))
(needs-rebuild (or no-prereqs
(funcall
- makefile-query-one-target-method
+ makefile-query-one-target-method-function
target-name
filename))))
(format "\t%s%s"
;;; ------------------------------------------------------------
(defun makefile-cleanup-continuations ()
- (if (eq major-mode 'makefile-mode)
+ (if (derived-mode-p 'makefile-mode)
(if (and makefile-cleanup-continuations
(not buffer-read-only))
(save-excursion
(defun makefile-warn-suspicious-lines ()
;; Returning non-nil cancels the save operation
- (if (eq major-mode 'makefile-mode)
+ (if (derived-mode-p 'makefile-mode)
(save-excursion
(goto-char (point-min))
(if (re-search-forward "^\\(\t+$\\| +\t\\)" nil t)
(count-lines (point-min) (point)))))))))
(defun makefile-warn-continuations ()
- (if (eq major-mode 'makefile-mode)
+ (if (derived-mode-p 'makefile-mode)
(save-excursion
(goto-char (point-min))
(if (re-search-forward "\\\\[ \t]+$" nil t)
"To be called as an anchored matcher by font-lock.
The anchor must have matched the opening parens in the first group."
(let ((s (match-string-no-properties 1)))
- (setq s (cond ((string= s "(") "\\(.*?\\)[ \t]*)")
- ((string= s "{") "\\(.*?\\)[ \t]*}")
- ((string= s "((") "\\(.*?\\)[ \t]*))")
- ((string= s "{{") "\\(.*?\\)[ \t]*}}")))
- (if s (looking-at s))))
+ ;; FIXME forward-sexp or somesuch would be better?
+ (if (setq s (cond ((string= s "(") ")")
+ ((string= s "{") "}")
+ ((string= s "((") "))")
+ ((string= s "{{") "}}")))
+ (re-search-forward (concat "\\(.*\\)[ \t]*" s) (line-end-position) t))))
(defun makefile-match-dependency (bound)
"Search for `makefile-dependency-regex' up to BOUND.
(provide 'make-mode)
-;;; arch-tag: bd23545a-de91-44fb-b1b2-feafbb2635a0
+;; arch-tag: bd23545a-de91-44fb-b1b2-feafbb2635a0
;;; make-mode.el ends here