Highlight text, not with faces, but with other texts


In earlier articles,1, 2  you learned how to highlight portions of your text file to get a better overview of it’s organization and contents.  In those articles, the text of interest was highlighted with different faces.  GNU Emacs lets you decorate your text not with just faces, but also with other texts.  In this article, you will learn how to highlight text not with a different face, but with a an alternative text, and profit from it.

Why would you want to highlight portions of your text with an alternative text? Instead of answering this question in abstract let us see a concrete example.

Consider any of the projects like Semantic1  ECB1 or for that matter any of the sub-projects of under CEDET1.  The projects target both GNU Emacs and XEmacs.  The project have long history and during the course of development, they have seen multiple versions (and thus capabilities) of the underlying platform.    As a result of  this, they have accumulated lots of glue code that checks for the platform and it’s capabilities.

Here is a typical code

(defun semantic-set-tag-read-only (tag &optional writable)
  "Enable the text in TAG to be made read-only.
Optional argument WRITABLE should be non-nil to make the text writable
instead of read-only."
  (let ((o (semantic-tag-overlay tag))
        (hook (if writable nil '(semantic-overlay-signal-read-only))))
    (if (featurep 'xemacs)
        ;; XEmacs extents have a 'read-only' property.
        (semantic-overlay-put o 'read-only (not writable))
      (semantic-overlay-put o 'modification-hooks hook)
      (semantic-overlay-put o 'insert-in-front-hooks hook)
      (semantic-overlay-put o 'insert-behind-hooks hook))))

The above Emacs Lisp code is from lisp/cedet/semantic/decorate.el1. Note the test for XEmacs with (featurep 'xemacs).

When you are working with such a code-base, you would want some visual cues that tell you which portions of compatibility code is active (or inactive) for a target platform or a feature-set.  In other words,  you would want Emacs to mark code that targets  XEmacs distinctly from those that target GNU Emacs.

In this article, you will learn how to do this. [CLICK HERE FOR UNSCALED GIF]

Highlight Regexp With String Overview 2018-10-26

Note how the string (featurep 'xemacs) has been replaced with the string nil.  With such a makeshift replacement, you spend literally zero time executing the compatibility checks, and more time on what matters the most–the active (or inactive) parts of the code.  Remember, you haven’t done any replacement, and modified the underlying file.  It only appears as if you have done a replacement.  Technically speaking, you have created a overlay1with a display1 property.

Let us see how this may be accomplished.

Step 1:  Install a custom command and a menu

Copy the Emacs Lisp snippet1 below to your .emacs and restart your Emacs.

(require 'hi-lock)

(defun my-highlight-regexp-with-string (&optional regexp string face)
  "Display each match of REGEXP as STRING with face FACE.
With a prefix arg, remove all such highlights."
  (interactive
   (unless current-prefix-arg
     (let* ((regexp (read-regexp "Regexp: "))
            (string (read-string (format "Display %s as : " (propertize regexp 'face 'fixed-pitch-serif)))))
       (list regexp string  (hi-lock-read-face-name)))))
  (if current-prefix-arg  (remove-overlays nil nil 'my-overlay t)
    (save-excursion
      (goto-char (point-min))
      (let ((case-fold-search nil))
        (while (re-search-forward regexp nil t)
          (let ((ov (make-overlay (match-beginning 0) (match-end 0))))
            (overlay-put ov 'my-overlay t)
            (overlay-put ov 'display string)
            (overlay-put ov 'face face)))))))

(defun my-remove-all-string-highlights ()
  "Remove all highlights created with `my-highlight-regexp-with-string'."
  (interactive)
  (remove-overlays nil nil 'my-overlay t))

(unless (lookup-key global-map [menu-bar extra-tools])
  (define-key-after global-map
    [menu-bar extra-tools]
    (cons "Extra Tools"
          (easy-menu-create-menu "Extra Tools" nil))
    'tools))

(global-set-key (kbd "C-x w o") 'my-highlight-regexp-with-string)

(dolist (item '("--"
                ["Highlight Regexp With String" my-highlight-regexp-with-string :help "(my-highlight-regexp-with-string &optional REGEXP STRING FACE)\n\nDisplay each match of REGEXP as STRING with face FACE.\nWith a prefix arg, remove all such highlights."]
                ["Remove All String Highlights" my-remove-all-string-highlights :help "(my-remove-all-string-highlights)\n\nRemove all highlights created with `my-highlight-regexp-with-string'."]))
  (easy-menu-add-item global-map '("menu-bar" "extra-tools") item nil))

(provide 'my-hi-lock)

This snippet does the following

  1. adds two new commands my-highlight-regexp-with-string and  my-remove-string-highlights
  2. adds a sub-menu named Extra Tools to the menu. To this sub-menu, it adds the above two commands with names Highlight Regexp With String and Remove All String Highlights.

Step 2: Ensure that you have  Extra Tools -> Highlight Regexp With String etc

Once you restart you Emacs,  your menu-bar should have an the sub-menu Extra Tools. Within this sub-menu you should have sub-items Highlight Regexp With String and Remove All String Highlights .  See the next step for a screenshot.  If you aren’t seeing these, repeat the previous steps.

Step 3: Highlight and Unhighlight Regexps with Strings

See the  GIF below for details.  [CLICK HERE FOR UNSCALED GIF]

Highlight Regexp With String 2018-10-26

Concluding Words

XEmacs1 is dead.  Many major projects like Org have already removed the XEmacs compatibility layer.1  However, projects like ECB1 are lagging behind in this task.1 This article sheds light on how you may skillfully tackle platform-specific code in projects like ECB.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this:
search previous next tag category expand menu location phone mail time cart zoom edit close