index rss mastodon twitter github linkedin email
Álvaro Ramírez

Álvaro Ramírez

15 September 2023 Redact that buffer

As I was getting ready to take an Emacs screenshot in the previous post, I figured I may want to redact email addresses before moving forward. I had a quick look for existing options and found redacted.el, built-in toggle-rot13-mode, and unpackaged/lorem-ipsum-overlay. All great options. I wanted a solution I could feed a single regular expression to obscure matches. I also wanted toggling capabilities, so I had a quick go at it…


I also wanted the ability to redact the entire buffer content, so feeding a space to the regexp query also translates to [[:graph:]], effectively redacting all visible characters.


The solution is overlay-based, ensuring the buffer content remains unchanged. The function may have its own rough edges, yet it certainly scratched the itch for the current need. I'll leave ya with the snippet.

(defun ar/toggle-redact-buffer ()
  "Redact buffer content matching regexp. A space redacts all."
  (let* ((redacted)
         (regexp (string-trim (read-regexp "Redact regexp" 'regexp-history-last)))
         (matches (let ((results '()))
                    (when (string-empty-p regexp)
                      (setq regexp "[[:graph:]]")
                      (setq regexp-history-last regexp)
                      (add-to-history 'regexp-history regexp))
                      (goto-char (point-min))
                      (while (re-search-forward regexp nil t)
                        (push (cons (match-beginning 0) (match-end 0)) results)))
                    (nreverse results))))
    (mapc (lambda (match)
            (dolist (overlay (overlays-in (car match) (cdr match)))
              (setq redacted t)
              (delete-overlay overlay))
            (unless redacted
              (overlay-put (make-overlay (car match) (cdr match))
                           'display (make-string (- (cdr match) (car match)) ?x))))