diff options
| author | Simon Marshall | 1995-11-09 08:26:32 +0000 |
|---|---|---|
| committer | Simon Marshall | 1995-11-09 08:26:32 +0000 |
| commit | 876f2438f38dab54b9321c8b65778b02bd5f3786 (patch) | |
| tree | 980122990d25632006a601f1897817a7364f566b | |
| parent | c81b38d300e90d03acee57daa0b2cbd9ce2944bf (diff) | |
| download | emacs-876f2438f38dab54b9321c8b65778b02bd5f3786.tar.gz emacs-876f2438f38dab54b9321c8b65778b02bd5f3786.zip | |
1. Use local hooks, not local variables.
2. Wrap font-lock-fontify-region, not called fns.
3. Guarantee anchored keywords don't span lines.
| -rw-r--r-- | lisp/font-lock.el | 365 |
1 files changed, 178 insertions, 187 deletions
diff --git a/lisp/font-lock.el b/lisp/font-lock.el index 9f3d1ebf9cf..edff5980e90 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | ;;; font-lock.el --- electric font lock mode | 1 | ;;; font-lock.el --- Electric font lock mode |
| 2 | |||
| 2 | ;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. |
| 3 | 4 | ||
| 4 | ;; Author: jwz, then rms, then sm <simon@gnu.ai.mit.edu> | 5 | ;; Author: jwz, then rms, then sm <simon@gnu.ai.mit.edu> |
| @@ -166,7 +167,8 @@ If LAXMATCH is non-nil, no error is signalled if there is no MATCH in MATCHER. | |||
| 166 | 167 | ||
| 167 | For example, an element of the form highlights (if not already highlighted): | 168 | For example, an element of the form highlights (if not already highlighted): |
| 168 | 169 | ||
| 169 | \"foo\" Occurrences of \"foo\" in `font-lock-keyword-face'. | 170 | \"\\\\\\=<foo\\\\\\=>\" Discrete occurrences of \"foo\" in the value of the |
| 171 | variable `font-lock-keyword-face'. | ||
| 170 | (\"fu\\\\(bar\\\\)\" . 1) Substring \"bar\" within all occurrences of \"fubar\" in | 172 | (\"fu\\\\(bar\\\\)\" . 1) Substring \"bar\" within all occurrences of \"fubar\" in |
| 171 | the value of `font-lock-keyword-face'. | 173 | the value of `font-lock-keyword-face'. |
| 172 | (\"fubar\" . fubar-face) Occurrences of \"fubar\" in the value of `fubar-face'. | 174 | (\"fubar\" . fubar-face) Occurrences of \"fubar\" in the value of `fubar-face'. |
| @@ -178,24 +180,25 @@ MATCH-ANCHORED should be of the form: | |||
| 178 | 180 | ||
| 179 | (MATCHER PRE-MATCH-FORM POST-MATCH-FORM MATCH-HIGHLIGHT ...) | 181 | (MATCHER PRE-MATCH-FORM POST-MATCH-FORM MATCH-HIGHLIGHT ...) |
| 180 | 182 | ||
| 181 | Where MATCHER is as for MATCH-HIGHLIGHT. PRE-MATCH-FORM and POST-MATCH-FORM | 183 | Where MATCHER is as for MATCH-HIGHLIGHT with one exception. The limit of the |
| 182 | are evaluated before the first, and after the last, instance MATCH-ANCHORED's | 184 | search is currently guaranteed to be (no greater than) the end of the line. |
| 183 | MATCHER is used. Therefore they can be used to initialise before, and cleanup | 185 | PRE-MATCH-FORM and POST-MATCH-FORM are evaluated before the first, and after |
| 184 | after, MATCHER is used. Typically, PRE-MATCH-FORM is used to move to some | 186 | the last, instance MATCH-ANCHORED's MATCHER is used. Therefore they can be |
| 185 | position relative to the original MATCHER, before starting with | 187 | used to initialise before, and cleanup after, MATCHER is used. Typically, |
| 186 | MATCH-ANCHORED's MATCHER. POST-MATCH-FORM might be used to move, before | 188 | PRE-MATCH-FORM is used to move to some position relative to the original |
| 187 | resuming with MATCH-ANCHORED's parent's MATCHER. | 189 | MATCHER, before starting with MATCH-ANCHORED's MATCHER. POST-MATCH-FORM might |
| 190 | be used to move, before resuming with MATCH-ANCHORED's parent's MATCHER. | ||
| 188 | 191 | ||
| 189 | For example, an element of the form highlights (if not already highlighted): | 192 | For example, an element of the form highlights (if not already highlighted): |
| 190 | 193 | ||
| 191 | (\"anchor\" (0 anchor-face) (\".*\\\\(item\\\\)\" nil nil (1 item-face))) | 194 | (\"\\\\\\=<anchor\\\\\\=>\" (0 anchor-face) (\"\\\\\\=<item\\\\\\=>\" nil nil (0 item-face))) |
| 192 | 195 | ||
| 193 | Occurrences of \"anchor\" in the value of `anchor-face', and subsequent | 196 | Discrete occurrences of \"anchor\" in the value of `anchor-face', and subsequent |
| 194 | occurrences of \"item\" on the same line (by virtue of the `.*' regexp) in the | 197 | discrete occurrences of \"item\" (on the same line) in the value of `item-face'. |
| 195 | value of `item-face'. (Here PRE-MATCH-FORM and POST-MATCH-FORM are nil. | 198 | (Here PRE-MATCH-FORM and POST-MATCH-FORM are nil. Therefore \"item\" is |
| 196 | Therefore \"item\" is initially searched for starting from the end of the match | 199 | initially searched for starting from the end of the match of \"anchor\", and |
| 197 | of \"anchor\", and searching for subsequent instance of \"anchor\" resumes from | 200 | searching for subsequent instance of \"anchor\" resumes from where searching |
| 198 | where searching for \"item\" concluded.) | 201 | for \"item\" concluded.) |
| 199 | 202 | ||
| 200 | Note that the MATCH-ANCHORED feature is experimental; in the future, we may | 203 | Note that the MATCH-ANCHORED feature is experimental; in the future, we may |
| 201 | replace it with other ways of providing this functionality. | 204 | replace it with other ways of providing this functionality. |
| @@ -322,7 +325,7 @@ This is normally set via `font-lock-defaults'.") | |||
| 322 | 325 | ||
| 323 | ;;;###autoload | 326 | ;;;###autoload |
| 324 | (defun font-lock-mode (&optional arg) | 327 | (defun font-lock-mode (&optional arg) |
| 325 | "Toggle Font Lock mode. | 328 | "[pretest] Toggle Font Lock mode. |
| 326 | With arg, turn Font Lock mode on if and only if arg is positive. | 329 | With arg, turn Font Lock mode on if and only if arg is positive. |
| 327 | 330 | ||
| 328 | When Font Lock mode is enabled, text is fontified as you type it: | 331 | When Font Lock mode is enabled, text is fontified as you type it: |
| @@ -362,17 +365,19 @@ size, you can use \\[font-lock-fontify-buffer]." | |||
| 362 | (if (equal (buffer-name) " *Compiler Input*") ; hack for bytecomp... | 365 | (if (equal (buffer-name) " *Compiler Input*") ; hack for bytecomp... |
| 363 | (setq on-p nil)) | 366 | (setq on-p nil)) |
| 364 | (if (not on-p) | 367 | (if (not on-p) |
| 365 | (remove-hook 'after-change-functions 'font-lock-after-change-function) | 368 | (remove-hook 'after-change-functions 'font-lock-after-change-function |
| 366 | (make-local-variable 'after-change-functions) | 369 | t) |
| 367 | (add-hook 'after-change-functions 'font-lock-after-change-function)) | 370 | (make-local-hook 'after-change-functions) |
| 371 | (add-hook 'after-change-functions 'font-lock-after-change-function | ||
| 372 | nil t)) | ||
| 368 | (set (make-local-variable 'font-lock-mode) on-p) | 373 | (set (make-local-variable 'font-lock-mode) on-p) |
| 369 | (cond (on-p | 374 | (cond (on-p |
| 370 | (font-lock-set-defaults) | 375 | (font-lock-set-defaults) |
| 371 | (make-local-variable 'before-revert-hook) | 376 | (make-local-hook 'before-revert-hook) |
| 372 | (make-local-variable 'after-revert-hook) | 377 | (make-local-hook 'after-revert-hook) |
| 373 | ;; If buffer is reverted, must clean up the state. | 378 | ;; If buffer is reverted, must clean up the state. |
| 374 | (add-hook 'before-revert-hook 'font-lock-revert-setup) | 379 | (add-hook 'before-revert-hook 'font-lock-revert-setup nil t) |
| 375 | (add-hook 'after-revert-hook 'font-lock-revert-cleanup) | 380 | (add-hook 'after-revert-hook 'font-lock-revert-cleanup nil t) |
| 376 | (run-hooks 'font-lock-mode-hook) | 381 | (run-hooks 'font-lock-mode-hook) |
| 377 | (cond (font-lock-fontified | 382 | (cond (font-lock-fontified |
| 378 | nil) | 383 | nil) |
| @@ -382,13 +387,13 @@ size, you can use \\[font-lock-fontify-buffer]." | |||
| 382 | (message "Fontifying %s... buffer too big." (buffer-name))))) | 387 | (message "Fontifying %s... buffer too big." (buffer-name))))) |
| 383 | (font-lock-fontified | 388 | (font-lock-fontified |
| 384 | (setq font-lock-fontified nil) | 389 | (setq font-lock-fontified nil) |
| 385 | (remove-hook 'before-revert-hook 'font-lock-revert-setup) | 390 | (remove-hook 'before-revert-hook 'font-lock-revert-setup t) |
| 386 | (remove-hook 'after-revert-hook 'font-lock-revert-cleanup) | 391 | (remove-hook 'after-revert-hook 'font-lock-revert-cleanup t) |
| 387 | (font-lock-unfontify-region (point-min) (point-max)) | 392 | (font-lock-unfontify-region (point-min) (point-max)) |
| 388 | (font-lock-thing-lock-cleanup)) | 393 | (font-lock-thing-lock-cleanup)) |
| 389 | (t | 394 | (t |
| 390 | (remove-hook 'before-revert-hook 'font-lock-revert-setup) | 395 | (remove-hook 'before-revert-hook 'font-lock-revert-setup t) |
| 391 | (remove-hook 'after-revert-hook 'font-lock-revert-cleanup) | 396 | (remove-hook 'after-revert-hook 'font-lock-revert-cleanup t) |
| 392 | (font-lock-thing-lock-cleanup))) | 397 | (font-lock-thing-lock-cleanup))) |
| 393 | (force-mode-line-update))) | 398 | (force-mode-line-update))) |
| 394 | 399 | ||
| @@ -402,23 +407,20 @@ size, you can use \\[font-lock-fontify-buffer]." | |||
| 402 | "Fontify the current buffer the way `font-lock-mode' would." | 407 | "Fontify the current buffer the way `font-lock-mode' would." |
| 403 | (interactive) | 408 | (interactive) |
| 404 | (let ((verbose (and (or font-lock-verbose (interactive-p)) | 409 | (let ((verbose (and (or font-lock-verbose (interactive-p)) |
| 405 | (not (zerop (buffer-size))))) | 410 | (not (zerop (buffer-size)))))) |
| 406 | (modified (buffer-modified-p))) | ||
| 407 | (set (make-local-variable 'font-lock-fontified) nil) | 411 | (set (make-local-variable 'font-lock-fontified) nil) |
| 408 | (if verbose (message "Fontifying %s..." (buffer-name))) | 412 | (if verbose (message "Fontifying %s..." (buffer-name))) |
| 409 | ;; Turn it on to run hooks and get the right `font-lock-keywords' etc. | 413 | ;; Turn it on to run hooks and get the right `font-lock-keywords' etc. |
| 410 | (or font-lock-mode (font-lock-set-defaults)) | 414 | (or font-lock-mode (font-lock-set-defaults)) |
| 411 | (condition-case nil | 415 | (condition-case nil |
| 412 | (save-excursion | 416 | (save-excursion |
| 413 | (font-lock-fontify-region (point-min) (point-max) verbose) | 417 | (save-match-data |
| 414 | (setq font-lock-fontified t)) | 418 | (font-lock-fontify-region (point-min) (point-max) verbose) |
| 419 | (setq font-lock-fontified t))) | ||
| 415 | ;; We don't restore the old fontification, so it's best to unfontify. | 420 | ;; We don't restore the old fontification, so it's best to unfontify. |
| 416 | (quit (font-lock-unfontify-region (point-min) (point-max)))) | 421 | (quit (font-lock-unfontify-region (point-min) (point-max)))) |
| 417 | (if verbose (message "Fontifying %s... %s." (buffer-name) | 422 | (if verbose (message "Fontifying %s... %s." (buffer-name) |
| 418 | (if font-lock-fontified "done" "aborted"))) | 423 | (if font-lock-fontified "done" "aborted"))) |
| 419 | (and (buffer-modified-p) | ||
| 420 | (not modified) | ||
| 421 | (set-buffer-modified-p nil)) | ||
| 422 | (font-lock-after-fontify-buffer))) | 424 | (font-lock-after-fontify-buffer))) |
| 423 | 425 | ||
| 424 | ;; Fontification functions. | 426 | ;; Fontification functions. |
| @@ -427,10 +429,22 @@ size, you can use \\[font-lock-fontify-buffer]." | |||
| 427 | ;; name used for `font-lock-fontify-syntactically-region', so a change isn't | 429 | ;; name used for `font-lock-fontify-syntactically-region', so a change isn't |
| 428 | ;; back-compatible. But you shouldn't be calling these directly, should you? | 430 | ;; back-compatible. But you shouldn't be calling these directly, should you? |
| 429 | (defun font-lock-fontify-region (beg end &optional loudly) | 431 | (defun font-lock-fontify-region (beg end &optional loudly) |
| 430 | (if font-lock-keywords-only | 432 | (let ((modified (buffer-modified-p)) |
| 431 | (font-lock-unfontify-region beg end) | 433 | (buffer-undo-list t) (inhibit-read-only t) |
| 432 | (font-lock-fontify-syntactically-region beg end loudly)) | 434 | (old-syntax-table (syntax-table)) |
| 433 | (font-lock-fontify-keywords-region beg end loudly)) | 435 | buffer-file-name buffer-file-truename) |
| 436 | (unwind-protect | ||
| 437 | (progn | ||
| 438 | ;; Use the fontification syntax table, if any. | ||
| 439 | (if font-lock-syntax-table (set-syntax-table font-lock-syntax-table)) | ||
| 440 | ;; Now do the fontification. | ||
| 441 | (if font-lock-keywords-only | ||
| 442 | (font-lock-unfontify-region beg end) | ||
| 443 | (font-lock-fontify-syntactically-region beg end loudly)) | ||
| 444 | (font-lock-fontify-keywords-region beg end loudly)) | ||
| 445 | ;; Clean up. | ||
| 446 | (set-syntax-table old-syntax-table) | ||
| 447 | (and (not modified) (buffer-modified-p) (set-buffer-modified-p nil))))) | ||
| 434 | 448 | ||
| 435 | ;; The following must be rethought, since keywords can override fontification. | 449 | ;; The following must be rethought, since keywords can override fontification. |
| 436 | ; ;; Now scan for keywords, but not if we are inside a comment now. | 450 | ; ;; Now scan for keywords, but not if we are inside a comment now. |
| @@ -445,9 +459,7 @@ size, you can use \\[font-lock-fontify-buffer]." | |||
| 445 | (buffer-undo-list t) (inhibit-read-only t) | 459 | (buffer-undo-list t) (inhibit-read-only t) |
| 446 | buffer-file-name buffer-file-truename) | 460 | buffer-file-name buffer-file-truename) |
| 447 | (remove-text-properties beg end '(face nil)) | 461 | (remove-text-properties beg end '(face nil)) |
| 448 | (and (buffer-modified-p) | 462 | (and (not modified) (buffer-modified-p) (set-buffer-modified-p nil)))) |
| 449 | (not modified) | ||
| 450 | (set-buffer-modified-p nil)))) | ||
| 451 | 463 | ||
| 452 | ;; Called when any modification is made to buffer text. | 464 | ;; Called when any modification is made to buffer text. |
| 453 | (defun font-lock-after-change-function (beg end old-len) | 465 | (defun font-lock-after-change-function (beg end old-len) |
| @@ -463,122 +475,109 @@ size, you can use \\[font-lock-fontify-buffer]." | |||
| 463 | (defun font-lock-fontify-syntactically-region (start end &optional loudly) | 475 | (defun font-lock-fontify-syntactically-region (start end &optional loudly) |
| 464 | "Put proper face on each string and comment between START and END. | 476 | "Put proper face on each string and comment between START and END. |
| 465 | START should be at the beginning of a line." | 477 | START should be at the beginning of a line." |
| 466 | (let ((inhibit-read-only t) (buffer-undo-list t) | 478 | (let ((synstart (if comment-start-skip |
| 467 | (modified (buffer-modified-p)) | ||
| 468 | (old-syntax (syntax-table)) | ||
| 469 | (synstart (if comment-start-skip | ||
| 470 | (concat "\\s\"\\|" comment-start-skip) | 479 | (concat "\\s\"\\|" comment-start-skip) |
| 471 | "\\s\"")) | 480 | "\\s\"")) |
| 472 | (comstart (if comment-start-skip | 481 | (comstart (if comment-start-skip |
| 473 | (concat "\\s<\\|" comment-start-skip) | 482 | (concat "\\s<\\|" comment-start-skip) |
| 474 | "\\s<")) | 483 | "\\s<")) |
| 475 | buffer-file-name buffer-file-truename | ||
| 476 | state prev prevstate) | 484 | state prev prevstate) |
| 477 | (if loudly (message "Fontifying %s... (syntactically...)" (buffer-name))) | 485 | (if loudly (message "Fontifying %s... (syntactically...)" (buffer-name))) |
| 478 | (unwind-protect | 486 | (save-restriction |
| 479 | (save-restriction | 487 | (widen) |
| 480 | (widen) | 488 | (goto-char start) |
| 481 | (goto-char start) | 489 | ;; |
| 482 | ;; | 490 | ;; Find the state at the `beginning-of-line' before `start'. |
| 483 | ;; Use the fontification syntax table, if any. | 491 | (if (eq start font-lock-cache-position) |
| 484 | (if font-lock-syntax-table (set-syntax-table font-lock-syntax-table)) | 492 | ;; Use the cache for the state of `start'. |
| 485 | ;; | 493 | (setq state font-lock-cache-state) |
| 486 | ;; Find the state at the `beginning-of-line' before `start'. | 494 | ;; Find the state of `start'. |
| 487 | (if (eq start font-lock-cache-position) | 495 | (if (null font-lock-beginning-of-syntax-function) |
| 488 | ;; Use the cache for the state of `start'. | 496 | ;; Use the state at the previous cache position, if any, or |
| 489 | (setq state font-lock-cache-state) | 497 | ;; otherwise calculate from `point-min'. |
| 490 | ;; Find the state of `start'. | 498 | (if (or (null font-lock-cache-position) |
| 491 | (if (null font-lock-beginning-of-syntax-function) | 499 | (< start font-lock-cache-position)) |
| 492 | ;; Use the state at the previous cache position, if any, or | 500 | (setq state (parse-partial-sexp (point-min) start)) |
| 493 | ;; otherwise calculate from `point-min'. | 501 | (setq state (parse-partial-sexp font-lock-cache-position start |
| 494 | (if (or (null font-lock-cache-position) | 502 | nil nil font-lock-cache-state))) |
| 495 | (< start font-lock-cache-position)) | 503 | ;; Call the function to move outside any syntactic block. |
| 496 | (setq state (parse-partial-sexp (point-min) start)) | 504 | (funcall font-lock-beginning-of-syntax-function) |
| 497 | (setq state (parse-partial-sexp | 505 | (setq state (parse-partial-sexp (point) start))) |
| 498 | font-lock-cache-position start | 506 | ;; Cache the state and position of `start'. |
| 499 | nil nil font-lock-cache-state))) | 507 | (setq font-lock-cache-state state |
| 500 | ;; Call the function to move outside any syntactic block. | 508 | font-lock-cache-position start)) |
| 501 | (funcall font-lock-beginning-of-syntax-function) | 509 | ;; |
| 502 | (setq state (parse-partial-sexp (point) start))) | 510 | ;; If the region starts inside a string, show the extent of it. |
| 503 | ;; Cache the state and position of `start'. | 511 | (if (nth 3 state) |
| 504 | (setq font-lock-cache-state state | 512 | (let ((beg (point))) |
| 505 | font-lock-cache-position start)) | 513 | (while (and (re-search-forward "\\s\"" end 'move) |
| 506 | ;; | 514 | (nth 3 (parse-partial-sexp beg (point) |
| 507 | ;; If the region starts inside a string, show the extent of it. | 515 | nil nil state)))) |
| 508 | (if (nth 3 state) | 516 | (put-text-property beg (point) 'face font-lock-string-face) |
| 509 | (let ((beg (point))) | 517 | (setq state (parse-partial-sexp beg (point) nil nil state)))) |
| 510 | (while (and (re-search-forward "\\s\"" end 'move) | 518 | ;; |
| 511 | (nth 3 (parse-partial-sexp beg (point) | 519 | ;; Likewise for a comment. |
| 512 | nil nil state)))) | 520 | (if (or (nth 4 state) (nth 7 state)) |
| 513 | (put-text-property beg (point) 'face font-lock-string-face) | 521 | (let ((beg (point))) |
| 514 | (setq state (parse-partial-sexp beg (point) nil nil state)))) | 522 | (save-restriction |
| 515 | ;; | 523 | (narrow-to-region (point-min) end) |
| 516 | ;; Likewise for a comment. | 524 | (condition-case nil |
| 517 | (if (or (nth 4 state) (nth 7 state)) | 525 | (progn |
| 518 | (let ((beg (point))) | 526 | (re-search-backward comstart (point-min) 'move) |
| 519 | (save-restriction | 527 | (forward-comment 1) |
| 520 | (narrow-to-region (point-min) end) | 528 | ;; forward-comment skips all whitespace, |
| 521 | (condition-case nil | 529 | ;; so go back to the real end of the comment. |
| 522 | (progn | 530 | (skip-chars-backward " \t")) |
| 523 | (re-search-backward comstart (point-min) 'move) | 531 | (error (goto-char end)))) |
| 524 | (forward-comment 1) | 532 | (put-text-property beg (point) 'face font-lock-comment-face) |
| 525 | ;; forward-comment skips all whitespace, | 533 | (setq state (parse-partial-sexp beg (point) nil nil state)))) |
| 526 | ;; so go back to the real end of the comment. | 534 | ;; |
| 527 | (skip-chars-backward " \t")) | 535 | ;; Find each interesting place between here and `end'. |
| 528 | (error (goto-char end)))) | 536 | (while (and (< (point) end) |
| 529 | (put-text-property beg (point) 'face font-lock-comment-face) | 537 | (setq prev (point) prevstate state) |
| 530 | (setq state (parse-partial-sexp beg (point) nil nil state)))) | 538 | (re-search-forward synstart end t) |
| 531 | ;; | 539 | (progn |
| 532 | ;; Find each interesting place between here and `end'. | 540 | ;; Clear out the fonts of what we skip over. |
| 533 | (while (and (< (point) end) | 541 | (remove-text-properties prev (point) '(face nil)) |
| 534 | (setq prev (point) prevstate state) | 542 | ;; Verify the state at that place |
| 535 | (re-search-forward synstart end t) | 543 | ;; so we don't get fooled by \" or \;. |
| 536 | (progn | 544 | (setq state (parse-partial-sexp prev (point) |
| 537 | ;; Clear out the fonts of what we skip over. | 545 | nil nil state)))) |
| 538 | (remove-text-properties prev (point) '(face nil)) | 546 | (let ((here (point))) |
| 539 | ;; Verify the state at that place | 547 | (if (or (nth 4 state) (nth 7 state)) |
| 540 | ;; so we don't get fooled by \" or \;. | 548 | ;; |
| 541 | (setq state (parse-partial-sexp prev (point) | 549 | ;; We found a real comment start. |
| 542 | nil nil state)))) | 550 | (let ((beg (match-beginning 0))) |
| 543 | (let ((here (point))) | 551 | (goto-char beg) |
| 544 | (if (or (nth 4 state) (nth 7 state)) | 552 | (save-restriction |
| 553 | (narrow-to-region (point-min) end) | ||
| 554 | (condition-case nil | ||
| 555 | (progn | ||
| 556 | (forward-comment 1) | ||
| 557 | ;; forward-comment skips all whitespace, | ||
| 558 | ;; so go back to the real end of the comment. | ||
| 559 | (skip-chars-backward " \t")) | ||
| 560 | (error (goto-char end)))) | ||
| 561 | (put-text-property beg (point) 'face | ||
| 562 | font-lock-comment-face) | ||
| 563 | (setq state (parse-partial-sexp here (point) nil nil state))) | ||
| 564 | (if (nth 3 state) | ||
| 545 | ;; | 565 | ;; |
| 546 | ;; We found a real comment start. | 566 | ;; We found a real string start. |
| 547 | (let ((beg (match-beginning 0))) | 567 | (let ((beg (match-beginning 0))) |
| 548 | (goto-char beg) | 568 | (while (and (re-search-forward "\\s\"" end 'move) |
| 549 | (save-restriction | 569 | (nth 3 (parse-partial-sexp here (point) |
| 550 | (narrow-to-region (point-min) end) | 570 | nil nil state)))) |
| 551 | (condition-case nil | 571 | (put-text-property beg (point) 'face font-lock-string-face) |
| 552 | (progn | 572 | (setq state (parse-partial-sexp here (point) |
| 553 | (forward-comment 1) | 573 | nil nil state)))))) |
| 554 | ;; forward-comment skips all whitespace, | 574 | ;; |
| 555 | ;; so go back to the real end of the comment. | 575 | ;; Make sure `prev' is non-nil after the loop |
| 556 | (skip-chars-backward " \t")) | 576 | ;; only if it was set on the very last iteration. |
| 557 | (error (goto-char end)))) | 577 | (setq prev nil))) |
| 558 | (put-text-property beg (point) 'face | 578 | ;; |
| 559 | font-lock-comment-face) | 579 | ;; Clean up. |
| 560 | (setq state (parse-partial-sexp here (point) nil nil state))) | 580 | (and prev (remove-text-properties prev end '(face nil))))) |
| 561 | (if (nth 3 state) | ||
| 562 | ;; | ||
| 563 | ;; We found a real string start. | ||
| 564 | (let ((beg (match-beginning 0))) | ||
| 565 | (while (and (re-search-forward "\\s\"" end 'move) | ||
| 566 | (nth 3 (parse-partial-sexp here (point) | ||
| 567 | nil nil state)))) | ||
| 568 | (put-text-property beg (point) 'face font-lock-string-face) | ||
| 569 | (setq state (parse-partial-sexp here (point) | ||
| 570 | nil nil state)))))) | ||
| 571 | ;; | ||
| 572 | ;; Make sure `prev' is non-nil after the loop | ||
| 573 | ;; only if it was set on the very last iteration. | ||
| 574 | (setq prev nil))) | ||
| 575 | ;; | ||
| 576 | ;; Clean up. | ||
| 577 | (set-syntax-table old-syntax) | ||
| 578 | (if prev (remove-text-properties prev end '(face nil))) | ||
| 579 | (and (buffer-modified-p) | ||
| 580 | (not modified) | ||
| 581 | (set-buffer-modified-p nil))))) | ||
| 582 | 581 | ||
| 583 | ;;; Additional text property functions. | 582 | ;;; Additional text property functions. |
| 584 | 583 | ||
| @@ -692,15 +691,21 @@ HIGHLIGHT should be of the form MATCH-HIGHLIGHT, see `font-lock-keywords'." | |||
| 692 | "Fontify according to KEYWORDS until LIMIT. | 691 | "Fontify according to KEYWORDS until LIMIT. |
| 693 | KEYWORDS should be of the form MATCH-ANCHORED, see `font-lock-keywords'." | 692 | KEYWORDS should be of the form MATCH-ANCHORED, see `font-lock-keywords'." |
| 694 | (let ((matcher (nth 0 keywords)) (lowdarks (nthcdr 3 keywords)) highlights) | 693 | (let ((matcher (nth 0 keywords)) (lowdarks (nthcdr 3 keywords)) highlights) |
| 694 | ;; Until we come up with a cleaner solution, we make LIMIT the end of line. | ||
| 695 | (save-excursion (end-of-line) (setq limit (min limit (point)))) | ||
| 696 | ;; Evaluate PRE-MATCH-FORM. | ||
| 695 | (eval (nth 1 keywords)) | 697 | (eval (nth 1 keywords)) |
| 696 | (save-match-data | 698 | (save-match-data |
| 699 | ;; Find an occurrence of `matcher' before `limit'. | ||
| 697 | (while (if (stringp matcher) | 700 | (while (if (stringp matcher) |
| 698 | (re-search-forward matcher limit t) | 701 | (re-search-forward matcher limit t) |
| 699 | (funcall matcher limit)) | 702 | (funcall matcher limit)) |
| 703 | ;; Apply each highlight to this instance of `matcher'. | ||
| 700 | (setq highlights lowdarks) | 704 | (setq highlights lowdarks) |
| 701 | (while highlights | 705 | (while highlights |
| 702 | (font-lock-apply-highlight (car highlights)) | 706 | (font-lock-apply-highlight (car highlights)) |
| 703 | (setq highlights (cdr highlights))))) | 707 | (setq highlights (cdr highlights))))) |
| 708 | ;; Evaluate POST-MATCH-FORM. | ||
| 704 | (eval (nth 2 keywords)))) | 709 | (eval (nth 2 keywords)))) |
| 705 | 710 | ||
| 706 | (defun font-lock-fontify-keywords-region (start end &optional loudly) | 711 | (defun font-lock-fontify-keywords-region (start end &optional loudly) |
| @@ -710,43 +715,29 @@ START should be at the beginning of a line." | |||
| 710 | (keywords (cdr (if (eq (car-safe font-lock-keywords) t) | 715 | (keywords (cdr (if (eq (car-safe font-lock-keywords) t) |
| 711 | font-lock-keywords | 716 | font-lock-keywords |
| 712 | (font-lock-compile-keywords)))) | 717 | (font-lock-compile-keywords)))) |
| 713 | (inhibit-read-only t) (buffer-undo-list t) | ||
| 714 | (modified (buffer-modified-p)) | ||
| 715 | (old-syntax (syntax-table)) | ||
| 716 | (bufname (buffer-name)) (count 0) | 718 | (bufname (buffer-name)) (count 0) |
| 717 | buffer-file-name buffer-file-truename) | 719 | keyword matcher highlights) |
| 718 | (unwind-protect | 720 | ;; |
| 719 | (let (keyword matcher highlights) | 721 | ;; Fontify each item in `font-lock-keywords' from `start' to `end'. |
| 720 | ;; | 722 | (while keywords |
| 721 | ;; Use the fontification syntax table, if any. | 723 | (if loudly (message "Fontifying %s... (regexps..%s)" bufname |
| 722 | (if font-lock-syntax-table (set-syntax-table font-lock-syntax-table)) | 724 | (make-string (setq count (1+ count)) ?.))) |
| 723 | ;; | ||
| 724 | ;; Fontify each item in `font-lock-keywords' from `start' to `end'. | ||
| 725 | (while keywords | ||
| 726 | (if loudly (message "Fontifying %s... (regexps..%s)" bufname | ||
| 727 | (make-string (setq count (1+ count)) ?.))) | ||
| 728 | ;; | ||
| 729 | ;; Find an occurrence of `matcher' from `start' to `end'. | ||
| 730 | (setq keyword (car keywords) matcher (car keyword)) | ||
| 731 | (goto-char start) | ||
| 732 | (while (if (stringp matcher) | ||
| 733 | (re-search-forward matcher end t) | ||
| 734 | (funcall matcher end)) | ||
| 735 | ;; Apply each highlight to this instance of `matcher', which may | ||
| 736 | ;; be specific highlights or more keywords anchored to `matcher'. | ||
| 737 | (setq highlights (cdr keyword)) | ||
| 738 | (while highlights | ||
| 739 | (if (numberp (car (car highlights))) | ||
| 740 | (font-lock-apply-highlight (car highlights)) | ||
| 741 | (font-lock-fontify-anchored-keywords (car highlights) end)) | ||
| 742 | (setq highlights (cdr highlights)))) | ||
| 743 | (setq keywords (cdr keywords)))) | ||
| 744 | ;; | 725 | ;; |
| 745 | ;; Clean up. | 726 | ;; Find an occurrence of `matcher' from `start' to `end'. |
| 746 | (set-syntax-table old-syntax) | 727 | (setq keyword (car keywords) matcher (car keyword)) |
| 747 | (and (buffer-modified-p) | 728 | (goto-char start) |
| 748 | (not modified) | 729 | (while (if (stringp matcher) |
| 749 | (set-buffer-modified-p nil))))) | 730 | (re-search-forward matcher end t) |
| 731 | (funcall matcher end)) | ||
| 732 | ;; Apply each highlight to this instance of `matcher', which may be | ||
| 733 | ;; specific highlights or more keywords anchored to `matcher'. | ||
| 734 | (setq highlights (cdr keyword)) | ||
| 735 | (while highlights | ||
| 736 | (if (numberp (car (car highlights))) | ||
| 737 | (font-lock-apply-highlight (car highlights)) | ||
| 738 | (font-lock-fontify-anchored-keywords (car highlights) end)) | ||
| 739 | (setq highlights (cdr highlights)))) | ||
| 740 | (setq keywords (cdr keywords))))) | ||
| 750 | 741 | ||
| 751 | ;; Various functions. | 742 | ;; Various functions. |
| 752 | 743 | ||
| @@ -1006,6 +997,7 @@ the face is also set; its value is the face name." | |||
| 1006 | (let ((set (funcall set-p face-name resource))) | 997 | (let ((set (funcall set-p face-name resource))) |
| 1007 | (and set (member (downcase set) '("on" "true")))))))) | 998 | (and set (member (downcase set) '("on" "true")))))))) |
| 1008 | (make-face face) | 999 | (make-face face) |
| 1000 | (add-to-list 'facemenu-unlisted-faces face) | ||
| 1009 | ;; Set attributes not set from X resources (and therefore `make-face'). | 1001 | ;; Set attributes not set from X resources (and therefore `make-face'). |
| 1010 | (or (funcall set-p face-name "Foreground") | 1002 | (or (funcall set-p face-name "Foreground") |
| 1011 | (condition-case nil | 1003 | (condition-case nil |
| @@ -1172,9 +1164,8 @@ the face is also set; its value is the face name." | |||
| 1172 | (save-match-data | 1164 | (save-match-data |
| 1173 | (condition-case nil | 1165 | (condition-case nil |
| 1174 | (save-restriction | 1166 | (save-restriction |
| 1175 | ;; Restrict ourselves to the end of the line. | 1167 | ;; Restrict to the end of line, currently guaranteed to be LIMIT. |
| 1176 | (end-of-line) | 1168 | (narrow-to-region (point-min) limit) |
| 1177 | (narrow-to-region (point-min) (min limit (point))) | ||
| 1178 | (goto-char (match-end 1)) | 1169 | (goto-char (match-end 1)) |
| 1179 | ;; Move over any item value, etc., to the next item. | 1170 | ;; Move over any item value, etc., to the next item. |
| 1180 | (while (not (looking-at "[ \t]*\\([,;]\\|$\\)")) | 1171 | (while (not (looking-at "[ \t]*\\([,;]\\|$\\)")) |