From cd73ec72a6c864a8979fa1041df8618fe67cf480 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Tue, 2 Nov 2021 16:20:15 +0100 Subject: Make lambdas/closures/byte code in `C-h b' clickable * lisp/help.el (help--describe-command): Add links for lambdas/closures/byte code (bug#24235). * lisp/emacs-lisp/pp.el (pp-display-expression): Autoload. --- lisp/emacs-lisp/pp.el | 1 + 1 file changed, 1 insertion(+) (limited to 'lisp/emacs-lisp/pp.el') diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index 0bf774dffd8..4ff2cd59eba 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -85,6 +85,7 @@ can handle, whenever this is possible. Output stream is STREAM, or value of `standard-output' (which see)." (princ (pp-to-string object) (or stream standard-output))) +;;;###autoload (defun pp-display-expression (expression out-buffer-name) "Prettify and display EXPRESSION in an appropriate way, depending on length. If a temporary buffer is needed for representation, it will be named -- cgit v1.2.3 From 6cf86ed4c1c7b5a7b74630347de0dfb413d3cd18 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Thu, 4 Nov 2021 21:44:46 +0100 Subject: 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. --- etc/NEWS | 5 + lisp/emacs-lisp/pp.el | 122 +++++++++++++++++++++ .../lisp/emacs-lisp/pp-resources/code-formats.erts | 97 ++++++++++++++++ test/lisp/emacs-lisp/pp-tests.el | 4 + 4 files changed, 228 insertions(+) create mode 100644 test/lisp/emacs-lisp/pp-resources/code-formats.erts (limited to 'lisp/emacs-lisp/pp.el') diff --git a/etc/NEWS b/etc/NEWS index 30df529c687..1b3f4c0524f 100644 --- a/etc/NEWS +++ b/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 diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index 4ff2cd59eba..5a643d94e4b 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -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 diff --git a/test/lisp/emacs-lisp/pp-resources/code-formats.erts b/test/lisp/emacs-lisp/pp-resources/code-formats.erts new file mode 100644 index 00000000000..821e326867b --- /dev/null +++ b/test/lisp/emacs-lisp/pp-resources/code-formats.erts @@ -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*"))) +=-=-= diff --git a/test/lisp/emacs-lisp/pp-tests.el b/test/lisp/emacs-lisp/pp-tests.el index b04030cc432..4cae1a73775 100644 --- a/test/lisp/emacs-lisp/pp-tests.el +++ b/test/lisp/emacs-lisp/pp-tests.el @@ -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. -- cgit v1.2.3 From 292f50d27b399370809ccb6bbabc365120fc2256 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Thu, 4 Nov 2021 21:52:56 +0100 Subject: Make lambda/closure help buttons format as Emacs Lisp * lisp/help.el (help--describe-command): Format lambda/closures as Emacs Lisp. * lisp/emacs-lisp/pp.el (pp-display-expression): Allow formatting as Emacs Lisp. --- lisp/emacs-lisp/pp.el | 9 +++++++-- lisp/help.el | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'lisp/emacs-lisp/pp.el') diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index 5a643d94e4b..ca3f2a270e2 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -90,8 +90,10 @@ Output stream is STREAM, or value of `standard-output' (which see)." (princ (pp-to-string object) (or stream standard-output))) ;;;###autoload -(defun pp-display-expression (expression out-buffer-name) +(defun pp-display-expression (expression out-buffer-name &optional lisp) "Prettify and display EXPRESSION in an appropriate way, depending on length. +If LISP, format with `pp-emacs-lisp-code'; use `pp' otherwise. + If a temporary buffer is needed for representation, it will be named after OUT-BUFFER-NAME." (let* ((old-show-function temp-buffer-show-function) @@ -119,7 +121,10 @@ after OUT-BUFFER-NAME." (message "See buffer %s." out-buffer-name))) (message "%s" (buffer-substring (point-min) (point)))))))) (with-output-to-temp-buffer out-buffer-name - (pp expression) + (if lisp + (with-current-buffer standard-output + (pp-emacs-lisp-code expression)) + (pp expression)) (with-current-buffer standard-output (emacs-lisp-mode) (setq buffer-read-only nil) diff --git a/lisp/help.el b/lisp/help.el index d10ea1c2867..2a72656bb0d 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1347,7 +1347,7 @@ Return nil if the key sequence is too long." (symbol-name (car definition)) (lambda (_) (pp-display-expression - definition "*Help Source*")))))) + definition "*Help Source*" t)))))) (t (insert "??\n")))) -- cgit v1.2.3 From fb1267d90a5c25a29dbdae170ea065e017b05d29 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Thu, 4 Nov 2021 22:07:48 +0100 Subject: Indent lambdas/closures better * lisp/emacs-lisp/pp.el (pp--format-function): Indent lambdas and closures better. --- lisp/emacs-lisp/pp.el | 13 ++++++++++++- test/lisp/emacs-lisp/pp-resources/code-formats.erts | 8 ++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'lisp/emacs-lisp/pp.el') diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index ca3f2a270e2..1d7b935b6d9 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -236,9 +236,20 @@ Ignores leading comment characters." (defun pp--format-function (sexp) (let* ((sym (car sexp)) (edebug (get sym 'edebug-form-spec)) - (indent (get sym 'lisp-indent-function))) + (indent (get sym 'lisp-indent-function)) + (doc (get sym 'doc-string-elt))) (when (eq indent 'defun) (setq indent 2)) + ;; We probably want to keep all the elements before the doc string + ;; on a single line. + (when doc + (setq indent (1- doc))) + ;; Special-case closures -- these shouldn't really exist in actual + ;; source code, so there's no indentation information. But make + ;; them output slightly better. + (when (and (not indent) + (eq sym 'closure)) + (setq indent 0)) (pp--insert "(" sym) (pop sexp) ;; Get the first entries on the first line. diff --git a/test/lisp/emacs-lisp/pp-resources/code-formats.erts b/test/lisp/emacs-lisp/pp-resources/code-formats.erts index 821e326867b..f48e262f69d 100644 --- a/test/lisp/emacs-lisp/pp-resources/code-formats.erts +++ b/test/lisp/emacs-lisp/pp-resources/code-formats.erts @@ -95,3 +95,11 @@ Also add the value to the front of the list in the variable `values'." (values--store-value result) (pp-display-expression result "*Pp Eval Output*"))) =-=-= + +Name: code-formats9 + +=-= +(lambda () + (interactive) + 1) +=-=-= -- cgit v1.2.3 From cb9f3e1158a7b3cf556bdeeb5c4ba5896279a573 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Thu, 4 Nov 2021 22:31:15 +0100 Subject: Fix up some list folding in pp-emacs-lisp-code * lisp/emacs-lisp/pp.el (pp--insert-lisp, pp--format-list) (pp--insert): Touch up list folding. --- lisp/emacs-lisp/pp.el | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'lisp/emacs-lisp/pp.el') diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index 1d7b935b6d9..67a21c53915 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -199,7 +199,9 @@ Ignores leading comment characters." (pp--insert-lisp sexp) (insert "\n") (goto-char (point-min)) - (indent-sexp)))) + (indent-sexp) + (while (re-search-forward " +$" nil t) + (replace-match ""))))) (defun pp--insert-lisp (sexp) (cl-case (type-of sexp) @@ -208,8 +210,14 @@ Ignores leading comment characters." ((consp (cdr sexp)) (if (and (length= sexp 2) (eq (car sexp) 'quote)) - (let ((print-quoted t)) - (prin1 sexp)) + (cond + ((symbolp (cadr sexp)) + (let ((print-quoted t)) + (prin1 sexp))) + ((consp (cadr sexp)) + (insert "'") + (pp--format-list (cadr sexp) + (set-marker (make-marker) (1- (point)))))) (pp--format-list sexp))) (t (princ sexp)))) @@ -227,11 +235,15 @@ Ignores leading comment characters." (defun pp--format-vector (sexp) (prin1 sexp)) -(defun pp--format-list (sexp) +(defun pp--format-list (sexp &optional start) (if (and (symbolp (car sexp)) (not (keywordp (car sexp)))) (pp--format-function sexp) - (prin1 sexp))) + (insert "(") + (pp--insert start (pop sexp)) + (while sexp + (pp--insert " " (pop sexp))) + (insert ")"))) (defun pp--format-function (sexp) (let* ((sym (car sexp)) @@ -300,7 +312,11 @@ Ignores leading comment characters." (insert ")")) (defun pp--insert (delim &rest things) - (let ((start (point))) + (let ((start (if (markerp delim) + (prog1 + delim + (setq delim nil)) + (point-marker)))) (when delim (insert delim)) (dolist (thing things) @@ -310,7 +326,8 @@ Ignores leading comment characters." (when (> (current-column) (window-width)) (save-excursion (goto-char start) - (insert "\n"))))) + (unless (looking-at "[ \t]+$") + (insert "\n")))))) (defun pp--indent-buffer () (goto-char (point-min)) -- cgit v1.2.3 From 4cf7af5a2a9aecb067d95b96a5965cc74627e86b Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Thu, 4 Nov 2021 23:16:47 +0100 Subject: Tweak multi-line expressions in pp--format-function * lisp/emacs-lisp/pp.el (pp--format-function): Fix up multi-line expressions. --- lisp/emacs-lisp/pp.el | 10 ++++++++-- test/lisp/emacs-lisp/pp-resources/code-formats.erts | 13 ++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'lisp/emacs-lisp/pp.el') diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index 67a21c53915..df837fa691e 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -267,8 +267,14 @@ Ignores leading comment characters." ;; Get the first entries on the first line. (if indent (pp--format-definition sexp indent edebug) - (while sexp - (pp--insert " " (pop sexp)))) + (let ((prev 0)) + (while sexp + (let ((start (point))) + ;; Don't put sexps on the same line as a multi-line sexp + ;; preceding it. + (pp--insert (if (> prev 1) "\n" " ") + (pop sexp)) + (setq prev (count-lines start (point))))))) (insert ")"))) (defun pp--format-definition (sexp indent edebug) diff --git a/test/lisp/emacs-lisp/pp-resources/code-formats.erts b/test/lisp/emacs-lisp/pp-resources/code-formats.erts index f48e262f69d..c2733d84dae 100644 --- a/test/lisp/emacs-lisp/pp-resources/code-formats.erts +++ b/test/lisp/emacs-lisp/pp-resources/code-formats.erts @@ -40,7 +40,8 @@ Name: code-formats3 (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)))) + bar-bar-bar-bar-bar-bar-bar-bar-bar-bar + 2)))) =-=-= @@ -103,3 +104,13 @@ Name: code-formats9 (interactive) 1) =-=-= + + +Name: code-formats10 + +=-= +(funcall foo (concat "zot" (if (length> site 0) site + "bar") + "+" + (string-replace " " "+" query))) +=-=-= -- cgit v1.2.3 From a78ac0c5df74be6925f48896fd024f1f6f363c44 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Thu, 4 Nov 2021 23:32:51 +0100 Subject: Try harder to keep lines short in pp-emacs-lisp-code * lisp/emacs-lisp/pp.el (pp--insert): Try harder to keep lines short. --- lisp/emacs-lisp/pp.el | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'lisp/emacs-lisp/pp.el') diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index df837fa691e..ffaa2aeb93a 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -333,7 +333,17 @@ Ignores leading comment characters." (save-excursion (goto-char start) (unless (looking-at "[ \t]+$") - (insert "\n")))))) + (insert "\n")) + (pp--indent-buffer) + (goto-char (point-max)) + ;; If we're still too wide, then go up one step and try to + ;; insert a newline there. + (when (> (current-column) (window-width)) + (condition-case () + (backward-up-list 1) + (:success (when (looking-back " " 2) + (insert "\n"))) + (error nil))))))) (defun pp--indent-buffer () (goto-char (point-min)) -- cgit v1.2.3 From c1865384d736cf290971e049a9d2f7869c7396da Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Fri, 5 Nov 2021 15:27:03 +0100 Subject: Allow 'pp' to limit the line widths * lisp/emacs-lisp/pp.el (pp-max-width, pp-use-max-width): New user options (bug#11934). (pp-to-string): Use it. (pp--insert-lisp): Tweak whether to use standard-output or not. (pp--max-width): New function. --- etc/NEWS | 5 ++ lisp/emacs-lisp/pp.el | 90 ++++++++++++++++------ .../lisp/emacs-lisp/pp-resources/code-formats.erts | 8 ++ 3 files changed, 78 insertions(+), 25 deletions(-) (limited to 'lisp/emacs-lisp/pp.el') diff --git a/etc/NEWS b/etc/NEWS index 08ff1f1e697..9b4112a8f2b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -422,6 +422,11 @@ Use 'exif-parse-file' and 'exif-field' instead. * Lisp Changes in Emacs 29.1 +--- +*** New user option 'pp-use-max-width'. +If non-nil, 'pp' will attempt to limit the line length when formatting +long lists and vectors. + --- *** New function 'pp-emacs-lisp-code'. 'pp' formats general Lisp sexps. This function does much the same, diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index ffaa2aeb93a..8ef5979a270 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -33,22 +33,43 @@ (defcustom pp-escape-newlines t "Value of `print-escape-newlines' used by pp-* functions." + :type 'boolean) + +(defcustom pp-max-width t + "Max width to use when formatting. +If nil, there's no max width. If t, use the window width. +Otherwise this should be a number." + :type '(choice (const :tag "none" nil) + (const :tag "window width" t) + number) + :version "29.1") + +(defcustom pp-use-max-width nil + "If non-nil, `pp'-related functions will try to fold lines. +The target width is given by the `pp-max-width' variable." :type 'boolean - :group 'pp) + :version "29.1") + +(defvar pp--inhibit-function-formatting nil) ;;;###autoload (defun pp-to-string (object) "Return a string containing the pretty-printed representation of OBJECT. OBJECT can be any Lisp object. Quoting characters are used as needed to make output that `read' can handle, whenever this is possible." - (with-temp-buffer - (lisp-mode-variables nil) - (set-syntax-table emacs-lisp-mode-syntax-table) - (let ((print-escape-newlines pp-escape-newlines) - (print-quoted t)) - (prin1 object (current-buffer))) - (pp-buffer) - (buffer-string))) + (if pp-use-max-width + (let ((pp--inhibit-function-formatting t)) + (with-temp-buffer + (pp-emacs-lisp-code object) + (buffer-string))) + (with-temp-buffer + (lisp-mode-variables nil) + (set-syntax-table emacs-lisp-mode-syntax-table) + (let ((print-escape-newlines pp-escape-newlines) + (print-quoted t)) + (prin1 object (current-buffer))) + (pp-buffer) + (buffer-string)))) ;;;###autoload (defun pp-buffer () @@ -56,7 +77,6 @@ to make output that `read' can handle, whenever this is possible." (interactive) (goto-char (point-min)) (while (not (eobp)) - ;; (message "%06d" (- (point-max) (point))) (cond ((ignore-errors (down-list 1) t) (save-excursion @@ -86,6 +106,9 @@ can handle, whenever this is possible. This function does not apply special formatting rules for Emacs Lisp code. See `pp-emacs-lisp-code' instead. +By default, this function won't limit the line length of lists +and vectors. Bind `pp-use-max-width' to a non-nil value to do so. + Output stream is STREAM, or value of `standard-output' (which see)." (princ (pp-to-string object) (or stream standard-output))) @@ -191,17 +214,19 @@ Ignores leading comment characters." ;;;###autoload (defun pp-emacs-lisp-code (sexp) - "Insert SEXP into the current buffer, formatted as Emacs Lisp code." + "Insert SEXP into the current buffer, formatted as Emacs Lisp code. +Use the `pp-max-width' variable to control the desired line length." (require 'edebug) - (let ((standard-output (current-buffer))) - (save-restriction - (narrow-to-region (point) (point)) + (let ((obuf (current-buffer))) + (with-temp-buffer + (emacs-lisp-mode) (pp--insert-lisp sexp) (insert "\n") (goto-char (point-min)) (indent-sexp) (while (re-search-forward " +$" nil t) - (replace-match ""))))) + (replace-match "")) + (insert-into-buffer obuf)))) (defun pp--insert-lisp (sexp) (cl-case (type-of sexp) @@ -213,30 +238,35 @@ Ignores leading comment characters." (cond ((symbolp (cadr sexp)) (let ((print-quoted t)) - (prin1 sexp))) + (prin1 sexp (current-buffer)))) ((consp (cadr sexp)) (insert "'") (pp--format-list (cadr sexp) (set-marker (make-marker) (1- (point)))))) (pp--format-list sexp))) (t - (princ sexp)))) + (princ sexp (current-buffer))))) ;; Print some of the smaller integers as characters, perhaps? (integer (if (<= ?0 sexp ?z) (let ((print-integers-as-characters t)) - (princ sexp)) - (princ sexp))) + (princ sexp (current-buffer))) + (princ sexp (current-buffer)))) (string (let ((print-escape-newlines t)) - (prin1 sexp))) - (otherwise (princ sexp)))) + (prin1 sexp (current-buffer)))) + (otherwise (princ sexp (current-buffer))))) (defun pp--format-vector (sexp) - (prin1 sexp)) + (insert "[") + (cl-loop for i from 0 + for element across sexp + do (pp--insert (and (> i 0) " ") element)) + (insert "]")) (defun pp--format-list (sexp &optional start) (if (and (symbolp (car sexp)) + (not pp--inhibit-function-formatting) (not (keywordp (car sexp)))) (pp--format-function sexp) (insert "(") @@ -292,7 +322,7 @@ Ignores leading comment characters." (cl-decf indent)) (when (stringp (car sexp)) (insert "\n") - (prin1 (pop sexp))) + (prin1 (pop sexp) (current-buffer))) ;; Then insert the rest with line breaks before each form. (while sexp (insert "\n") @@ -329,7 +359,7 @@ Ignores leading comment characters." (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)) + (when (> (current-column) (pp--max-width)) (save-excursion (goto-char start) (unless (looking-at "[ \t]+$") @@ -338,13 +368,23 @@ Ignores leading comment characters." (goto-char (point-max)) ;; If we're still too wide, then go up one step and try to ;; insert a newline there. - (when (> (current-column) (window-width)) + (when (> (current-column) (pp--max-width)) (condition-case () (backward-up-list 1) (:success (when (looking-back " " 2) (insert "\n"))) (error nil))))))) +(defun pp--max-width () + (cond ((numberp pp-max-width) + pp-max-width) + ((null pp-max-width) + most-positive-fixnum) + ((eq pp-max-width t) + (window-width)) + (t + (error "Invalid pp-max-width value: %s" pp-max-width)))) + (defun pp--indent-buffer () (goto-char (point-min)) (while (not (eobp)) diff --git a/test/lisp/emacs-lisp/pp-resources/code-formats.erts b/test/lisp/emacs-lisp/pp-resources/code-formats.erts index c2733d84dae..2b2001d0964 100644 --- a/test/lisp/emacs-lisp/pp-resources/code-formats.erts +++ b/test/lisp/emacs-lisp/pp-resources/code-formats.erts @@ -114,3 +114,11 @@ Name: code-formats10 "+" (string-replace " " "+" query))) =-=-= + + +Name: code-formats11 + +=-= +(lambda () + [(foo bar) (foo bar)]) +=-=-= -- cgit v1.2.3 From 82d0550648969ce10303b67b7a8da51c4e855501 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sat, 6 Nov 2021 02:20:06 +0100 Subject: Remove messaging in pp-display-expression. * lisp/emacs-lisp/pp.el (pp-display-expression): Remove confusing message -- we don't usually say that we've popped up a new buffer when we do so. --- lisp/emacs-lisp/pp.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'lisp/emacs-lisp/pp.el') diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index 8ef5979a270..3f5e1a48469 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -140,8 +140,7 @@ after OUT-BUFFER-NAME." (select-window window) (run-hooks 'temp-buffer-show-hook)) (when (window-live-p old-selected) - (select-window old-selected)) - (message "See buffer %s." out-buffer-name))) + (select-window old-selected)))) (message "%s" (buffer-substring (point-min) (point)))))))) (with-output-to-temp-buffer out-buffer-name (if lisp -- cgit v1.2.3 From d69b5a9caaf7697eb70b9eb5e63fae8b94ccd798 Mon Sep 17 00:00:00 2001 From: Lars Ingebrigtsen Date: Sun, 7 Nov 2021 02:44:42 +0100 Subject: Fix pp-emacs-lisp-code for `when' and related * lisp/emacs-lisp/pp.el (pp--format-definition): Skip edebug specs we don't understand at all. --- lisp/emacs-lisp/pp.el | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lisp/emacs-lisp/pp.el') diff --git a/lisp/emacs-lisp/pp.el b/lisp/emacs-lisp/pp.el index 3f5e1a48469..8464b5a5198 100644 --- a/lisp/emacs-lisp/pp.el +++ b/lisp/emacs-lisp/pp.el @@ -310,6 +310,9 @@ Use the `pp-max-width' variable to control the desired line length." (while (and (cl-plusp indent) sexp) (insert " ") + ;; We don't understand all the edebug specs. + (unless (consp edebug) + (setq edebug nil)) (if (and (consp (car edebug)) (eq (caar edebug) '&rest)) (pp--insert-binding (pop sexp)) -- cgit v1.2.3