mirror of https://github.com/Chizi123/.emacs.d.git

Chizi123
2018-11-18 21067e7cbe6d7a0f65ff5c317a96b5c337b0b3d8
commit | author | age
5cb5f7 1 ;;; volatile-highlights.el --- Minor mode for visual feedback on some operations.
C 2
3 ;; Copyright (C) 2001, 2010-2016 K-talo Miyazaki, all rights reserved.
4
5 ;; Author: K-talo Miyazaki <Keitaro dot Miyazaki at gmail dot com>
6 ;; Created: 03 October 2001. (as utility functions in my `.emacs' file.)
7 ;;          14 March   2010. (re-written as library `volatile-highlights.el')
8 ;; Keywords: emulations convenience wp
9 ;; Package-Version: 20160612.155
10 ;; Revision: $Id: cb468976642bf1d30cbb2070ee846c4736ee077d $
11 ;; URL: http://www.emacswiki.org/emacs/download/volatile-highlights.el
12 ;; GitHub: http://github.com/k-talo/volatile-highlights.el
13 ;; Version: 1.15
14 ;; Contributed by: Ryan Thompson and Le Wang.
15
16 ;; This file is not part of GNU Emacs.
17
18 ;; This program is free software: you can redistribute it and/or modify
19 ;; it under the terms of the GNU General Public License as published by
20 ;; the Free Software Foundation, either version 3 of the License, or
21 ;; (at your option) any later version.
22
23 ;; This program is distributed in the hope that it will be useful,
24 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
25 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26 ;; GNU General Public License for more details.
27
28 ;; You should have received a copy of the GNU General Public License
29 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
30
31 ;;; Commentary:
32 ;;
33 ;; Overview
34 ;; ========
35 ;; This library provides minor mode `volatile-highlights-mode', which
36 ;; brings visual feedback to some operations by highlighting portions
37 ;; relating to the operations.
38 ;;
39 ;; All of highlights made by this library will be removed
40 ;; when any new operation is executed.
41 ;;
42 ;;
43 ;; INSTALLING
44 ;; ==========
45 ;; To install this library, save this file to a directory in your
46 ;; `load-path' (you can view the current `load-path' using "C-h v
47 ;; load-path" within Emacs), then add the following line to your
48 ;; .emacs start up file:
49 ;;
50 ;;    (require 'volatile-highlights)
51 ;;    (volatile-highlights-mode t)
52 ;;
53 ;;
54 ;; USING
55 ;; =====
56 ;; To toggle volatile highlighting, type `M-x volatile-highlights-mode <RET>'.
57 ;;
58 ;; While this minor mode is on, a string `VHL' will be displayed on the modeline.
59 ;;
60 ;; Currently, operations listed below will be highlighted While the minor mode
61 ;; `volatile-highlights-mode' is on:
62 ;;
63 ;;    - `undo':
64 ;;      Volatile highlights will be put on the text inserted by `undo'.
65 ;;
66 ;;    - `yank' and `yank-pop':
67 ;;      Volatile highlights will be put on the text inserted by `yank'
68 ;;      or `yank-pop'.
69 ;;
70 ;;    - `kill-region', `kill-line', any other killing function:
71 ;;      Volatile highlights will be put at the positions where the
72 ;;      killed text used to be.
73 ;;
74 ;;    - `delete-region':
75 ;;      Same as `kill-region', but not as reliable since
76 ;;      `delete-region' is an inline function.
77 ;;
78 ;;    - `find-tag':
79 ;;      Volatile highlights will be put on the tag name which was found
80 ;;      by `find-tag'.
81 ;;
82 ;;    - `occur-mode-goto-occurrence' and `occur-mode-display-occurrence':
83 ;;      Volatile highlights will be put on the occurrence which is selected
84 ;;      by `occur-mode-goto-occurrence' or `occur-mode-display-occurrence'.
85 ;;
86 ;;    - Non incremental search operations:
87 ;;      Volatile highlights will be put on the the text found by
88 ;;      commands listed below:
89 ;;
90 ;;        `nonincremental-search-forward'
91 ;;        `nonincremental-search-backward'
92 ;;        `nonincremental-re-search-forward'
93 ;;        `nonincremental-re-search-backward'
94 ;;        `nonincremental-repeat-search-forward'
95 ;;        `nonincremental-repeat-search-backwar'
96 ;;
97 ;; Highlighting support for each operations can be turned on/off individually
98 ;; via customization. Also check out the customization group
99 ;;
100 ;;   `M-x customize-group RET volatile-highlights RET'
101 ;;
102 ;;
103 ;; EXAMPLE SNIPPETS FOR USING VOLATILE HIGHLIGHTS WITH OTHER PACKAGES
104 ;; ==================================================================
105 ;;
106 ;; - vip-mode
107 ;;
108 ;;   (vhl/define-extension 'vip 'vip-yank)
109 ;;   (vhl/install-extension 'vip)
110 ;;   
111 ;; - evil-mode
112 ;;
113 ;;   (vhl/define-extension 'evil 'evil-paste-after 'evil-paste-before
114 ;;                         'evil-paste-pop 'evil-move)
115 ;;   (vhl/install-extension 'evil)
116 ;;
117 ;; - undo-tree
118 ;;
119 ;;   (vhl/define-extension 'undo-tree 'undo-tree-yank 'undo-tree-move)
120 ;;   (vhl/install-extension 'undo-tree)
121
122
123 ;;; Change Log:
124 ;;
125 ;; v1.15 Sun Jun 12 10:40:31 2016 JST
126 ;;   - Update documents, example snippets for other packages,
127 ;;     regarding #14.
128 ;;
129 ;; v1.14 Sun Jun 12 10:12:30 2016 JST
130 ;;   - Update documents, especially supporting `evil-mode',
131 ;;     regarding #13.
132 ;;   - Fixed a bug #14, an extension won't be loaded properly
133 ;;     when it was installed by `vhl/install-extension'.
134 ;;
135 ;; v1.13 Sat May 21 11:02:36 2016 JST
136 ;;   - Fixed a bug that highlighting was not working with nested volatile
137 ;;     highlighting aware operations like `yak-pop'.
138 ;;
139 ;; v1.12  Sun Feb 21 19:09:29 2016 JST
140 ;;   - Added autoload cookie.
141 ;;
142 ;; v1.11  Sun Oct  5 13:05:38 2014 JST
143 ;;   - Fixed an error "Symbol's function definition is void: return",
144 ;;     that occurs when highlight being created with `hideshow' commands.
145 ;;
146 ;; v1.10  Thu Mar 21 22:37:27 2013 JST
147 ;;   - Use inherit in face definition when detected.
148 ;;   - Suppress compiler warnings regarding to emacs/xemacs private
149 ;;     functions by file local variable.
150 ;;
151 ;; v1.9  Tue Mar  5 00:52:35 2013 JST
152 ;;   - Fixed errors in shell caused by dummy functions.
153 ;;
154 ;; v1.8  Wed Feb 15 00:08:14 2012 JST
155 ;;   - Added "Contributed by: " line in header.
156 ;;   - Added extension for hideshow.
157 ;;
158 ;; v1.7  Mon Feb 13 23:31:18 2012 JST
159 ;;   - Fixed a bug required features are not loaded.
160 ;;
161 ;; v1.6  Thu Feb  2 06:59:48 2012 JST
162 ;;   - Removed extensions for non standard features.
163 ;;   - Suppress compiler warning "function `vhl/.make-list-string'
164 ;;     defined multiple times".
165 ;;   - Fixed compiler error "Symbol's function definition is void:
166 ;;     vhl/.make-list-string".
167 ;;
168 ;;  v1.5  Tue Jan 31 22:19:04 2012 JST
169 ;;   - Added extension for highlighting the position where text was
170 ;;     killed from.
171 ;;   - Added extension for highlighting the position where text was
172 ;;     deleted from.
173 ;;   - Provide a macro `vhl/define-extension' for easily defining new
174 ;;     simple extensions with a single line of code. For usage
175 ;;     examples, see the definitions of the undo, yank, kill, and
176 ;;     delete extensions.
177 ;;
178 ;;  v1.4  Sun Jan 15 20:23:58 2012 JST
179 ;;   - Suppress compiler warnings regarding to emacs/xemacs private
180 ;;     functions.
181 ;;   - Fixed bugs which occurs to xemacs.
182 ;;
183 ;;  v1.3, Sat Dec 18 16:44:14 2010 JST
184 ;;   - Added extension for non-incremental search operations.
185 ;;   - Fixed a bug that highlights won't be appear when
186 ;;     occurrences is in folded line.
187 ;;
188 ;;  v1.2, Tue Nov 30 01:07:48 2010 JST
189 ;;   - In `vhl/ext/occur', highlight all occurrences.
190 ;;
191 ;;  v1.1, Tue Nov  9 20:36:09 2010 JST
192 ;;   - Fixed a bug that mode toggling feature was not working.
193
194 ;;; Code:
195
196 (defconst vhl/version "1.8")
197
198 (eval-when-compile
199   (require 'cl)
200   (require 'easy-mmode)
201   (require 'advice))
202
203 (provide 'volatile-highlights)
204
205
206 ;;;============================================================================
207 ;;;
208 ;;;  Private Variables.
209 ;;;
210 ;;;============================================================================
211
212 (eval-and-compile
213   (defconst vhl/.xemacsp (string-match "XEmacs" emacs-version)
214     "A flag if the emacs is xemacs or not."))
215
216 (defvar vhl/.hl-lst nil
217   "List of volatile highlights.")
218
219
220 ;;;============================================================================
221 ;;;
222 ;;;  Faces.
223 ;;;
224 ;;;============================================================================
225
226 (defgroup volatile-highlights nil
227   "Visual feedback on operations."
228   :group 'editing)
229
230
231 ;; Borrowed from `slime.el'.
232 (defun vhl/.face-inheritance-possible-p ()
233   "Return true if the :inherit face attribute is supported."
234   (assq :inherit custom-face-attributes))
235
236 (defface vhl/default-face
237   (cond
238    ((or vhl/.xemacsp
239         (not (vhl/.face-inheritance-possible-p)))
240     '((((class color) (background light))
241        (:background "yellow1"))
242       (((class color) (background dark))
243        (:background "SkyBlue4"))
244       (t :inverse-video t)))
245    (t
246     '((t
247        :inherit secondary-selection
248        ))))
249     "Face used for volatile highlights."
250     :group 'volatile-highlights)
251
252
253 ;;;============================================================================
254 ;;;
255 ;;;  Minor Mode Definition.
256 ;;;
257 ;;;============================================================================
258 ;;;###autoload
259 (easy-mmode-define-minor-mode
260  volatile-highlights-mode "Minor mode for visual feedback on some operations."
261  :global t
262  :init-value nil
263  :lighter " VHl"
264  (if volatile-highlights-mode
265      (vhl/load-extensions)
266    (vhl/unload-extensions)))
267
268
269 (defcustom Vhl/highlight-zero-width-ranges nil
270   "If t, highlight the positions of zero-width ranges.
271
272 For example, if a deletion is highlighted, then the position
273 where the deleted text used to be would be highlighted."
274   :type 'boolean
275   :group 'volatile-highlights)
276
277
278 ;;;============================================================================
279 ;;;
280 ;;;  Public Functions/Commands.
281 ;;;
282 ;;;============================================================================
283
284 ;;-----------------------------------------------------------------------------
285 ;; (vhl/add-range BEG END &OPTIONAL BUF FACE) => VOID
286 ;;-----------------------------------------------------------------------------
287 (defun vhl/add-range (beg end &optional buf face)
288   "Add a volatile highlight to the buffer `BUF' at the position
289 specified by `BEG' and `END' using the face `FACE'.
290
291 When the buffer `BUF' is not specified or its value is `nil',
292 volatile highlight will be added to current buffer.
293
294 When the face `FACE' is not specified or its value is `nil',
295 the default face `vhl/default-face' will
296 be used as the value."
297   (let* ((face (or face 'vhl/default-face))
298          (hl (vhl/.make-hl beg end buf face)))
299     (setq vhl/.hl-lst
300           (cons hl vhl/.hl-lst))
301     (add-hook 'pre-command-hook 'vhl/clear-all)))
302 (define-obsolete-function-alias 'vhl/add 'vhl/add-range "1.5")
303
304 ;;-----------------------------------------------------------------------------
305 ;; (vhl/add-position POS &OPTIONAL BUF FACE) => VOID
306 ;;-----------------------------------------------------------------------------
307 (defun vhl/add-position (pos &rest other-args)
308   "Highlight buffer position POS as a change.
309
310 If Vhl/highlight-zero-width-ranges is nil, do nothing.
311
312 Optional args are the same as `vhl/add-range'."
313   (when (and Vhl/highlight-zero-width-ranges (not (zerop (buffer-size))))
314     (when (> pos (buffer-size))
315         (setq pos (- pos 1)))
316     (apply 'vhl/add-range pos (+ pos 1) other-args)))
317
318 ;;-----------------------------------------------------------------------------
319 ;; (vhl/clear-all) => VOID
320 ;;-----------------------------------------------------------------------------
321 (defun vhl/clear-all ()
322   "Clear all volatile highlights."
323   (interactive)
324   (while vhl/.hl-lst
325     (vhl/.clear-hl (car vhl/.hl-lst))
326     (setq vhl/.hl-lst
327           (cdr vhl/.hl-lst)))
328       (remove-hook 'pre-command-hook 'vhl/clear-all))
329
330 ;;-----------------------------------------------------------------------------
331 ;; (vhl/force-clear-all) => VOID
332 ;;-----------------------------------------------------------------------------
333 (defun vhl/force-clear-all ()
334   "Force clear all volatile highlights in current buffer."
335   (interactive)
336   (vhl/.force-clear-all-hl))
337
338
339 ;;;============================================================================
340 ;;;
341 ;;;  Private Functions.
342 ;;;
343 ;;;============================================================================
344
345 ;;-----------------------------------------------------------------------------
346 ;; (vhl/.make-hl BEG END BUF FACE) => HIGHLIGHT
347 ;;-----------------------------------------------------------------------------
348 (defun vhl/.make-hl (beg end buf face)
349   "Make a volatile highlight at the position specified by `BEG' and `END'."
350   (let (hl)
351     (cond
352      (vhl/.xemacsp
353       ;; XEmacs
354       (setq hl (make-extent beg end buf))
355       (set-extent-face hl face)
356       (highlight-extent hl t)
357       (set-extent-property hl 'volatile-highlights t))
358      (t
359       ;; GNU Emacs
360       (setq hl (make-overlay beg end buf))
361       (overlay-put hl 'face face)
362       (overlay-put hl 'priority 1)
363       (overlay-put hl 'volatile-highlights t)))
364      hl))
365
366 ;;-----------------------------------------------------------------------------
367 ;; (vhl/.clear-hl HIGHLIGHT) => VOID
368 ;;-----------------------------------------------------------------------------
369 (defun vhl/.clear-hl (hl)
370   "Clear one highlight."
371   (cond
372    ;; XEmacs (not tested!)
373    (vhl/.xemacsp
374     (and (extentp hl)
375          (delete-extent hl)))
376    ;; GNU Emacs
377    (t
378     (and (overlayp hl)
379          (delete-overlay hl)))))
380
381 ;;-----------------------------------------------------------------------------
382 ;; (vhl/.force-clear-all-hl) => VOID
383 ;;-----------------------------------------------------------------------------
384 (defun vhl/.force-clear-all-hl ()
385   "Force clear all volatile highlights in current buffer."
386   (cond
387    ;; XEmacs (not tested!)
388    (vhl/.xemacsp
389       (map-extents (lambda (hl maparg)
390                      (and (extent-property hl 'volatile-highlights)
391                           (vhl/.clear-hl hl)))))
392    ;; GNU Emacs
393    (t
394     (save-restriction
395       (widen)
396       (mapcar (lambda (hl)
397                 (and (overlay-get hl 'volatile-highlights)
398                      (vhl/.clear-hl hl)))
399               (overlays-in (point-min) (point-max)))))))
400
401
402 ;;;============================================================================
403 ;;;
404 ;;;  Functions to manage extensions.
405 ;;;
406 ;;;============================================================================
407 (defvar vhl/.installed-extensions nil)
408
409 (defun vhl/install-extension (sym)
410   (let ((fn-on  (intern (format "vhl/ext/%s/on" sym)))
411         (fn-off (intern (format "vhl/ext/%s/off" sym)))
412         (cust-name (intern (format "vhl/use-%s-extension-p" sym))))
413     (pushnew sym vhl/.installed-extensions)
414     (eval `(defcustom ,cust-name t
415              ,(format "A flag if highlighting support for `%s' is on or not." sym)
416              :type 'boolean
417              :group 'volatile-highlights
418              :set (lambda (sym-to-set val)
419                     (set-default sym-to-set val)
420                     (if val
421                         (when volatile-highlights-mode
422                           (vhl/load-extension (quote ,sym)))
423                       (vhl/unload-extension (quote ,sym))))))))
424
425 (defun vhl/load-extension (sym)
426   (let ((fn-on  (intern (format "vhl/ext/%s/on" sym)))
427         (cust-name (intern (format "vhl/use-%s-extension-p" sym))))
428     (if (functionp fn-on)
429         (when (and (boundp cust-name)
430                    (eval cust-name))
431           (apply fn-on nil))
432       (message "[vhl] No load function for extension  `%s'" sym))))
433
434 (defun vhl/unload-extension (sym)
435   (let ((fn-off (intern (format "vhl/ext/%s/off" sym))))
436     (if (functionp fn-off)
437         (apply fn-off nil)
438       (message "[vhl] No unload function for extension  `%s'" sym))))
439
440 (defun vhl/load-extensions ()
441   (dolist (sym vhl/.installed-extensions)
442     (vhl/load-extension sym)))
443
444 (defun vhl/unload-extensions ()
445   (dolist (sym vhl/.installed-extensions)
446     (vhl/unload-extension sym)))
447
448
449 ;;;============================================================================
450 ;;;
451 ;;;  Utility functions/macros for extensions.
452 ;;;
453 ;;;============================================================================
454 (defvar vhl/.after-change-hook-depth 0)
455
456 (defun vhl/.push-to-after-change-hook (fn-name)
457   ;; Debug
458   ;; (if (zerop vhl/.after-change-hook-depth)
459   ;;     (message "vlh: push: %s" fn-name)
460   ;;   (message "vlh: skip push: %s" fn-name))
461   (when (zerop vhl/.after-change-hook-depth)
462     (add-hook 'after-change-functions
463               'vhl/.make-vhl-on-change))
464   (setq vhl/.after-change-hook-depth
465         (1+ vhl/.after-change-hook-depth)))
466
467 (defun vhl/.pop-from-after-change-hook (fn-name)
468   (setq vhl/.after-change-hook-depth
469         (1- vhl/.after-change-hook-depth))
470   ;; Debug
471   ;; (if (zerop vhl/.after-change-hook-depth)
472   ;;     (message "vlh: pop: %s" fn-name)
473   ;;   (message "vlh: skip pop: %s" fn-name))
474   (when (zerop vhl/.after-change-hook-depth)
475     (remove-hook 'after-change-functions
476                  'vhl/.make-vhl-on-change)))
477
478 (defun vhl/advice-defined-p (fn-name class ad-name)
479   (and (ad-is-advised fn-name)
480        (assq ad-name
481              (ad-get-advice-info-field fn-name class))))
482
483 (defun vhl/disable-advice-if-defined (fn-name class ad-name)
484   (when (vhl/advice-defined-p fn-name class ad-name)
485     (ad-disable-advice fn-name class ad-name)
486     (ad-activate fn-name)))
487
488 (defun vhl/.make-vhl-on-change (beg end len-removed)
489   (let ((insert-p (zerop len-removed)))
490     (if insert-p
491         ;; Highlight the insertion
492         (vhl/add-range beg end)
493       ;; Highlight the position of the deletion
494       (vhl/add-position beg))))
495
496 (defmacro vhl/give-advice-to-make-vhl-on-changes (fn-name)
497   (let* ((ad-name (intern (concat "vhl/make-vhl-on-"
498                                  (format "%s" fn-name)))))
499     (or (symbolp fn-name)
500         (error "vhl/give-advice-to-make-vhl-on-changes: `%s' is not type of symbol." fn-name))
501     `(progn
502        (defadvice ,fn-name (around
503                               ,ad-name
504                               (&rest args))
505          (vhl/.push-to-after-change-hook (quote ,fn-name))
506          (unwind-protect
507              ad-do-it
508            (vhl/.pop-from-after-change-hook (quote ,fn-name))))
509        ;; Enable advice.
510        (ad-enable-advice (quote ,fn-name) 'around (quote ,ad-name))
511        (ad-activate (quote ,fn-name)))))
512
513 (defmacro vhl/cancel-advice-to-make-vhl-on-changes (fn-name)
514   (let ((ad-name (intern (concat "vhl/make-vhl-on-"
515                                  (format "%s" fn-name)))))
516     `(vhl/disable-advice-if-defined (quote ,fn-name) 'around (quote ,ad-name))))
517
518 (defun vhl/require-noerror (feature &optional filename)
519   (condition-case c
520       (require feature)
521     (file-error nil)))
522
523 (eval-and-compile
524 ;; Utility function by Ryan Thompson.
525 (defun vhl/.make-list-string (items)
526   "Makes an English-style list from a list of strings.
527
528 Converts a list of strings into a string that lists the items
529 separated by commas, as well as the word `and' before the last
530 item. In other words, returns a string of the way those items
531 would be listed in english.
532
533 This is included as a private support function for generating
534 lists of symbols to be included docstrings of auto-generated
535 extensions."
536   (assert (listp items))
537   (cond ((null items)
538          ;; Zero items
539          "")
540         ((null (cdr items))
541          ;; One item
542          (assert (stringp (first items)))
543          (format "%s" (first items)))
544         ((null (cddr items))
545          ;; Two items
546          (assert (stringp (first items)))
547          (assert (stringp (second items)))
548          (apply 'format "%s and %s" items))
549         ((null (cdddr items))
550          ;; Three items
551          (assert (stringp (first items)))
552          (assert (stringp (second items)))
553          (assert (stringp (third items)))
554          (apply 'format "%s, %s, and %s" items))
555         (t
556          ;; 4 or more items
557          (format "%s, %s" (first items) (vhl/.make-list-string (rest items)))))))
558
559 ;; The following makes it trivial to define simple vhl extensions
560 (defmacro vhl/define-extension (name &rest functions)
561   "Define a VHL extension called NAME that applies standard VHL
562   advice to each of FUNCTIONS."
563   (assert (first functions))
564   (let* ((name-string (symbol-name (eval name)))
565          (function-list-string (vhl/.make-list-string
566                                 (mapcar (lambda (f) (format "`%s'" (symbol-name (eval f))))
567                                         functions)))
568          (on-function-name (intern (format "vhl/ext/%s/on" name-string)))
569          (on-body-form (cons
570                         'progn
571                         (mapcar (lambda (f)
572                                   `(vhl/give-advice-to-make-vhl-on-changes ,(eval f)))
573                                 functions)))
574          (on-doc-string (format "Turn on volatile highlighting for %s." function-list-string))
575
576          (off-function-name (intern (format "vhl/ext/%s/off" name-string)))
577          (off-body-form (cons
578                          'progn
579                          (mapcar (lambda (f)
580                                    `(vhl/cancel-advice-to-make-vhl-on-changes ,(eval f)))
581                                  functions)))
582          (off-doc-string (format "Turn off volatile highlighting for %s." function-list-string)))
583     `(progn
584        (defun ,on-function-name ()
585          ,on-doc-string
586          (interactive)
587          ,on-body-form)
588        (defun ,off-function-name ()
589          ,off-doc-string
590          (interactive)
591          ,off-body-form)
592        nil)))
593
594
595 ;;;============================================================================
596 ;;;
597 ;;;  Extensions.
598 ;;;
599 ;;;============================================================================
600
601 ;;-----------------------------------------------------------------------------
602 ;; Extension for supporting undo.
603 ;;   -- Put volatile highlights on the text inserted by `undo'.
604 ;;      (and may be `redo'...)
605 ;;-----------------------------------------------------------------------------
606
607 (vhl/define-extension 'undo 'primitive-undo)
608 (vhl/install-extension 'undo)
609
610
611 ;;-----------------------------------------------------------------------------
612 ;; Extension for supporting yank/yank-pop.
613 ;;   -- Put volatile highlights on the text inserted by `yank' or `yank-pop'.
614 ;;-----------------------------------------------------------------------------
615
616 (vhl/define-extension 'yank 'yank 'yank-pop)
617 (vhl/install-extension 'yank)
618
619 ;;-----------------------------------------------------------------------------
620 ;; Extension for supporting kill.
621 ;;   -- Put volatile highlights on the positions where killed text
622 ;;      used to be.
623 ;;-----------------------------------------------------------------------------
624
625 (vhl/define-extension 'kill 'kill-region)
626 (vhl/install-extension 'kill)
627
628 ;;-----------------------------------------------------------------------------
629 ;; Extension for supporting `delete-region'.
630 ;;   -- Put volatile highlights on the positions where deleted text
631 ;;      used to be. This is not so reliable since `delete-region' is
632 ;;      an inline function and is pre-compiled sans advice into many
633 ;;      other deletion functions.
634 ;;-----------------------------------------------------------------------------
635
636 (vhl/define-extension 'delete 'delete-region)
637 (vhl/install-extension 'delete)
638
639
640 ;;-----------------------------------------------------------------------------
641 ;; Extension for supporting etags.
642 ;;   -- Put volatile highlights on the tag name which was found by `find-tag'.
643 ;;-----------------------------------------------------------------------------
644 (defun vhl/ext/etags/on ()
645   "Turn on volatile highlighting for `etags'."
646   (interactive)
647   (require 'etags)
648
649   (defadvice find-tag (after vhl/ext/etags/make-vhl-after-find-tag (tagname &optional next-p regexp-p))
650     (let ((pos (point))
651           (len (length tagname)))
652       (save-excursion
653         (search-forward tagname)
654         (vhl/add-range (- (point) len) (point)))))
655   (ad-activate 'find-tag))
656
657 (defun vhl/ext/etags/off ()
658   "Turn off volatile highlighting for `etags'."
659   (interactive)
660   (vhl/disable-advice-if-defined
661    'find-tag 'after 'vhl/ext/etags/make-vhl-after-find-tag))
662
663 (vhl/install-extension 'etags)
664
665
666 ;;-----------------------------------------------------------------------------
667 ;; Extension for supporting occur.
668 ;;   -- Put volatile highlights on occurrence which is selected by
669 ;;      `occur-mode-goto-occurrence' or `occur-mode-display-occurrence'.
670 ;;-----------------------------------------------------------------------------
671 (defun vhl/ext/occur/on ()
672   "Turn on volatile highlighting for `occur'."
673   (interactive)
674
675   (lexical-let ((*occur-str* nil)) ;; Text in current line.
676     (defun vhl/ext/occur/.pre-hook-fn ()
677       (save-excursion
678         (let* ((bol (progn (beginning-of-line) (point)))
679                (eol (progn (end-of-line) (point)))
680                (bos (text-property-any bol eol 'occur-match t)))
681           (setq *occur-str* (and bos eol
682                                  (buffer-substring bos eol))))))
683
684     (defun vhl/ext/occur/.post-hook-fn ()
685       (let ((marker (and *occur-str*
686                          (get-text-property 0 'occur-target *occur-str*)))
687             (len (length *occur-str*))
688             (ptr 0)
689             (be-lst nil))
690         (when marker
691           ;; Detect position of each occurrence by scanning face
692           ;; `list-matching-lines-face' put on them.
693           (while (and ptr
694                       (setq ptr (text-property-any ptr len
695                                                    'face
696                                                    list-matching-lines-face
697                                                    *occur-str*)))
698             (let ((beg ptr)
699                   (end (or (setq ptr
700                                  (next-single-property-change
701                                   ptr 'face *occur-str*))
702                            ;; Occurrence ends at eol.
703                            len)))
704               (push (list beg end)
705                     be-lst)))
706           ;; Put volatile highlights on occurrences.
707           (with-current-buffer (marker-buffer marker)
708             (let* ((bol (marker-position marker)))
709               (dolist (be be-lst)
710                 (let ((pt-beg (+ bol (nth 0 be)))
711                       (pt-end (+ bol (nth 1 be))))
712                   ;; When the occurrence is in folded line,
713                   ;; put highlight over whole line which
714                   ;; contains folded part.
715                   (dolist (ov (overlays-at pt-beg))
716                     (when (overlay-get ov 'invisible)
717                       ;;(message "INVISIBLE: %s" ov)
718                       (save-excursion
719                         (goto-char (overlay-start ov))
720                         (beginning-of-line)
721                         (setq pt-beg (min pt-beg (point)))
722                         (goto-char (overlay-end ov))
723                         (end-of-line)
724                         (setq pt-end (max pt-end (point))))))
725
726                   (vhl/add-range pt-beg
727                                  pt-end
728                                  nil
729                                  list-matching-lines-face))))))))
730
731
732     (defadvice occur-mode-goto-occurrence (before vhl/ext/occur/pre-hook (&optional event))
733       (vhl/ext/occur/.pre-hook-fn))
734     (defadvice occur-mode-goto-occurrence (after vhl/ext/occur/post-hook (&optional event))
735       (vhl/ext/occur/.post-hook-fn))
736
737     (defadvice occur-mode-display-occurrence (before vhl/ext/occur/pre-hook ())
738       (vhl/ext/occur/.pre-hook-fn))
739     (defadvice occur-mode-display-occurrence (after vhl/ext/occur/post-hook ())
740       (vhl/ext/occur/.post-hook-fn))
741
742     (defadvice occur-mode-goto-occurrence-other-window (before vhl/ext/occur/pre-hook ())
743       (vhl/ext/occur/.pre-hook-fn))
744     (defadvice occur-mode-goto-occurrence-other-window (after vhl/ext/occur/post-hook ())
745       (vhl/ext/occur/.post-hook-fn))
746
747     (ad-activate 'occur-mode-goto-occurrence)
748     (ad-activate 'occur-mode-display-occurrence)
749     (ad-activate 'occur-mode-goto-occurrence-other-window)))
750
751 (defun vhl/ext/occur/off ()
752   "Turn off volatile highlighting for `occur'."
753   (interactive)
754
755   (vhl/disable-advice-if-defined
756    'occur-mode-goto-occurrence 'before 'vhl/ext/occur/pre-hook)
757   (vhl/disable-advice-if-defined
758    'occur-mode-goto-occurrence 'after 'vhl/ext/occur/post-hook)
759
760   (vhl/disable-advice-if-defined
761    'occur-mode-display-occurrence 'before 'vhl/ext/occur/pre-hook)
762   (vhl/disable-advice-if-defined
763    'occur-mode-display-occurrence 'after 'vhl/ext/occur/post-hook)
764
765   (vhl/disable-advice-if-defined
766    'occur-mode-goto-occurrence-other-window 'before 'vhl/ext/occur/pre-hook)
767   (vhl/disable-advice-if-defined
768    'occur-mode-goto-occurrence-other-window 'after 'vhl/ext/occur/post-hook))
769
770 (vhl/install-extension 'occur)
771
772
773 ;;-----------------------------------------------------------------------------
774 ;; Extension for non-incremental search operations.
775 ;;   -- Put volatile highlights on the text found by non-incremental search
776 ;;      operations.
777 ;;-----------------------------------------------------------------------------
778
779 (defmacro vhl/ext/nonincremental-search/.advice-to-vhl (fn)
780   `(when (fboundp (quote ,fn))
781       (defadvice ,fn (after
782                       ,(intern (format "vhl/ext/nonincremental-search/%s"
783                                        fn))
784                       (&rest args))
785         (when ad-return-value
786           (vhl/add-range (match-beginning 0) (match-end 0) nil 'match)))
787       (ad-activate (quote ,fn))))
788
789 (defmacro vhl/ext/nonincremental-search/.disable-advice-to-vhl (fn)
790   `(vhl/disable-advice-if-defined
791     (quote ,fn)
792     'after
793     (quote ,(intern (format "vhl/ext/nonincremental-search/%s" fn)))))
794
795 (defun vhl/ext/nonincremental-search/on ()
796   "Turn on volatile highlighting for non-incremental search operations."
797   (interactive)
798   (when (vhl/require-noerror 'menu-bar nil)
799     (vhl/ext/nonincremental-search/.advice-to-vhl nonincremental-search-forward)
800     (vhl/ext/nonincremental-search/.advice-to-vhl nonincremental-search-backward)
801     (vhl/ext/nonincremental-search/.advice-to-vhl nonincremental-re-search-forward)
802     (vhl/ext/nonincremental-search/.advice-to-vhl nonincremental-re-search-backward)
803     (vhl/ext/nonincremental-search/.advice-to-vhl nonincremental-repeat-search-forward)
804     (vhl/ext/nonincremental-search/.advice-to-vhl nonincremental-repeat-search-backward)))
805
806 (defun vhl/ext/nonincremental-search/off ()
807   "Turn off volatile highlighting for  non-incremental search operations."
808   (interactive)
809   (when (vhl/require-noerror 'menu-bar nil)
810     (vhl/ext/nonincremental-search/.disable-advice-to-vhl nonincremental-search-forward)
811     (vhl/ext/nonincremental-search/.disable-advice-to-vhl nonincremental-search-backward)
812     (vhl/ext/nonincremental-search/.disable-advice-to-vhl nonincremental-re-search-forward)
813     (vhl/ext/nonincremental-search/.disable-advice-to-vhl nonincremental-re-search-backward)
814     (vhl/ext/nonincremental-search/.disable-advice-to-vhl nonincremental-repeat-search-forward)
815     (vhl/ext/nonincremental-search/.disable-advice-to-vhl nonincremental-repeat-search-backward)))
816
817 (vhl/install-extension 'nonincremental-search)
818
819
820 ;;-----------------------------------------------------------------------------
821 ;; Extension for hideshow.
822 ;;   -- Put volatile highlights on the text blocks which are shown/hidden
823 ;;      by hideshow.
824 ;;-----------------------------------------------------------------------------
825
826 (defun vhl/ext/hideshow/.activate ()
827   (defadvice hs-show-block (around vhl/ext/hideshow/vhl/around-hook (&optional end))
828     (let* ((bol (save-excursion (progn (beginning-of-line) (point))))
829            (eol (save-excursion (progn (end-of-line) (point))))
830            (ov-folded (car (delq nil 
831                                  (mapcar #'(lambda (ov)
832                                              (and (overlay-get ov 'hs)
833                                                   ov))
834                                          (overlays-in bol (1+ eol))))))
835            (boov (and ov-folded (overlay-start ov-folded)))
836            (eoov (and ov-folded (overlay-end ov-folded))))
837     
838       ad-do-it
839     
840       (when (and boov eoov)
841         (vhl/add-range boov eoov))))
842   (ad-activate 'hs-show-block))
843
844 (defun vhl/ext/hideshow/on ()
845   "Turn on volatile highlighting for `hideshow'."
846   (interactive)
847   
848   (cond
849    ((featurep 'hideshow)
850     (vhl/ext/hideshow/.activate))
851    (t
852     (eval-after-load "hideshow" '(vhl/ext/hideshow/.activate)))))
853
854 (defun vhl/ext/hideshow/off ()
855   (vhl/disable-advice-if-defined 'hs-show-block
856                                  'after
857                                  'vhl/ext/hideshow/vhl/around-hook))
858
859 (vhl/install-extension 'hideshow)
860
861
862 ;;;============================================================================
863 ;;;
864 ;;;  Suppress compiler warnings regarding to emacs/xemacs private functions.
865 ;;;
866 ;;;============================================================================
867
868 ;; Local variables:
869 ;; byte-compile-warnings: (not unresolved)
870 ;; End:
871
872 ;;; volatile-highlights.el ends here