;;; xr-prettify.el --- Display regular expressions as xr forms ;; Copyright (C) 2018 Clément Pit--Claudel ;; Author: Clément Pit--Claudel ;; Version: 0.1 ;; Keywords: convenience, lisp, tools ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; `xr-prettify-minor-mode' uses syntax highlighting and display properties to make ELisp ;; regular expressions more readable. More precisely, it replaces "complex ;; enough" regular expressions with an equivalent "rx" form. The underlying ;; buffer text is not modified. ;; ;; For example, `xr-prettify` prettifies this: ;; "\\(?:\\_<\\\\newc\\_>\\s-*\\)?" ;; into this (`^' indicates a different color): ;; (opt symbol-start "\\newc" symbol-end (zero-or-more (syntax whitespace))) ;; ;; The appearance of the replacement can be customized using `xr-prettify-face' ;; (which see). ;; ;; Suggested setup: ;; (add-hook 'lisp-mode-hook 'xr-prettify-minor-mode) ;;; Code: (require 'font-lock) (require 'xr) (defgroup xr-prettify nil "Display regular expressions in `rx' form." :group 'programming) ;; FIXME reveal while typing (defun xr-prettify--maybe-replace-string () "Possibly display the string starting before (point) as an `rx' form." (save-excursion (let ((ppss-state (syntax-ppss (point)))) (when (nth 3 ppss-state) (let* ((start (1- (point))) (eol (point-at-eol)) (end (save-excursion (parse-partial-sexp (point) (1+ eol) nil nil ppss-state 'syntax-table) (point)))) (when (and (<= end eol) (search-forward "\\\\" end t)) (let* ((txt (buffer-substring-no-properties start end)) (str (ignore-errors (read txt))) (rx (and str (ignore-errors (xr str)))) (pretty (and rx (prin1-to-string `(rx ,rx))))) (when (and pretty (not (string= pretty txt))) (put-text-property start end 'display pretty))))))) nil)) (defconst xr-prettify--keywords '(("\"" (0 (progn (xr-prettify--maybe-replace-string) nil)))) "Font-lock keyword list used internally.") ;;;###autoload (define-minor-mode xr-prettify-minor-mode "Display regular expressions in `rx' form to improve readability. When this mode is active, strings are displayed in `rx' syntax, and highlighted with `xr-prettify-face'." :lighter " xr" :group 'xr-prettify (cond (xr-prettify-minor-mode (font-lock-add-keywords nil xr-prettify--keywords) (make-local-variable 'font-lock-extra-managed-props) (add-to-list 'font-lock-extra-managed-props 'display)) (t (font-lock-remove-keywords nil xr-prettify--keywords))) (if (>= emacs-major-version 25) (font-lock-flush) (with-no-warnings (font-lock-fontify-buffer)))) (provide 'xr-prettify) ;;; xr-prettify.el ends here