0

I spend a lot of time in XML buffers using nxml-mode (Emacs 26). Out of hundreds of XML elements, I am only interested in one or two. How can I have Emacs always show the XML elements I'm interested in with a different colour? This will help me keep track of the important elements while working without having to keep searching with C-s and C-r.

For example, in the following XML file, I want the tags for element THING_NAME to show up in a different coloured font instead of the default blue, and leave the tags for elemenst XML_FILE, THING_VERSION, and THING_TYPE in the default colour.

<?xml version='1.0' encoding='ISO-8859-'?>
<XML_FILE>
  <THING_VERSION>2.2</THING_VERSION>
  <THING_NAME>BOB</THING_NAME>
  <THING_TYPE>ITEM</THING_TYPE>
</XML_FILE>

Here's a screenshot. It would be great if the highlighted tags for THING_NAME were in a different colour, like pink or red, to make it easier to see in large files.

[THING_NAME element should be a different colour[1]

I've tried adding font-lock-add-keywords to init.el but it had no effect. For example:

(font-lock-add-keywords 'nxml-mode
        '(("THING_NAME" . font-lock-keyword-face)))

I also tried adding a hook to the mode using add-hook from the Emacs manual:

(add-hook 'nxml-mode-hook
         (lambda ()
          (font-lock-add-keywords nil
           '(("\\(THING_NAME\\)" 1
              font-lock-warning-face t)))))

After reading the nxml-mode Emacs documentation and Emacs wiki entries, and installing themes from MELPA and looking at the code, I'm still unsure of how to proceed.

This has been driving me crazy! Any help would be very appreciated, and I'm sure many others would find this useful. Maybe I am approaching this the wrong way. Would it be better to have an always-on search that permanently highlighted specific matches?


Solution after the response from glucas, shown below

Thanks to glucas I created a regexp interactive highlight for "THING_NAME". The keys I typed were:

 M-s h r   THING_NAME   RET   RET

I extended this to good final solution by creating a keyboard macro to automatically bind C-c t to the interactive highlight in ~/.emacs.d/init.el. The macro is named thingname, so I can also type M-x thingname. Notice how the regexp search term "THING_NAME" is escaped as "?T ?H ?I ?N ?G ?_ ?N ?A ?M ?E":

(fset 'thingname
  [?\M-s ?h ?r ?T ?H ?I ?N ?G ?_ ?N ?A ?M ?E return return])
(global-set-key (kbd "C-c t") 'thingname)

Applied to the example XML above, it looks like this:

enter image description here

You can add multiple highlights, each with a different colour, by repeating the call to M-s h r as many times as needed. Here, I add another highlight for "THING_WEIGHT" to the same binding:

(fset 'thingname
  [?\M-s ?h ?r ?T ?H ?I ?N ?G ?_ ?N ?A ?M ?E return return
   ?\M-s ?h ?r ?T ?H ?I ?N ?G ?_ ?W ?E ?I ?G ?H ?T return return])
(global-set-key (kbd "C-c t") 'thingname)

enter image description here

1
  • You could also create a function rather than a keyboard macro. I'll add an example.
    – glucas
    Jan 23, 2020 at 21:09

1 Answer 1

1

Emacs provides a general-purpose highlight mechanism which might work here. See Interactive Highlighting in the Emacs manual.

The relevant commands are highlight-phrase or highlight-regexp to define what you want to highlight (and in what color). You can ask Hi Lock mode to save the highlight instructions in the file itself using hi-lock-write-interactive-patterns. That gives you a flexible way to define and persist highlight instructions without writing any Elisp.

Alternatively you can define you own functions to set up highlighting with the same commands, and hook them to nxml mode. That would be a better approach if you want the same highlight rules across many files and/or cannot add comments to the files.

For example:

(defun my-xml-highlights ()
  (interactive)
  (highlight-phrase "THING_NAME" 'hi-yellow)
  (highlight-phrase "THING_WEIGHT" 'hi-pink))

(global-set-key (kbd "C-c t") 'my-xml-highlights)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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