Quickly adding face properties to regions

Posted: - Modified: | emacs
  • [2024-09-20 Fri]: Set the first frame of the animated GIF to a reasonable backup image.
  • [2024-09-20 Fri]: Add :init-value nil to the mode.
output-2024-09-20-13:09:17.gif
Figure 1: Screencast of modifying face properties

Sometimes I just want to make some text look a little fancier in the buffer so that I can make a thumbnail or display a message. This my-add-face-text-property function lets me select a region and temporarily change its height, make it bold, or do other things. It will work in text-mode or enriched-mode buffers (not Org Mode or programming buffers like *scratch*, as those do a lot of font-locking).

(defun my-add-face-text-property (start end attribute value)
  (interactive
   (let ((attribute (intern
                     (completing-read
                      "Attribute: "
                      (mapcar (lambda (o) (symbol-name (car o)))
                              face-attribute-name-alist)))))
     (list (point)
           (mark)
           attribute
           (read-face-attribute '(()) attribute))))
  (add-face-text-property start end (list attribute value)))

enriched-mode has some keyboard shortcuts for face attributes (M-o b for bold, M-o i for italic). I can add some keyboard shortcuts for other properties even if they can't be saved in text/enriched format.

(defun my-face-text-larger (start end)
  (interactive "r")
  (add-face-text-property
   start end
   (list :height (floor (+ 50 (car (alist-get :height (get-text-property start 'face) '(100))))))))
(defun my-face-text-smaller (start end)
  (interactive "r")
  (add-face-text-property
   start end
   (list :height (floor (- (car (alist-get :height (get-text-property start 'face) '(100))) 50)))))

What's an easy way to make this keyboard shortcut available during the rare times I want it? I know, maybe I'll make a quick minor mode so I don't have to dedicate those keyboard shortcuts all the time. repeat-mode lets me change the size by repeating just the last keystroke.

  (defvar-keymap my-face-text-property-mode-map
    "M-o p" #'my-add-face-text-property
    "M-o +" #'my-face-text-larger
    "M-o -" #'my-face-text-smaller)
  (define-minor-mode my-face-text-property-mode
    "Make it easy to modify face properties."
    :init-value nil
    (repeat-mode 1))
  (defvar-keymap my-face-text-property-mode-repeat-map
    :repeat t
    "+" #'my-face-text-larger
    "-" #'my-face-text-smaller)
  (dolist (cmd '(my-face-text-larger my-face-text-smaller))
    (put cmd 'repeat-map 'my-face-text-property-mode-repeat-map))
This is part of my Emacs configuration.
View org source for this post
You can comment with Disqus or you can e-mail me at sacha@sachachua.com.