Skip to content

Commit

Permalink
Switch to symbol-overlay from highlight-symbol and highlight combo
Browse files Browse the repository at this point in the history
I have struggled to tune `hightlight-symbol` for a last few weeks. I've
encountered numerous issues, like automatically highlighted symbol not being
visible in current line (with `font-lock`'s background) due to conflict with
hl-line mode's overlay, jit-lock mode not flushing (required an advice
workaround), automatic highlighting clobbering `helpful-mode`
fontification (haven't got to the bottom of it), conflict in `highlihgt-symbol`
defun (both `highlight` and `highlight-symbol` defined it). It also seem to be
unmaintained - last version on MELPA is from 2016.

I've chosen to switch to `symbol-overlay`. Amongst others it defines its own
symbol highlighting. So I decided to use that instead of Exordium's custom one
that required `highlight`.

The last but not least `symbol-overlay` seems to be maintained and
`modus-themes` - that I use and intent to port to Exordium - has built in
support for it.
  • Loading branch information
pkryger committed Dec 10, 2024
1 parent 5d93ff0 commit 5087f6a
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 86 deletions.
10 changes: 0 additions & 10 deletions modules/init-help.el
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
(load (file-name-concat (locate-user-emacs-file "modules") "init-require"))))
(exordium-require 'init-lib)
(exordium-require 'init-helm)
(exordium-require 'init-highlight)

;;; Which Key - display available keybindings in popup.
(when exordium-enable-which-key
Expand Down Expand Up @@ -50,15 +49,6 @@
(helm-describe-variable-function #'helpful-variable)
(helm-describe-function-function #'helpful-function))

;; TODO: seems like `font-lock-add-keywords' destroys all formating in
;; `helpful-mode'. The former is used by `highlight-symbol' so will
;; not enable it now.
;; (when exordium-highlight-symbol
;; (use-package highlight-symbol
;; :defer t
;; :hook ((helpful-mode . highlight-symbol-mode)
;; (helpful-mode . highlight-symbol-nav-mode))))

(use-package paren
:ensure nil
:commands (show-paren-local-mode))
Expand Down
166 changes: 90 additions & 76 deletions modules/init-highlight.el
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,21 @@
;;
;; If `exordium-line-mode' is t, the line under the cursor is highlighted.
;;
;; If `exordium-highlight-symbol-at-point' is t, the symbol under the cursor is
;; If `exordium-highlight-symbol' is t, the symbol under the cursor is
;; highlighted after a small delay using a dim background.
;;
;; Alternatively, one can use the key C-c C-SPACE to highlight/un-highlight the
;; symbol under the cursor in the current buffer. Up to 4 different symbols
;; may be highlighted at one time, using different colors. Feel free to rebind
;; function `exordium-highlight-symbol-at-point' to a better key, like for example:
;; Alternatively, one can use the key C-c C-SPC to highlight/un-highlight the
;; symbol under the cursor in the current buffer. When point is in symbol that
;; has been highlighted it is possible to, for example navigate between
;; different instances of the symbol. See `symbol-overlay-map-help' and
;; `exordium-highlight-symbol-map-modifier' for more information.

;; Feel free to rebind function `symbol-overlay-put' to a better key, like for
;; example:
;;
;; (bind-key "C-RET" #'exordium-highlight-symbol-at-point)
;; (bind-key "<f6>" #'exordium-highlight-symbol-at-point)
;; (bind-key "C-RET" #'sybmol-overlay-put)
;; (bind-key "<f6>" #'sybmol-overlay-put)
;;
;; Notes: Exordium uses 2 packages for highlighting the symbol under
;; point. One is "highlight-symbol" used for automatic highlighting after a
;; delay, and the other is the built-in "hi-lock" used for highlighting using
;; a key. highlight-symbol's usage of faces is a bit broken which is why we
;; also use hi-lock.

;;; Code:

Expand All @@ -31,9 +30,6 @@
(load (file-name-concat (locate-user-emacs-file "modules") "init-require"))))
(exordium-require 'init-prefs)

(use-package highlight
:defer t)

;;; Highlight the line where the cursor is
(use-package hl-line
:ensure nil
Expand All @@ -42,70 +38,88 @@
(global-hl-line-mode +1))


;;; Highlight symbol under point automatically after a small delay.
(when exordium-highlight-symbol
(use-package highlight-symbol
;; N.B. the `highlight-symbol' package has not been updated for a while (at
;; the time of writing this comment in 2024 last update was from 2016) and
;; it forcibly defines its own alias for `highlight-symbol-at-point',
;; clobbering the one delivered with Emacs in `hi-lock'. However, the
;; `highlight-symbol' implementation is nicer, as it allows to remove
;; highlighting with the same keybinding. Also the `highlight-symbol-mode'
;; is the mode that is turned on (`hi-lock-mode' is not turned on), so
;; let's keep that implementation, by ensuring load order.
:after (hi-lock)
;; Also, the `highlight-symbol-flush' implementation is not accounting for
;; `jit-lock-mode', which causes a few seconds delay when automatically
;; highlighted symbols. Call `font-lock-ensure' to speed things up, but
;; limit it to the visible portion of a buffer.
:functions (exordium--highlight-symbol-ensure)
:init
(defun exordium--highlight-symbol-ensure ()
(when (eq (font-lock-value-in-major-mode font-lock-support-mode)
'jit-lock-mode)
(font-lock-ensure (window-start) (window-end))))

:diminish highlight-symbol-mode
:hook ((prog-mode . highlight-symbol-mode)
(prog-mode . highlight-symbol-nav-mode)
(help-mode . highlight-symbol-mode)
(help-mode . highlight-symbol-nav-mode))
:custom
(highlight-symbol-on-navigation-p t)
:config
(advice-add 'highlight-symbol-flush
:after #'exordium--highlight-symbol-ensure)))


;;; Highlight/unhighlight symbol under point using a key.

(defvar-local exordium-highlighted-symbols ()
"List of regexps for the currently highlighted symbols.
This variable is buffer-local.")
(defvar exordium--symbol-overlay-original-keymap nil
"Original value of `symbol-overlay-map'.
Used to allow for new bindings according to
`exordium-highlight-symbol-map-modifier' setting when evaluating
`use-package' form.")

(use-package hi-lock
:ensure nil
:demand t
:autoload (hi-lock-regexp-okay)
:functions (exordium-highlight-symbol-at-point)
(use-package symbol-overlay
:diminish
:commands (symbol-overlay-map-help)
:init
(defun exordium-highlight-symbol-at-point ()
"Toggle highlighting of occurrences of the symbol under point.
Faces from `hi-lock-face-defaults' are used to perform the highlight, so up
to the number of elements in that list of different symbols can
be highlighted using different colors at one time."
(interactive)
(when-let* ((regexp (ignore-errors (hi-lock-regexp-okay
(find-tag-default-as-symbol-regexp)))))
(cond ((member regexp exordium-highlighted-symbols)
;; Remove highlight for this symbol.
(setq exordium-highlighted-symbols (remove regexp exordium-highlighted-symbols))
(hi-lock-unface-buffer regexp))
(t
;; Add highlight for this symbol.
(setq exordium-highlighted-symbols (cons regexp exordium-highlighted-symbols))
(hi-lock-face-symbol-at-point)))))
:bind ("C-c C-SPC" . #'exordium-highlight-symbol-at-point))
(when exordium-highlight-symbol
(let ((form '(add-hook 'prog-mode-hook #'symbol-overlay-mode)))
(if (boundp 'prog-mode-hook)
(eval form)
(eval-after-load 'prog-mode `,form)))
(when exordium-help-extensions
(let ((form '(add-hook 'helpful-mode-hook #'symbol-overlay-mode)))
(if (boundp 'helpful-mode-hook)
(eval form)
(eval-after-load 'helpful-mode `,form)))))

:bind
("C-c C-SPC" . #'symbol-overlay-put)

:config
(unless exordium--symbol-overlay-original-keymap
(setq exordium--symbol-overlay-original-keymap
(copy-keymap symbol-overlay-map)))

(if-let* ((template (alist-get exordium-highlight-symbol-map-modifier
'((meta . "M-%c")
(control . "C-%c")
(super . "s-%c")
(hyper . "H-%c"))))
(map (make-sparse-keymap)))
(progn
(map-keymap (lambda (key definition)
(when (and (functionp definition) (< ? key 127))
(bind-key (format template key) definition map)))
exordium--symbol-overlay-original-keymap)
(bind-keys :map map
((format template ?N) . symbol-overlay-switch-forward)
((format template ?P) . symbol-overlay-switch-backward))
(setq symbol-overlay-map map))
(bind-keys :map symbol-overlay-map
("N" . symbol-overlay-switch-forward)
("P" . symbol-overlay-switch-backward)))

(when exordium-help-extensions
;; Like in `casual' bind help to "C-o", unless it has been bound above.
(unless (and (eq exordium-highlight-symbol-map-modifier 'control)
(catch 'bound
(map-keymap (lambda (key _)
(when (eq key ?o) (throw 'bound key)))
exordium--symbol-overlay-original-keymap)))
(bind-keys :map symbol-overlay-map
("C-o" . symbol-overlay-map-help))))

;; Add ts-modes handling. Do it here, as it can't be referred to a definiens
;; in a definiendum. The reason being that, when using :custom, the
;; unevaluated definiendum is installed for setting when the relevant
;; defcustom is evaluated. The latter happens when feature is loaded. This
;; is nice as it allows to install a custom standard value for variable,
;; without a need to set it to the standard. However, at such a point
;; there's no standard value for the variable (the definiens).
(setq symbol-overlay-ignore-functions
(append
symbol-overlay-ignore-functions
(delq
nil (mapcar
(lambda (elt)
(when-let* ((mode (car elt))
(ts-mode (intern (replace-regexp-in-string
(rx "-mode" string-end)
"-ts-mode"
(symbol-name mode))))
((not (eq ts-mode mode)))
((fboundp ts-mode))
((not (assq ts-mode symbol-overlay-ignore-functions))))
(cons ts-mode (cdr elt))))
symbol-overlay-ignore-functions)))))


;; Highlight color name and Hex values in buffer.
Expand Down
23 changes: 23 additions & 0 deletions modules/init-prefs.el
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,29 @@ displayed by the current font default will be used."
:group 'exordium
:type 'boolean)

(defcustom exordium-highlight-symbol-map-modifier 'meta
"Modifier key for key bindings when point is in a highlighted symbol.
By default `symbol-overlay-map' (which see) defines single letter
bindings. This conflicts with self-insert commands and
historically it was not Exordium's default. That is a
highlighted symbol used to be editable by pressing any letter.
Setting this variable to a value of KEY will rebind single
LETTER binding in `symbol-overlay-key' to \"<KEY>-<LETTER>\"
form. Possible KEY values are:
* \\='original - use original \"<LETTER>\" bindings, as defined
in `overlay-symbol-map', which see.
* \\='meta, \\='control, \\='super, or \\='hyper - use
\"M-<LETTER>\", \"C-<LETTER>\", \"s-<LETTER>\", or
\"H-<LETTER>\" respectively."
:type '(choice (symbol :tag "Original `overlay-symbol' bindings" 'original)
(symbol :tag "Meta prefix for bindings" 'meta)
(symbol :tag "Control prefix for bindings" 'control)
(symbol :tag "Super prefix for bindings" 'super)
(symbol :tag "Hyper prefix for bindings" 'hyper))
:group 'exordium)

(defcustom exordium-skip-taps-update nil
"Whether to skip taps update when updating configuration.
If set to nil, each tap need to be updated manually,
Expand Down

0 comments on commit 5087f6a

Please sign in to comment.