]> git.bundesbrandschatzamt.de Git - emacsconfig.git/commitdiff
add symbol-overlay
authorAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Thu, 11 May 2023 16:24:56 +0000 (18:24 +0200)
committerAndreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
Thu, 11 May 2023 16:24:56 +0000 (18:24 +0200)
Signed-off-by: Andreas Gerler <baronNOSPAMbundesbrandschatzamt.de>
elpa/symbol-overlay-20230503.1051/symbol-overlay-autoloads.el [new file with mode: 0644]
elpa/symbol-overlay-20230503.1051/symbol-overlay-pkg.el [new file with mode: 0644]
elpa/symbol-overlay-20230503.1051/symbol-overlay.el [new file with mode: 0644]

diff --git a/elpa/symbol-overlay-20230503.1051/symbol-overlay-autoloads.el b/elpa/symbol-overlay-20230503.1051/symbol-overlay-autoloads.el
new file mode 100644 (file)
index 0000000..a332d98
--- /dev/null
@@ -0,0 +1,95 @@
+;;; symbol-overlay-autoloads.el --- automatically extracted autoloads  -*- lexical-binding: t -*-
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+                         (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "symbol-overlay" "symbol-overlay.el" (0 0 0
+;;;;;;  0))
+;;; Generated autoloads from symbol-overlay.el
+
+(autoload 'symbol-overlay-mode "symbol-overlay" "\
+Minor mode for auto-highlighting symbol at point.
+
+This is a minor mode.  If called interactively, toggle the
+`Symbol-Overlay mode' mode.  If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is `toggle'.  Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate `symbol-overlay-mode'.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'symbol-overlay-put "symbol-overlay" "\
+Toggle all overlays of symbol at point." t nil)
+
+(autoload 'symbol-overlay-count "symbol-overlay" "\
+Show count of symbol at point." t nil)
+
+(autoload 'symbol-overlay-remove-all "symbol-overlay" "\
+Remove all highlighted symbols in the buffer.
+When called interactively, then also reset
+`symbol-overlay-keywords-alist'." t nil)
+
+(autoload 'symbol-overlay-save-symbol "symbol-overlay" "\
+Copy symbol at point." t nil)
+
+(autoload 'symbol-overlay-toggle-in-scope "symbol-overlay" "\
+Toggle overlays to be showed in buffer or only in scope." t nil)
+
+(autoload 'symbol-overlay-echo-mark "symbol-overlay" "\
+Jump back to the mark." t nil)
+
+(autoload 'symbol-overlay-jump-next "symbol-overlay" "\
+Jump to the next location of symbol at point." t nil)
+
+(autoload 'symbol-overlay-jump-prev "symbol-overlay" "\
+Jump to the previous location of symbol at point." t nil)
+
+(autoload 'symbol-overlay-jump-first "symbol-overlay" "\
+Jump to the first location." t nil)
+
+(autoload 'symbol-overlay-jump-last "symbol-overlay" "\
+Jump to the last location." t nil)
+
+(autoload 'symbol-overlay-jump-to-definition "symbol-overlay" "\
+Jump to the definition of symbol at point.
+The definition syntax should be defined in a function stored in
+`symbol-overlay-definition-function' that returns the definition's regexp
+with the input symbol." t nil)
+
+(autoload 'symbol-overlay-switch-forward "symbol-overlay" "\
+Switch forward to another symbol." t nil)
+
+(autoload 'symbol-overlay-switch-backward "symbol-overlay" "\
+Switch backward to another symbol." t nil)
+
+(autoload 'symbol-overlay-isearch-literally "symbol-overlay" "\
+Isearch symbol at point literally." t nil)
+
+(autoload 'symbol-overlay-query-replace "symbol-overlay" "\
+Query replace symbol at point." t nil)
+
+(autoload 'symbol-overlay-rename "symbol-overlay" "\
+Rename symbol at point on all its occurrences." t nil)
+
+(register-definition-prefixes "symbol-overlay" '("symbol-overlay-"))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; symbol-overlay-autoloads.el ends here
diff --git a/elpa/symbol-overlay-20230503.1051/symbol-overlay-pkg.el b/elpa/symbol-overlay-20230503.1051/symbol-overlay-pkg.el
new file mode 100644 (file)
index 0000000..6701eef
--- /dev/null
@@ -0,0 +1,2 @@
+;;; Generated package description from symbol-overlay.el  -*- no-byte-compile: t -*-
+(define-package "symbol-overlay" "20230503.1051" "Highlight symbols with keymap-enabled overlays" '((emacs "24.3") (seq "2.2")) :commit "72ff963a0f44497b6cc688607357ee65c68ecc84" :authors '(("wolray" . "wolrayNOSPAMfoxmail.com")) :maintainers '(("wolray" . "wolrayNOSPAMfoxmail.com")) :maintainer '("wolray" . "wolrayNOSPAMfoxmail.com") :keywords '("faces" "matching") :url "https://github.com/wolray/symbol-overlay/")
diff --git a/elpa/symbol-overlay-20230503.1051/symbol-overlay.el b/elpa/symbol-overlay-20230503.1051/symbol-overlay.el
new file mode 100644 (file)
index 0000000..dc360a7
--- /dev/null
@@ -0,0 +1,814 @@
+;;; symbol-overlay.el --- Highlight symbols with keymap-enabled overlays -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017 wolray
+
+;; Author: wolray <wolrayNOSPAMfoxmail.com>
+;; Version: 4.1
+;; Package-Version: 20230503.1051
+;; Package-Commit: 72ff963a0f44497b6cc688607357ee65c68ecc84
+;; URL: https://github.com/wolray/symbol-overlay/
+;; Keywords: faces, matching
+;; Package-Requires: ((emacs "24.3") (seq "2.2"))
+
+;; 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 3 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
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; 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 <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Highlighting symbols with overlays while providing a keymap for various
+;; operations about highlighted symbols.  It was originally inspired by the
+;; package `highlight-symbol'.  The fundamental difference is that in
+;; `symbol-overlay' every symbol is highlighted by the Emacs built-in function
+;; `overlay-put' rather than the `font-lock' mechanism used in
+;; `highlight-symbol'.
+
+;; Advantages
+
+;; When highlighting symbols in a buffer of regular size and language,
+;; `overlay-put' behaves as fast as the traditional highlighting method
+;; `font-lock'.  However, for a buffer of major-mode with complicated keywords
+;; syntax, like haskell-mode, `font-lock' is quite slow even the buffer is less
+;; than 100 lines.  Besides, when counting the number of highlighted
+;; occurrences, `highlight-symbol' will call the function `how-many' twice,
+;; which could also result in an unpleasant delay in a large buffer.  Those
+;; problems don't exist in `symbol-overlay'.
+
+;; When putting overlays on symbols, an auto-activated overlay-inside keymap
+;; will enable you to call various useful commands with a single keystroke.
+
+;; Toggle all overlays of symbol at point: `symbol-overlay-put'
+;; Jump between locations of symbol at point: `symbol-overlay-jump-next' &
+;; `symbol-overlay-jump-prev'
+;; Switch to the closest symbol highlighted nearby:
+;; `symbol-overlay-switch-forward' & `symbol-overlay-switch-backward'
+;; Minor mode for auto-highlighting symbol at point: `symbol-overlay-mode'
+;; Remove all highlighted symbols in the buffer: `symbol-overlay-remove-all'
+;; Copy symbol at point: `symbol-overlay-save-symbol'
+;; Toggle overlays to be showed in buffer or only in scope:
+;; `symbol-overlay-toggle-in-scope'
+;; Jump back to the position before a recent jump: `symbol-overlay-echo-mark'
+;; Jump to the definition of symbol at point: `symbol-overlay-jump-to-definition'
+;; Isearch symbol at point literally:
+;; `symbol-overlay-isearch-literally'
+;; Query replace symbol at point: `symbol-overlay-query-replace'
+;; Rename symbol at point on all its occurrences: `symbol-overlay-rename'
+
+;; Usage
+
+;; To use `symbol-overlay' in your Emacs, you need only to bind these keys:
+;; (require 'symbol-overlay)
+;; (global-set-key (kbd "M-i") 'symbol-overlay-put)
+;; (global-set-key (kbd "M-n") 'symbol-overlay-switch-forward)
+;; (global-set-key (kbd "M-p") 'symbol-overlay-switch-backward)
+;; (global-set-key (kbd "<f7>") 'symbol-overlay-mode)
+;; (global-set-key (kbd "<f8>") 'symbol-overlay-remove-all)
+
+;; Default key-bindings are defined in `symbol-overlay-map'.
+;; You can re-bind the commands to any keys you prefer by simply writing
+;; (define-key symbol-overlay-map (kbd "your-prefer-key") 'any-command)
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'thingatpt)
+(require 'seq)
+
+(defgroup symbol-overlay nil
+  "Highlight symbols with keymap-enabled overlays."
+  :group 'convenience)
+
+;;; Faces
+
+(defface symbol-overlay-default-face
+  '((t (:inherit highlight)))
+  "Symbol Overlay default face"
+  :group 'symbol-overlay)
+
+(defface symbol-overlay-face-1
+  '((t (:background "dodger blue" :foreground "black")))
+  "Symbol Overlay default candidate 1"
+  :group 'symbol-overlay)
+
+(defface symbol-overlay-face-2
+  '((t (:background "hot pink" :foreground "black")))
+  "Symbol Overlay default candidate 2"
+  :group 'symbol-overlay)
+
+(defface symbol-overlay-face-3
+  '((t (:background "yellow" :foreground "black")))
+  "Symbol Overlay default candidate 3"
+  :group 'symbol-overlay)
+
+(defface symbol-overlay-face-4
+  '((t (:background "orchid" :foreground "black")))
+  "Symbol Overlay default candidate 4"
+  :group 'symbol-overlay)
+
+(defface symbol-overlay-face-5
+  '((t (:background "red" :foreground "black")))
+  "Symbol Overlay default candidate 5"
+  :group 'symbol-overlay)
+
+(defface symbol-overlay-face-6
+  '((t (:background "salmon" :foreground "black")))
+  "Symbol Overlay default candidate 6"
+  :group 'symbol-overlay)
+
+(defface symbol-overlay-face-7
+  '((t (:background "spring green" :foreground "black")))
+  "Symbol Overlay default candidate 7"
+  :group 'symbol-overlay)
+
+(defface symbol-overlay-face-8
+  '((t (:background "turquoise" :foreground "black")))
+  "Symbol Overlay default candidate 8"
+  :group 'symbol-overlay)
+
+;;; Options
+
+(defcustom symbol-overlay-faces '(symbol-overlay-face-1
+                                  symbol-overlay-face-2
+                                  symbol-overlay-face-3
+                                  symbol-overlay-face-4
+                                  symbol-overlay-face-5
+                                  symbol-overlay-face-6
+                                  symbol-overlay-face-7
+                                  symbol-overlay-face-8)
+  "Faces used for overlays."
+  :type '(repeat face)
+  :group 'symbol-overlay)
+
+(defcustom symbol-overlay-displayed-window t
+  "See `symbol-overlay-maybe-put-temp'."
+  :group 'symbol-overlay
+  :type 'boolean)
+
+(defcustom symbol-overlay-idle-time 0.5
+  "Idle time after every command and before the temporary highlighting."
+  :group 'symbol-overlay
+  :type 'float)
+
+(defcustom symbol-overlay-overlay-created-functions '()
+  "Functions called after overlay creation that may modify the overlay."
+  :group 'symbol-overlay
+  :type 'hook)
+
+(defcustom symbol-overlay-ignore-functions
+  '((c-mode . symbol-overlay-ignore-function-c)
+    (c++-mode . symbol-overlay-ignore-function-c++)
+    (python-mode . symbol-overlay-ignore-function-python)
+    (java-mode . symbol-overlay-ignore-function-java)
+    (go-mode . symbol-overlay-ignore-function-go))
+  "Functions to determine whether a symbol should be ignored.
+
+This is an association list that maps a MAJOR-MODE symbol to a
+function that determines whether a symbol should be ignored.
+For instance, such a function could use a major mode's font-lock
+definitions to prevent a language's keywords from getting highlighted."
+  :group 'symbol-overlay
+  :type '(repeat (cons (function :tag "Mode") function)))
+
+;;; Internal
+
+(defvar symbol-overlay-inhibit-map nil
+  "When non-nil, don't use `symbol-overlay-map'.
+This is intended for buffers/modes that use the keymap text
+property for their own purposes.  Because this package uses
+overlays it would always override the text property keymaps
+of such packages.")
+(put 'symbol-overlay-inhibit-map 'safe-local-variable 'booleanp)
+
+(defvar symbol-overlay-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "i") #'symbol-overlay-put)
+    (define-key map (kbd "h") #'symbol-overlay-map-help)
+    (define-key map (kbd "p") #'symbol-overlay-jump-prev)
+    (define-key map (kbd "n") #'symbol-overlay-jump-next)
+    (define-key map (kbd "<") #'symbol-overlay-jump-first)
+    (define-key map (kbd ">") #'symbol-overlay-jump-last)
+    (define-key map (kbd "w") #'symbol-overlay-save-symbol)
+    (define-key map (kbd "t") #'symbol-overlay-toggle-in-scope)
+    (define-key map (kbd "e") #'symbol-overlay-echo-mark)
+    (define-key map (kbd "d") #'symbol-overlay-jump-to-definition)
+    (define-key map (kbd "s") #'symbol-overlay-isearch-literally)
+    (define-key map (kbd "q") #'symbol-overlay-query-replace)
+    (define-key map (kbd "r") #'symbol-overlay-rename)
+    map)
+  "Keymap automatically activated inside overlays.
+You can re-bind the commands to any keys you prefer.")
+
+(defvar-local symbol-overlay-keywords-alist nil)
+(put 'symbol-overlay-keywords-alist 'permanent-local t)
+
+(defun symbol-overlay-map-help ()
+  "Display the bindings in `symbol-overlay-map'."
+  (interactive)
+  (let ((buf (get-buffer-create "*Help*")))
+    (with-help-window "*Help*"
+      (with-current-buffer buf
+        (insert (substitute-command-keys "\\{symbol-overlay-map}"))))))
+
+(defvar symbol-overlay-mode-map (make-sparse-keymap)
+  "Keymap for `symbol-overlay-mode'.")
+
+;;;###autoload
+(define-minor-mode symbol-overlay-mode
+  "Minor mode for auto-highlighting symbol at point."
+  :lighter " SO"
+  :keymap symbol-overlay-mode-map
+  (if symbol-overlay-mode
+      (progn
+        (add-hook 'post-command-hook #'symbol-overlay-post-command nil t)
+        (symbol-overlay-update-timer symbol-overlay-idle-time))
+    (remove-hook 'post-command-hook #'symbol-overlay-post-command t)
+    (symbol-overlay-remove-temp)))
+
+(defun symbol-overlay-get-list (dir &optional symbol exclude)
+  "Get all highlighted overlays in the buffer.
+If SYMBOL is non-nil, get the overlays that belong to it.
+DIR is an integer.
+If EXCLUDE is non-nil, get all overlays excluding those belong to SYMBOL."
+  (let ((overlays (cond ((= dir 0) (overlays-in (point-min) (point-max)))
+                        ((< dir 0) (overlays-in (point-min) (point)))
+                        ((> dir 0) (overlays-in
+                                    (if (looking-at-p "\\_>") (1- (point)) (point))
+                                    (point-max))))))
+    (seq-filter
+     (lambda (ov)
+       (let ((value (overlay-get ov 'symbol))
+             (end (overlay-end ov)))
+         (and value
+              (or (>= dir 0) (< end (point)))
+              (or (not symbol)
+                  (if (string= value symbol) (not exclude)
+                    (and exclude (not (string= value ""))))))))
+     overlays)))
+
+(defun symbol-overlay-get-symbol (&optional noerror)
+  "Get the symbol at point.
+If NOERROR is non-nil, just return nil when no symbol is found."
+  (or (thing-at-point 'symbol)
+      (unless noerror (user-error "No symbol at point"))))
+
+(defun symbol-overlay-regexp (symbol)
+  "Return a regexp to match SYMBOL."
+  (concat "\\_<" (regexp-quote symbol) "\\_>"))
+
+(defun symbol-overlay-assoc (symbol)
+  "Get SYMBOL's associated list in `symbol-overlay-keywords-alist'."
+  (assoc symbol symbol-overlay-keywords-alist))
+
+(defun symbol-overlay-maybe-remove (keyword)
+  "Delete the KEYWORD list and all its overlays."
+  (when keyword
+    (mapc 'delete-overlay (symbol-overlay-get-list 0 (car keyword)))
+    (setq symbol-overlay-keywords-alist
+          (delq keyword symbol-overlay-keywords-alist))
+    (cddr keyword)))
+
+(defvar-local symbol-overlay-temp-symbol nil
+  "Symbol for temporary highlighting.")
+
+(defvar-local symbol-overlay-scope nil
+  "If non-nil, force to narrow to scope before temporary highlighting.")
+
+(defun symbol-overlay-narrow (scope &optional window)
+  "Narrow to a specific region.
+Region might be current scope or displayed window,
+depending on SCOPE and WINDOW."
+  (if scope
+      (let ((pt (point))
+            min max p)
+        (save-excursion
+          (save-restriction
+            (narrow-to-defun)
+            (setq min (point-min)
+                  max (point-max)
+                  p (or (/= pt (point)) (= pt (point-max))))))
+        (save-excursion
+          (and p (setq min (progn (backward-paragraph) (point))
+                       max (progn (forward-paragraph) (point))))
+          (narrow-to-region min max)))
+    (when (and window (eq (window-buffer) (current-buffer)))
+      (narrow-to-region (window-start) (window-end)))))
+
+(defun symbol-overlay-remove-temp ()
+  "Delete all temporary overlays."
+  (mapc 'delete-overlay (symbol-overlay-get-list 0 ""))
+  (setq symbol-overlay-temp-symbol nil))
+
+(defun symbol-overlay-maybe-put-temp ()
+  "Highlight symbol at point when there are more than 2 occurrences.
+This only affects symbols in the current displayed window if
+`symbol-overlay-displayed-window' is non-nil."
+  (when symbol-overlay-mode
+    (let* ((case-fold-search nil)
+           (symbol (symbol-overlay-get-symbol t))
+           p)
+      (when (and symbol
+                 (not (symbol-overlay-assoc symbol))
+                 (not (symbol-overlay-ignored-p symbol)))
+        (symbol-overlay-remove-temp)
+        (save-excursion
+          (save-restriction
+            (symbol-overlay-narrow symbol-overlay-scope
+                                   symbol-overlay-displayed-window)
+            (goto-char (point-min))
+            (let ((re (symbol-overlay-regexp symbol)))
+              (re-search-forward re nil t)
+              (save-match-data
+                (while (re-search-forward re nil t)
+                  (symbol-overlay-put-one symbol)
+                  (or p (setq p t))))
+              (when p
+                (symbol-overlay-put-one symbol)
+                (setq symbol-overlay-temp-symbol symbol)))))))))
+
+(defun symbol-overlay-ignored-p (symbol)
+  "Determine whether SYMBOL should be temporarily highlighted."
+  (let ((f (cdr (assoc major-mode symbol-overlay-ignore-functions))))
+    (when f
+      (funcall f symbol))))
+
+(defvar symbol-overlay-timer nil
+  "Timer for temporary highlighting.")
+
+(defun symbol-overlay-cancel-timer ()
+  "Cancel `symbol-overlay-timer' if it is running."
+  (when symbol-overlay-timer
+    (cancel-timer symbol-overlay-timer)))
+
+(defun symbol-overlay-idle-timer ()
+  "Idle timer callback.
+This is used to maybe highlight the symbol at point in whichever
+buffer happens to be current when the timer is fired."
+  (symbol-overlay-maybe-put-temp))
+
+(defun symbol-overlay-update-timer (value)
+  "Update `symbol-overlay-timer' with new idle-time VALUE."
+  (symbol-overlay-cancel-timer)
+  (setq symbol-overlay-timer
+        (and value (> value 0)
+             (run-with-idle-timer value t #'symbol-overlay-idle-timer))))
+
+(defun symbol-overlay-post-command ()
+  "Installed on `post-command-hook'."
+  (unless (or (null symbol-overlay-temp-symbol)
+              (string= (symbol-overlay-get-symbol t) symbol-overlay-temp-symbol))
+    (symbol-overlay-remove-temp)))
+
+(defun symbol-overlay-put-one (symbol &optional face)
+  "Put overlay on current occurrence of SYMBOL after a match.
+If FACE is non-nil, use it as the overlay’s face.
+Otherwise apply `symbol-overlay-default-face'."
+  (let ((ov (make-overlay (match-beginning 0) (match-end 0))))
+    (if face (progn (overlay-put ov 'face face)
+                    (unless symbol-overlay-inhibit-map
+                      (overlay-put ov 'keymap symbol-overlay-map))
+                    (overlay-put ov 'evaporate t)
+                    (overlay-put ov 'symbol symbol))
+      (overlay-put ov 'face 'symbol-overlay-default-face)
+      (overlay-put ov 'symbol ""))
+    (dolist (fun symbol-overlay-overlay-created-functions)
+      (funcall fun ov))))
+
+(defun symbol-overlay-put-all (symbol scope &optional keyword)
+  "Put overlays on all occurrences of SYMBOL in the buffer.
+The face is picked from `symbol-overlay-faces'.
+If SCOPE is non-nil, put overlays only on occurrences in scope.
+If KEYWORD is non-nil, remove it then use its color on new overlays."
+  (when symbol-overlay-temp-symbol
+    (symbol-overlay-remove-temp))
+  (let* ((case-fold-search nil)
+         (face (or (car (cl-set-difference
+                         symbol-overlay-faces
+                         (mapcar #'cddr symbol-overlay-keywords-alist)))
+                   ;; If we have exhausted the available faces, then just
+                   ;; keep using the last face for all subsequent symbols.
+                   (car (last symbol-overlay-faces)))))
+    (save-excursion
+      (save-restriction
+        (symbol-overlay-narrow scope)
+        (goto-char (point-min))
+        (let ((re (symbol-overlay-regexp symbol)))
+          (while (re-search-forward re nil t)
+            (symbol-overlay-put-one symbol face)))))
+    (setq keyword `(,symbol ,scope . ,face))
+    (push keyword symbol-overlay-keywords-alist)
+    keyword))
+
+(defun symbol-overlay-maybe-count (keyword &optional show-color)
+  "Show the number of KEYWORD's occurrences.
+If SHOW-COLOR is non-nil, display the color used by current overlay."
+  (when keyword
+    (let* ((symbol (car keyword))
+           (before (symbol-overlay-get-list -1 symbol))
+           (after (symbol-overlay-get-list 1 symbol))
+           (count (length before))
+           ;; Log to echo area but not *Messages*
+           message-log-max)
+      (message (concat "%s: %d/%d"
+                       (and (cadr keyword) " in scope")
+                       (and show-color (format " (%s)" (cddr keyword))))
+               symbol
+               (+ count 1)
+               (+ count (length after))))))
+
+(defun symbol-overlay-match-keyword-list (symbol keywords)
+  "Return non-nil is SYMBOL is among KEYWORDS.
+KEYWORDS is a list of strings.  SYMBOL is expected to be a return
+value of `symbol-overlay-get-symbol'."
+  (cl-find symbol keywords :test #'string=))
+
+(defun symbol-overlay-refresh (beg end _len)
+  "Refresh overlays.  Installed on `after-change-functions'.
+BEG, END and LEN are the beginning, end and length of changed text."
+  (unless (or (minibufferp)
+              (not (or symbol-overlay-keywords-alist
+                       symbol-overlay-temp-symbol)))
+    (let ((case-fold-search nil)
+          (re "\\(\\sw\\|\\s_\\)+"))
+      (save-excursion
+        (save-match-data
+          (goto-char end)
+          (and (looking-at-p re)
+               (setq end (re-search-forward "\\_>")))
+          (goto-char beg)
+          (and (not (looking-at-p "\\_<"))
+               (looking-at-p (concat "\\(" re "\\|\\_>\\)"))
+               (setq beg (re-search-backward "\\_<")))
+          (mapc (lambda (ov)
+                  (and (overlay-get ov 'symbol)
+                       (delete-overlay ov)))
+                (overlays-in beg end))
+          (mapc (lambda (keyword)
+                  (let* ((symbol (car keyword))
+                         (re (symbol-overlay-regexp symbol)))
+                    (goto-char beg)
+                    (while (re-search-forward re end t)
+                      (symbol-overlay-put-one symbol (cddr keyword)))))
+                symbol-overlay-keywords-alist))))))
+
+(add-hook 'after-change-functions #'symbol-overlay-refresh)
+
+(defun symbol-overlay-after-revert ()
+  "Restore overlays after the buffer was reverted."
+  (save-restriction
+    (widen)
+    (symbol-overlay-refresh (point-min) (point-max) nil)))
+
+(add-hook 'after-revert-hook #'symbol-overlay-after-revert)
+
+;;; Language-Specific Ignore
+
+(defvar c-font-lock-extra-types)
+(defun symbol-overlay-ignore-function-c (symbol)
+  "Determine whether SYMBOL should be ignored (C Language)."
+  (symbol-overlay-match-keyword-list
+   symbol
+   (append c-font-lock-extra-types
+           '("auto" "break" "case" "char" "const" "continue"
+             "default" "do" "double" "else" "enum" "extern"
+             "float" "for" "goto" "if" "inline" "int" "long"
+             "register" "restrict" "return" "short" "signed"
+             "sizeof" "static" "struct" "switch" "typedef"
+             "union" "unsigned" "void" "volatile" "while"))))
+
+(defvar c++-font-lock-extra-types)
+(defun symbol-overlay-ignore-function-c++ (symbol)
+  "Determine whether SYMBOL should be ignored (C++)."
+  (symbol-overlay-match-keyword-list
+   symbol
+   (append c++-font-lock-extra-types
+           '("alignas" "alignof" "asm" "auto" "bool" "break"
+             "case" "catch" "char" "char16_t" "char32_t" "class"
+             "const" "const_cast" "constexpr" "continue"
+             "decltype" "default" "delete" "do" "double"
+             "dynamic_cast" "else" "enum" "explicit" "export"
+             "extern" "false" "final" "float" "for" "friend"
+             "goto" "if" "inline" "int" "long" "mutable"
+             "namespace" "new" "noexcept" "nullptr" "operator"
+             "override" "private" "protected" "public" "register"
+             "reinterpret_cast" "return" "short" "signed"
+             "sizeof" "static" "static_assert" "static_cast"
+             "struct" "switch" "template" "this" "thread_local"
+             "throw" "true" "try" "typedef" "typeid" "typename"
+             "union" "unsigned" "using" "virtual" "void"
+             "volatile" "wchar_t" "while"))))
+
+(defvar python-font-lock-keywords)
+(defun symbol-overlay-ignore-function-python (symbol)
+  "Determine whether SYMBOL should be ignored (Python)."
+  (let* ((keyword-symbol (car python-font-lock-keywords))
+         (keyword (if (stringp keyword-symbol)
+                      keyword-symbol
+                    (symbol-name keyword-symbol))))
+    (string-match-p keyword symbol)))
+
+(defvar go-builtins)
+(defvar go-constants)
+(defvar go-mode-keywords)
+(defun symbol-overlay-ignore-function-go (symbol)
+  "Determine whether SYMBOL should be ignored (Go)."
+  ;; Remove \_< and \_> so we can string compare with keywords
+  (or (symbol-overlay-match-keyword-list symbol go-builtins)
+      (symbol-overlay-match-keyword-list symbol go-constants)
+      (symbol-overlay-match-keyword-list symbol go-mode-keywords)))
+
+;; From https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
+(defun symbol-overlay-ignore-function-java (symbol)
+  "Determine whether SYMBOL should be ignored (Java)."
+  (symbol-overlay-match-keyword-list
+   symbol
+   '("abstract" "continue" "for"         "new"       "switch"
+     "assert"   "default"  "goto"        "package"   "synchronized"
+     "boolean"  "do"       "if"          "private"   "this"
+     "break"    "double"   "implements"  "protected" "throw"
+     "byte"     "else"     "import"      "public"    "throws"
+     "case"     "enum"      "instanceof" "return"    "transient"
+     "catch"    "extends"   "int"        "short"     "try"
+     "char"     "final"     "interface"  "static"    "void"
+     "class"    "finally"   "long"       "strictfp"  "volatile"
+     "const*"   "float"     "native"     "super"     "while")))
+
+;;; Commands
+
+;;;###autoload
+(defun symbol-overlay-put ()
+  "Toggle all overlays of symbol at point."
+  (interactive)
+  (unless (minibufferp)
+    (let* ((symbol (symbol-overlay-get-symbol))
+           (keyword (symbol-overlay-assoc symbol)))
+      (symbol-overlay-adjust-position)
+      (if keyword
+          (if (symbol-overlay-maybe-reput symbol keyword)
+              (symbol-overlay-maybe-count keyword)
+            (symbol-overlay-maybe-remove keyword)
+            (symbol-overlay-maybe-put-temp))
+        (symbol-overlay-maybe-count
+         (symbol-overlay-put-all symbol symbol-overlay-scope)
+         t)))))
+
+(defun symbol-overlay-adjust-position ()
+  "Backward one char if at the end of the symbol."
+  (when (looking-at-p "\\_>") (backward-char)))
+
+;;;###autoload
+(defun symbol-overlay-count ()
+  "Show count of symbol at point."
+  (interactive)
+  (unless (minibufferp)
+    (let* ((symbol (symbol-overlay-get-symbol))
+           (keyword (symbol-overlay-assoc symbol)))
+      (symbol-overlay-adjust-position)
+      (symbol-overlay-maybe-count keyword))))
+
+;;;###autoload
+(defun symbol-overlay-remove-all ()
+  "Remove all highlighted symbols in the buffer.
+When called interactively, then also reset
+`symbol-overlay-keywords-alist'."
+  (interactive)
+  (unless (minibufferp)
+    (mapc 'delete-overlay (symbol-overlay-get-list 0))
+    (when (called-interactively-p 'any)
+      (setq symbol-overlay-keywords-alist nil))))
+
+(add-hook 'before-revert-hook #'symbol-overlay-remove-all)
+
+;;;###autoload
+(defun symbol-overlay-save-symbol ()
+  "Copy symbol at point."
+  (interactive)
+  (unless (minibufferp)
+    (let ((bounds (bounds-of-thing-at-point 'symbol)))
+      (kill-ring-save (car bounds) (cdr bounds))
+      (message "Current symbol saved"))))
+
+;;;###autoload
+(defun symbol-overlay-toggle-in-scope ()
+  "Toggle overlays to be showed in buffer or only in scope."
+  (interactive)
+  (unless (minibufferp)
+    (let* ((symbol (symbol-overlay-get-symbol))
+           (keyword (symbol-overlay-assoc symbol)))
+      (if keyword
+          (let ((scope (not (cadr keyword))))
+            (symbol-overlay-maybe-count
+             (symbol-overlay-put-all symbol scope keyword))
+            (setq symbol-overlay-scope scope))
+        (setq symbol-overlay-scope (not symbol-overlay-scope))))))
+
+(defun symbol-overlay-maybe-reput (symbol keyword)
+  "Put overlays on SYMBOL that is not highlighted in scope.
+KEYWORD provides the scope information."
+  (when (and (cadr keyword)
+             (not (seq-find #'(lambda (ov)
+                                (string= (overlay-get ov 'symbol) symbol))
+                            (overlays-at
+                             (car (bounds-of-thing-at-point 'symbol))))))
+    (symbol-overlay-put-all symbol t keyword)))
+
+;;;###autoload
+(defun symbol-overlay-echo-mark ()
+  "Jump back to the mark."
+  (interactive)
+  (let* ((pt (mark))
+         (symbol (symbol-overlay-get-symbol))
+         (keyword (symbol-overlay-assoc symbol)))
+    (and pt (goto-char pt))
+    (symbol-overlay-maybe-reput symbol keyword)))
+
+(defun symbol-overlay-jump-call (jump-function dir)
+  "A general jumping process during which JUMP-FUNCTION is called to jump.
+DIR must be non-zero."
+  (unless (minibufferp)
+    (let* ((symbol (symbol-overlay-get-symbol))
+           (keyword (symbol-overlay-assoc symbol)))
+      (push-mark nil t)
+      (funcall jump-function symbol dir)
+      (when keyword
+        (symbol-overlay-maybe-reput symbol keyword)
+        (symbol-overlay-maybe-count keyword)))))
+
+(defun symbol-overlay-basic-jump (symbol dir)
+  "Jump to SYMBOL's next location in the direction DIR.
+DIR must be non-zero."
+  (let* ((case-fold-search nil)
+         (bounds (bounds-of-thing-at-point 'symbol))
+         (offset (- (point) (if (> dir 0) (cdr bounds) (car bounds))))
+         target
+         (re (symbol-overlay-regexp symbol)))
+    (goto-char (- (point) offset))
+    (setq target (re-search-forward re nil t dir))
+    (unless target
+      (goto-char (if (> dir 0) (point-min) (point-max)))
+      (setq target (re-search-forward re nil nil dir)))
+    (goto-char (+ target offset))))
+
+;;;###autoload
+(defun symbol-overlay-jump-next ()
+  "Jump to the next location of symbol at point."
+  (interactive)
+  (symbol-overlay-adjust-position)
+  (symbol-overlay-jump-call #'symbol-overlay-basic-jump 1))
+
+;;;###autoload
+(defun symbol-overlay-jump-prev ()
+  "Jump to the previous location of symbol at point."
+  (interactive)
+  (symbol-overlay-adjust-position)
+  (symbol-overlay-jump-call #'symbol-overlay-basic-jump -1))
+
+;;;###autoload
+(defun symbol-overlay-jump-first ()
+  "Jump to the first location."
+  (interactive)
+  (symbol-overlay-adjust-position)
+  (let* ((symbol (symbol-overlay-get-symbol))
+         (before (symbol-overlay-get-list -1 symbol))
+         (count (length before)))
+    (symbol-overlay-jump-call #'symbol-overlay-basic-jump (- count))))
+
+;;;###autoload
+(defun symbol-overlay-jump-last ()
+  "Jump to the last location."
+  (interactive)
+  (symbol-overlay-adjust-position)
+  (let* ((symbol (symbol-overlay-get-symbol))
+         (after (symbol-overlay-get-list 1 symbol))
+         (count (length after)))
+    (symbol-overlay-jump-call #'symbol-overlay-basic-jump (- count 1))))
+
+(defvar-local symbol-overlay-definition-function
+  '(lambda (symbol) (concat "(?def[a-z-]* " (symbol-overlay-regexp symbol)))
+  "An one-argument function that returns a regexp.")
+
+;;;###autoload
+(defun symbol-overlay-jump-to-definition ()
+  "Jump to the definition of symbol at point.
+The definition syntax should be defined in a function stored in
+`symbol-overlay-definition-function' that returns the definition's regexp
+with the input symbol."
+  (interactive)
+  (symbol-overlay-jump-call
+   '(lambda (symbol dir)
+      (let ((pt (point)) p)
+        (symbol-overlay-basic-jump symbol dir)
+        (while (not (or p (save-excursion
+                            (beginning-of-line)
+                            (skip-chars-forward " \t")
+                            (looking-at-p
+                             (funcall symbol-overlay-definition-function
+                                      symbol)))))
+          (symbol-overlay-basic-jump symbol dir)
+          (and (= pt (point)) (setq p t)))))
+   1))
+
+(defun symbol-overlay-switch-symbol (dir)
+  "Switch to the closest symbol highlighted nearby, in the direction DIR.
+DIR must be 1 or -1."
+  (unless (minibufferp)
+    (let* ((symbol (symbol-overlay-get-symbol t))
+           (list (symbol-overlay-get-list dir symbol t)))
+      (or list
+          (user-error (concat "No more "
+                              (if (> dir 0) "forward" "backward")
+                              " symbols")))
+      (push-mark nil t)
+      (goto-char (overlay-start (car list)))
+      (symbol-overlay-maybe-count
+       (symbol-overlay-assoc (symbol-overlay-get-symbol))))))
+
+;;;###autoload
+(defun symbol-overlay-switch-forward ()
+  "Switch forward to another symbol."
+  (interactive)
+  (symbol-overlay-switch-symbol 1))
+
+;;;###autoload
+(defun symbol-overlay-switch-backward ()
+  "Switch backward to another symbol."
+  (interactive)
+  (symbol-overlay-switch-symbol -1))
+
+;;;###autoload
+(defun symbol-overlay-isearch-literally ()
+  "Isearch symbol at point literally."
+  (interactive)
+  (unless (minibufferp)
+    (let ((symbol (symbol-overlay-get-symbol)))
+      (beginning-of-thing 'symbol)
+      (isearch-forward nil t)
+      (isearch-yank-string symbol))))
+
+;;;###autoload
+(defun symbol-overlay-query-replace ()
+  "Query replace symbol at point."
+  (interactive)
+  (unless (minibufferp)
+    (let* ((case-fold-search nil)
+           (symbol (symbol-overlay-get-symbol))
+           (keyword (symbol-overlay-assoc symbol))
+           (scope (cadr keyword))
+           defaults new)
+      (and scope (user-error "Query-replace invalid in scope"))
+      (beginning-of-thing 'symbol)
+      (push-mark nil t)
+      (setq new (read-string "Replacement: " symbol)
+            defaults (cons symbol new))
+      (unless (string= new symbol)
+        (symbol-overlay-maybe-remove (symbol-overlay-assoc new))
+        (setq keyword (symbol-overlay-put-all new scope keyword))
+        (query-replace-regexp (symbol-overlay-regexp symbol) new)
+        (setq query-replace-defaults
+              (if (< emacs-major-version 25) `,defaults `(,defaults))))
+      (when (string= new (symbol-overlay-get-symbol t))
+        (beginning-of-thing 'symbol)
+        (symbol-overlay-maybe-count keyword)))))
+
+;;;###autoload
+(defun symbol-overlay-rename ()
+  "Rename symbol at point on all its occurrences."
+  (interactive)
+  (unless (minibufferp)
+    (let* ((case-fold-search nil)
+           (symbol (symbol-overlay-get-symbol))
+           (keyword (symbol-overlay-assoc symbol))
+           (scope (if keyword (cadr keyword) symbol-overlay-scope))
+           new)
+      (beginning-of-thing 'symbol)
+      (push-mark nil t)
+      (setq new (read-string (concat "Rename" (and scope " in scope") " to: ")
+                             symbol))
+      (unless (string= new symbol)
+        (symbol-overlay-maybe-remove (symbol-overlay-assoc new))
+        (save-excursion
+          (save-restriction
+            (symbol-overlay-narrow scope)
+            (goto-char (point-min))
+            (let ((inhibit-modification-hooks t)
+                  (re (symbol-overlay-regexp symbol)))
+              (while (re-search-forward re nil t) (replace-match new t)))))
+        (when keyword
+          (setq keyword (symbol-overlay-put-all new scope keyword))))
+      (when (string= new (symbol-overlay-get-symbol t))
+        (symbol-overlay-maybe-count keyword)))))
+
+;;; _
+(provide 'symbol-overlay)
+;; Local Variables:
+;; indent-tabs-mode: nil
+;; End:
+;;; symbol-overlay.el ends here