2

windows 10, emacs 26.1.

To highlight symbol I use package highlight-symbol

http://nschum.de/src/emacs/highlight-symbol/

Nice.

But I need symbol "=" to be a separator.

enter image description here As you can see the test=this is highlight. But I don't like this. I need to highlight only word test. Of course I can press SPC between test and =. But it not comfortable. Suppose I have 100 symbols =.

Same result in text-mode:

enter image description here

Has any alternative for this package? Better that this package.

12
  • Better in what way? Is there a problem you are trying to solve?
    – phils
    Nov 29 '18 at 12:11
  • No problem with current package "highlight-symbol" . But I want try something else to compare. Maybe found smt better features than in package "highlight-symbol". Nov 29 '18 at 12:12
  • @Drew I need symbol "=" to be a separator. I update my post Nov 30 '18 at 9:14
  • = is a symbol-constituent character in the syntax table used by lisp-interaction-mode (which is what the *scratch* buffer is using). In other modes it might not be a symbol character (in c-mode it is a punctuation character, for example). I'm not sure why you would be writing test=this in elisp code, but I wouldn't particularly recommend changing the elisp syntax table. In other modes it might be more reasonable to customize syntax entries, if desired. So, what kind of text is this? For which mode(s) do you want this behaviour?
    – phils
    Nov 30 '18 at 9:46
  • test=this not in elisp code. It maybe in any buffer. E.g. shell mode. In log files and so on. Nov 30 '18 at 10:16
3

First of all note that the behavior of highlight-symbol in your first example is actually right. The *scratch* buffer is in lisp-interaction-mode. The contents of the buffer is supposed to be Elisp and test=this is a symbol in Elisp. For an instance the following is a legal Elisp form and you can eval it in the *scratch*-buffer:

(setq test=this t)

Phil stated this clearly in his comment.

Symbols are built from characters with word syntax and symbol syntax. The syntax is stored in the syntax table of a buffer and usually comes with the major-mode of the buffer.

An example of a major mode where = does not have symbol syntax but punctuation syntax is c-mode.
If you put your buffer into c-mode with M-x c-mode RET the command highlight-symbol works as you want it to work. If point is in test of the string test=this only test is highlighted and not the full string test=this.

You made your second attempt with text-mode. What syntax does = have in text-mode? Does it end a sentence? No actually not. Is it a symbol. Yeah that fits better. So = ended up with symbol syntax in text mode. That has the effect that test=this is interpreted as one symbol in text mode. But, that is a rather weak decision. If you like you can change the syntax of = in text mode with the following hook:

(defun my-=-is-punctuation ()
  "Give ?= punctuation syntax."
  (modify-syntax-entry ?= "."))

(add-hook 'text-mode-hook #'my-=-is-punctuation)

If you activate text-mode in a buffer after installing that hook you get the wanted behavior of highlight-symbol there.

Changing the syntax table of some established major mode as personal customization is a quite drastic measure. It may be that some syntax based features of that mode do not work anymore afterwards.

Alternatively you can advise highlight-symbol a bit to fit your purpose. We can just temporarily modify the syntax table when calling highlight-syntax and we can modify highlight-syntax-border-pattern such that also the equal sign = counts as a border.
If we do not like that the equal sign is also highlighted we need to exclude it from the regexp group to be highlighted. Therefore it is important to know that font-lock-add-keywords allows to identify the regexp group to be highlighted.
In highlight-symbol-add-symbol-with-face the regexp group to be highlighted is hard-coded as 0 -- the full regexp. We want to replace it with 1 -- the group excluding the potentially present equal signs. Because its hard-coded we need an :override advice for highlight-symbol-add-symbol-with-face. That is a pity since such an :override advice does not follow development changes in highlight-symbol-add-symbol-with-face. At least it works with highlight-symbol-20160102.2009.

As long as highlight-symbol-add-symbol-with-face does not change you can use the following code in your init file. (It is likely that it is possible to adapt the advice of highlight-symbol-add-symbol-with-face if it changes.)

Install the Elisp code restart Emacs and call highlight-symbol as you are used to. It will no longer interpret test=this as one symbol but as two symbols separated by a punctuation.

(defun my-highlight-symbol-ad (oldfun &rest args)
  "Call 'highlight-symbol' with modified syntax table."
  (let ((orig (char-syntax ?=)))
    (unwind-protect
    (progn
      (modify-syntax-entry ?= ".")
      (apply oldfun args))
      (modify-syntax-entry ?= (string orig)))))

(advice-add 'highlight-symbol :around #'my-highlight-symbol-ad)

(defun my-highlight-symbol-add-symbol-with-face-ad (symbol face)
  "Put SYMBOL with FACE into `font-lock-keywords'.
Do it like `highlight-symbol-add-symbol-with-face' does
but use regexp group 1 instead of 0.
Note that after installing that advice you need to
use a group in `highlight-symbol-border-pattern'.
The original setting of `highlight-symbol-border-pattern'
without groups does not work anymore."
  (let ((keywords `(,symbol 1 ',face prepend)))
    (push keywords highlight-symbol-keyword-alist)
    (font-lock-add-keywords nil (list keywords) 'append)
    (highlight-symbol-flush)))

(advice-add 'highlight-symbol-add-symbol-with-face :override #'my-highlight-symbol-add-symbol-with-face-ad)

(setq highlight-symbol-border-pattern '("\\(?:=\\|\\_<\\)\\(" . "\\)\\(?:\\_>\\|=\\)"))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.