tibbe
tibbe

Reputation: 9009

Emacs modes: highlighting uses of variable under point

In Python mode, if I put the point on the x argument in the below function definition

def f(x):
  #   ^------ point here
  print x

the use of x in the function body gets highlighted in yellow.

Upvotes: 6

Views: 2387

Answers (4)

Drew
Drew

Reputation: 30701

Command hlt-highlight-symbol in library highlight.el does what you want. (See also option hlt-auto-faces-flag.) It does what library highlight-symbol does (including navigation among occurrences), and more. See Highlight library.

Also, Emacs 24.4 (i.e., current development snapshot), command hi-lock-face-symbol-at-point does what you want, I think (differently).

Upvotes: 2

user355252
user355252

Reputation:

I'd not implement such a feature in a major mode itself. A generic minor mode that tries to support as many major modes as possible based on generic Emacs interfaces (e.g. syntax tables) is a better fit, and unsurprisingly, someone already wrote such a mode: highlight-symbol.

With this package and the following code in your init.el, Emacs will highlight all occurrences of the symbol (e.g. variable, function, class) under point:

(add-hook 'prog-mode-hook #'highlight-symbol-mode)

This package also provides a bunch of other utilities to work with the symbol under point, such as highlight-symbol-nav-mode, which lets you jump to the next and previous occurrence of the symbol under point with C-n and C-p respectively. Take a look at the source to see what it's capable of.

Upvotes: 3

Andreas Röhler
Andreas Röhler

Reputation: 4804

(require 'hi-lock)


(defvar args-highlighted-p nil)
(defvar args-highlighted-regexp "\_<.+\_>")

(defun highlight-args ()
  "With cursor at function's argument, highlight args in body.

When already highlighted, un-highlight. "
  (interactive)
  (save-excursion
    (if args-highlighted-p
    (progn
      (setq args-highlighted-p nil)
      (hi-lock-unface-buffer args-highlighted-regexp))
      (let ((erg (prin1-to-string (symbol-at-point)))
        (end (funcall end-of-defun-function)))
    (if
        erg
        (progn
          (setq args-highlighted-p t)
          (setq args-highlighted-regexp (concat "\\_<" erg "\\_>"))
          (hi-lock-face-symbol-at-point)
          (while
          (re-search-forward "\_<erg\_>" nil t end)
        (hi-lock-face-symbol-at-point))))))))

Upvotes: 1

Inaimathi
Inaimathi

Reputation: 14065

Not sure how that mode specifically does it, but here's a highlight-tags minor mode I wrote as a thought exercise a while ago that does something similar for matching sgml tags.

It doesn't do a very good job of figuring out which tags to hit, but the relevant parts for you would be highlight-tags-update/hide/show anyhow. Keep in mind that since an sgml tag only has one matching tag, I got away with just having a global pair of overlays for a buffer. Your use case might have more highlights, so you'll need to keep a list of them instead.

The way that yours would work in the abstract is:

  1. Take the output of word-at-point
  2. Find all occurrences of word in the following block (probably using some combination of the python-nav-*-block commands and search-forward)
  3. Collect the start/end of each match
  4. Create a new overlay for each start/end pair with make-overlay, and return the list of these overlays.

You'd then want a function that took the output of the above and stored it somewhere so that you could later (mapcar #'delete-overlay overlays).

Finally, you'd add a hook to post-command-hook that ran a function to remove the old overlays and generate new ones.

Upvotes: 0

Related Questions