(face-read-string): Set the default value arg of completing-read.
[bpt/emacs.git] / lisp / hi-lock.el
CommitLineData
e8af40ee 1;;; hi-lock.el --- minor mode for interactive automatic highlighting
abb2db1c 2
0d30b337
TTN
3;; Copyright (C) 2000, 2001, 2002, 2003, 2004,
4;; 2005 Free Software Foundation, Inc.
abb2db1c
GM
5
6;; Author: David M. Koppelman, koppel@ee.lsu.edu
7;; Keywords: faces, minor-mode, matching, display
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to the
086add15
LK
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
abb2db1c 25
e8af40ee 26;;; Commentary:
71296446 27;;
abb2db1c
GM
28;; With the hi-lock commands text matching interactively entered
29;; regexp's can be highlighted. For example, `M-x highlight-regexp
30;; RET clearly RET RET' will highlight all occurrences of `clearly'
31;; using a yellow background face. New occurrences of `clearly' will
32;; be highlighted as they are typed. `M-x unhighlight-regexp RET'
33;; will remove the highlighting. Any existing face can be used for
34;; highlighting and a set of appropriate faces is provided. The
35;; regexps can be written into the current buffer in a form that will
36;; be recognized the next time the corresponding file is read.
37;;
38;; Applications:
39;;
40;; In program source code highlight a variable to quickly see all
41;; places it is modified or referenced:
42;; M-x highlight-regexp ground_contact_switches_closed RET RET
43;;
44;; In a shell or other buffer that is showing lots of program
45;; output, highlight the parts of the output you're interested in:
46;; M-x highlight-regexp Total execution time [0-9]+ RET hi-blue-b RET
47;;
48;; In buffers displaying tables, highlight the lines you're interested in:
49;; M-x highlight-lines-matching-regexp January 2000 RET hi-black-b RET
50;;
51;; When writing text, highlight personal cliches. This can be
52;; amusing.
108ee42b 53;; M-x highlight-phrase as can be seen RET RET
abb2db1c 54;;
108ee42b 55;; Setup:
abb2db1c
GM
56;;
57;; Put the following code in your .emacs file. This turns on
108ee42b 58;; hi-lock mode and adds a "Regexp Highlighting" entry
abb2db1c
GM
59;; to the edit menu.
60;;
61;; (hi-lock-mode 1)
71296446 62;;
abb2db1c
GM
63;; You might also want to bind the hi-lock commands to more
64;; finger-friendly sequences:
65
66;; (define-key hi-lock-map "\C-z\C-h" 'highlight-lines-matching-regexp)
67;; (define-key hi-lock-map "\C-zi" 'hi-lock-find-patterns)
68;; (define-key hi-lock-map "\C-zh" 'highlight-regexp)
108ee42b 69;; (define-key hi-lock-map "\C-zp" 'highlight-phrase)
abb2db1c
GM
70;; (define-key hi-lock-map "\C-zr" 'unhighlight-regexp)
71;; (define-key hi-lock-map "\C-zb" 'hi-lock-write-interactive-patterns))
72
73;; See the documentation for hi-lock-mode `C-h f hi-lock-mode' for
74;; additional instructions.
75
76;; Sample file patterns:
77
78; Hi-lock: (("^;;; .*" (0 (quote hi-black-hb) t)))
79; Hi-lock: ( ("make-variable-buffer-\\(local\\)" (0 font-lock-keyword-face)(1 'italic append)))))
80; Hi-lock: end
81
82;;; Code:
83
588aca27 84(eval-and-compile
abb2db1c
GM
85 (require 'font-lock))
86
abb2db1c
GM
87(defgroup hi-lock-interactive-text-highlighting nil
88 "Interactively add and remove font-lock patterns for highlighting text."
89 :group 'faces)
90
91;;;###autoload
92(defcustom hi-lock-mode nil
93 "Toggle hi-lock, for interactively adding font-lock text-highlighting patterns."
94 :set (lambda (symbol value)
95 (hi-lock-mode (or value 0)))
96 :initialize 'custom-initialize-default
97 :type 'boolean
98 :group 'hi-lock-interactive-text-highlighting
99 :require 'hi-lock)
100
101(defcustom hi-lock-file-patterns-range 10000
102 "Limit of search in a buffer for hi-lock patterns.
103When a file is visited and hi-lock mode is on patterns starting
104up to this limit are added to font-lock's patterns. See documentation
105of functions `hi-lock-mode' and `hi-lock-find-patterns'."
106 :type 'integer
107 :group 'hi-lock-interactive-text-highlighting)
108
109(defcustom hi-lock-exclude-modes
110 '(rmail-mode mime/viewer-mode gnus-article-mode)
111 "List of major modes in which hi-lock will not run.
112For security reasons since font lock patterns can specify function
113calls."
f5bd8092 114 :type '(repeat symbol)
abb2db1c
GM
115 :group 'hi-lock-interactive-text-highlighting)
116
117
118(defgroup hi-lock-faces nil
119 "Faces for hi-lock."
120 :group 'hi-lock-interactive-text-highlighting)
121
122(defface hi-yellow
e0d815a2 123 '((((min-colors 88) (background dark))
ea81d57e
DN
124 (:background "yellow1" :foreground "black"))
125 (((background dark)) (:background "yellow" :foreground "black"))
126 (((min-colors 88)) (:background "yellow1"))
a0b8c939 127 (t (:background "yellow")))
abb2db1c
GM
128 "Default face for hi-lock mode."
129 :group 'hi-lock-faces)
130
131(defface hi-pink
16cdf141 132 '((((background dark)) (:background "pink" :foreground "black"))
a0b8c939 133 (t (:background "pink")))
abb2db1c
GM
134 "Face for hi-lock mode."
135 :group 'hi-lock-faces)
136
137(defface hi-green
e0d815a2 138 '((((min-colors 88) (background dark))
ea81d57e
DN
139 (:background "green1" :foreground "black"))
140 (((background dark)) (:background "green" :foreground "black"))
e0d815a2 141 (((min-colors 88)) (:background "green1"))
a0b8c939 142 (t (:background "green")))
abb2db1c
GM
143 "Face for hi-lock mode."
144 :group 'hi-lock-faces)
145
146(defface hi-blue
16cdf141 147 '((((background dark)) (:background "light blue" :foreground "black"))
a0b8c939 148 (t (:background "light blue")))
abb2db1c
GM
149 "Face for hi-lock mode."
150 :group 'hi-lock-faces)
151
152(defface hi-black-b
153 '((t (:weight bold)))
154 "Face for hi-lock mode."
155 :group 'hi-lock-faces)
156
157(defface hi-blue-b
ea81d57e
DN
158 '((((min-colors 88)) (:weight bold :foreground "blue1"))
159 (t (:weight bold :foreground "blue")))
abb2db1c
GM
160 "Face for hi-lock mode."
161 :group 'hi-lock-faces)
162
163(defface hi-green-b
ea81d57e
DN
164 '((((min-colors 88)) (:weight bold :foreground "green1"))
165 (t (:weight bold :foreground "green")))
abb2db1c
GM
166 "Face for hi-lock mode."
167 :group 'hi-lock-faces)
168
169(defface hi-red-b
ea81d57e
DN
170 '((((min-colors 88)) (:weight bold :foreground "red1"))
171 (t (:weight bold :foreground "red")))
abb2db1c
GM
172 "Face for hi-lock mode."
173 :group 'hi-lock-faces)
174
175(defface hi-black-hb
c3b27206 176 '((t (:weight bold :height 1.67 :inherit variable-pitch)))
abb2db1c
GM
177 "Face for hi-lock mode."
178 :group 'hi-lock-faces)
179
180(defvar hi-lock-file-patterns nil
181 "Patterns found in file for hi-lock. Should not be changed.")
182
183(defvar hi-lock-interactive-patterns nil
184 "Patterns provided to hi-lock by user. Should not be changed.")
185
186(defvar hi-lock-face-history
187 (list "hi-yellow" "hi-pink" "hi-green" "hi-blue" "hi-black-b"
188 "hi-blue-b" "hi-red-b" "hi-green-b" "hi-black-hb")
189 "History list of faces for hi-lock interactive functions.")
190
191;(dolist (f hi-lock-face-history) (unless (facep f) (error "%s not a face" f)))
192
193(defvar hi-lock-regexp-history nil
194 "History of regexps used for interactive fontification.")
195
196(defvar hi-lock-file-patterns-prefix "Hi-lock"
197 "Regexp for finding hi-lock patterns at top of file.")
198
199(make-variable-buffer-local 'hi-lock-interactive-patterns)
200(put 'hi-lock-interactive-patterns 'permanent-local t)
201(make-variable-buffer-local 'hi-lock-regexp-history)
202(put 'hi-lock-regexp-history 'permanent-local t)
203(make-variable-buffer-local 'hi-lock-file-patterns)
204(put 'hi-lock-file-patterns 'permanent-local t)
205
206(defvar hi-lock-menu (make-sparse-keymap "Hi Lock")
207 "Menu for hi-lock mode.")
208
209(define-key-after hi-lock-menu [highlight-regexp]
210 '(menu-item "Highlight Regexp..." highlight-regexp
211 :help "Highlight text matching PATTERN (a regexp)."))
212
108ee42b
GM
213(define-key-after hi-lock-menu [highlight-phrase]
214 '(menu-item "Highlight Phrase..." highlight-phrase
215 :help "Highlight text matching PATTERN (a regexp processed to match phrases)."))
216
abb2db1c
GM
217(define-key-after hi-lock-menu [highlight-lines-matching-regexp]
218 '(menu-item "Highlight Lines..." highlight-lines-matching-regexp
219 :help "Highlight lines containing match of PATTERN (a regexp).."))
220
221(define-key-after hi-lock-menu [unhighlight-regexp]
222 '(menu-item "Remove Highlighting..." unhighlight-regexp
223 :help "Remove previously entered highlighting pattern."
224 :enable hi-lock-interactive-patterns))
225
226(define-key-after hi-lock-menu [hi-lock-write-interactive-patterns]
227 '(menu-item "Patterns to Buffer" hi-lock-write-interactive-patterns
228 :help "Insert interactively added REGEXPs into buffer at point."
229 :enable hi-lock-interactive-patterns))
230
231(define-key-after hi-lock-menu [hi-lock-find-patterns]
232 '(menu-item "Patterns from Buffer" hi-lock-find-patterns
233 :help "Use patterns (if any) near top of buffer."))
234
235(defvar hi-lock-map (make-sparse-keymap "Hi Lock")
236 "Key map for hi-lock.")
237
238(define-key hi-lock-map "\C-xwi" 'hi-lock-find-patterns)
239(define-key hi-lock-map "\C-xwl" 'highlight-lines-matching-regexp)
108ee42b 240(define-key hi-lock-map "\C-xwp" 'highlight-phrase)
abb2db1c
GM
241(define-key hi-lock-map "\C-xwh" 'highlight-regexp)
242(define-key hi-lock-map "\C-xwr" 'unhighlight-regexp)
243(define-key hi-lock-map "\C-xwb" 'hi-lock-write-interactive-patterns)
244
245(unless (assq 'hi-lock-mode minor-mode-map-alist)
246 (setq minor-mode-map-alist (cons (cons 'hi-lock-mode hi-lock-map)
247 minor-mode-map-alist)))
248
249(unless (assq 'hi-lock-mode minor-mode-alist)
250 (setq minor-mode-alist (cons '(hi-lock-mode " H") minor-mode-alist)))
251
252
253;; Visible Functions
254
255
256;;;###autoload
257(defun hi-lock-mode (&optional arg)
258 "Toggle minor mode for interactively adding font-lock highlighting patterns.
259
260If ARG positive turn hi-lock on. Issuing a hi-lock command will also
108ee42b 261turn hi-lock on. When hi-lock is turned on, a \"Regexp Highlighting\"
abb2db1c
GM
262submenu is added to the \"Edit\" menu. The commands in the submenu,
263which can be called interactively, are:
264
265\\[highlight-regexp] REGEXP FACE
266 Highlight matches of pattern REGEXP in current buffer with FACE.
267
108ee42b
GM
268\\[highlight-phrase] PHRASE FACE
269 Highlight matches of phrase PHRASE in current buffer with FACE.
270 (PHRASE can be any REGEXP, but spaces will be replaced by matches
271 to whitespace and initial lower-case letters will become case insensitive.)
71296446 272
abb2db1c
GM
273\\[highlight-lines-matching-regexp] REGEXP FACE
274 Highlight lines containing matches of REGEXP in current buffer with FACE.
275
276\\[unhighlight-regexp] REGEXP
277 Remove highlighting on matches of REGEXP in current buffer.
278
279\\[hi-lock-write-interactive-patterns]
280 Write active REGEXPs into buffer as comments (if possible). They will
281 be read the next time file is loaded or when the \\[hi-lock-find-patterns] command
282 is issued. The inserted regexps are in the form of font lock keywords.
283 (See `font-lock-keywords') They may be edited and re-loaded with \\[hi-lock-find-patterns],
284 any valid `font-lock-keywords' form is acceptable.
285
286\\[hi-lock-find-patterns]
287 Re-read patterns stored in buffer (in the format produced by \\[hi-lock-write-interactive-patterns]).
288
289When hi-lock is started and if the mode is not excluded, the
290beginning of the buffer is searched for lines of the form:
291 Hi-lock: FOO
292where FOO is a list of patterns. These are added to the font lock keywords
293already present. The patterns must start before position (number
294of characters into buffer) `hi-lock-file-patterns-range'. Patterns
295will be read until
296 Hi-lock: end
297is found. A mode is excluded if it's in the list `hi-lock-exclude-modes'."
298 (interactive)
299 (let ((hi-lock-mode-prev hi-lock-mode))
300 (setq hi-lock-mode
108ee42b
GM
301 (if (null arg) (not hi-lock-mode)
302 (> (prefix-numeric-value arg) 0)))
abb2db1c
GM
303 ;; Turned on.
304 (when (and (not hi-lock-mode-prev) hi-lock-mode)
ffc30f4f 305 (add-hook 'find-file-hook 'hi-lock-find-file-hook)
abb2db1c 306 (add-hook 'font-lock-mode-hook 'hi-lock-font-lock-hook)
71dd9295
CY
307 (if (null (default-value 'font-lock-defaults))
308 (setq-default font-lock-defaults '(nil)))
309 (if (null font-lock-defaults)
310 (setq font-lock-defaults '(nil)))
048e6895
RS
311 (unless font-lock-mode
312 (font-lock-mode 1))
abb2db1c 313 (define-key-after menu-bar-edit-menu [hi-lock]
108ee42b
GM
314 (cons "Regexp Highlighting" hi-lock-menu))
315 (dolist (buffer (buffer-list))
316 (with-current-buffer buffer (hi-lock-find-patterns))))
abb2db1c
GM
317 ;; Turned off.
318 (when (and hi-lock-mode-prev (not hi-lock-mode))
108ee42b
GM
319 (dolist (buffer (buffer-list))
320 (with-current-buffer buffer
321 (when (or hi-lock-interactive-patterns hi-lock-file-patterns)
322 (font-lock-remove-keywords nil hi-lock-interactive-patterns)
323 (font-lock-remove-keywords nil hi-lock-file-patterns)
324 (setq hi-lock-interactive-patterns nil
325 hi-lock-file-patterns nil)
326 (when font-lock-mode (hi-lock-refontify)))))
71dd9295
CY
327
328 (let ((fld (default-value 'font-lock-defaults)))
329 (if (and fld (listp fld) (null (car fld)))
330 (setq-default font-lock-defaults (cdr fld))))
abb2db1c 331 (define-key-after menu-bar-edit-menu [hi-lock] nil)
ffc30f4f 332 (remove-hook 'find-file-hook 'hi-lock-find-file-hook)
abb2db1c
GM
333 (remove-hook 'font-lock-mode-hook 'hi-lock-font-lock-hook))))
334
335
336;;;###autoload
337(defalias 'highlight-lines-matching-regexp 'hi-lock-line-face-buffer)
338;;;###autoload
339(defun hi-lock-line-face-buffer (regexp &optional face)
108ee42b 340 "Set face of all lines containing a match of REGEXP to FACE.
abb2db1c
GM
341
342Interactively, prompt for REGEXP then FACE. Buffer-local history
343list maintained for regexps, global history maintained for faces.
344\\<minibuffer-local-map>Use \\[next-history-element] and \\[previous-history-element] to retrieve next or previous history item.
8564afc9 345\(See info node `Minibuffer History')"
abb2db1c
GM
346 (interactive
347 (list
348 (hi-lock-regexp-okay
349 (read-from-minibuffer "Regexp to highlight line: "
350 (cons (or (car hi-lock-regexp-history) "") 1 )
351 nil nil 'hi-lock-regexp-history))
352 (hi-lock-read-face-name)))
353 (unless hi-lock-mode (hi-lock-mode))
354 (or (facep face) (setq face 'rwl-yellow))
355 (hi-lock-set-pattern
b18f5523
SM
356 ;; The \\(?:...\\) grouping construct ensures that a leading ^, +, * or ?
357 ;; or a trailing $ in REGEXP will be interpreted correctly.
358 (list (concat "^.*\\(?:" regexp "\\).*$") (list 0 (list 'quote face) t))))
abb2db1c 359
108ee42b 360
abb2db1c
GM
361;;;###autoload
362(defalias 'highlight-regexp 'hi-lock-face-buffer)
363;;;###autoload
364(defun hi-lock-face-buffer (regexp &optional face)
108ee42b 365 "Set face of each match of REGEXP to FACE.
abb2db1c
GM
366
367Interactively, prompt for REGEXP then FACE. Buffer-local history
368list maintained for regexps, global history maintained for faces.
369\\<minibuffer-local-map>Use \\[next-history-element] and \\[previous-history-element] to retrieve next or previous history item.
8564afc9 370\(See info node `Minibuffer History')"
abb2db1c
GM
371 (interactive
372 (list
373 (hi-lock-regexp-okay
374 (read-from-minibuffer "Regexp to highlight: "
375 (cons (or (car hi-lock-regexp-history) "") 1 )
376 nil nil 'hi-lock-regexp-history))
377 (hi-lock-read-face-name)))
378 (or (facep face) (setq face 'rwl-yellow))
379 (unless hi-lock-mode (hi-lock-mode))
380 (hi-lock-set-pattern (list regexp (list 0 (list 'quote face) t))))
381
108ee42b
GM
382;;;###autoload
383(defalias 'highlight-phrase 'hi-lock-face-phrase-buffer)
384;;;###autoload
385(defun hi-lock-face-phrase-buffer (regexp &optional face)
386 "Set face of each match of phrase REGEXP to FACE.
387
388Whitespace in REGEXP converted to arbitrary whitespace and initial
389lower-case letters made case insensitive."
390 (interactive
391 (list
392 (hi-lock-regexp-okay
393 (hi-lock-process-phrase
394 (read-from-minibuffer "Phrase to highlight: "
395 (cons (or (car hi-lock-regexp-history) "") 1 )
396 nil nil 'hi-lock-regexp-history)))
397 (hi-lock-read-face-name)))
398 (or (facep face) (setq face 'rwl-yellow))
399 (unless hi-lock-mode (hi-lock-mode))
400 (hi-lock-set-pattern (list regexp (list 0 (list 'quote face) t))))
401
abb2db1c
GM
402;;;###autoload
403(defalias 'unhighlight-regexp 'hi-lock-unface-buffer)
404;;;###autoload
405(defun hi-lock-unface-buffer (regexp)
108ee42b 406 "Remove highlighting of each match to REGEXP set by hi-lock.
abb2db1c
GM
407
408Interactively, prompt for REGEXP. Buffer-local history of inserted
409regexp's maintained. Will accept only regexps inserted by hi-lock
108ee42b 410interactive functions. \(See `hi-lock-interactive-patterns'.\)
abb2db1c 411\\<minibuffer-local-must-match-map>Use \\[minibuffer-complete] to complete a partially typed regexp.
cf667bc5 412\(See info node `Minibuffer History'.\)"
abb2db1c 413 (interactive
59b7ded8 414 (if (and (display-popup-menus-p) (vectorp (this-command-keys)))
cf667bc5
EZ
415 (catch 'snafu
416 (or
417 (x-popup-menu
418 t
419 (cons
420 `keymap
421 (cons "Select Pattern to Unhighlight"
422 (mapcar (lambda (pattern)
423 (list (car pattern)
424 (format
425 "%s (%s)" (car pattern)
426 (symbol-name
427 (car
428 (cdr (car (cdr (car (cdr pattern))))))))
429 (cons nil nil)
430 (car pattern)))
431 hi-lock-interactive-patterns))))
432 ;; If the user clicks outside the menu, meaning that they
433 ;; change their mind, x-popup-menu returns nil, and
434 ;; interactive signals a wrong number of arguments error.
435 ;; To prevent that, we return an empty string, which will
436 ;; effectively disable the rest of the function.
437 (throw 'snafu '(""))))
abb2db1c
GM
438 (let ((history-list (mapcar (lambda (p) (car p))
439 hi-lock-interactive-patterns)))
440 (unless hi-lock-interactive-patterns
441 (error "No highlighting to remove"))
442 (list
443 (completing-read "Regexp to unhighlight: "
932c309e 444 hi-lock-interactive-patterns nil t
abb2db1c
GM
445 (car (car hi-lock-interactive-patterns))
446 (cons 'history-list 1))))))
447 (let ((keyword (assoc regexp hi-lock-interactive-patterns)))
448 (when keyword
449 (font-lock-remove-keywords nil (list keyword))
450 (setq hi-lock-interactive-patterns
451 (delq keyword hi-lock-interactive-patterns))
452 (hi-lock-refontify))))
453
454;;;###autoload
455(defun hi-lock-write-interactive-patterns ()
456 "Write interactively added patterns, if any, into buffer at point.
457
458Interactively added patterns are those normally specified using
459`highlight-regexp' and `highlight-lines-matching-regexp'; they can
460be found in variable `hi-lock-interactive-patterns'."
461 (interactive)
462 (let ((prefix (format "%s %s:" (or comment-start "") "Hi-lock")))
463 (when (> (+ (point) (length prefix)) hi-lock-file-patterns-range)
464 (beep)
465 (message
466 "Warning, inserted keywords not close enough to top of file."))
467 (mapcar
468 (lambda (pattern)
469 (insert (format "%s (%s) %s\n"
470 prefix (prin1-to-string pattern) (or comment-end ""))))
471 hi-lock-interactive-patterns)))
472
473
474;; Implementation Functions
475
108ee42b
GM
476(defun hi-lock-process-phrase (phrase)
477 "Convert regexp PHRASE to a regexp that matches phrases.
478
479Blanks in PHRASE replaced by regexp that matches arbitrary whitespace
480and initial lower-case letters made case insensitive."
481 (let ((mod-phrase nil))
482 (setq mod-phrase
483 (replace-regexp-in-string
484 "\\<[a-z]" (lambda (m) (format "[%s%s]" (upcase m) m)) phrase))
485 (setq mod-phrase
486 (replace-regexp-in-string
487 "\\s-+" "[ \t\n]+" mod-phrase nil t))))
488
abb2db1c
GM
489(defun hi-lock-regexp-okay (regexp)
490 "Return REGEXP if it appears suitable for a font-lock pattern.
491
492Otherwise signal an error. A pattern that matches the null string is
493not suitable."
494 (if (string-match regexp "")
495 (error "Regexp cannot match an empty string")
496 regexp))
497
498(defun hi-lock-read-face-name ()
499 "Read face name from minibuffer with completion and history."
500 (intern (completing-read
501 "Highlight using face: "
502 obarray 'facep t
503 (cons (car hi-lock-face-history)
504 (let ((prefix
505 (try-completion
506 (substring (car hi-lock-face-history) 0 1)
507 (mapcar (lambda (f) (cons f f))
508 hi-lock-face-history))))
509 (if (and (stringp prefix)
510 (not (equal prefix (car hi-lock-face-history))))
511 (length prefix) 0)))
512 '(hi-lock-face-history . 0))))
513
514(defun hi-lock-find-file-hook ()
515 "Add hi-lock patterns, if present."
516 (hi-lock-find-patterns))
517
518(defun hi-lock-current-line (&optional end)
519 "Return line number of line at point.
520Optional argument END is maximum excursion."
521 (interactive)
522 (save-excursion
523 (beginning-of-line)
524 (1+ (count-lines 1 (or end (point))))))
525
526(defun hi-lock-set-pattern (pattern)
527 "Add PATTERN to list of interactively highlighted patterns and refontify."
528 (hi-lock-set-patterns (list pattern)))
529
530(defun hi-lock-set-patterns (patterns)
531 "Add PATTERNS to list of interactively highlighted patterns and refontify.."
532 (dolist (pattern patterns)
533 (unless (member pattern hi-lock-interactive-patterns)
534 (font-lock-add-keywords nil (list pattern))
535 (add-to-list 'hi-lock-interactive-patterns pattern)))
536 (hi-lock-refontify))
537
538(defun hi-lock-set-file-patterns (patterns)
539 "Replace file patterns list with PATTERNS and refontify."
108ee42b
GM
540 (when (or hi-lock-file-patterns patterns)
541 (font-lock-remove-keywords nil hi-lock-file-patterns)
542 (setq hi-lock-file-patterns patterns)
543 (font-lock-add-keywords nil hi-lock-file-patterns)
544 (hi-lock-refontify)))
abb2db1c
GM
545
546(defun hi-lock-refontify ()
547 "Unfontify then refontify buffer. Used when hi-lock patterns change."
548 (interactive)
108ee42b
GM
549 (unless font-lock-mode (font-lock-mode 1))
550 (font-lock-fontify-buffer))
abb2db1c
GM
551
552(defun hi-lock-find-patterns ()
553 "Find patterns in current buffer for hi-lock."
554 (interactive)
555 (unless (memq major-mode hi-lock-exclude-modes)
556 (let ((all-patterns nil)
557 (target-regexp (concat "\\<" hi-lock-file-patterns-prefix ":")))
558 (save-excursion
62cec9fe
SM
559 (save-restriction
560 (widen)
561 (goto-char (point-min))
562 (re-search-forward target-regexp
563 (+ (point) hi-lock-file-patterns-range) t)
564 (beginning-of-line)
565 (while (and (re-search-forward target-regexp (+ (point) 100) t)
566 (not (looking-at "\\s-*end")))
ed6773fa
JB
567 (condition-case nil
568 (setq all-patterns (append (read (current-buffer)) all-patterns))
569 (error (message "Invalid pattern list expression at %d"
570 (hi-lock-current-line)))))))
108ee42b 571 (when hi-lock-mode (hi-lock-set-file-patterns all-patterns))
abb2db1c 572 (if (interactive-p)
8a26c165 573 (message "Hi-lock added %d patterns." (length all-patterns))))))
abb2db1c
GM
574
575(defun hi-lock-font-lock-hook ()
576 "Add hi lock patterns to font-lock's."
577 (when hi-lock-mode
578 (font-lock-add-keywords nil hi-lock-file-patterns)
579 (font-lock-add-keywords nil hi-lock-interactive-patterns)))
580
581(provide 'hi-lock)
582
ffc30f4f 583;; arch-tag: d2e8fd07-4cc9-4c6f-a200-1e729bc54066
abb2db1c 584;;; hi-lock.el ends here