[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
pretty-printing funcalls with keywords
This is the same as the current pprint-function-call, but tries to treat
keyword arguments specially. It makes frames displayed in the debugger a
bit prettier.
-Miles
--
Miles Bader -- HCRC, University of Edinburgh -- miles@cogsci.ed.ac.uk
Ich bin ein Virus. Mach' mit und kopiere mich in Deine .signature.
97% of everything is grunge
;;; Stuff to make pretty-printing function-calls with keyword args nicer
(in-package :pretty-print)
(defun function-lambda-list-template (fun)
"Return a template corresponding to this FUNs lambda list (which is just
something that `looks' like it, e.g., one element for each arg + the &
keywords). A second value returned is NIL if none could be found, T if
the template is really a lambda-list, or :TYPES if it's actually the types
of the lambda list args (which is often just as useful)."
(typecase fun
((satisfies eval:interpreted-function-p) ; yick
(values (cadr (function-lambda-expression fun))
t))
(compiled-function
;; get the types of the lambda list instead...
(let ((fun-type (kernel:%function-header-type fun)))
(if (and (listp fun-type)
(eq (car fun-type) 'function))
(values (cadr fun-type) :types)
(values nil nil))))
(t
(values nil nil))))
(defun pprint-function-call (stream list &rest noise)
(declare (ignore noise))
(let ((template
(and (fboundp (car list))
(function-lambda-list-template (symbol-function (car list))))))
(pprint-logical-block (stream list :prefix "(" :suffix ")")
;; function name
(output-object (pprint-pop) stream)
(pprint-exit-if-list-exhausted)
;; arg indentation
(write-char #\Space stream)
(pprint-newline :fill stream)
(pprint-indent :current 0 stream)
;; args
(let ((in-keywords-p nil))
(loop
(when (not in-keywords-p)
;; see if are now
(loop
(when (null template)
(return))
(let ((ll-thing (pop template)))
(unless (member ll-thing lambda-list-keywords :test #'eq)
(return))
(when (eq ll-thing '&key)
(setf in-keywords-p t)))))
(cond (in-keywords-p
;; Print keywords arg values either on the same line with
;; their keyword, or on the next line, indented 3 spaces in.
(let* ((keyword (pprint-pop))
(value (pprint-pop)))
(pprint-logical-block (stream nil)
(output-object keyword stream)
(pprint-indent :block 3 stream)
(write-char #\Space stream)
(pprint-newline :fill stream)
(output-object value stream))))
(t
(output-object (pprint-pop) stream)))
(pprint-exit-if-list-exhausted)
(write-char #\Space stream)
(pprint-newline :linear stream))))))
(defun pprint-cond (stream list &rest noise)
(declare (ignore noise))
(funcall (formatter
"~:<~^~W~^ ~@_~:I~@{~:/PP:PPRINT-LINEAR/~^ ~_~}~:>")
stream
list))