X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/be3d2d66d2dff979604134c5dc5fb506ded4aa54..f67b40b3d890918f1e856a5052f86c3c724f0658:/lisp/hi-lock.el diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el index c3e2d81476..7226433c80 100644 --- a/lisp/hi-lock.el +++ b/lisp/hi-lock.el @@ -1,17 +1,17 @@ ;;; hi-lock.el --- minor mode for interactive automatic highlighting ;; Copyright (C) 2000, 2001, 2002, 2003, 2004, -;; 2005 Free Software Foundation, Inc. +;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -;; Author: David M. Koppelman, koppel@ee.lsu.edu +;; Author: David M. Koppelman, koppel@ece.lsu.edu ;; Keywords: faces, minor-mode, matching, display ;; 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 @@ -19,9 +19,7 @@ ;; 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 . ;;; Commentary: ;; @@ -33,7 +31,8 @@ ;; will remove the highlighting. Any existing face can be used for ;; highlighting and a set of appropriate faces is provided. The ;; regexps can be written into the current buffer in a form that will -;; be recognized the next time the corresponding file is read. +;; be recognized the next time the corresponding file is read (when +;; file patterns is turned on). ;; ;; Applications: ;; @@ -60,6 +59,14 @@ ;; ;; (global-hi-lock-mode 1) ;; +;; To enable the use of patterns found in files (presumably placed +;; there by hi-lock) include the following in your .emacs file: +;; +;; (setq hi-lock-file-patterns-policy 'ask) +;; +;; If you get tired of being asked each time a file is loaded replace +;; `ask' with a function that returns t if patterns should be read. +;; ;; You might also want to bind the hi-lock commands to more ;; finger-friendly sequences: @@ -91,12 +98,22 @@ (defcustom hi-lock-file-patterns-range 10000 "Limit of search in a buffer for hi-lock patterns. -When a file is visited and hi-lock mode is on patterns starting +When a file is visited and hi-lock mode is on, patterns starting up to this limit are added to font-lock's patterns. See documentation of functions `hi-lock-mode' and `hi-lock-find-patterns'." :type 'integer :group 'hi-lock) +(defcustom hi-lock-highlight-range 200000 + "Size of area highlighted by hi-lock when font-lock not active. +Font-lock is not active in buffers that do their own highlighting, +such as the buffer created by `list-colors-display'. In those buffers +hi-lock patterns will only be applied over a range of +`hi-lock-highlight-range' characters. If font-lock is active then +highlighting will be applied throughout the buffer." + :type 'integer + :group 'hi-lock) + (defcustom hi-lock-exclude-modes '(rmail-mode mime/viewer-mode gnus-article-mode) "List of major modes in which hi-lock will not run. @@ -105,6 +122,20 @@ calls." :type '(repeat symbol) :group 'hi-lock) +(defcustom hi-lock-file-patterns-policy 'ask + "Specify when hi-lock should use patterns found in file. +If `ask', prompt when patterns found in buffer; if bound to a function, +use patterns when function returns t (function is called with patterns +as first argument); if nil or `never' or anything else, don't use file +patterns." + :type '(choice (const :tag "Do not use file patterns" never) + (const :tag "Ask about file patterns" ask) + (function :tag "Function to check file patterns")) + :group 'hi-lock + :version "22.1") + +;; It can have a function value. +(put 'hi-lock-file-patterns-policy 'risky-local-variable t) (defgroup hi-lock-faces nil "Faces for hi-lock." @@ -186,17 +217,17 @@ calls." "History of regexps used for interactive fontification.") (defvar hi-lock-file-patterns-prefix "Hi-lock" - "Regexp for finding hi-lock patterns at top of file.") + "Search target for finding hi-lock patterns at top of file.") (defvar hi-lock-archaic-interface-message-used nil - "True if user alerted that global-hi-lock-mode is now the global switch. -Earlier versions of hi-lock used hi-lock-mode as the global switch, -the message is issued if it appears that hi-lock-mode is used assuming + "True if user alerted that `global-hi-lock-mode' is now the global switch. +Earlier versions of hi-lock used `hi-lock-mode' as the global switch; +the message is issued if it appears that `hi-lock-mode' is used assuming that older functionality. This variable avoids multiple reminders.") (defvar hi-lock-archaic-interface-deduce nil - "If non-nil, sometimes assume that hi-lock-mode means global-hi-lock-mode. -Assumption is made if hi-lock-mode used in the *scratch* buffer while + "If non-nil, sometimes assume that `hi-lock-mode' means `global-hi-lock-mode'. +Assumption is made if `hi-lock-mode' used in the *scratch* buffer while a library is being loaded.") (make-variable-buffer-local 'hi-lock-interactive-patterns) @@ -247,14 +278,13 @@ a library is being loaded.") ;; Visible Functions - ;;;###autoload (define-minor-mode hi-lock-mode "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; to turn hi-lock on in all buffers use -global-hi-lock-mode or in your .emacs file (global-hi-lock-mode 1). +If ARG positive, turn hi-lock on. Issuing a hi-lock command will also +turn hi-lock on. To turn hi-lock on in all buffers use +`global-hi-lock-mode' or in your .emacs file (global-hi-lock-mode 1). 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: @@ -274,26 +304,33 @@ called interactively, are: Remove highlighting on matches of REGEXP in current buffer. \\[hi-lock-write-interactive-patterns] - Write active REGEXPs into buffer as comments (if possible). They will + Write active REGEXPs into buffer as comments (if possible). They may be read the next time file is loaded or when the \\[hi-lock-find-patterns] command is issued. The inserted regexps are in the form of font lock keywords. - (See `font-lock-keywords') They may be edited and re-loaded with \\[hi-lock-find-patterns], - any valid `font-lock-keywords' form is acceptable. + (See `font-lock-keywords'.) They may be edited and re-loaded with \\[hi-lock-find-patterns], + any valid `font-lock-keywords' form is acceptable. When a file is + loaded the patterns are read if `hi-lock-file-patterns-policy' is + 'ask and the user responds y to the prompt, or if + `hi-lock-file-patterns-policy' is bound to a function and that + function returns t. \\[hi-lock-find-patterns] Re-read patterns stored in buffer (in the format produced by \\[hi-lock-write-interactive-patterns]). -When hi-lock is started and if the mode is not excluded, the -beginning of the buffer is searched for lines of the form: +When hi-lock is started and if the mode is not excluded or patterns +rejected, the beginning of the buffer is searched for lines of the +form: Hi-lock: FOO -where FOO is a list of patterns. These are added to the font lock keywords -already present. The patterns must start before position (number -of characters into buffer) `hi-lock-file-patterns-range'. Patterns -will be read until +where FOO is a list of patterns. These are added to the font lock +keywords already present. The patterns must start before position +\(number of characters into buffer) `hi-lock-file-patterns-range'. +Patterns will be read until Hi-lock: end -is found. A mode is excluded if it's in the list `hi-lock-exclude-modes'." +is found. A mode is excluded if it's in the list `hi-lock-exclude-modes'." :group 'hi-lock - :lighter " H" + :lighter (:eval (if (or hi-lock-interactive-patterns + hi-lock-file-patterns) + " Hi" "")) :global nil :keymap hi-lock-map (when (and (equal (buffer-name) "*scratch*") @@ -306,7 +343,7 @@ is found. A mode is excluded if it's in the list `hi-lock-exclude-modes'." (warn "Possible archaic use of (hi-lock-mode). Use (global-hi-lock-mode 1) in .emacs to enable hi-lock for all buffers, -use (hi-lock-mode 1) for individual buffers. For compatibility with Emacs +use (hi-lock-mode 1) for individual buffers. For compatibility with Emacs versions before 22 use the following in your .emacs file: (if (functionp 'global-hi-lock-mode) @@ -330,13 +367,13 @@ versions before 22 use the following in your .emacs file: (when hi-lock-file-patterns (font-lock-remove-keywords nil hi-lock-file-patterns) (setq hi-lock-file-patterns nil)) - (if font-lock-mode - (font-lock-fontify-buffer))) + (remove-overlays nil nil 'hi-lock-overlay t) + (when font-lock-fontified (font-lock-fontify-buffer))) (define-key-after menu-bar-edit-menu [hi-lock] nil) (remove-hook 'font-lock-mode-hook 'hi-lock-font-lock-hook t))) ;;;###autoload -(define-global-minor-mode global-hi-lock-mode +(define-globalized-minor-mode global-hi-lock-mode hi-lock-mode turn-on-hi-lock-if-enabled :group 'hi-lock) @@ -354,7 +391,7 @@ versions before 22 use the following in your .emacs file: 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 @@ -379,7 +416,7 @@ list maintained for regexps, global history maintained for faces. 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 @@ -423,7 +460,7 @@ interactive functions. \(See `hi-lock-interactive-patterns'.\) \\Use \\[minibuffer-complete] to complete a partially typed regexp. \(See info node `Minibuffer History'.\)" (interactive - (if (and (display-popup-menus-p) (vectorp (this-command-keys))) + (if (and (display-popup-menus-p) (not last-nonmenu-event)) (catch 'snafu (or (x-popup-menu @@ -461,7 +498,9 @@ interactive functions. \(See `hi-lock-interactive-patterns'.\) (font-lock-remove-keywords nil (list keyword)) (setq hi-lock-interactive-patterns (delq keyword hi-lock-interactive-patterns)) - (font-lock-fontify-buffer)))) + (remove-overlays + nil nil 'hi-lock-overlay-regexp (hi-lock-string-serialize regexp)) + (when font-lock-fontified (font-lock-fontify-buffer))))) ;;;###autoload (defun hi-lock-write-interactive-patterns () @@ -474,9 +513,11 @@ be found in variable `hi-lock-interactive-patterns'." (if (null hi-lock-interactive-patterns) (error "There are no interactive patterns")) (let ((beg (point))) - (mapcar + (mapc (lambda (pattern) - (insert (format "Hi-lock: (%s)\n" (prin1-to-string pattern)))) + (insert (format "%s: (%s)\n" + hi-lock-file-patterns-prefix + (prin1-to-string pattern)))) hi-lock-interactive-patterns) (comment-region beg (point))) (when (> (point) hi-lock-file-patterns-range) @@ -526,25 +567,34 @@ not suitable." "Highlight REGEXP with face FACE." (let ((pattern (list regexp (list 0 (list 'quote face) t)))) (unless (member pattern hi-lock-interactive-patterns) - (font-lock-add-keywords nil (list pattern)) + (font-lock-add-keywords nil (list pattern) t) (push pattern hi-lock-interactive-patterns) - (let ((buffer-undo-list t) - (inhibit-read-only t) - (mod (buffer-modified-p))) - (save-excursion - (goto-char (point-min)) - (while (re-search-forward regexp (point-max) t) - (put-text-property - (match-beginning 0) (match-end 0) 'face face) - (goto-char (match-end 0)))) - (set-buffer-modified-p mod))))) + (if font-lock-fontified + (font-lock-fontify-buffer) + (let* ((serial (hi-lock-string-serialize regexp)) + (range-min (- (point) (/ hi-lock-highlight-range 2))) + (range-max (+ (point) (/ hi-lock-highlight-range 2))) + (search-start + (max (point-min) + (- range-min (max 0 (- range-max (point-max)))))) + (search-end + (min (point-max) + (+ range-max (max 0 (- (point-min) range-min)))))) + (save-excursion + (goto-char search-start) + (while (re-search-forward regexp search-end t) + (let ((overlay (make-overlay (match-beginning 0) (match-end 0)))) + (overlay-put overlay 'hi-lock-overlay t) + (overlay-put overlay 'hi-lock-overlay-regexp serial) + (overlay-put overlay 'face face)) + (goto-char (match-end 0))))))))) (defun hi-lock-set-file-patterns (patterns) "Replace file patterns list with PATTERNS and 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) + (font-lock-add-keywords nil hi-lock-file-patterns t) (font-lock-fontify-buffer))) (defun hi-lock-find-patterns () @@ -566,17 +616,53 @@ not suitable." (setq all-patterns (append (read (current-buffer)) all-patterns)) (error (message "Invalid pattern list expression at %d" (line-number-at-pos))))))) - (when hi-lock-mode (hi-lock-set-file-patterns all-patterns)) - (if (interactive-p) - (message "Hi-lock added %d patterns." (length all-patterns)))))) + (when (and all-patterns + hi-lock-mode + (cond + ((eq this-command 'hi-lock-find-patterns) t) + ((functionp hi-lock-file-patterns-policy) + (funcall hi-lock-file-patterns-policy all-patterns)) + ((eq hi-lock-file-patterns-policy 'ask) + (y-or-n-p "Add patterns from this buffer to hi-lock? ")) + (t nil))) + (hi-lock-set-file-patterns all-patterns) + (if (interactive-p) + (message "Hi-lock added %d patterns." (length all-patterns))))))) (defun hi-lock-font-lock-hook () - "Add hi lock patterns to font-lock's." + "Add hi-lock patterns to font-lock's." (if font-lock-mode - (progn (font-lock-add-keywords nil hi-lock-file-patterns) - (font-lock-add-keywords nil hi-lock-interactive-patterns)) + (progn + (font-lock-add-keywords nil hi-lock-file-patterns t) + (font-lock-add-keywords nil hi-lock-interactive-patterns t)) (hi-lock-mode -1))) +(defvar hi-lock-string-serialize-hash + (make-hash-table :test 'equal) + "Hash table used to assign unique numbers to strings.") + +(defvar hi-lock-string-serialize-serial 1 + "Number assigned to last new string in call to `hi-lock-string-serialize'. +A string is considered new if it had not previously been used in a call to +`hi-lock-string-serialize'.") + +(defun hi-lock-string-serialize (string) + "Return unique serial number for STRING." + (interactive) + (let ((val (gethash string hi-lock-string-serialize-hash))) + (if val val + (puthash string + (setq hi-lock-string-serialize-serial + (1+ hi-lock-string-serialize-serial)) + hi-lock-string-serialize-hash) + hi-lock-string-serialize-serial))) + +(defun hi-lock-unload-function () + "Unload the Hi-Lock library." + (global-hi-lock-mode -1) + ;; continue standard unloading + nil) + (provide 'hi-lock) ;; arch-tag: d2e8fd07-4cc9-4c6f-a200-1e729bc54066