Download
(require 'frame-fns nil t)
(when (< emacs-major-version 21) (require 'faces+ nil t))
(require 'menu-bar+ nil t)
(defvar hi-lock-mode)
(defvar hlt-act-on-any-face-flag)
(define-key-after menu-bar-edit-menu [hlt-copy-props]
'(menu-item "Copy Text Properties" hlt-copy-props
:help "Copy text properties at point, for subsequent pasting") 'paste)
(define-key-after menu-bar-edit-menu [hlt-yank-props]
'(menu-item "Paste Text Properties" hlt-yank-props
:help "Paste previously copied text properties to text in region"
:enable (and mark-active (not buffer-read-only)))
'hlt-copy-props)
(when (boundp 'menu-bar-edit-region-menu)
(define-key menu-bar-edit-region-menu [separator-highlight] '("--"))
(define-key menu-bar-edit-region-menu [hlt-yank-props]
'(menu-item "Paste Text Properties" hlt-yank-props
:help "Paste previously copied text properties to text in region"
:enable (and mark-active (not buffer-read-only))))
(define-key menu-bar-edit-region-menu [hlt-unhighlight-region-for-face]
'(menu-item "Unhighlight for Face..." hlt-unhighlight-region-for-face
:help "Remove highlighting for a given face in the region"))
(define-key menu-bar-edit-region-menu [hlt-unhighlight-region]
'(menu-item "Unhighlight" hlt-unhighlight-region
:help "Remove highlighting (faces) in the region"))
(define-key menu-bar-edit-region-menu [hlt-highlight-regexp-region]
'(menu-item "Highlight Regexp..." hlt-highlight-regexp-region
:help "Highlight parts of region that match a regexp"))
(define-key menu-bar-edit-region-menu [hlt-highlight-region]
'(menu-item "Highlight" hlt-highlight-region
:help "Highlight all text in the region")))
(when (boundp 'facemenu-mouse-menu)
(easy-menu-add-item facemenu-mouse-menu ()
["Paste Text Properties" hlt-yank-props
(and mark-active (not buffer-read-only))] 'dp)
(easy-menu-add-item facemenu-mouse-menu ()
["Copy Text Properties" hlt-copy-props t] 'dp))
(easy-menu-add-item facemenu-menu ()
["Paste Text Properties" hlt-yank-props
(and mark-active (not buffer-read-only))] 'dp)
(easy-menu-add-item facemenu-menu () ["Copy Text Properties" hlt-copy-props t] 'dp)
(defgroup highlight nil
"Highlighting."
:prefix "hlt-" :group 'editing :group 'convenience :group 'wp :group 'faces
:link `(url-link :tag "Send Bug Report"
,(concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
highlight.el bug: \
&body=Describe bug here, starting with `emacs -q'. \
Don't forget to mention your Emacs and library versions."))
:link '(url-link :tag "Download" "http://www.emacswiki.org/highlight.el")
:link '(url-link :tag "Description" "http://www.emacswiki.org/HighLight")
:link '(emacs-commentary-link :tag "Commentary" "highlight"))
(unless (facep 'minibuffer-prompt)
(defface minibuffer-prompt '((((background dark)) (:foreground "cyan"))
(t (:foreground "dark blue")))
"*Face for minibuffer prompts."
:group 'basic-faces))
(when (fboundp 'next-single-char-property-change)
(defface hlt-property-highlight '((((background dark)) (:background "Navy"))
(t (:background "Wheat")))
"*Face used to highlight all links."
:group 'highlight :group 'faces)
(defcustom hlt-act-on-any-face-flag nil
"*Non-nil means highlight actions apply to all text with a face.
nil means that they apply only to text that has been highlighted.
Consult the doc for particular actions, to see if they are affected by
this option."
:type 'boolean :group 'highlight)
(defvar hlt-prop-highlighting-state '(nil . nil)
"Cons representing the state of property highlighting.
The car indicates whether property highlighting is on (nil means off).
The cdr is the position of the last mouse click that changed state, as
a marker."))
(defcustom hlt-max-region-no-warning 100000
"*Maximum size (chars) of region to highlight without confirmation.
This is used only for highlighting of a regexp, which can be slow."
:type 'integer :group 'highlight)
(defcustom hlt-use-overlays-flag 'only
"*Non-nil means use overlays to highlight; nil means use text properties.
This value also affects some actions, such as unhighlighting, for text
that is highlighted. If the value is `only' (the default value), then
those actions only affect overlay highlighting. Otherwise, they
affect both kinds of highlighting."
:type '(choice
(const :tag "Highlight using text properties, not overlays" nil)
(const :tag "Highlight using overlays, not text properties" only)
(sexp :tag
"Highlight using overlays, but act also on highlight text properties" t))
:group 'highlight)
(defcustom hlt-default-copy/yank-props '(face)
"*Properties that `hlt-copy-props' and `hlt-yank-props' use by default.
You can use a prefix argument with those commands to override the
default behavior.
Either a list of properties (symbols) or `t', meaning all properties."
:type '(choice
(const :tag "All properties" t)
(repeat (symbol :tag "Property")))
:group 'highlight)
(defvar hlt-last-regexp nil "The last regexp highlighted.")
(defvar hlt-last-face 'highlight "The last face used by highlight commands.")
(defvar hlt-previous-use-overlays-flag-value nil "Previous value of `hlt-use-overlays-flag'.")
(defvar hlt-copied-props ()
"Plist of text properties last copied using `hlt-copy-props'.")
(defun hlt-choose-default-face (face)
"Choose a face for highlighting."
(interactive (list (read-face-name "Use highlighting face: ")))
(setq hlt-last-face face)
(when (interactive-p) (message "Highlighting will now use face `%s'" face)))
(defun hlt-highlighter (start-event)
"Highlight the text you drag the mouse over.
The face used is the last face that was used for highlighting.
You can use command `hlt-choose-default-face' to choose a different face."
(interactive "e")
(save-excursion
(run-hooks 'mouse-leave-buffer-hook)
(let* ((original-window (selected-window))
(echo-keystrokes 0)
(start-posn (event-start start-event))
(start-point (posn-point start-posn))
(end-point start-point)
(start-window (posn-window start-posn)))
(let ((read-only buffer-read-only)
(modified-p (buffer-modified-p))
(inhibit-modification-hooks t)
(overlay (and hlt-use-overlays-flag
(make-overlay start-point start-point)))
(font-lock-fontify-region-function 'ignore)
event)
(setq buffer-read-only nil)
(track-mouse
(while (progn (setq event (read-event))
(or (mouse-movement-p event)
(memq (car-safe event) '(switch-frame select-window))))
(unless (memq (car-safe event) '(switch-frame select-window))
(setq end-point (posn-point (event-end event))))
(cond (hlt-use-overlays-flag
(setq overlay (move-overlay overlay start-point end-point))
(overlay-put overlay 'face hlt-last-face)
(overlay-put overlay 'hlt-highlight hlt-last-face))
(t
(put-text-property start-point end-point 'face hlt-last-face)
(put-text-property start-point end-point 'hlt-highlight hlt-last-face)
(put-text-property start-point end-point 'font-lock-ignore t)
))))
(setq buffer-read-only read-only)
(set-buffer-modified-p modified-p)))))
(defun hlt-eraser (start-event)
"Erase highlights that you click or drag the mouse over.
If `hlt-use-overlays-flag' is non-nil, then remove overlay
highlighting for the last face that was used for highlighting. (You
can use command `hlt-choose-default-face' first to choose a different
face.) If `hlt-use-overlays-flag' is not `only', then remove
text-property highlighting for *ALL* faces (not just highlighting
faces). This means, in particular, that a value of nil erases both
overlays for the last face and text properties for all faces."
(interactive "e")
(save-excursion
(run-hooks 'mouse-leave-buffer-hook)
(let* ((original-window (selected-window))
(echo-keystrokes 0)
(start-posn (event-start start-event))
(start (posn-point start-posn))
(end start)
(start-window (posn-window start-posn)))
(let ((read-only buffer-read-only)
(modified-p (buffer-modified-p))
(inhibit-modification-hooks t)
(font-lock-fontify-region-function 'ignore)
event)
(setq buffer-read-only nil)
(track-mouse
(while (progn (setq event (read-event))
(or (mouse-movement-p event)
(memq (car-safe event) '(switch-frame select-window))))
(unless (memq (car-safe event) '(switch-frame select-window))
(let ((posn-point (posn-point (event-end event))))
(setq end (max end posn-point)
start (min start posn-point))))
(when hlt-use-overlays-flag
(dolist (ov (overlays-in start end))
(hlt-unhighlight-for-overlay ov start end hlt-last-face)))
(unless (eq 'only hlt-use-overlays-flag)
(remove-text-properties
start end '(face nil hlt-highlight nil font-lock-ignore nil)))))
(setq buffer-read-only read-only)
(set-buffer-modified-p modified-p)))))
(defun hlt-highlighter-mouse ()
"Same as `hlt-highlighter', but for binding to a menu item."
(interactive)
(message "Drag mouse to highlight text") (sleep-for 1)
(hlt-highlighter (if (> emacs-major-version 21)
(read-event)
(read-event)
(read-event))))
(defun hlt-eraser-mouse ()
"Same as `hlt-eraser', but for binding to a menu item."
(interactive)
(message "Drag mouse over to erase highlighting") (sleep-for 1)
(hlt-eraser (if (> emacs-major-version 21)
(read-event)
(read-event)
(read-event))))
(defun hlt-highlight (&optional prefix)
"Highlight region, regexp (PREFIX +), or unhighlight region (PREFIX -).
PREFIX arg non-negative means `hlt-highlight-regexp-region'
PREFIX arg negative means `hlt-unhighlight-region'
PREFIX arg nil means `hlt-highlight-region'.
If the region is not active or it is empty, then use the whole buffer.
The face used is the last face that was used for highlighting.
You can use command `hlt-choose-default-face' to choose a different face."
(interactive "P")
(setq current-prefix-arg nil)
(if prefix
(if (natnump (prefix-numeric-value prefix))
(call-interactively 'hlt-highlight-regexp-region)
(save-excursion (call-interactively 'hlt-unhighlight-region)))
(call-interactively 'hlt-highlight-region)))
(defun hlt-highlight-region (&optional start end face msg-p mouse-p)
"Highlight either the region/buffer or new input that you type.
Use the region if active, or the buffer otherwise.
If *all* of the following are true, the apply the last-used face as a
text property to the next and subsequent chars that you type, and add
that face to a facemenu menu (`Text Properties' or one of its
submenus):
* You call this command interactively.
* You use no prefix arg.
* Option `prop-use-overlays-flag' is nil
* The last property used for highlighting was `face'.
Otherwise, the behavior respects `hlt-use-overlays-flag' and depends
on the optional arguments, as follows:
Optional args START and END are the limits of the area to act on.
They default to the region limits. If the region is not active or
it is empty, then use the whole buffer.
Optional 3rd arg FACE is the face to use.
Interactively, this is the last face that was used for highlighting.
(You can use command `hlt-choose-default-face' to choose a different face.)
Optional 4th arg MSG-P non-nil means to display a progress message.
Interactively, MSG-P is t.
Optional 5th arg MOUSE-P non-nil means use property `mouse-face', not
`face'. Interactively, MOUSE-P is provided by the prefix arg."
(interactive `(,@(hlt-region-or-buffer-limits) nil t ,current-prefix-arg))
(unless (and start end) (let ((start-end (hlt-region-or-buffer-limits)))
(setq start (car start-end)
end (cadr start-end))))
(if face (setq hlt-last-face face) (setq face hlt-last-face))
(when (and msg-p (or mark-active mouse-p)) (message "Highlighting..."))
(let ((read-only buffer-read-only)
(modified-p (buffer-modified-p))
(inhibit-modification-hooks t)
(font-lock-fontify-region-function 'ignore)
overlay)
(setq buffer-read-only nil)
(cond (hlt-use-overlays-flag
(setq overlay (make-overlay start end))
(overlay-put overlay (if mouse-p 'mouse-face 'face) face)
(overlay-put overlay 'hlt-highlight face))
(mouse-p (put-text-property start end 'mouse-face face))
((interactive-p)
(message "Text you type now will have face `%s'." face)
(facemenu-add-new-face face)
(facemenu-add-face face (and mark-active start) (and mark-active end))
(when (and mark-active start end (/= start end))
(put-text-property start end 'hlt-highlight face)
(put-text-property start end 'font-lock-ignore t)))
(t (put-text-property start end 'face face)
(put-text-property start end 'hlt-highlight face)
(put-text-property start end 'font-lock-ignore t)))
(setq buffer-read-only read-only)
(set-buffer-modified-p modified-p))
(let ((remove-msg (substitute-command-keys
"`\\[negative-argument] \\[hlt-highlight]' to remove highlighting.")))
(when (and msg-p (or mark-active mouse-p))
(message "Highlighting... done. %s" remove-msg))))
(defun hlt-highlight-regexp-region (&optional start end regexp face msg-p mouse-p nth)
"Highlight regular expression REGEXP in region/buffer.
Use the region if active, or the buffer otherwise.
Optional args START and END are the limits of the area to act on.
They default to the region limits.
Optional 4th arg FACE is the face to use.
Interactively, this is the last face that was used for highlighting.
(You can use command `hlt-choose-default-face' to choose a different face.)
Optional 5th arg MSG-P:
t means to treat this as an interactive call when deciding to
display all messages.
non-nil & non-t means to display only error and warning messages.
Optional 6th arg MOUSE-P non-nil means to use `mouse-face' property,
not `face'. Interactively, this is provided by the prefix arg.
Optional 7th arg NTH determines which regexp subgroup is highlighted.
If nil or 0, the entire regexp is highlighted. Otherwise, the NTH
regexp subgroup (\"\\\\(...\\\\)\" expression) is highlighted.
(NTH is not available interactively.)"
(interactive
`(,@(hlt-region-or-buffer-limits)
,(if (fboundp 'icicle-read-string-completing)
(icicle-read-string-completing "Regexp to highlight: "
hlt-last-regexp
(lambda (c) (string-match "regexp" (symbol-name c)))
(if (and (boundp 'hi-lock-mode) hi-lock-mode)
'hi-lock-regexp-history
'regexp-history))
(read-string "Regexp to highlight: "
nil (if (and (boundp 'hi-lock-mode) hi-lock-mode)
'hi-lock-regexp-history
'regexp-history)
hlt-last-regexp))
nil t ,current-prefix-arg))
(unless (and start end) (let ((start-end (hlt-region-or-buffer-limits)))
(setq start (car start-end)
end (cadr start-end))))
(unless regexp (setq regexp hlt-last-regexp))
(unless (stringp regexp)
(error "HIGHLIGHT-REGEXP-REGION: REGEXP arg is not a string: `%S'" regexp))
(if face (setq hlt-last-face face) (setq face hlt-last-face))
(let ((reg-size (abs (- end start))))
(when (and msg-p
(> reg-size hlt-max-region-no-warning)
(not (progn
(and (fboundp 'flash-ding)
(flash-ding 'no-terminate-macros (selected-frame)))
(y-or-n-p (substitute-command-keys
(format "Lots of highlighting slows \
things down. Do you really want to highlight up to %d chars? "
reg-size))))))
(error "OK, highlighting was cancelled")))
(when (eq t msg-p) (message (concat "Highlighting occurrences of `" regexp "'...")))
(let ((hits-p nil))
(save-excursion
(goto-char start)
(while (and (< start end) (not (eobp)) (re-search-forward regexp end t)
(setq hits-p t))
(condition-case nil
(progn (forward-char 1) (setq start (1+ (point))))
(end-of-buffer (setq start end)))
(hlt-highlight-region (match-beginning (or nth 0))
(match-end (or nth 0)) face nil mouse-p)))
(when (eq t msg-p)
(if hits-p
(message "Highlighting occurrences of `%s' done. %s" regexp
(substitute-command-keys
"`\\[negative-argument] \\[hlt-highlight]' to remove highlighting."))
(message "No occurrences of `%s'" regexp))))
(setq hlt-last-regexp regexp))
(defun hlt-highlight-regexp-to-end (regexp &optional face msg-p mouse-p nth)
"Highlight text after cursor that matches REGEXP.
The behavior respects `hlt-use-overlays-flag' and depends on the
optional arguments, as follows:
Optional 2nd arg FACE is the face to use.
Interactively, this is the last face that was used for highlighting.
(You can use command `hlt-choose-default-face' to choose a different
face.)
Optional 3rd arg MSG-P non-nil means to display a progress message.
Interactively, MSG-P is t.
Optional 4th arg MOUSE-P non-nil means use property `mouse-face', not
`face'. Interactively, MOUSE-P is provided by the prefix arg.
Optional 5th arg NTH determines which regexp subgroup is highlighted.
If nil or 0, the entire regexp is highlighted. Otherwise, the NTH
regexp subgroup (\"\\\\(...\\\\)\" expression) is highlighted.
(NTH is not available interactively.)"
(interactive
(list (read-string "Regexp to highlight after cursor: " nil
(if (and (boundp 'hi-lock-mode) hi-lock-mode)
'hi-lock-regexp-history
'regexp-history)
hlt-last-regexp)
nil t current-prefix-arg))
(if face (setq hlt-last-face face) (setq face hlt-last-face))
(let ((remove-msg
(and msg-p
(substitute-command-keys
"`\\[negative-argument] \\[hlt-highlight]' to remove highlighting."))))
(when msg-p
(message "Highlighting occurrences of `%s' after cursor..." regexp))
(hlt-highlight-regexp-region (point) (point-max) regexp face
(and msg-p 'error-msgs-only) mouse-p nth)
(when msg-p
(message "Highlighting occurrences of `%s' done. %s" regexp remove-msg)))
(setq hlt-last-regexp regexp))
(defun hlt-unhighlight-region (&optional start end face msg-p mouse-p)
"Remove all highlighting in region or buffer.
Use the region if active, or the buffer otherwise.
The arguments are the same as those for `hlt-highlight-region'.
If `hlt-use-overlays-flag' is non-nil, then remove overlay highlighting.
If `hlt-use-overlays-flag' is not `only', then remove text-property
highlighting. This means, in particular, that a value of nil removes
both overlays and text properties."
(interactive `(,@(hlt-region-or-buffer-limits) nil t ,current-prefix-arg))
(unless (and start end) (let ((start-end (hlt-region-or-buffer-limits)))
(setq start (car start-end)
end (cadr start-end))))
(when msg-p (message "Removing highlighting..."))
(let ((read-only-p buffer-read-only)
(modified-p (buffer-modified-p)))
(setq buffer-read-only nil)
(when hlt-use-overlays-flag
(dolist (ov (overlays-in start end))
(hlt-unhighlight-for-overlay ov start end face)))
(unless (eq 'only hlt-use-overlays-flag)
(let ((beg start)
hi-face)
(while (< beg end)
(when (setq hi-face (get-text-property beg 'hlt-highlight))
(when (or (null face) (eq hi-face face))
(remove-text-properties
beg (1+ beg) (if mouse-p
'(mouse-face nil hlt-highlight nil font-lock-ignore nil)
'(face nil hlt-highlight nil font-lock-ignore nil)))))
(setq beg (1+ beg)))))
(setq buffer-read-only read-only-p)
(set-buffer-modified-p modified-p))
(when msg-p (message "Removing highlighting... done.")))
(defun hlt-unhighlight-region-for-face (&optional face start end mouse-p)
"Remove any highlighting in the region that uses FACE.
Same as `hlt-unhighlight-region', but removes only highlighting
that uses FACE. Interactively, you are prompted for the face.
This works only for overlay highlighting, not text-property
highlighting.
Note: When text in the region has been highlighted using more than one
face, unhighlighting for one of those faces can mean that adjacent
highlighting outside the region appears to change. That outside text
still has the same multiple-overlay face highlighting, but the overlay
stacking order is not the same as it was.
Optional arg FACE is the face to use.
Interactively, this is the last face that was used for highlighting.
(You can use command `hlt-choose-default-face' to choose a different face.)
Optional args START and END are the limits of the area to act on.
They default to the region limits.
Optional arg MOUSE-P non-nil means use `mouse-face' property, not
`face'. Interactively, MOUSE-P is provided by the prefix arg."
(interactive `(,(read-face-name "Remove highlight overlays that use face: ")
,@(hlt-region-or-buffer-limits) ,current-prefix-arg))
(if face (setq hlt-last-face face) (setq face hlt-last-face))
(unless (and start end) (let ((start-end (hlt-region-or-buffer-limits)))
(setq start (car start-end)
end (cadr start-end))))
(hlt-unhighlight-region start end face (interactive-p) mouse-p))
(defun hlt-delete-highlight-overlay (overlay &optional face)
"Delete OVERLAY if it was created by highlighting (library `highlight').
Optional arg FACE is a face symbol. If non-nil, then delete only
overlays with that FACE."
(let ((highlight-face (overlay-get overlay 'hlt-highlight)))
(when (and highlight-face (or (not face) (eq face highlight-face)))
(delete-overlay overlay))))
(defun hlt-unhighlight-for-overlay (overlay start end &optional face)
"Remove OVERLAY highlighting from START to END.
Acts only on an OVERLAY that was created by library `highlight'.
OVERLAY might be moved or split or both.
Optional arg FACE is a face symbol. If non-nil, then remove only
highlighting with that FACE."
(when (< end start) (setq start (prog1 end (setq end start))))
(let ((oface (overlay-get overlay 'hlt-highlight))
(ostart (overlay-start overlay))
(oend (overlay-end overlay)))
(when (and oface (or (not face) (eq face oface)))
(if (< ostart start)
(if (<= oend end)
(move-overlay overlay ostart start)
(move-overlay (copy-overlay overlay) ostart start)
(move-overlay overlay end oend))
(if (> oend end)
(move-overlay overlay end oend)
(delete-overlay overlay))))))
(unless (fboundp 'copy-overlay)
(defun copy-overlay (o)
"Return a copy of overlay O."
(let ((o1 (if (overlay-buffer o)
(make-overlay (overlay-start o) (overlay-end o)
(overlay-buffer o))
(let ((o1 (make-overlay (point-min) (point-min))))
(delete-overlay o1)
o1)))
(props (overlay-properties o)))
(while props
(overlay-put o1 (pop props) (pop props)))
o1)))
(defun hlt-replace-highlight-face (old-face new-face &optional start end msg-p mouse-p)
"Replace OLD-FACE by NEW-FACE in overlay highlighting in the region.
This command applies only to overlay highlighting created by library
`highlight.el'.
Update the last-used highlighting face.
With a prefix argument, replace OLD-FACE as the `mouse-face' property,
not the `face' property.
Other arguments:
Optional args START and END are the limits of the area to act on.
They default to the region limits. If the region is not active or
it is empty, then use the whole buffer.
Optional arg MSG-P non-nil means display a progress message.
Optional arg MOUSE-P non-nil means use `mouse-face' property, not
`face'. Interactively, MOUSE-P is provided by the prefix arg."
(interactive `(,(read-face-name "Replace face in region highlights. Old face: ")
,(read-face-name "New face: ")
,@(hlt-region-or-buffer-limits) t ,current-prefix-arg))
(unless (and start end) (let ((start-end (hlt-region-or-buffer-limits)))
(setq start (car start-end)
end (cadr start-end))))
(when msg-p (message "Replacing highlighting face `%s'..." old-face))
(let ((read-only-p buffer-read-only)
(modified-p (buffer-modified-p)))
(setq buffer-read-only nil)
(dolist (ov (overlays-in start end))
(when (eq old-face (overlay-get ov (if mouse-p 'mouse-face 'face)))
(overlay-put ov (if mouse-p 'mouse-face 'face) new-face)
(overlay-put ov 'hlt-highlight new-face)))
(setq buffer-read-only read-only-p)
(set-buffer-modified-p modified-p))
(setq hlt-last-face new-face)
(when msg-p (message "Replacing overlay highlighting face `%s'... done." old-face)))
(defun hlt-highlight-single-quotations (&optional face)
"Highlight single-quoted text in the region.
This means, for example, commands and keys between `'s: `foobar'.
If the region is not active or it is empty, then use the whole buffer.
With a prefix argument, prompt for the highlighting face to use.
Otherwise, use the last face used for highlighting.
You can also use command `hlt-choose-default-face' to choose a different face."
(interactive "P")
(if face
(setq face (read-face-name "Use highlighting face: ") hlt-last-face face)
(setq face hlt-last-face))
(apply #'hlt-highlight-regexp-region
(append (hlt-region-or-buffer-limits)
(list "`\\([^']+\\)'" face (and (interactive-p) t) nil 1))))
(defun hlt-mouse-face-each-line (&optional start end face msg-p)
"Put `mouse-face' on each line of buffer in region.
If the region is active and not empty, then limit mouse-face
highlighting to the region. Otherwise, use the whole buffer.
With a prefix argument, prompt for the highlighting face to use.
Otherwise, use the last face used for highlighting.
You can also use command `hlt-choose-default-face' to choose a different face.
Optional args START and END are the limits of the area to act on.
They default to the region limits.
Optional arg MSG-P non-nil means display a progress message."
(interactive `(,@(hlt-region-or-buffer-limits) ,current-prefix-arg t))
(unless (and start end) (let ((start-end (hlt-region-or-buffer-limits)))
(setq start (car start-end)
end (cadr start-end))))
(if face
(setq face (read-face-name "Use highlighting face: ") hlt-last-face face)
(setq face hlt-last-face))
(when msg-p (message "Putting mouse face `%s' on each line..." face))
(let ((buffer-read-only nil)
(inhibit-field-text-motion t)
overlay)
(save-excursion
(save-restriction
(narrow-to-region start end)
(goto-char (point-min))
(while (not (eobp))
(cond (hlt-use-overlays-flag
(setq overlay
(make-overlay (point) (setq start (progn (end-of-line) (point)))))
(overlay-put overlay 'mouse-face face)
(overlay-put overlay 'hlt-highlight face))
(t
(put-text-property (point) (progn (end-of-line) (point)) 'mouse-face face)
(put-text-property start end 'hlt-highlight face)))
(forward-line 1)))))
(when msg-p (message "Putting mouse face `%s' on each line... done." face)))
(defun hlt-toggle-use-overlays-flag ()
"Toggle `hlt-use-overlays-flag'.
If the current value is non-nil, it is set to nil.
If the current value is nil, it is set to the last non-nil value."
(interactive)
(let ((before-toggle hlt-use-overlays-flag))
(if hlt-use-overlays-flag
(setq hlt-use-overlays-flag nil)
(setq hlt-use-overlays-flag hlt-previous-use-overlays-flag-value))
(setq hlt-previous-use-overlays-flag-value before-toggle))
(message
(cond ((eq hlt-use-overlays-flag 'only)
"Highlight actions now use only overlay properties, not text properties")
(hlt-use-overlays-flag
"Highlighting with overlays now, but actions affect also text properties")
(t "Highlight actions now use only text properties, not overlay properties"))))
(defalias 'hlt-paste-props 'hlt-yank-props)
(defun hlt-yank-props (start end &optional arg msgp)
"Yank (paste) copied text properties over the active region.
Interactively, do nothing if there is no nonempty active region.
By default, yank only the copied properties defined by
`hlt-default-copy/yank-props'.
With a plain or non-negative prefix arg, yank all copied properties.
With a negative prefix arg, you are prompted for the copied properties
to yank. To finish entering properties, hit `RET RET' (i.e., twice).
NOTE: If the list of copied text properties is empty, then yanking
REMOVES ALL PROPERTIES from the text in the region. This
provides an easy way to UNpropertize text."
(interactive "r\nP\np")
(unless (or (and transient-mark-mode mark-active (not (eq (mark) (point))))
(not msgp))
(error "No region to paste properties to"))
(let ((read-only buffer-read-only)
(modified-p (buffer-modified-p))
(inhibit-modification-hooks t)
(font-lock-fontify-region-function 'ignore)
(props-to-yank (hlt-props-to-copy/yank hlt-copied-props arg)))
(undo-boundary)
(setq buffer-read-only nil)
(set-text-properties start end props-to-yank)
(cond ((fboundp 'plist-member)
(put-text-property
start end 'hlt-highlight (and (plist-member props-to-yank 'face) t))
(put-text-property
start end 'font-lock-ignore (and (plist-member props-to-yank 'face) t)))
(t
(put-text-property
start end 'hlt-highlight (and (member 'face props-to-yank) t))
(put-text-property
start end 'font-lock-ignore (and (member 'face props-to-yank) t))))
(setq buffer-read-only read-only)
(set-buffer-modified-p modified-p)
(when msgp
(if props-to-yank
(message "Yanked propert%s `%s'" (if (car (cddr props-to-yank)) "ies" "y")
(let ((pprops ()))
(while props-to-yank
(push (pop props-to-yank) pprops)
(pop props-to-yank))
(mapconcat #'symbol-name (nreverse pprops) "', `")))
(message "ALL PROPERTIES REMOVED (yanked empty list of properties)")))))
(defun hlt-mouse-copy-props (&optional event arg msgp)
"Same as `hlt-copy-props', but copy at mouse pointer, not at point."
(interactive "e\nP\np")
(with-current-buffer (window-buffer (posn-window (event-end event)))
(save-excursion (goto-char (posn-point (event-end event)))
(hlt-copy-props (point) arg msgp))))
(defun hlt-copy-props (&optional position arg msgp)
"Copy text properties at point for use by `hlt-yank-props'.
Properties are copied to `hlt-copied-props'.
By default, copy the properties defined by
`hlt-default-copy/yank-props'.
With a plain or non-negative prefix arg, copy all properties.
With a negative prefix arg, you are prompted for the properties to
copy. To finish entering properties, hit `RET RET' (i.e., twice)."
(interactive "d\nP\np")
(unless position (setq position (point)))
(let ((props-to-copy (hlt-props-to-copy/yank (text-properties-at position) arg)))
(setq hlt-copied-props props-to-copy)
(when msgp
(if props-to-copy
(message "Copied propert%s `%s'" (if (car (cddr props-to-copy)) "ies" "y")
(let ((pprops ()))
(while props-to-copy
(push (pop props-to-copy) pprops)
(pop props-to-copy))
(mapconcat #'symbol-name (nreverse pprops) "', `")))
(message "Emptied copied properties list - yanking will REMOVE ALL")))))
(defun hlt-props-to-copy/yank (avail-props arg)
"Return a plist of properties to copy or yank.
AVAIL-PROPS is a plist of available properties.
ARG is from a raw prefix argument.
If nil, then use the properties from AVAIL-PROPS that are also
among those specified by `hlt-default-copy/yank-props'.
If a plain or non-negative prefix arg, then use all properties in
AVAIL-PROPS.
If a negative prefix arg, then prompt for the properties
to use, using completion against the candidates in AVAIL-PROPS."
(cond ((and arg (natnump (prefix-numeric-value arg)))
(copy-sequence avail-props))
(arg
(let ((props-avail avail-props)
(props-alist ()))
(while props-avail
(push (cons (symbol-name (pop props-avail)) (pop props-avail)) props-alist))
(if (not (cdr props-alist))
avail-props
(hlt-subplist (hlt-read-props-completing props-alist) avail-props))))
(t
(if (eq t hlt-default-copy/yank-props)
avail-props
(hlt-subplist hlt-default-copy/yank-props avail-props)))))
(defun hlt-subplist (properties available)
"Return a plist with entries from plist AVAILABLE for PROPERTIES.
PROPERTIES is a list of properties without their values."
(let ((plist ())
(prop+val nil))
(dolist (prop properties)
(when (setq prop+val (if (fboundp 'plist-member)
(plist-member available prop)
(member prop available)))
(push prop plist)
(push (cadr prop+val) plist)))
(nreverse plist)))
(defun hlt-read-props-completing (props)
"Read text properties from among those in PROPS.
PROPS is an alist whose cars are text property names (strings)."
(let ((prompt1 "Property (RET for each, empty input to finish): ")
(prompt2 "Property: ")
(props-to-copy ())
prop)
(setq prop (completing-read prompt1 props nil t)
props (delete (assoc prop props) props))
(unless (string= "" prop)
(push (intern prop) props-to-copy)
(while (and props (not (string= "" prop)))
(setq prop (completing-read prompt2 props nil t)
props (delete (assoc prop props) props))
(unless (string= "" prop) (push (intern prop) props-to-copy)))
(nreverse props-to-copy))))
(when (fboundp 'next-single-char-property-change)
(defun hlt-show-default-face (face)
"Show FACE, by default, the default highlighting face.
With a prefix argument, prompt for the highlighting face to show.
Otherwise, show the last face used for highlighting.
You can also use command `hlt-choose-default-face' to choose a different face."
(interactive (list (if current-prefix-arg
(read-face-name "Show highlighting face: ")
hlt-last-face)))
(hlt-listify-invisibility-spec)
(remove-from-invisibility-spec face))
(defun hlt-listify-invisibility-spec ()
"Convert `buffer-invisibility-spec' to list form.
If it is already a list, do nothing.
If it is t, set it to a list of all `invisible' spec values in the buffer.
That is, for each character in the buffer that has property `invisible',
the invisibility criteria specified by that value are accumulated."
(unless (listp buffer-invisibility-spec)
(setq buffer-invisibility-spec nil)
(let ((start (point-min))
(end (point-max))
spec)
(dolist (ov (overlays-in start end))
(when (setq spec (overlay-get ov 'invisible))
(unless (listp spec) (setq spec (list spec)))
(setq buffer-invisibility-spec
(hlt-set-union spec buffer-invisibility-spec))))
(while (< start end)
(when (setq spec (get-text-property start 'invisible))
(unless (listp spec) (setq spec (list spec)))
(setq buffer-invisibility-spec
(hlt-set-union spec buffer-invisibility-spec)))
(setq start (1+ start)))))
buffer-invisibility-spec)
(defun hlt-set-union (list1 list2)
"Combine LIST1 and LIST2 using a set-union operation.
The result list contains all items that appear in either LIST1 or
LIST2. This is a non-destructive function; it copies the data if
necessary."
(cond ((null list1) list2)
((null list2) list1)
((equal list1 list2) list1)
(t
(or (>= (length list1) (length list2))
(setq list1 (prog1 list2 (setq list2 list1))))
(while list2
(unless (member (car list2) list1)
(setq list1 (cons (car list2) list1)))
(setq list2 (cdr list2)))
list1)))
(defun hlt-set-intersection (list1 list2)
"Set intersection of lists LIST1 and LIST2.
This is a non-destructive operation: it copies the data if necessary."
(and list1 list2
(if (equal list1 list2)
list1
(let ((result ()))
(unless (>= (length list1) (length list2))
(setq list1 (prog1 list2 (setq list2 list1))))
(while list2
(when (member (car list2) list1)
(setq result (cons (car list2) result)))
(setq list2 (cdr list2)))
result))))
(defun hlt-hide-default-face (&optional start end face)
"Hide the last face used for highlighting.
With a prefix argument, prompt for the highlighting face to hide,
instead. You can also use command `hlt-choose-default-face' to
choose a different face.
If `hlt-act-on-any-face-flag' is non-nil, then the face to be hidden
can be any face you choose. Otherwise, it must be a face that has
been used for highlighting.
Hiding a face at some location means two things:
1) setting its `invisible' property there, making it susceptible to
being hidden by `buffer-invisibility-spec', and
2) adding it to `buffer-invisibility-spec', so that it is hidden.
This command hides all text with the specified face that has the
`invisible' property, throughout the entire buffer. However, it only
adds the `invisible' property to text with an overlay or text
property, depending on `hlt-use-overlays-flag', and it only does so
within the region, if the region is active.
Non-interactively:
FACE is the face to hide. It defaults to the last highlighting face.
START and END are the limits of the area to act on. They default to
the region limits."
(interactive `(,@(hlt-region-or-buffer-limits)
,(if current-prefix-arg
(read-face-name "Hide highlighting face: ")
hlt-last-face)))
(unless (and start end) (let ((start-end (hlt-region-or-buffer-limits)))
(setq start (car start-end)
end (cadr start-end))))
(hlt-listify-invisibility-spec)
(save-excursion
(save-window-excursion
(goto-char start)
(let ((zone-beg start)
zone-end zone)
(while (and zone-beg (< zone-beg end))
(setq zone (hlt-next-highlight zone-beg end face nil nil 'no-error-msg)
zone-beg (car zone)
zone-end (cdr zone))
(when hlt-use-overlays-flag
(let ((overlays (overlays-at zone-beg)))
(while overlays
(when (and (or hlt-act-on-any-face-flag
(eq face (overlay-get (car overlays) 'hlt-highlight)))
(eq face (overlay-get (car overlays) 'face)))
(overlay-put (car overlays) 'invisible
(hlt-add-listifying
(overlay-get (car overlays) 'invisible)
face)))
(when overlays (setq overlays (cdr overlays))))))
(when (and (not (eq hlt-use-overlays-flag 'only))
(or hlt-act-on-any-face-flag
(eq face (get-text-property (point) 'hlt-highlight)))
(let ((pt-faces (get-text-property (point) 'face)))
(if (consp pt-faces) (memq face pt-faces) (eq face pt-faces))))
(put-text-property zone-beg zone-end 'invisible
(hlt-add-listifying
(get-text-property zone-beg 'invisible)
face)))
(hlt-add-to-invisibility-spec face))))))
(defun hlt-add-to-invisibility-spec (element)
"Add ELEMENT to `buffer-invisibility-spec'.
See documentation for `buffer-invisibility-spec' for the kind of elements
that can be added."
(when (eq buffer-invisibility-spec t) (setq buffer-invisibility-spec (list t)))
(add-to-list 'buffer-invisibility-spec element))
(defun hlt-add-listifying (orig-val val-to-add)
"Add VAL-TO-ADD to list ORIG-VAL, listifying ORIG-VAL first if needed."
(unless (listp orig-val) (setq orig-val (list orig-val)))
(add-to-list 'orig-val val-to-add)
orig-val)
(defun hlt-next-highlight (&optional start end face mouse-p backward-p no-error-p)
"Go to the next highlight in FACE.
Interactively, FACE is the last face used for highlighting, but
you can use command `hlt-choose-default-face' to choose a different face.
If `hlt-act-on-any-face-flag' is non-nil, then the target face can be
any face you choose. Otherwise, it must be a face that has been used
for highlighting.
If `hlt-use-overlays-flag' is non-nil, then overlay highlighting is
targeted. If `hlt-use-overlays-flag' is not `only', then
text-property highlighting is targeted. This means, in particular,
that a value of nil targets both overlays and text properties.
If the region is active and not empty, then limit movement to the
region. Otherwise, use the whole buffer.
When called non-interactively:
- non-nil argument NO-ERROR-P means do not raise an error if no
highlight with FACE is found, and leave point at END.
- Return a cons of the limits of the text starting at point that has
property `hlt-highlight' of value FACE: (BEGIN-FACE . END-FACE), where
BEGIN-FACE is point and END-FACE is the first position just after
value FACE ends."
(interactive `(,@(hlt-region-or-buffer-limits) nil ,current-prefix-arg))
(unless (and start end) (let ((start-end (hlt-region-or-buffer-limits)))
(setq start (car start-end)
end (cadr start-end))))
(if face (setq hlt-last-face face) (setq face hlt-last-face))
(when backward-p (setq end (prog1 start (setq start end))))
(let ((face-found nil)
(orig-point (point))
(beg start))
(while (and (not (if backward-p (bobp) (eobp)))
(not (eq face face-found))
(not (= beg end)))
(save-restriction
(narrow-to-region beg end)
(setq beg (if backward-p
(goto-char (previous-single-char-property-change
(point) (if mouse-p 'mouse-face 'face)
nil (point-min)))
(goto-char (next-single-char-property-change
(point) (if mouse-p 'mouse-face 'face)
nil (point-max))))))
(when hlt-use-overlays-flag
(let ((overlays (overlays-at (point))))
(while overlays
(when (and (or hlt-act-on-any-face-flag
(eq face (overlay-get (car overlays) 'hlt-highlight)))
(eq face (overlay-get (car overlays) 'face)))
(setq face-found face
overlays ()))
(when overlays (setq overlays (cdr overlays))))))
(when (and (not face-found)
(not (eq hlt-use-overlays-flag 'only))
(or hlt-act-on-any-face-flag
(eq face (get-text-property (point) 'hlt-highlight)))
(let ((pt-faces (get-text-property (point) 'face)))
(if (consp pt-faces) (memq face pt-faces) (eq face pt-faces))))
(setq face-found face)))
(unless (or (and (eq face face-found) (not (eq (point) orig-point))) no-error-p)
(goto-char orig-point)
(error "No %s highlight with face `%s'" (if backward-p "previous" "next") face)))
(unless (interactive-p)
(cons (point)
(next-single-char-property-change (point) (if mouse-p 'mouse-face 'face)
nil (if backward-p start end)))))
(defun hlt-previous-highlight (&optional start end face mouse-p no-error-p)
"Go to the previous highlight in the last face used for highlighting.
This is the same as `hlt-previous-highlight', except movement is backward."
(interactive `(,@(hlt-region-or-buffer-limits) nil ,current-prefix-arg))
(unless (and start end) (let ((start-end (hlt-region-or-buffer-limits)))
(setq start (car start-end)
end (cadr start-end))))
(hlt-next-highlight start end face mouse-p t no-error-p))
(defun hlt-highlight-faces-in-buffer (start end)
"List of highlighting faces in current buffer between START and END.
This includes faces used in overlays and as text properties.
Only highlighting faces are included, that is, faces associated with a
`hlt-highlight' property."
(save-excursion
(save-window-excursion
(let ((faces ())
(beg start)
face)
(setq end (min end (point-max)))
(goto-char beg)
(while (< beg end)
(save-restriction
(narrow-to-region beg end)
(setq beg (goto-char (next-single-char-property-change (point) 'face
nil (point-max)))))
(when (setq face (get-text-property (point) 'hlt-highlight))
(add-to-list 'faces face))
(let ((overlays (overlays-at (point))))
(while overlays
(when (and (overlay-get (car overlays) 'hlt-highlight)
(setq face (overlay-get (car overlays) 'face)))
(add-to-list 'faces face)
(setq overlays ()))
(when overlays (setq overlays (cdr overlays))))))
faces))))
(defun hlt-toggle-act-on-any-face-flag ()
"Toggle `hlt-act-on-any-face-flag'."
(interactive)
(setq hlt-act-on-any-face-flag (not hlt-act-on-any-face-flag))
(message (if hlt-act-on-any-face-flag
"Highlight actions now apply to any face, not just a highlighting face"
"Highlight actions now apply only to a highlighting face")))
)
(when (fboundp 'next-single-char-property-change)
(defun hlt-highlight-property-with-value (prop &optional values start end face
type msg-p mouse-p)
"Highlight text in region with property PROP of a value in VALUES.
Non-nil VALUES means do this only where PROP has a value in VALUES.
Interactively, you are prompted for PROP and VALUES. For VALUES you
can enter either a list or a single, non-list value. A list is
always interpreted as a list of values, not as a single list value.
Using `RET' with no input means highlight for any non-nil value.
Optional args START and END are the limits of the area to act on.
They default to the region limits (buffer, if no active region).
Optional 5th arg FACE is the face to use for highlighting.
Interactively, this is the last face that was used for highlighting.
(Use command `hlt-choose-default-face' to choose a different face.)
Optional 6th arg TYPE is `overlay', `text', or nil, and specifies the
type of character property - nil means to look for both overlay and
text properties. Interactively, TYPE is derived from
`hlt-use-overlays-flag'.
Optional 7th arg MSG-P non-nil means to display a progress message.
Optional 8th arg MOUSE-P non-nil means use the `mouse-face' property,
not the `face' property, for highlighting. Interactively, MOUSE-P
is provided by the prefix arg."
(interactive
`(,(intern (read-string "Property to highlight: " nil 'highlight-property-history))
,(let* ((strg (read-string "Property value: "))
(vals (if (string= "" strg)
()
(car (read-from-string strg)))))
(unless (listp vals) (setq vals (list vals)))
vals)
,@(hlt-region-or-buffer-limits)
nil
,(if hlt-use-overlays-flag
(if (eq hlt-use-overlays-flag 'only) 'overlay nil)
'text)
t
,current-prefix-arg))
(unless (and start end) (let ((start-end (hlt-region-or-buffer-limits)))
(setq start (car start-end)
end (cadr start-end))))
(if face (setq hlt-last-face face) (setq face hlt-last-face))
(when (and msg-p (or mark-active mouse-p)) (message "Highlighting..."))
(let ((zone-end nil))
(unless (and start end)
(setq start (point-min)
end (point-max)))
(condition-case highlight-property-with-value
(save-excursion
(while (and (< start end)
(let* ((charval (and (or (not type) (eq type 'overlay))
(get-char-property start prop)))
(textval (and (or (not type) (eq type 'text))
(get-text-property start prop)))
(currval (hlt-flat-list charval textval)))
(if values
(not (hlt-set-intersection values currval))
(not currval))))
(setq start (next-single-char-property-change start prop nil end)))
(while (and start (< start end))
(setq zone-end (or (next-single-char-property-change start prop nil end) end))
(hlt-highlight-region start zone-end face nil mouse-p)
(setq start zone-end)
(while (and (< start end)
(let* ((charval (and (or (not type) (eq type 'overlay))
(get-char-property start prop)))
(textval (and (or (not type) (eq type 'text))
(get-text-property start prop)))
(currval (hlt-flat-list charval textval)))
(if values
(not (hlt-set-intersection values currval))
(not currval))))
(setq start (next-single-char-property-change start prop nil end)))))
(quit (hlt-unhighlight-region start end face))
(error (hlt-unhighlight-region start end face)
(error (error-message-string highlight-property-with-value)))))
(let ((remove-msg (substitute-command-keys
"`\\[negative-argument] \\[hlt-highlight]' to remove highlighting.")))
(when (and msg-p (or mark-active mouse-p))
(message "Highlighting... done. %s" remove-msg))))
(defun hlt-flat-list (val1 val2)
"Return a flat list with all values in VAL1 and VAL2."
(let ((result ()))
(unless (listp val1) (setq val1 (list val1)))
(unless (listp val2) (setq val2 (list val2)))
(while val1 (add-to-list 'result (pop val1)))
(while val2 (add-to-list 'result (pop val2)))
result))
(defun hlt-mouse-toggle-link-highlighting ()
"Alternately highlight and unhighlight links on a mouse click.
Do nothing if the click is at a different location from the last one.
This calls `hlt-toggle-link-highlighting' to do the toggling.
Links in the entire buffer are affected, even if the region is active.
This is intended to be used on `post-command-hook'."
(when (and (string-match "mouse" (format "%S" (event-basic-type last-command-event)))
(memq 'click (event-modifiers last-command-event)))
(let* ((estart (event-start last-command-event))
(pos (copy-marker (posn-point estart))))
(when (integer-or-marker-p pos)
(save-excursion
(with-current-buffer (window-buffer (posn-window estart))
(when (condition-case nil
(get-char-property (min pos (point-max)) 'mouse-face)
(error nil))
(hlt-toggle-link-highlighting nil nil pos))))))))
(defun hlt-toggle-link-highlighting (&optional start end pos)
"Alternately highlight and unhighlight links.
A link is considered to be any text with property `mouse-face'.
Calls `hlt-toggle-property-highlighting', passing the args."
(interactive `(,@(hlt-region-or-buffer-limits)))
(hlt-toggle-property-highlighting 'mouse-face start end 'hlt-property-highlight
(interactive-p) nil pos))
(defun hlt-mouse-toggle-property-highlighting (prop &optional face msg-p mouse-p)
"Alternately highlight and unhighlight text on a mouse click.
Do nothing if the click is at a different location from the last one.
Call `hlt-toggle-link-highlighting', passing the args.
Propertized text in the entire buffer is (un)highlighted, even if the
region is active.
This is intended to be used on `post-command-hook'."
(when (and (string-match "mouse" (format "%S" (event-basic-type last-command-event)))
(memq 'click (event-modifiers last-command-event)))
(let* ((estart (event-start last-command-event))
(pos (copy-marker (posn-point estart))))
(when (integer-or-marker-p pos)
(save-excursion
(with-current-buffer (window-buffer (posn-window estart))
(when (condition-case nil
(get-char-property (min pos (point-max)) prop)
(error nil))
(hlt-toggle-property-highlighting prop nil nil
face (interactive-p) mouse-p pos))))))))
(defun hlt-toggle-property-highlighting (prop &optional start end face
msg-p mouse-p pos)
"Alternately highlight/unhighlight all text that has property PROP.
Highlighting is done using overlays.
Optional arg POS is a buffer position. If it is the same as the
position recorded in `hlt-prop-highlighting-state', then do not
toggle. In any case, update `hlt-prop-highlighting-state' with POS.
Other args are the same as for `hlt-highlight-property-with-value'."
(interactive
`(,(intern (read-string "Property to highlight: " nil 'highlight-property-history))
,@(hlt-region-or-buffer-limits)
nil t ,current-prefix-arg))
(when (or (not pos) (equal pos (cdr hlt-prop-highlighting-state)))
(cond ((car hlt-prop-highlighting-state)
(hlt-unhighlight-all-prop prop start end face (interactive-p) mouse-p)
(setcar hlt-prop-highlighting-state nil))
(t
(hlt-highlight-all-prop prop start end face (interactive-p) mouse-p)
(setcar hlt-prop-highlighting-state t))))
(when pos (setcdr hlt-prop-highlighting-state pos)))
(defun hlt-highlight-all-prop (prop &optional start end face msg-p mouse-p)
"Highlight all text that has a non-nil property PROP using FACE.
Highlight using overlays.
Args are the same as for `hlt-highlight-property-with-value'."
(interactive `(,@(hlt-region-or-buffer-limits)))
(hlt-highlight-property-with-value
prop () start end face 'overlay (interactive-p) mouse-p))
(defun hlt-unhighlight-all-prop (prop &optional start end face msg-p mouse-p)
"Unhighlight all text highlighted with face `hlt-property-highlight'.
Args are the same as for `hlt-highlight-property-with-value'."
(interactive `(,@(hlt-region-or-buffer-limits)))
(let ((hlt-use-overlays-flag 'only))
(hlt-unhighlight-region-for-face face start end mouse-p)))
)
(defun hlt-region-or-buffer-limits ()
"Return the start and end of the region as a list, smallest first.
If the region is empty or not active, then bob and eob are used."
(if (or (not mark-active) (null (mark)) (= (point) (mark)))
(list (point-min) (point-max))
(if (< (point) (mark)) (list (point) (mark)) (list (mark) (point)))))
(provide 'highlight)