Принтер CL - сложная и замечательная вещь, и я забыл большинство того, что я знал о нем, так что этот ответ вполне может быть неправильным.
Нет тривиального способа управления печать больших строк: вы можете управлять печатью больших общих массивов с помощью *print-array*
, но в этом случае есть специальное исключение для строк.
Тогда существует плохой подход и менее плохой подход.
плохой подход : определите метод на print-object
. Я думаю, что вам разрешено делать это для строк, но если вы сделаете это, то ваш метод будет вызываться всякий раз, когда вы хотите, чтобы строка была напечатана, поэтому вам лучше быть уверенным, что это правильно. Вероятно, способ обеспечить это - убедиться, что он слушает какую-то переменную и, если переменная не просит ее сделать что-то, он просто использует call-next-method
, чтобы выполнить реализацию, которая, вероятно, является правильной.
Менее плохой подход : используйте таблицу отправки симпатичного принтера, чтобы сделать то, что вам нужно. Это менее плохо (и, возможно, даже хорошо), потому что это не изменит того, что происходит, когда *print-pretty*
ложно, и вы также можете просто вернуть исходную таблицу, когда захотите.
Вот игрушка попытаться сделать это. Предупреждение : я не потратил достаточно времени, чтобы достаточно серьезно подумать о том, как это взаимодействует со всеми настройками управления принтером, и, как я уже сказал, я забыл много деталей, поэтому это почти наверняка просто неверно в много случаев. Так что не используйте это в рабочем коде, но что-то вроде этого может быть достаточно для целей отладки, где то, что напечатано, просто должно сказать вам достаточно для отладки программы и не должно быть правильным во всех деталях.
(defvar *toy-print-pprint-dispatch*
;; a copy of the default pprint dispatch table
(copy-pprint-dispatch nil))
(defvar *longest-string*
;; the longest string we try to print properly
40)
(defun write-string-maybe (stream string)
;; Maybe write a string.
(check-type string string "not a string")
(cond (*print-readably*
(write string :stream stream :pretty nil :readably t))
((<= (length string) *longest-string*)
(write string :stream stream :pretty nil))
(t
;; pretty sure this is wrong as it should defang the string
;; at least
(print-unreadable-object (string stream :type t)
(write-string string stream :start 0 :end *longest-string*)
(write-string "..." stream )))))
(set-pprint-dispatch 'string 'write-string-maybe 0 *toy-print-pprint-dispatch*)
(defun monkeys (length)
"Generate a random string"
(with-output-to-string (out)
(dotimes (i length)
(write-char
(code-char
(let ((c (random 27)))
(if (zerop c)
(if (zerop (random 5)) 10 32)
(+ 95 c)))) out))))
(defun test-it ()
(let ((*print-pretty* t)
(*print-pprint-dispatch* *toy-print-pprint-dispatch*))
(print (monkeys *longest-string*))
(print (monkeys (* *longest-string* 2)))
(let ((*print-pretty* nil))
(print (monkeys (* *longest-string* 2))))
(values)))
А теперь:
> (test-it)
"pcbkhetnbanuvsvsvqobbqlcodnafmpgdnlku pf"
#<simple-base-string vehgsgnjxixyp`hq`wcwwskmcg`r`jdplcsbdxvo...>
"tp ixreii ixpeb`pgrvcobcbysgikylabidrierclrijo`edugnerlslj srryypbpravomcuxupynf"