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
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]
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
Emacs Lisp snippet1 below to your
.emacs and restart your
(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
- adds two new commands
- adds a sub-menu named
Extra Toolsto the menu. To this sub-menu, it adds the above two commands with names
Highlight Regexp With Stringand
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]
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.