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.

a_subscriber
  • 3,854
  • 1
  • 17
  • 47
  • 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". – a_subscriber Nov 29 '18 at 12:12
  • @Drew I need symbol "=" to be a separator. I update my post – a_subscriber Nov 30 '18 at 09: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 09:46
  • test=this not in elisp code. It maybe in any buffer. E.g. shell mode. In log files and so on. – a_subscriber Nov 30 '18 at 10:16
  • The point is that "symbol" can mean different things in different buffers, so the *specific* major modes you're interested in is important to the question. Your screenshot is of a buffer in `lisp-interaction-mode`, so that *is* an elisp buffer (and `test=this` is a valid elisp symbol). – phils Nov 30 '18 at 11:32
  • @phils Not help. I get same result is text mode. I updated my post. – a_subscriber Nov 30 '18 at 11:50
  • You can temporarily change the syntax of `=` with the following advice (put it into your init file and restart Emacs): `(defun my-highlight-symbol-ad (oldfun &rest args) "Call 'highlight-symbol' with modified syntax table." (interactive) (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)` – Tobias Nov 30 '18 at 13:29
  • @Tobias I get error message after call "my-highlight-symbol-ad" - funcall-interactively: Wrong number of arguments: (lambda (oldfun &rest args) "Call 'highlight-symbol' with modified syntax table." (interactive) (let ((orig (char-syntax 61))) (unwind-protect (progn (modify-syntax-entry 61 ".") (apply oldfun args)) (modify-syntax-entry 61 (string orig))))), 0 – a_subscriber Nov 30 '18 at 13:41
  • No don't call `my-highlight-symbol-ad` directly! Use `highlight-symbol` as usual after executing the `advice-add`. The advice modifies the behavior of `highlight-symbol`. – Tobias Nov 30 '18 at 13:43
  • I was fooled by my customizations. The code above does only highlight the free-standing occurrences of the symbol. and not that ones in `symbol=symbol`. It is because font lock uses symbol boundaries to identify the symbols and `=` has still symbol-syntax in `fundamental-mode`. You could change the syntax of `=` permanently if you like. But it may be that that has other unwanted consequences. – Tobias Nov 30 '18 at 14:43
  • You can try [msearch.el](https://www.emacswiki.org/emacs/msearch) There you can just search for the mouse selection without boundaries. Therefore, if you select `foo` with the mouse it will also highlight `foo` in `foobar`. You can also set the search string boundaries to word. So `foo` in `foobar` will not be highlighted but `foo` in `foo_bar` will. You can freeze the current highlighting. Meaning that `foo` will still be highlighted even if you select `bar`. `bar` will be highlighted with another color in that case. – Tobias Nov 30 '18 at 14:51

1 Answers1

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 '("\\(?:=\\|\\_<\\)\\(" . "\\)\\(?:\\_>\\|=\\)"))
Tobias
  • 32,569
  • 1
  • 34
  • 75