mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-04-27 08:43:40 -07:00
Add new basic Emacs Lisp code formatting function
* lisp/emacs-lisp/pp.el (pp-emacs-lisp-code): New interface function. (pp): Mention it. (pp--insert-lisp, pp--format-vector, pp--format-list) (pp--format-function, pp--format-definition, pp--insert-binding) (pp--insert, pp--indent-buffer): New helper functions.
This commit is contained in:
parent
4c6afb527b
commit
6cf86ed4c1
4 changed files with 228 additions and 0 deletions
5
etc/NEWS
5
etc/NEWS
|
|
@ -414,6 +414,11 @@ Use 'exif-parse-file' and 'exif-field' instead.
|
|||
|
||||
* Lisp Changes in Emacs 29.1
|
||||
|
||||
---
|
||||
*** New function 'pp-emacs-lisp-code'.
|
||||
'pp' formats general Lisp sexps. This function does much the same,
|
||||
but applies formatting rules appropriate for Emacs Lisp code.
|
||||
|
||||
+++
|
||||
*** New function 'file-has-changed-p'.
|
||||
This convenience function is useful when writing code that parses
|
||||
|
|
|
|||
|
|
@ -82,6 +82,10 @@ to make output that `read' can handle, whenever this is possible."
|
|||
"Output the pretty-printed representation of OBJECT, any Lisp object.
|
||||
Quoting characters are printed as needed to make output that `read'
|
||||
can handle, whenever this is possible.
|
||||
|
||||
This function does not apply special formatting rules for Emacs
|
||||
Lisp code. See `pp-emacs-lisp-code' instead.
|
||||
|
||||
Output stream is STREAM, or value of `standard-output' (which see)."
|
||||
(princ (pp-to-string object) (or stream standard-output)))
|
||||
|
||||
|
|
@ -180,6 +184,124 @@ Ignores leading comment characters."
|
|||
(insert (pp-to-string (macroexpand-1 (pp-last-sexp))))
|
||||
(pp-macroexpand-expression (pp-last-sexp))))
|
||||
|
||||
;;;###autoload
|
||||
(defun pp-emacs-lisp-code (sexp)
|
||||
"Insert SEXP into the current buffer, formatted as Emacs Lisp code."
|
||||
(require 'edebug)
|
||||
(let ((standard-output (current-buffer)))
|
||||
(save-restriction
|
||||
(narrow-to-region (point) (point))
|
||||
(pp--insert-lisp sexp)
|
||||
(insert "\n")
|
||||
(goto-char (point-min))
|
||||
(indent-sexp))))
|
||||
|
||||
(defun pp--insert-lisp (sexp)
|
||||
(cl-case (type-of sexp)
|
||||
(vector (pp--format-vector sexp))
|
||||
(cons (cond
|
||||
((consp (cdr sexp))
|
||||
(if (and (length= sexp 2)
|
||||
(eq (car sexp) 'quote))
|
||||
(let ((print-quoted t))
|
||||
(prin1 sexp))
|
||||
(pp--format-list sexp)))
|
||||
(t
|
||||
(princ sexp))))
|
||||
;; Print some of the smaller integers as characters, perhaps?
|
||||
(integer
|
||||
(if (<= ?0 sexp ?z)
|
||||
(let ((print-integers-as-characters t))
|
||||
(princ sexp))
|
||||
(princ sexp)))
|
||||
(string
|
||||
(let ((print-escape-newlines t))
|
||||
(prin1 sexp)))
|
||||
(otherwise (princ sexp))))
|
||||
|
||||
(defun pp--format-vector (sexp)
|
||||
(prin1 sexp))
|
||||
|
||||
(defun pp--format-list (sexp)
|
||||
(if (and (symbolp (car sexp))
|
||||
(not (keywordp (car sexp))))
|
||||
(pp--format-function sexp)
|
||||
(prin1 sexp)))
|
||||
|
||||
(defun pp--format-function (sexp)
|
||||
(let* ((sym (car sexp))
|
||||
(edebug (get sym 'edebug-form-spec))
|
||||
(indent (get sym 'lisp-indent-function)))
|
||||
(when (eq indent 'defun)
|
||||
(setq indent 2))
|
||||
(pp--insert "(" sym)
|
||||
(pop sexp)
|
||||
;; Get the first entries on the first line.
|
||||
(if indent
|
||||
(pp--format-definition sexp indent edebug)
|
||||
(while sexp
|
||||
(pp--insert " " (pop sexp))))
|
||||
(insert ")")))
|
||||
|
||||
(defun pp--format-definition (sexp indent edebug)
|
||||
(while (and (cl-plusp indent)
|
||||
sexp)
|
||||
(insert " ")
|
||||
(if (and (consp (car edebug))
|
||||
(eq (caar edebug) '&rest))
|
||||
(pp--insert-binding (pop sexp))
|
||||
(if (null (car sexp))
|
||||
(insert "()")
|
||||
(pp--insert-lisp (car sexp)))
|
||||
(pop sexp))
|
||||
(pop edebug)
|
||||
(cl-decf indent))
|
||||
(when (stringp (car sexp))
|
||||
(insert "\n")
|
||||
(prin1 (pop sexp)))
|
||||
;; Then insert the rest with line breaks before each form.
|
||||
(while sexp
|
||||
(insert "\n")
|
||||
(if (keywordp (car sexp))
|
||||
(progn
|
||||
(pp--insert-lisp (pop sexp))
|
||||
(when sexp
|
||||
(pp--insert " " (pop sexp))))
|
||||
(pp--insert-lisp (pop sexp)))))
|
||||
|
||||
(defun pp--insert-binding (sexp)
|
||||
(insert "(")
|
||||
(while sexp
|
||||
(if (consp (car sexp))
|
||||
;; Newlines after each (...) binding.
|
||||
(progn
|
||||
(pp--insert-lisp (car sexp))
|
||||
(when (cdr sexp)
|
||||
(insert "\n")))
|
||||
;; Keep plain symbols on the same line.
|
||||
(pp--insert " " (car sexp)))
|
||||
(pop sexp))
|
||||
(insert ")"))
|
||||
|
||||
(defun pp--insert (delim &rest things)
|
||||
(let ((start (point)))
|
||||
(when delim
|
||||
(insert delim))
|
||||
(dolist (thing things)
|
||||
(pp--insert-lisp thing))
|
||||
;; We need to indent what we have so far to see if we have to fold.
|
||||
(pp--indent-buffer)
|
||||
(when (> (current-column) (window-width))
|
||||
(save-excursion
|
||||
(goto-char start)
|
||||
(insert "\n")))))
|
||||
|
||||
(defun pp--indent-buffer ()
|
||||
(goto-char (point-min))
|
||||
(while (not (eobp))
|
||||
(lisp-indent-line)
|
||||
(forward-line 1)))
|
||||
|
||||
(provide 'pp) ; so (require 'pp) works
|
||||
|
||||
;;; pp.el ends here
|
||||
|
|
|
|||
97
test/lisp/emacs-lisp/pp-resources/code-formats.erts
Normal file
97
test/lisp/emacs-lisp/pp-resources/code-formats.erts
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
Code:
|
||||
(lambda ()
|
||||
(emacs-lisp-mode)
|
||||
(let ((code (read (current-buffer))))
|
||||
(erase-buffer)
|
||||
(pp-emacs-lisp-code code)
|
||||
(untabify (point-min) (point-max))))
|
||||
|
||||
Name: code-formats1
|
||||
|
||||
=-=
|
||||
(defun foo (bar)
|
||||
"Yes."
|
||||
(let ((a 1)
|
||||
(b 2))
|
||||
(zot 1 2 (funcall bar 2))))
|
||||
=-=-=
|
||||
|
||||
|
||||
Name: code-formats2
|
||||
|
||||
=-=
|
||||
(defun pp-emacs-lisp-code (sexp)
|
||||
"Insert SEXP into the current buffer, formatted as Emacs Lisp code."
|
||||
(require 'edebug)
|
||||
(let ((start (point))
|
||||
(standard-output (current-buffer)))
|
||||
(pp--insert-lisp sexp)
|
||||
(insert "\n")
|
||||
(goto-char start)
|
||||
(indent-sexp)))
|
||||
=-=-=
|
||||
|
||||
|
||||
Name: code-formats3
|
||||
|
||||
=-=
|
||||
(defun foo (bar)
|
||||
"Yes."
|
||||
(let ((a 1)
|
||||
(b 2))
|
||||
(zot-zot-zot-zot-zot-zot 1 2 (funcall
|
||||
bar-bar-bar-bar-bar-bar-bar-bar-bar-bar 2))))
|
||||
=-=-=
|
||||
|
||||
|
||||
Name: code-formats4
|
||||
|
||||
=-=
|
||||
(defun foo (bar)
|
||||
"Yes."
|
||||
(let ((a 1)
|
||||
(b 2)
|
||||
foo bar zotfoo bar zotfoo bar zotfoo bar zotfoo bar zotfoo bar zotfoo
|
||||
bar zot)
|
||||
(zot 1 2 (funcall bar 2))))
|
||||
=-=-=
|
||||
|
||||
|
||||
Name: code-formats5
|
||||
|
||||
=-=
|
||||
(defgroup pp ()
|
||||
"Pretty printer for Emacs Lisp."
|
||||
:prefix "pp-"
|
||||
:group 'lisp)
|
||||
=-=-=
|
||||
|
||||
Name: code-formats6
|
||||
|
||||
=-=
|
||||
(defcustom pp-escape-newlines t
|
||||
"Value of `print-escape-newlines' used by pp-* functions."
|
||||
:type 'boolean
|
||||
:group 'pp)
|
||||
=-=-=
|
||||
|
||||
Name: code-formats7
|
||||
|
||||
=-=
|
||||
(defun pp (object &optional stream)
|
||||
(princ (pp-to-string object) (or stream standard-output)))
|
||||
=-=-=
|
||||
|
||||
|
||||
Name: code-formats8
|
||||
|
||||
=-=
|
||||
(defun pp-eval-expression (expression)
|
||||
"Evaluate EXPRESSION and pretty-print its value.
|
||||
Also add the value to the front of the list in the variable `values'."
|
||||
(interactive (list (read--expression "Eval: ")))
|
||||
(message "Evaluating...")
|
||||
(let ((result (eval expression lexical-binding)))
|
||||
(values--store-value result)
|
||||
(pp-display-expression result "*Pp Eval Output*")))
|
||||
=-=-=
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
;;; Code:
|
||||
|
||||
(require 'pp)
|
||||
(require 'ert-x)
|
||||
|
||||
(ert-deftest pp-print-quote ()
|
||||
(should (string= (pp-to-string 'quote) "quote"))
|
||||
|
|
@ -32,4 +33,7 @@
|
|||
(should (string= (pp-to-string '(quotefoo)) "(quotefoo)\n"))
|
||||
(should (string= (pp-to-string '(a b)) "(a b)\n")))
|
||||
|
||||
(ert-deftest test-indentation ()
|
||||
(ert-test-erts-file (ert-resource-file "code-formats.erts")))
|
||||
|
||||
;;; pp-tests.el ends here.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue