pp.el 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. ;;; pp.el --- pretty printer for Emacs Lisp
  2. ;; Copyright (C) 1989, 1993, 2001-2012 Free Software Foundation, Inc.
  3. ;; Author: Randal Schwartz <merlyn@stonehenge.com>
  4. ;; Keywords: lisp
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;;; Code:
  18. (defvar font-lock-verbose)
  19. (defgroup pp nil
  20. "Pretty printer for Emacs Lisp."
  21. :prefix "pp-"
  22. :group 'lisp)
  23. (defcustom pp-escape-newlines t
  24. "Value of `print-escape-newlines' used by pp-* functions."
  25. :type 'boolean
  26. :group 'pp)
  27. ;;;###autoload
  28. (defun pp-to-string (object)
  29. "Return a string containing the pretty-printed representation of OBJECT.
  30. OBJECT can be any Lisp object. Quoting characters are used as needed
  31. to make output that `read' can handle, whenever this is possible."
  32. (with-temp-buffer
  33. (lisp-mode-variables nil)
  34. (set-syntax-table emacs-lisp-mode-syntax-table)
  35. (let ((print-escape-newlines pp-escape-newlines)
  36. (print-quoted t))
  37. (prin1 object (current-buffer)))
  38. (pp-buffer)
  39. (buffer-string)))
  40. ;;;###autoload
  41. (defun pp-buffer ()
  42. "Prettify the current buffer with printed representation of a Lisp object."
  43. (goto-char (point-min))
  44. (while (not (eobp))
  45. ;; (message "%06d" (- (point-max) (point)))
  46. (cond
  47. ((ignore-errors (down-list 1) t)
  48. (save-excursion
  49. (backward-char 1)
  50. (skip-chars-backward "'`#^")
  51. (when (and (not (bobp)) (memq (char-before) '(?\s ?\t ?\n)))
  52. (delete-region
  53. (point)
  54. (progn (skip-chars-backward " \t\n") (point)))
  55. (insert "\n"))))
  56. ((ignore-errors (up-list 1) t)
  57. (while (looking-at-p "\\s)")
  58. (forward-char 1))
  59. (delete-region
  60. (point)
  61. (progn (skip-chars-forward " \t\n") (point)))
  62. (insert ?\n))
  63. (t (goto-char (point-max)))))
  64. (goto-char (point-min))
  65. (indent-sexp))
  66. ;;;###autoload
  67. (defun pp (object &optional stream)
  68. "Output the pretty-printed representation of OBJECT, any Lisp object.
  69. Quoting characters are printed as needed to make output that `read'
  70. can handle, whenever this is possible.
  71. Output stream is STREAM, or value of `standard-output' (which see)."
  72. (princ (pp-to-string object) (or stream standard-output)))
  73. (defun pp-display-expression (expression out-buffer-name)
  74. "Prettify and display EXPRESSION in an appropriate way, depending on length.
  75. If a temporary buffer is needed for representation, it will be named
  76. after OUT-BUFFER-NAME."
  77. (let* ((old-show-function temp-buffer-show-function)
  78. ;; Use this function to display the buffer.
  79. ;; This function either decides not to display it at all
  80. ;; or displays it in the usual way.
  81. (temp-buffer-show-function
  82. (function
  83. (lambda (buf)
  84. (with-current-buffer buf
  85. (goto-char (point-min))
  86. (end-of-line 1)
  87. (if (or (< (1+ (point)) (point-max))
  88. (>= (- (point) (point-min)) (frame-width)))
  89. (let ((temp-buffer-show-function old-show-function)
  90. (old-selected (selected-window))
  91. (window (display-buffer buf)))
  92. (goto-char (point-min)) ; expected by some hooks ...
  93. (make-frame-visible (window-frame window))
  94. (unwind-protect
  95. (progn
  96. (select-window window)
  97. (run-hooks 'temp-buffer-show-hook))
  98. (select-window old-selected)
  99. (message "See buffer %s." out-buffer-name)))
  100. (message "%s" (buffer-substring (point-min) (point)))
  101. ))))))
  102. (with-output-to-temp-buffer out-buffer-name
  103. (pp expression)
  104. (with-current-buffer standard-output
  105. (emacs-lisp-mode)
  106. (setq buffer-read-only nil)
  107. (set (make-local-variable 'font-lock-verbose) nil)))))
  108. ;;;###autoload
  109. (defun pp-eval-expression (expression)
  110. "Evaluate EXPRESSION and pretty-print its value.
  111. Also add the value to the front of the list in the variable `values'."
  112. (interactive
  113. (list (read-from-minibuffer "Eval: " nil read-expression-map t
  114. 'read-expression-history)))
  115. (message "Evaluating...")
  116. (setq values (cons (eval expression) values))
  117. (pp-display-expression (car values) "*Pp Eval Output*"))
  118. ;;;###autoload
  119. (defun pp-macroexpand-expression (expression)
  120. "Macroexpand EXPRESSION and pretty-print its value."
  121. (interactive
  122. (list (read-from-minibuffer "Macroexpand: " nil read-expression-map t
  123. 'read-expression-history)))
  124. (pp-display-expression (macroexpand expression) "*Pp Macroexpand Output*"))
  125. (defun pp-last-sexp ()
  126. "Read sexp before point. Ignores leading comment characters."
  127. (let ((stab (syntax-table)) (pt (point)) start exp)
  128. (set-syntax-table emacs-lisp-mode-syntax-table)
  129. (save-excursion
  130. (forward-sexp -1)
  131. ;; If first line is commented, ignore all leading comments:
  132. (if (save-excursion (beginning-of-line) (looking-at-p "[ \t]*;"))
  133. (progn
  134. (setq exp (buffer-substring (point) pt))
  135. (while (string-match "\n[ \t]*;+" exp start)
  136. (setq start (1+ (match-beginning 0))
  137. exp (concat (substring exp 0 start)
  138. (substring exp (match-end 0)))))
  139. (setq exp (read exp)))
  140. (setq exp (read (current-buffer)))))
  141. (set-syntax-table stab)
  142. exp))
  143. ;;;###autoload
  144. (defun pp-eval-last-sexp (arg)
  145. "Run `pp-eval-expression' on sexp before point.
  146. With argument, pretty-print output into current buffer.
  147. Ignores leading comment characters."
  148. (interactive "P")
  149. (if arg
  150. (insert (pp-to-string (eval (pp-last-sexp))))
  151. (pp-eval-expression (pp-last-sexp))))
  152. ;;;###autoload
  153. (defun pp-macroexpand-last-sexp (arg)
  154. "Run `pp-macroexpand-expression' on sexp before point.
  155. With argument, pretty-print output into current buffer.
  156. Ignores leading comment characters."
  157. (interactive "P")
  158. (if arg
  159. (insert (pp-to-string (macroexpand (pp-last-sexp))))
  160. (pp-macroexpand-expression (pp-last-sexp))))
  161. ;;; Test cases for quote
  162. ;; (pp-eval-expression ''(quote quote))
  163. ;; (pp-eval-expression ''((quote a) (quote b)))
  164. ;; (pp-eval-expression ''('a 'b)) ; same as above
  165. ;; (pp-eval-expression ''((quote (quote quote)) (quote quote)))
  166. ;; These do not satisfy the quote test.
  167. ;; (pp-eval-expression ''quote)
  168. ;; (pp-eval-expression ''(quote))
  169. ;; (pp-eval-expression ''(quote . quote))
  170. ;; (pp-eval-expression ''(quote a b))
  171. ;; (pp-eval-expression ''(quotefoo))
  172. ;; (pp-eval-expression ''(a b))
  173. (provide 'pp) ; so (require 'pp) works
  174. ;;; pp.el ends here