aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Pfeiffer2005-05-16 20:13:09 +0000
committerDaniel Pfeiffer2005-05-16 20:13:09 +0000
commit92984345bcd7d07d6527de73f4e66af5b7386d64 (patch)
tree67815b0bb4ecd4720117c9c8e4e09d9af5b07828
parent228b550a6441376d1be0fe42a8e9acf49fe0c860 (diff)
downloademacs-92984345bcd7d07d6527de73f4e66af5b7386d64.tar.gz
emacs-92984345bcd7d07d6527de73f4e66af5b7386d64.zip
(makefile-dependency-regex): Turn it into a var, and refine it to mask one more level of nested vars.
(makefile-rule-action-regex): Turn it into a var, and refine it so it recognizes backslashed continuation lines as belonging to the same command. (makefile-macroassign-regex): Refine it so it recognizes backslashed continuation lines as belonging to the same command. (makefile-var-use-regex): Don't look at the next char, because it might be the same one to be skipped by the initial [^$], leading to an overlooked variable use. (makefile-make-font-lock-keywords): Remove two parameters, which are now variables that some of the modes set locally. Handle dependency and rule action matching through functions, because regexps alone match too often. Dependency matching now comes last, so it can check, whether a colon already matched something else. (makefile-mode): Inform that font-lock improves makefile parsing capabilities. (makefile-match-dependency, makefile-match-action): New functions.
-rw-r--r--lisp/progmodes/make-mode.el116
1 files changed, 70 insertions, 46 deletions
diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el
index bc30bfdfc56..8467310d1da 100644
--- a/lisp/progmodes/make-mode.el
+++ b/lisp/progmodes/make-mode.el
@@ -257,26 +257,24 @@ not be enclosed in { } or ( )."
257;; Note that the first big subexpression is used by font lock. Note 257;; Note that the first big subexpression is used by font lock. Note
258;; that if you change this regexp you might have to fix the imenu 258;; that if you change this regexp you might have to fix the imenu
259;; index in makefile-imenu-generic-expression. 259;; index in makefile-imenu-generic-expression.
260(defconst makefile-dependency-regex 260(defvar makefile-dependency-regex
261 ;; Allow for one nested level $($(var:a=b):c=d) 261 ;; Allow for two nested levels $(v1:$(v2:$(v3:a=b)=c)=d)
262 ;; Scan non-$ constructs char by char, so we don't miss a $ while allowing $$. 262 "^ *\\(\\(?: *\\$\\(?:[({]\\(?:\\$\\(?:[({]\\(?:\\$\\(?:[^({]\\|.[^\n$#})]+?[})]\\)\\|[^\n$#)}]\\)+?[})]\\|[^({]\\)\\|[^\n$#)}]\\)+?[})]\\|[^({]\\)\\| *[^ \n$#:=]+\\)+?\\)[ \t]*\\(:\\)\\(?:[ \t]*$\\|[^=\n]\\(?:[^#\n]*?;[ \t]*\\(.+\\)\\)?\\)"
263 ;; Since we must allow space between targets, I then don't know how to evite a command starting with :.
264 "^ *\\(\\(?:\\$[({]\\(?:\\$[({][^ \t\n#})]+?[})]\\|[^\n#]\\)+?[})]\\|[^\n#:=]\\)+?\\)[ \t]*:\\(?:[ \t]*$\\|[^=\n].*$\\)"
265 "Regex used to find dependency lines in a makefile.") 263 "Regex used to find dependency lines in a makefile.")
266 264
267(defconst makefile-rule-action-regex 265(defvar makefile-rule-action-regex
268 "^\t[ \t]*\\([-@]*\\)[ \t]*\\(.+\\)" 266 "^\t[ \t]*\\([-@]*\\)[ \t]*\\(\\(?:.+\\\\\n\\)*.+\\)"
269 "Regex used to highlight rule action lines in font lock mode.") 267 "Regex used to highlight rule action lines in font lock mode.")
270 268
271;; Note that the first and second subexpression is used by font lock. Note 269;; Note that the first and second subexpression is used by font lock. Note
272;; that if you change this regexp you might have to fix the imenu index in 270;; that if you change this regexp you might have to fix the imenu index in
273;; makefile-imenu-generic-expression. 271;; makefile-imenu-generic-expression.
274(defconst makefile-macroassign-regex 272(defconst makefile-macroassign-regex
275 "^ *\\([^ \n\t][^:#= \t\n]*\\)[ \t]*\\(?:!=[ \t]*\\(.*\\)\\|[*:+]?[:?]?=\\)" 273 "^ *\\([^ \n\t][^:#= \t\n]*\\)[ \t]*\\(?:!=[ \t]*\\(\\(?:.+\\\\\n\\)*.+\\)\\|[*:+]?[:?]?=\\)"
276 "Regex used to find macro assignment lines in a makefile.") 274 "Regex used to find macro assignment lines in a makefile.")
277 275
278(defconst makefile-var-use-regex 276(defconst makefile-var-use-regex
279 "[^$]\\$[({]\\([-a-zA-Z0-9_.]+\\|[@%<?^+*][FD]?\\)[}):]" 277 "[^$]\\$[({]\\([-a-zA-Z0-9_.]+\\|[@%<?^+*][FD]?\\)"
280 "Regex used to find $(macro) uses in a makefile.") 278 "Regex used to find $(macro) uses in a makefile.")
281 279
282(defconst makefile-ignored-files-in-pickup-regex 280(defconst makefile-ignored-files-in-pickup-regex
@@ -323,20 +321,17 @@ not be enclosed in { } or ( )."
323 ".endif" ".for" ".if" ".ifdef" ".ifmake" ".ifndef" ".ifnmake" ".undef") 321 ".endif" ".for" ".if" ".ifdef" ".ifmake" ".ifndef" ".ifnmake" ".undef")
324 "List of keywords understood by BSD make.") 322 "List of keywords understood by BSD make.")
325 323
326(defun makefile-make-font-lock-keywords (dependency action var keywords space 324(defun makefile-make-font-lock-keywords (var keywords space
327 &optional negation 325 &optional negation
328 &rest font-lock-keywords) 326 &rest font-lock-keywords)
329 `(;; Do macro assignments. These get the "variable-name" face. 327 `(;; Do macro assignments. These get the "variable-name" face.
330 (,makefile-macroassign-regex 328 (,makefile-macroassign-regex
331 (1 font-lock-variable-name-face) 329 (1 font-lock-variable-name-face)
332 ;; This is for after != 330 ;; This is for after !=
333 (2 'makefile-shell-face prepend t)) 331 (2 'makefile-shell-face prepend t))
334 332
335 ;; Do dependencies.
336 (,dependency 1 'makefile-targets-face prepend)
337
338 ;; Rule actions. 333 ;; Rule actions.
339 (,action 334 (makefile-match-action
340 (1 font-lock-type-face) 335 (1 font-lock-type-face)
341 (2 'makefile-shell-face prepend) 336 (2 'makefile-shell-face prepend)
342 ;; Only makepp has builtin commands. 337 ;; Only makepp has builtin commands.
@@ -359,9 +354,9 @@ not be enclosed in { } or ( )."
359 "\\>[ \t]*\\([^: \t\n#]*\\)") 354 "\\>[ \t]*\\([^: \t\n#]*\\)")
360 (1 font-lock-keyword-face) (2 font-lock-variable-name-face)) 355 (1 font-lock-keyword-face) (2 font-lock-variable-name-face))
361 356
362 ,(if negation 357 ,@(if negation
363 `(,negation (1 font-lock-negation-char-face prepend) 358 `((,negation (1 font-lock-negation-char-face prepend)
364 (2 font-lock-negation-char-face prepend t))) 359 (2 font-lock-negation-char-face prepend t))))
365 360
366 ,@(if space 361 ,@(if space
367 '(;; Highlight lines that contain just whitespace. 362 '(;; Highlight lines that contain just whitespace.
@@ -376,28 +371,27 @@ not be enclosed in { } or ( )."
376 ;; They can make a tab fail to be effective. 371 ;; They can make a tab fail to be effective.
377 ("^\\( +\\)\t" 1 makefile-space-face))) 372 ("^\\( +\\)\t" 1 makefile-space-face)))
378 373
379 ,@font-lock-keywords)) 374 ,@font-lock-keywords
375
376 ;; Do dependencies.
377 (makefile-match-dependency
378 (1 'makefile-targets-face prepend)
379 (3 'makefile-shell-face prepend t))))
380 380
381(defconst makefile-font-lock-keywords 381(defconst makefile-font-lock-keywords
382 (makefile-make-font-lock-keywords 382 (makefile-make-font-lock-keywords
383 makefile-dependency-regex
384 makefile-rule-action-regex
385 makefile-var-use-regex 383 makefile-var-use-regex
386 makefile-statements 384 makefile-statements
387 t)) 385 t))
388 386
389(defconst makefile-automake-font-lock-keywords 387(defconst makefile-automake-font-lock-keywords
390 (makefile-make-font-lock-keywords 388 (makefile-make-font-lock-keywords
391 makefile-dependency-regex
392 makefile-rule-action-regex
393 makefile-var-use-regex 389 makefile-var-use-regex
394 makefile-automake-statements 390 makefile-automake-statements
395 t)) 391 t))
396 392
397(defconst makefile-gmake-font-lock-keywords 393(defconst makefile-gmake-font-lock-keywords
398 (makefile-make-font-lock-keywords 394 (makefile-make-font-lock-keywords
399 makefile-dependency-regex
400 makefile-rule-action-regex
401 makefile-var-use-regex 395 makefile-var-use-regex
402 makefile-gmake-statements 396 makefile-gmake-statements
403 t 397 t
@@ -407,8 +401,8 @@ not be enclosed in { } or ( )."
407 1 'makefile-targets-face prepend) 401 1 'makefile-targets-face prepend)
408 402
409 ;; $(function ...) ${function ...} 403 ;; $(function ...) ${function ...}
410 '("[^$]\\$[({]\\(\\S +\\s \\)" 404 '("[^$]\\$[({]\\([-a-zA-Z0-9_.]+\\s \\)"
411 1 font-lock-function-name-face) 405 1 font-lock-function-name-face prepend)
412 406
413 ;; $(shell ...) ${shell ...} 407 ;; $(shell ...) ${shell ...}
414 '("[^$]\\$\\([({]\\)shell[ \t]+" 408 '("[^$]\\$\\([({]\\)shell[ \t]+"
@@ -417,24 +411,23 @@ not be enclosed in { } or ( )."
417 411
418(defconst makefile-makepp-font-lock-keywords 412(defconst makefile-makepp-font-lock-keywords
419 (makefile-make-font-lock-keywords 413 (makefile-make-font-lock-keywords
420 makefile-dependency-regex
421 ;; Don't care about initial tab, but I don't know how to font-lock correctly without.
422 "^\t[ \t]*\\(\\(?:[ \t]*noecho\\>\\|[ \t]*ignore[-_]error\\>\\|[ \t]*[-@]+\\)*\\)[ \t]*\\(\\(&\\S +\\)?.+\\)"
423 makefile-var-use-regex 414 makefile-var-use-regex
424 makefile-makepp-statements 415 makefile-makepp-statements
425 nil 416 nil
426 "^\\(?: [ \t]*\\)?\\(?:and[ \t]+\\|else[ \t]+\\|or[ \t]+\\)?if\\(n\\)\\(?:def\\|eq\\|sys\\)\\>" 417 "^\\(?: [ \t]*\\)?\\(?:and[ \t]+\\|else[ \t]+\\|or[ \t]+\\)?if\\(n\\)\\(?:def\\|eq\\|sys\\)\\>"
427 418
428 '("[^$]\\(\\$[({]\\(?:target\\|output\\)s?[})]\\)" 419 '("[^$]\\(\\$[({]\\(?:target\\|output\\)s?\\_>.*?[})]\\)"
429 1 'makefile-targets-face prepend) 420 1 'makefile-targets-face prepend)
430 421
431 ;; Colon modifier keywords. 422 ;; Colon modifier keywords.
432 '(":\\s *\\(build_c\\(?:ache\\|heck\\)\\|env\\(?:ironment\\)?\\|foreach\\|signature\\|scanner\\|quickscan\\|smartscan\\)\\>" 423 '("\\(:\\s *\\)\\(build_c\\(?:ache\\|heck\\)\\|env\\(?:ironment\\)?\\|foreach\\|signature\\|scanner\\|quickscan\\|smartscan\\)\\>\\([^:\n]*\\)"
433 1 font-lock-keyword-face t) 424 (1 font-lock-type-face t)
425 (2 font-lock-keyword-face t)
426 (3 font-lock-variable-name-face t))
434 427
435 ;; $(function ...) $((function ...)) ${function ...} ${{function ...}} 428 ;; $(function ...) $((function ...)) ${function ...} ${{function ...}}
436 '("[^$]\\$\\(((?\\|{{?\\)\\(\\S +\\s \\)" 429 '("[^$]\\$\\(?:((?\\|{{?\\)\\([-a-zA-Z0-9_.]+\\s \\)"
437 2 font-lock-function-name-face) 430 1 font-lock-function-name-face prepend)
438 431
439 ;; $(shell ...) $((shell ...)) ${shell ...} ${{shell ...}} 432 ;; $(shell ...) $((shell ...)) ${shell ...} ${{shell ...}}
440 '("[^$]\\$\\(((?\\|{{?\\)shell\\(?:[-_]\\(?:global[-_]\\)?once\\)?[ \t]+" 433 '("[^$]\\$\\(((?\\|{{?\\)shell\\(?:[-_]\\(?:global[-_]\\)?once\\)?[ \t]+"
@@ -466,11 +459,9 @@ not be enclosed in { } or ( )."
466 '("perl[-_]begin\\s *\\(?:\\s #.*\\)?\n\\(\\(?:.*\n\\)+?\\)\\s *perl[-_]end\\>" 459 '("perl[-_]begin\\s *\\(?:\\s #.*\\)?\n\\(\\(?:.*\n\\)+?\\)\\s *perl[-_]end\\>"
467 1 'makefile-makepp-perl-face t))) 460 1 'makefile-makepp-perl-face t)))
468 461
469;; A lot more could be done for variables here:
470(defconst makefile-bsdmake-font-lock-keywords 462(defconst makefile-bsdmake-font-lock-keywords
471 (makefile-make-font-lock-keywords 463 (makefile-make-font-lock-keywords
472 "^ *\\(\\(?:\\$[({]\\(?:\\$[({][^\n#})]+?[})]\\|[^\n#]\\)+?[})]\\|[^\n#:=]\\)+?\\)[ \t]*[:!]\\(?:[ \t]*$\\|[^=\n].*$\\)" 464 ;; A lot more could be done for variables here:
473 "^\t[ \t]*\\([-+@]*\\)[ \t]*\\(.+\\)"
474 makefile-var-use-regex 465 makefile-var-use-regex
475 makefile-bsdmake-statements 466 makefile-bsdmake-statements
476 t 467 t
@@ -489,9 +480,8 @@ not be enclosed in { } or ( )."
489 ("\\\\\n" 0 "."))) 480 ("\\\\\n" 0 ".")))
490 481
491(defvar makefile-imenu-generic-expression 482(defvar makefile-imenu-generic-expression
492 (list 483 `(("Dependencies" ,makefile-dependency-regex 1)
493 (list "Dependencies" makefile-dependency-regex 1) 484 ("Macro Assignment" ,makefile-macroassign-regex 1))
494 (list "Macro Assignment" makefile-macroassign-regex 1))
495 "Imenu generic expression for Makefile mode. See `imenu-generic-expression'.") 485 "Imenu generic expression for Makefile mode. See `imenu-generic-expression'.")
496 486
497;;; ------------------------------------------------------------ 487;;; ------------------------------------------------------------
@@ -695,6 +685,11 @@ last should be correctly chosen based on the file name, except if
695it is *.mk. This function ends by invoking the function(s) 685it is *.mk. This function ends by invoking the function(s)
696`makefile-mode-hook'. 686`makefile-mode-hook'.
697 687
688It is strongly recommended to use `font-lock-mode', because that
689provides additional parsing information. This is used for
690example to see that a rule action `echo foo: bar' is a not rule
691dependency, despite the colon.
692
698\\{makefile-mode-map} 693\\{makefile-mode-map}
699 694
700In the browser, use the following keys: 695In the browser, use the following keys:
@@ -849,14 +844,26 @@ Makefile mode can be configured by modifying the following variables:
849;;;###autoload 844;;;###autoload
850(define-derived-mode makefile-makepp-mode makefile-mode "Makeppfile" 845(define-derived-mode makefile-makepp-mode makefile-mode "Makeppfile"
851 "An adapted `makefile-mode' that knows about makepp." 846 "An adapted `makefile-mode' that knows about makepp."
847 (set (make-local-variable 'makefile-rule-action-regex)
848 ;; Don't care about initial tab, but I don't know how to font-lock correctly without.
849 "^\t[ \t]*\\(\\(?:\\(?:noecho\\|ignore[-_]error\\|[-@]+\\)[ \t]*\\)*\\)\\(\\(&\\S +\\)?\\(?:.+\\\\\n\\)*.+\\)")
850
852 (setq font-lock-defaults 851 (setq font-lock-defaults
853 `(makefile-makepp-font-lock-keywords ,@(cdr font-lock-defaults)))) 852 `(makefile-makepp-font-lock-keywords ,@(cdr font-lock-defaults))))
854 853
855;;;###autoload 854;;;###autoload
856(define-derived-mode makefile-bsdmake-mode makefile-mode "BSDmakefile" 855(define-derived-mode makefile-bsdmake-mode makefile-mode "BSDmakefile"
857 "An adapted `makefile-mode' that knows about BSD make." 856 "An adapted `makefile-mode' that knows about BSD make."
857 (set (make-local-variable 'makefile-dependency-regex)
858 ;; Identical to default, except allows `!' instead of `:'.
859 "^ *\\(\\(?: *\\$\\(?:[({]\\(?:\\$\\(?:[({]\\(?:\\$\\(?:[^({]\\|.[^\n$#})]+?[})]\\)\\|[^\n$#)}]\\)+?[})]\\|[^({]\\)\\|[^\n$#)}]\\)+?[})]\\|[^({]\\)\\| *[^ \n$#:=]+\\)+?\\)[ \t]*\\([:!]\\)\\(?:[ \t]*$\\|[^=\n]\\(?:[^#\n]*?;[ \t]*\\(.+\\)\\)?\\)")
860 (set (make-local-variable 'makefile-rule-action-regex)
861 "^\t[ \t]*\\([-+@]*\\)[ \t]*\\(\\(?:.+\\\\\n\\)*.+\\)")
858 (setq font-lock-defaults 862 (setq font-lock-defaults
859 `(makefile-bsdmake-font-lock-keywords ,@(cdr font-lock-defaults)))) 863 `(makefile-bsdmake-font-lock-keywords ,@(cdr font-lock-defaults))
864 imenu-generic-expression
865 `(("Dependencies" ,makefile-dependency-regex 1)
866 ,@(cdr imenu-generic-expression))))
860 867
861 868
862 869
@@ -867,7 +874,7 @@ Makefile mode can be configured by modifying the following variables:
867 (interactive) 874 (interactive)
868 (let ((here (point))) 875 (let ((here (point)))
869 (end-of-line) 876 (end-of-line)
870 (if (re-search-forward makefile-dependency-regex (point-max) t) 877 (if (makefile-match-dependency (point-max))
871 (progn (beginning-of-line) t) ; indicate success 878 (progn (beginning-of-line) t) ; indicate success
872 (goto-char here) nil))) 879 (goto-char here) nil)))
873 880
@@ -876,7 +883,7 @@ Makefile mode can be configured by modifying the following variables:
876 (interactive) 883 (interactive)
877 (let ((here (point))) 884 (let ((here (point)))
878 (beginning-of-line) 885 (beginning-of-line)
879 (if (re-search-backward makefile-dependency-regex (point-min) t) 886 (if (makefile-match-dependency (point-min) t)
880 (progn (beginning-of-line) t) ; indicate success 887 (progn (beginning-of-line) t) ; indicate success
881 (goto-char here) nil))) 888 (goto-char here) nil)))
882 889
@@ -983,7 +990,7 @@ Anywhere else just self-inserts."
983 (setq makefile-has-prereqs nil) 990 (setq makefile-has-prereqs nil)
984 (save-excursion 991 (save-excursion
985 (goto-char (point-min)) 992 (goto-char (point-min))
986 (while (re-search-forward makefile-dependency-regex nil t) 993 (while (makefile-match-dependency nil)
987 (makefile-add-this-line-targets))) 994 (makefile-add-this-line-targets)))
988 (message "Read targets OK."))) 995 (message "Read targets OK.")))
989 996
@@ -1676,6 +1683,23 @@ The anchor must have matched the opening parens in the first group."
1676 ((string= s "{{") "\\(.*?\\)[ \t]*}}"))) 1683 ((string= s "{{") "\\(.*?\\)[ \t]*}}")))
1677 (if s (looking-at s)))) 1684 (if s (looking-at s))))
1678 1685
1686(defun makefile-match-dependency (bound &optional backward)
1687 "Search for `makefile-dependency-regex' up to BOUND.
1688Optionally search BACKWARD.
1689Checks that the colon has not already been fontified, else we
1690matched in a rule action."
1691 (catch 'found
1692 (while (funcall (if backward 're-search-backward 're-search-forward)
1693 makefile-dependency-regex bound t)
1694 (or (get-text-property (match-beginning 2) 'face)
1695 (throw 'found t)))))
1696
1697(defun makefile-match-action (bound)
1698 (catch 'found
1699 (while (re-search-forward makefile-rule-action-regex bound t)
1700 (or (eq ?\\ (char-after (- (match-beginning 0) 2)))
1701 (throw 'found t)))))
1702
1679(defun makefile-do-macro-insertion (macro-name) 1703(defun makefile-do-macro-insertion (macro-name)
1680 "Insert a macro reference." 1704 "Insert a macro reference."
1681 (if (not (zerop (length macro-name))) 1705 (if (not (zerop (length macro-name)))