diff options
| author | Jambunathan K | 2012-12-04 16:13:47 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2012-12-04 16:13:47 -0500 |
| commit | b85aec936c85449faeaca36f52994487633e2e48 (patch) | |
| tree | df8d13f220ee277e7c847c12bc2eea020fdbf63b | |
| parent | 47a6e6df2b6430c1047538260750cdbe78c566d5 (diff) | |
| download | emacs-b85aec936c85449faeaca36f52994487633e2e48.tar.gz emacs-b85aec936c85449faeaca36f52994487633e2e48.zip | |
* lisp/hi-lock.el (hi-lock-auto-select-face): New user variable.
(hi-lock-auto-select-face-defaults): New buffer local variable.
(hi-lock-read-face-name): Honor `hi-lock-auto-select-face'.
(hi-lock-unface-buffer): Prompt user with useful defaults.
With prefix arg, unhighlight all hi-lock patterns in buffer.
Fixes: debbugs:11095
| -rw-r--r-- | lisp/ChangeLog | 8 | ||||
| -rw-r--r-- | lisp/hi-lock.el | 160 |
2 files changed, 116 insertions, 52 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 352e5a7e970..ff9b0e2a86f 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,11 @@ | |||
| 1 | 2012-12-04 Jambunathan K <kjambunathan@gmail.com> | ||
| 2 | |||
| 3 | * hi-lock.el (hi-lock-auto-select-face): New user variable. | ||
| 4 | (hi-lock-auto-select-face-defaults): New buffer local variable. | ||
| 5 | (hi-lock-read-face-name): Honor `hi-lock-auto-select-face'. | ||
| 6 | (hi-lock-unface-buffer): Prompt user with useful defaults. | ||
| 7 | With prefix arg, unhighlight all hi-lock patterns in buffer. | ||
| 8 | |||
| 1 | 2012-12-04 Stefan Monnier <monnier@iro.umontreal.ca> | 9 | 2012-12-04 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 10 | ||
| 3 | * obsolete/terminal.el, obsolete/longlines.el: Add obsolecence info. | 11 | * obsolete/terminal.el, obsolete/longlines.el: Add obsolecence info. |
diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el index 59743124cc5..5496a7581c3 100644 --- a/lisp/hi-lock.el +++ b/lisp/hi-lock.el | |||
| @@ -135,6 +135,13 @@ patterns." | |||
| 135 | ;; It can have a function value. | 135 | ;; It can have a function value. |
| 136 | (put 'hi-lock-file-patterns-policy 'risky-local-variable t) | 136 | (put 'hi-lock-file-patterns-policy 'risky-local-variable t) |
| 137 | 137 | ||
| 138 | (defcustom hi-lock-auto-select-face nil | ||
| 139 | "Non-nil if highlighting commands should not prompt for face names. | ||
| 140 | When non-nil, each hi-lock command will cycle through faces in | ||
| 141 | `hi-lock-face-defaults'." | ||
| 142 | :type 'boolean | ||
| 143 | :version "24.4") | ||
| 144 | |||
| 138 | (defgroup hi-lock-faces nil | 145 | (defgroup hi-lock-faces nil |
| 139 | "Faces for hi-lock." | 146 | "Faces for hi-lock." |
| 140 | :group 'hi-lock | 147 | :group 'hi-lock |
| @@ -211,8 +218,13 @@ patterns." | |||
| 211 | "hi-blue-b" "hi-red-b" "hi-green-b" "hi-black-hb") | 218 | "hi-blue-b" "hi-red-b" "hi-green-b" "hi-black-hb") |
| 212 | "Default faces for hi-lock interactive functions.") | 219 | "Default faces for hi-lock interactive functions.") |
| 213 | 220 | ||
| 214 | ;;(dolist (f hi-lock-face-defaults) | 221 | (defvar-local hi-lock--auto-select-face-defaults |
| 215 | ;; (unless (facep f) (error "%s not a face" f))) | 222 | (let ((l (copy-sequence hi-lock-face-defaults))) |
| 223 | (setcdr (last l) l)) | ||
| 224 | "Circular list of faces used for interactive highlighting. | ||
| 225 | When `hi-lock-auto-select-face' is non-nil, use the face at the | ||
| 226 | head of this list for next interactive highlighting. See also | ||
| 227 | `hi-lock-read-face-name'.") | ||
| 216 | 228 | ||
| 217 | (define-obsolete-variable-alias 'hi-lock-regexp-history | 229 | (define-obsolete-variable-alias 'hi-lock-regexp-history |
| 218 | 'regexp-history | 230 | 'regexp-history |
| @@ -463,50 +475,87 @@ updated as you type." | |||
| 463 | 475 | ||
| 464 | (declare-function x-popup-menu "menu.c" (position menu)) | 476 | (declare-function x-popup-menu "menu.c" (position menu)) |
| 465 | 477 | ||
| 478 | (defun hi-lock--regexps-at-point () | ||
| 479 | (let ((regexps '())) | ||
| 480 | ;; When using overlays, there is no ambiguity on the best | ||
| 481 | ;; choice of regexp. | ||
| 482 | (let ((desired-serial (get-char-property | ||
| 483 | (point) 'hi-lock-overlay-regexp))) | ||
| 484 | (when desired-serial | ||
| 485 | (catch 'regexp | ||
| 486 | (maphash | ||
| 487 | (lambda (regexp serial) | ||
| 488 | (when (= serial desired-serial) | ||
| 489 | (push regexp regexps))) | ||
| 490 | hi-lock-string-serialize-hash)))) | ||
| 491 | ;; With font-locking on, check if the cursor is on an highlighted text. | ||
| 492 | ;; Checking for hi-lock face is a good heuristic. | ||
| 493 | (and (string-match "\\`hi-lock-" (face-name (face-at-point))) | ||
| 494 | (let* ((hi-text | ||
| 495 | (buffer-substring-no-properties | ||
| 496 | (previous-single-property-change (point) 'face) | ||
| 497 | (next-single-property-change (point) 'face)))) | ||
| 498 | ;; Compute hi-lock patterns that match the | ||
| 499 | ;; highlighted text at point. Use this later in | ||
| 500 | ;; during completing-read. | ||
| 501 | (dolist (hi-lock-pattern hi-lock-interactive-patterns) | ||
| 502 | (let ((regexp (car hi-lock-pattern))) | ||
| 503 | (if (string-match regexp hi-text) | ||
| 504 | (push regexp regexps)))))))) | ||
| 505 | |||
| 466 | ;;;###autoload | 506 | ;;;###autoload |
| 467 | (defalias 'unhighlight-regexp 'hi-lock-unface-buffer) | 507 | (defalias 'unhighlight-regexp 'hi-lock-unface-buffer) |
| 468 | ;;;###autoload | 508 | ;;;###autoload |
| 469 | (defun hi-lock-unface-buffer (regexp) | 509 | (defun hi-lock-unface-buffer (regexp) |
| 470 | "Remove highlighting of each match to REGEXP set by hi-lock. | 510 | "Remove highlighting of each match to REGEXP set by hi-lock. |
| 471 | Interactively, prompt for REGEXP, accepting only regexps | 511 | Interactively, prompt for REGEXP, accepting only regexps |
| 472 | previously inserted by hi-lock interactive functions." | 512 | previously inserted by hi-lock interactive functions. |
| 513 | If REGEXP is t (or if \\[universal-argument] was specified interactively), | ||
| 514 | then remove all hi-lock highlighting." | ||
| 473 | (interactive | 515 | (interactive |
| 474 | (if (and (display-popup-menus-p) | 516 | (cond |
| 475 | (listp last-nonmenu-event) | 517 | (current-prefix-arg (list t)) |
| 476 | use-dialog-box) | 518 | ((and (display-popup-menus-p) |
| 477 | (catch 'snafu | 519 | (listp last-nonmenu-event) |
| 478 | (or | 520 | use-dialog-box) |
| 479 | (x-popup-menu | 521 | (catch 'snafu |
| 480 | t | 522 | (or |
| 481 | (cons | 523 | (x-popup-menu |
| 482 | `keymap | 524 | t |
| 483 | (cons "Select Pattern to Unhighlight" | 525 | (cons |
| 484 | (mapcar (lambda (pattern) | 526 | `keymap |
| 485 | (list (car pattern) | 527 | (cons "Select Pattern to Unhighlight" |
| 486 | (format | 528 | (mapcar (lambda (pattern) |
| 487 | "%s (%s)" (car pattern) | 529 | (list (car pattern) |
| 488 | (symbol-name | 530 | (format |
| 489 | (car | 531 | "%s (%s)" (car pattern) |
| 490 | (cdr (car (cdr (car (cdr pattern)))))))) | 532 | (symbol-name |
| 491 | (cons nil nil) | 533 | (car |
| 492 | (car pattern))) | 534 | (cdr (car (cdr (car (cdr pattern)))))))) |
| 493 | hi-lock-interactive-patterns)))) | 535 | (cons nil nil) |
| 494 | ;; If the user clicks outside the menu, meaning that they | 536 | (car pattern))) |
| 495 | ;; change their mind, x-popup-menu returns nil, and | 537 | hi-lock-interactive-patterns)))) |
| 496 | ;; interactive signals a wrong number of arguments error. | 538 | ;; If the user clicks outside the menu, meaning that they |
| 497 | ;; To prevent that, we return an empty string, which will | 539 | ;; change their mind, x-popup-menu returns nil, and |
| 498 | ;; effectively disable the rest of the function. | 540 | ;; interactive signals a wrong number of arguments error. |
| 499 | (throw 'snafu '("")))) | 541 | ;; To prevent that, we return an empty string, which will |
| 500 | (let ((history-list (mapcar (lambda (p) (car p)) | 542 | ;; effectively disable the rest of the function. |
| 501 | hi-lock-interactive-patterns))) | 543 | (throw 'snafu '(""))))) |
| 502 | (unless hi-lock-interactive-patterns | 544 | (t |
| 503 | (error "No highlighting to remove")) | 545 | ;; Un-highlighting triggered via keyboard action. |
| 546 | (unless hi-lock-interactive-patterns | ||
| 547 | (error "No highlighting to remove")) | ||
| 548 | ;; Infer the regexp to un-highlight based on cursor position. | ||
| 549 | (let* ((defaults (hi-lock--regexps-at-point))) | ||
| 504 | (list | 550 | (list |
| 505 | (completing-read "Regexp to unhighlight: " | 551 | (completing-read (if (null defaults) |
| 506 | hi-lock-interactive-patterns nil t | 552 | "Regexp to unhighlight: " |
| 507 | (car (car hi-lock-interactive-patterns)) | 553 | (format "Regexp to unhighlight (default %s): " |
| 508 | (cons 'history-list 1)))))) | 554 | (car defaults))) |
| 509 | (let ((keyword (assoc regexp hi-lock-interactive-patterns))) | 555 | hi-lock-interactive-patterns |
| 556 | nil t nil nil defaults)))))) | ||
| 557 | (dolist (keyword (if (eq regexp t) hi-lock-interactive-patterns | ||
| 558 | (list (assoc regexp hi-lock-interactive-patterns)))) | ||
| 510 | (when keyword | 559 | (when keyword |
| 511 | (font-lock-remove-keywords nil (list keyword)) | 560 | (font-lock-remove-keywords nil (list keyword)) |
| 512 | (setq hi-lock-interactive-patterns | 561 | (setq hi-lock-interactive-patterns |
| @@ -567,20 +616,25 @@ not suitable." | |||
| 567 | regexp)) | 616 | regexp)) |
| 568 | 617 | ||
| 569 | (defun hi-lock-read-face-name () | 618 | (defun hi-lock-read-face-name () |
| 570 | "Read face name from minibuffer with completion and history." | 619 | "Return face name for interactive highlighting. |
| 571 | (intern (completing-read | 620 | When `hi-lock-auto-select-face' is non-nil, just return the next face. |
| 572 | "Highlight using face: " | 621 | Otherwise, read face name from minibuffer with completion and history." |
| 573 | obarray 'facep t | 622 | (if hi-lock-auto-select-face |
| 574 | (cons (car hi-lock-face-defaults) | 623 | ;; Return current head and rotate the face list. |
| 575 | (let ((prefix | 624 | (pop hi-lock--auto-select-face-defaults) |
| 576 | (try-completion | 625 | (intern (completing-read |
| 577 | (substring (car hi-lock-face-defaults) 0 1) | 626 | "Highlight using face: " |
| 578 | hi-lock-face-defaults))) | 627 | obarray 'facep t |
| 579 | (if (and (stringp prefix) | 628 | (cons (car hi-lock-face-defaults) |
| 580 | (not (equal prefix (car hi-lock-face-defaults)))) | 629 | (let ((prefix |
| 581 | (length prefix) 0))) | 630 | (try-completion |
| 582 | 'face-name-history | 631 | (substring (car hi-lock-face-defaults) 0 1) |
| 583 | (cdr hi-lock-face-defaults)))) | 632 | hi-lock-face-defaults))) |
| 633 | (if (and (stringp prefix) | ||
| 634 | (not (equal prefix (car hi-lock-face-defaults)))) | ||
| 635 | (length prefix) 0))) | ||
| 636 | 'face-name-history | ||
| 637 | (cdr hi-lock-face-defaults))))) | ||
| 584 | 638 | ||
| 585 | (defun hi-lock-set-pattern (regexp face) | 639 | (defun hi-lock-set-pattern (regexp face) |
| 586 | "Highlight REGEXP with face FACE." | 640 | "Highlight REGEXP with face FACE." |
| @@ -656,6 +710,8 @@ not suitable." | |||
| 656 | (font-lock-add-keywords nil hi-lock-interactive-patterns t))) | 710 | (font-lock-add-keywords nil hi-lock-interactive-patterns t))) |
| 657 | 711 | ||
| 658 | (defvar hi-lock-string-serialize-hash | 712 | (defvar hi-lock-string-serialize-hash |
| 713 | ;; FIXME: don't map strings to numbers but to unique strings via | ||
| 714 | ;; hash-consing, with a weak hash-table. | ||
| 659 | (make-hash-table :test 'equal) | 715 | (make-hash-table :test 'equal) |
| 660 | "Hash table used to assign unique numbers to strings.") | 716 | "Hash table used to assign unique numbers to strings.") |
| 661 | 717 | ||