X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/abb2db1cf3b6505afedcafb51e6f8dca36585b9c..9a2c63fb6aae5753fb4a87a9afe12d83aa1c265f:/lisp/hi-lock.el diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el index 554eacd2f4..99eeb69817 100644 --- a/lisp/hi-lock.el +++ b/lisp/hi-lock.el @@ -1,6 +1,6 @@ -;;; hi-lock.el --- Minor mode for interactive automatic highlighting. +;;; hi-lock.el --- minor mode for interactive automatic highlighting -;; Copyright (C) 2000 Free Software Foundation, Inc. +;; Copyright (C) 2000, 2001 Free Software Foundation, Inc. ;; Author: David M. Koppelman, koppel@ee.lsu.edu ;; Keywords: faces, minor-mode, matching, display @@ -22,8 +22,8 @@ ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. -;;; Commentary -;; +;;; Commentary: +;; ;; With the hi-lock commands text matching interactively entered ;; regexp's can be highlighted. For example, `M-x highlight-regexp ;; RET clearly RET RET' will highlight all occurrences of `clearly' @@ -49,22 +49,23 @@ ;; ;; When writing text, highlight personal cliches. This can be ;; amusing. -;; M-x highlight-regexp as can be seen RET RET +;; M-x highlight-phrase as can be seen RET RET ;; -;; Setup +;; Setup: ;; ;; Put the following code in your .emacs file. This turns on -;; hi-lock mode and adds an "Automatic Highlighting" entry +;; hi-lock mode and adds a "Regexp Highlighting" entry ;; to the edit menu. ;; ;; (hi-lock-mode 1) -;; +;; ;; You might also want to bind the hi-lock commands to more ;; finger-friendly sequences: ;; (define-key hi-lock-map "\C-z\C-h" 'highlight-lines-matching-regexp) ;; (define-key hi-lock-map "\C-zi" 'hi-lock-find-patterns) ;; (define-key hi-lock-map "\C-zh" 'highlight-regexp) +;; (define-key hi-lock-map "\C-zp" 'highlight-phrase) ;; (define-key hi-lock-map "\C-zr" 'unhighlight-regexp) ;; (define-key hi-lock-map "\C-zb" 'hi-lock-write-interactive-patterns)) @@ -79,10 +80,9 @@ ;;; Code: -(eval-when-compile +(eval-and-compile (require 'font-lock)) -;;;###autoload (defgroup hi-lock-interactive-text-highlighting nil "Interactively add and remove font-lock patterns for highlighting text." :group 'faces) @@ -110,7 +110,7 @@ of functions `hi-lock-mode' and `hi-lock-find-patterns'." "List of major modes in which hi-lock will not run. For security reasons since font lock patterns can specify function calls." - :type 'variable + :type '(repeat symbol) :group 'hi-lock-interactive-text-highlighting) @@ -119,22 +119,26 @@ calls." :group 'hi-lock-interactive-text-highlighting) (defface hi-yellow - '((t (:background "yellow"))) + '((((background dark)) (:background "yellow" :foreground "black")) + (t (:background "yellow"))) "Default face for hi-lock mode." :group 'hi-lock-faces) (defface hi-pink - '((t (:background "pink"))) + '((((background dark)) (:background "pink" :foreground "black")) + (t (:background "pink"))) "Face for hi-lock mode." :group 'hi-lock-faces) (defface hi-green - '((t (:background "green"))) + '((((background dark)) (:background "green" :foreground "black")) + (t (:background "green"))) "Face for hi-lock mode." :group 'hi-lock-faces) (defface hi-blue - '((t (:background "light blue"))) + '((((background dark)) (:background "light blue" :foreground "black")) + (t (:background "light blue"))) "Face for hi-lock mode." :group 'hi-lock-faces) @@ -159,7 +163,7 @@ calls." :group 'hi-lock-faces) (defface hi-black-hb - '((t (:weight bold :family "helv" :height 200))) + '((t (:weight bold :height 1.67 :inherit variable-pitch))) "Face for hi-lock mode." :group 'hi-lock-faces) @@ -196,6 +200,10 @@ calls." '(menu-item "Highlight Regexp..." highlight-regexp :help "Highlight text matching PATTERN (a regexp).")) +(define-key-after hi-lock-menu [highlight-phrase] + '(menu-item "Highlight Phrase..." highlight-phrase + :help "Highlight text matching PATTERN (a regexp processed to match phrases).")) + (define-key-after hi-lock-menu [highlight-lines-matching-regexp] '(menu-item "Highlight Lines..." highlight-lines-matching-regexp :help "Highlight lines containing match of PATTERN (a regexp)..")) @@ -219,6 +227,7 @@ calls." (define-key hi-lock-map "\C-xwi" 'hi-lock-find-patterns) (define-key hi-lock-map "\C-xwl" 'highlight-lines-matching-regexp) +(define-key hi-lock-map "\C-xwp" 'highlight-phrase) (define-key hi-lock-map "\C-xwh" 'highlight-regexp) (define-key hi-lock-map "\C-xwr" 'unhighlight-regexp) (define-key hi-lock-map "\C-xwb" 'hi-lock-write-interactive-patterns) @@ -239,13 +248,18 @@ calls." "Toggle minor mode for interactively adding font-lock highlighting patterns. If ARG positive turn hi-lock on. Issuing a hi-lock command will also -turn hi-lock on. When hi-lock turned on an \"Automatic Highlighting\" +turn hi-lock on. When hi-lock is turned on, a \"Regexp Highlighting\" submenu is added to the \"Edit\" menu. The commands in the submenu, which can be called interactively, are: \\[highlight-regexp] REGEXP FACE Highlight matches of pattern REGEXP in current buffer with FACE. +\\[highlight-phrase] PHRASE FACE + Highlight matches of phrase PHRASE in current buffer with FACE. + (PHRASE can be any REGEXP, but spaces will be replaced by matches + to whitespace and initial lower-case letters will become case insensitive.) + \\[highlight-lines-matching-regexp] REGEXP FACE Highlight lines containing matches of REGEXP in current buffer with FACE. @@ -274,22 +288,26 @@ is found. A mode is excluded if it's in the list `hi-lock-exclude-modes'." (interactive) (let ((hi-lock-mode-prev hi-lock-mode)) (setq hi-lock-mode - (if (null arg) (not hi-lock-mode) - (> (prefix-numeric-value arg) 0))) + (if (null arg) (not hi-lock-mode) + (> (prefix-numeric-value arg) 0))) ;; Turned on. (when (and (not hi-lock-mode-prev) hi-lock-mode) - (if (not font-lock-mode) (turn-on-font-lock)) (add-hook 'find-file-hooks 'hi-lock-find-file-hook) (add-hook 'font-lock-mode-hook 'hi-lock-font-lock-hook) (define-key-after menu-bar-edit-menu [hi-lock] - (cons "Automatic Highlighting" hi-lock-menu)) - (hi-lock-find-patterns)) + (cons "Regexp Highlighting" hi-lock-menu)) + (dolist (buffer (buffer-list)) + (with-current-buffer buffer (hi-lock-find-patterns)))) ;; Turned off. (when (and hi-lock-mode-prev (not hi-lock-mode)) - (font-lock-remove-keywords nil hi-lock-interactive-patterns) - (font-lock-remove-keywords nil hi-lock-file-patterns) - (setq hi-lock-interactive-patterns nil) - (hi-lock-refontify) + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + (when (or hi-lock-interactive-patterns hi-lock-file-patterns) + (font-lock-remove-keywords nil hi-lock-interactive-patterns) + (font-lock-remove-keywords nil hi-lock-file-patterns) + (setq hi-lock-interactive-patterns nil + hi-lock-file-patterns nil) + (when font-lock-mode (hi-lock-refontify))))) (define-key-after menu-bar-edit-menu [hi-lock] nil) (remove-hook 'find-file-hooks 'hi-lock-find-file-hook) (remove-hook 'font-lock-mode-hook 'hi-lock-font-lock-hook)))) @@ -299,12 +317,12 @@ is found. A mode is excluded if it's in the list `hi-lock-exclude-modes'." (defalias 'highlight-lines-matching-regexp 'hi-lock-line-face-buffer) ;;;###autoload (defun hi-lock-line-face-buffer (regexp &optional face) - "Set face of all lines containing matches of REGEXP to FACE. + "Set face of all lines containing a match of REGEXP to FACE. Interactively, prompt for REGEXP then FACE. Buffer-local history list maintained for regexps, global history maintained for faces. \\Use \\[next-history-element] and \\[previous-history-element] to retrieve next or previous history item. -(See info node `Minibuffer History')" +\(See info node `Minibuffer History')" (interactive (list (hi-lock-regexp-okay @@ -315,18 +333,21 @@ list maintained for regexps, global history maintained for faces. (unless hi-lock-mode (hi-lock-mode)) (or (facep face) (setq face 'rwl-yellow)) (hi-lock-set-pattern - (list (concat "^.*" regexp ".*$") (list 0 (list 'quote face) t)))) + ;; The \\(?:...\\) grouping construct ensures that a leading ^, +, * or ? + ;; or a trailing $ in REGEXP will be interpreted correctly. + (list (concat "^.*\\(?:" regexp "\\).*$") (list 0 (list 'quote face) t)))) + ;;;###autoload (defalias 'highlight-regexp 'hi-lock-face-buffer) ;;;###autoload (defun hi-lock-face-buffer (regexp &optional face) - "Set face of all matches of REGEXP to FACE. + "Set face of each match of REGEXP to FACE. Interactively, prompt for REGEXP then FACE. Buffer-local history list maintained for regexps, global history maintained for faces. \\Use \\[next-history-element] and \\[previous-history-element] to retrieve next or previous history item. -(See info node `Minibuffer History')" +\(See info node `Minibuffer History')" (interactive (list (hi-lock-regexp-okay @@ -338,40 +359,69 @@ list maintained for regexps, global history maintained for faces. (unless hi-lock-mode (hi-lock-mode)) (hi-lock-set-pattern (list regexp (list 0 (list 'quote face) t)))) +;;;###autoload +(defalias 'highlight-phrase 'hi-lock-face-phrase-buffer) +;;;###autoload +(defun hi-lock-face-phrase-buffer (regexp &optional face) + "Set face of each match of phrase REGEXP to FACE. + +Whitespace in REGEXP converted to arbitrary whitespace and initial +lower-case letters made case insensitive." + (interactive + (list + (hi-lock-regexp-okay + (hi-lock-process-phrase + (read-from-minibuffer "Phrase to highlight: " + (cons (or (car hi-lock-regexp-history) "") 1 ) + nil nil 'hi-lock-regexp-history))) + (hi-lock-read-face-name))) + (or (facep face) (setq face 'rwl-yellow)) + (unless hi-lock-mode (hi-lock-mode)) + (hi-lock-set-pattern (list regexp (list 0 (list 'quote face) t)))) + ;;;###autoload (defalias 'unhighlight-regexp 'hi-lock-unface-buffer) ;;;###autoload (defun hi-lock-unface-buffer (regexp) - "Remove highlighting of matches to REGEXP set by hi-lock. + "Remove highlighting of each match to REGEXP set by hi-lock. Interactively, prompt for REGEXP. Buffer-local history of inserted regexp's maintained. Will accept only regexps inserted by hi-lock -interactive functions. (See `hi-lock-interactive-patterns') +interactive functions. \(See `hi-lock-interactive-patterns'.\) \\Use \\[minibuffer-complete] to complete a partially typed regexp. -(See info node `Minibuffer History'.)" +\(See info node `Minibuffer History'.\)" (interactive - (if (vectorp (this-command-keys)) - (x-popup-menu - t - (cons - `keymap - (cons "Select Pattern to Unhighlight" - (mapcar (lambda (pattern) - (list (car pattern) - (format - "%s (%s)" (car pattern) - (symbol-name - (car (cdr (car (cdr (car (cdr pattern)))))))) - (cons nil nil) - (car pattern))) - hi-lock-interactive-patterns)))) + (if (and (display-popup-menus-p) (vectorp (this-command-keys))) + (catch 'snafu + (or + (x-popup-menu + t + (cons + `keymap + (cons "Select Pattern to Unhighlight" + (mapcar (lambda (pattern) + (list (car pattern) + (format + "%s (%s)" (car pattern) + (symbol-name + (car + (cdr (car (cdr (car (cdr pattern)))))))) + (cons nil nil) + (car pattern))) + hi-lock-interactive-patterns)))) + ;; If the user clicks outside the menu, meaning that they + ;; change their mind, x-popup-menu returns nil, and + ;; interactive signals a wrong number of arguments error. + ;; To prevent that, we return an empty string, which will + ;; effectively disable the rest of the function. + (throw 'snafu '("")))) (let ((history-list (mapcar (lambda (p) (car p)) hi-lock-interactive-patterns))) (unless hi-lock-interactive-patterns (error "No highlighting to remove")) (list (completing-read "Regexp to unhighlight: " - hi-lock-interactive-patterns t t + hi-lock-interactive-patterns nil t (car (car hi-lock-interactive-patterns)) (cons 'history-list 1)))))) (let ((keyword (assoc regexp hi-lock-interactive-patterns))) @@ -403,6 +453,19 @@ be found in variable `hi-lock-interactive-patterns'." ;; Implementation Functions +(defun hi-lock-process-phrase (phrase) + "Convert regexp PHRASE to a regexp that matches phrases. + +Blanks in PHRASE replaced by regexp that matches arbitrary whitespace +and initial lower-case letters made case insensitive." + (let ((mod-phrase nil)) + (setq mod-phrase + (replace-regexp-in-string + "\\<[a-z]" (lambda (m) (format "[%s%s]" (upcase m) m)) phrase)) + (setq mod-phrase + (replace-regexp-in-string + "\\s-+" "[ \t\n]+" mod-phrase nil t)))) + (defun hi-lock-regexp-okay (regexp) "Return REGEXP if it appears suitable for a font-lock pattern. @@ -454,25 +517,17 @@ Optional argument END is maximum excursion." (defun hi-lock-set-file-patterns (patterns) "Replace file patterns list with PATTERNS and refontify." - (font-lock-remove-keywords nil hi-lock-file-patterns) - (setq hi-lock-file-patterns patterns) - (font-lock-add-keywords nil hi-lock-file-patterns) - (hi-lock-refontify)) + (when (or hi-lock-file-patterns patterns) + (font-lock-remove-keywords nil hi-lock-file-patterns) + (setq hi-lock-file-patterns patterns) + (font-lock-add-keywords nil hi-lock-file-patterns) + (hi-lock-refontify))) (defun hi-lock-refontify () "Unfontify then refontify buffer. Used when hi-lock patterns change." (interactive) - (font-lock-unfontify-buffer) - (cond - (jit-lock-mode (jit-lock-fontify-buffer)) - ;; Need a better way, since this assumes too much about lazy lock. - (lazy-lock-mode - (let ((windows (get-buffer-window-list (current-buffer) 'nomini t))) - (while windows - (lazy-lock-fontify-window (car windows)) - (setq windows (cdr windows))))) - (t (font-lock-fontify-buffer)))) - + (unless font-lock-mode (font-lock-mode 1)) + (font-lock-fontify-buffer)) (defun hi-lock-find-patterns () "Find patterns in current buffer for hi-lock." @@ -481,27 +536,23 @@ Optional argument END is maximum excursion." (let ((all-patterns nil) (target-regexp (concat "\\<" hi-lock-file-patterns-prefix ":"))) (save-excursion - (widen) - (goto-char (point-min)) - (re-search-forward target-regexp - (+ (point) hi-lock-file-patterns-range) t) - (beginning-of-line) - (while - (and - (re-search-forward target-regexp (+ (point) 100) t) - (not (looking-at "\\s-*end"))) - (let - ((patterns - (condition-case nil - (read (current-buffer)) - (error (message - (format "Could not read expression at %d" - (hi-lock-current-line))) nil)))) - (if patterns - (setq all-patterns (append patterns all-patterns)))))) - (if (and (not hi-lock-mode) all-patterns) - (hi-lock-mode 1)) - (if hi-lock-mode (hi-lock-set-file-patterns all-patterns)) + (save-restriction + (widen) + (goto-char (point-min)) + (re-search-forward target-regexp + (+ (point) hi-lock-file-patterns-range) t) + (beginning-of-line) + (while (and (re-search-forward target-regexp (+ (point) 100) t) + (not (looking-at "\\s-*end"))) + (let ((patterns + (condition-case nil + (read (current-buffer)) + (error (message + (format "Could not read expression at %d" + (hi-lock-current-line))) nil)))) + (if patterns + (setq all-patterns (append patterns all-patterns))))))) + (when hi-lock-mode (hi-lock-set-file-patterns all-patterns)) (if (interactive-p) (message (format "Hi-lock added %d patterns." (length all-patterns))))))) @@ -513,6 +564,5 @@ Optional argument END is maximum excursion." (provide 'hi-lock) +;;; arch-tag: d2e8fd07-4cc9-4c6f-a200-1e729bc54066 ;;; hi-lock.el ends here - -