Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
213 lines (190 sloc) 8.05 KB
;;; highlight-symbol.el --- automatic and manual symbol highlighting
;; Copyright (C) 2007 Nikolaj Schumacher <bugs * nschum , de>
;;; License ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License
;; as published by the Free Software Foundation; either version 2
;; of the License, or (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <>.
;;; Configuration ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Add the following to your .emacs file:
;; (require 'highlight-symbol)
;; (global-set-key [(control f3)] 'highlight-symbol-at-point)
;; (global-set-key [f3] 'highlight-symbol-next)
;; (global-set-key [(shift f3)] 'highlight-symbol-prev)
;; (global-set-key [(meta f3)] 'highlight-symbol-prev)))
;;; Usage ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Use `highlight-symbol-at-point' to toggle highlighting of the symbol at
;; point throughout the current buffer. Use `highlight-symbol-mode' to keep the
;; symbol at point highlighted.
;; The functions `highlight-symbol-next', `highlight-symbol-prev',
;; `highlight-symbol-next-in-defun' and `highlight-symbol-prev-in-defun' allow
;; for cycling through the locations of any symbol at point.
;;; Changes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 2007-04-20 (0.9.1)
;; Fixed bug in `highlight-symbol-jump'. (thanks to Per Nordlöw)
;; 2007-04-06 (0.9)
;; Initial release.
;;; Customizable Variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defgroup highlight-symbol nil
"Automatic and manual symbols highlighting"
:group 'convenience)
(defface highlight-symbol-face
'((((class color) (background dark))
(:background "gray30"))
(((class color) (background light))
(:background "gray90")))
"*Face used by `highlight-symbol-mode'."
:group 'highlight-symbol)
(defcustom highlight-symbol-idle-delay 1.5
"*Number of seconds of idle time before highlighting the current symbol.
If this variable is set to 0, no idle time is required.
Changing this does not take effect until `highlight-symbol-mode' has been
disabled for all buffers."
:type 'number
:group 'highlight-symbol)
(defvar highlight-symbol-faces '('hi-yellow 'hi-pink 'hi-green 'hi-blue)
"The faces that, in this order, will be used for `highlight-symbol-at-point'.
This list will be rotated after each call to `highlight-symbol-at-point', so
that the first element will go to the end.")
;;; Interactive Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-minor-mode highlight-symbol-mode
"Minor mode that highlights the symbol under point throughout the buffer.
Highlighting takes place after `highlight-symbol-idle-delay'."
nil " hl-s" nil
(require 'thingatpt)
(require 'hi-lock)
(if highlight-symbol-mode
;; on
(add-to-list 'highlight-symbol-instances (current-buffer))
(unless highlight-symbol-timer
(setq highlight-symbol-timer
(when (and highlight-symbol-idle-delay
(/= highlight-symbol-idle-delay 0))
(run-with-idle-timer highlight-symbol-idle-delay t
(add-hook 'post-command-hook 'highlight-symbol-mode-post-command nil t))
;; off
(remove-hook 'post-command-hook 'highlight-symbol-mode-post-command t)
(setq highlight-symbol-instances
(delete (current-buffer) highlight-symbol-instances))
(unless (or highlight-symbol-instances
(null highlight-symbol-timer))
(cancel-timer highlight-symbol-timer)
(setq highlight-symbol-timer nil))
(kill-local-variable 'highlight-symbol)))
(defun highlight-symbol-at-point ()
"Toggle highlighting of the symbol at point.
This highlights or unhighlights the symbol at point using the first
element in of `highlight-symbol-faces'."
(let ((symbol (highlight-symbol-get-symbol)))
(if (member symbol highlight-symbol-list)
;; remove
(setq highlight-symbol-list (delete symbol highlight-symbol-list))
(hi-lock-unface-buffer symbol))
;; add
(when (equal symbol highlight-symbol)
(let ((face (pop highlight-symbol-faces)))
;; rotate faces
(setq highlight-symbol-faces
(nconc highlight-symbol-faces `(,face)))
;; highlight
(hi-lock-set-pattern symbol face)
(push symbol highlight-symbol-list)))))
(defun highlight-symbol-next ()
"Jump to the next location of the symbol at point within the function."
(highlight-symbol-jump 1))
(defun highlight-symbol-prev ()
"Jump to the previous location of the symbol at point within the function."
(highlight-symbol-jump -1))
(defun highlight-symbol-next-in-defun ()
"Jump to the next location of the symbol at point within the defun."
(highlight-symbol-jump 1)))
(defun highlight-symbol-prev-in-defun ()
"Jump to the previous location of the symbol at point within the defun."
(highlight-symbol-jump -11)))
;;; Internal ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar highlight-symbol-timer nil)
(defvar highlight-symbol-instances nil)
(defvar highlight-symbol nil)
(make-variable-buffer-local 'highlight-symbol)
(defvar highlight-symbol-list nil)
(make-variable-buffer-local 'highlight-symbol-list)
(defun highlight-symbol-get-symbol ()
"Return a regular expression dandifying the symbol at point."
(let ((symbol (thing-at-point 'symbol)))
(when symbol (concat "\\_<" (regexp-quote symbol) "\\_>"))))
(defun highlight-symbol-temp-highlight ()
"Highlight the current symbol until a command is executed."
(when highlight-symbol-mode
(let ((symbol (highlight-symbol-get-symbol)))
(unless (or (equal symbol highlight-symbol)
(member symbol highlight-symbol-list))
(setq highlight-symbol symbol)
(hi-lock-set-pattern symbol 'highlight-symbol-face)))))
(defun highlight-symbol-mode-remove-temp ()
"Remove the temporary symbol highlighting."
(when highlight-symbol
(hi-lock-unface-buffer highlight-symbol)
(setq highlight-symbol nil)))
(defun highlight-symbol-mode-post-command ()
"After a command, change the temporary highlighting.
Remove the temporary symbol highlighting and, unless a timeout is specified,
create the new one."
(unless (eq this-command 'highlight-symbol-jump-to-next)
(if highlight-symbol-timer
(defun highlight-symbol-jump (dir)
"Jump to the next or previous occurence of the symbol at point.
DIR has to be 1 or -1."
(let ((symbol (highlight-symbol-get-symbol)))
(if symbol
(let* ((case-fold-search nil)
(bounds (bounds-of-thing-at-point 'symbol))
(offset (- (point) (if (< 0 dir) (cdr bounds) (car bounds)))))
;; move a little, so we don't find the same instance again
(goto-char (- (point) offset))
(let ((target (re-search-forward symbol nil t dir)))
(unless target
(goto-char (if (< 0 dir) (point-min) (point-max)))
(setq target (re-search-forward symbol nil nil dir)))
(goto-char (+ target offset))))
(message "No symbol at point"))))
(provide 'highlight-symbol)
Jump to Line
Something went wrong with that request. Please try again.