Klimi's new dotfiles with stow.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

331 рядки
12 KiB

4 роки тому
  1. ;; Pretty printer patch for SBCL, which adds the "annotations" feature
  2. ;; required for sending presentations through pretty-printing streams.
  3. ;;
  4. ;; The section marked "Changed functions" and the DEFSTRUCT
  5. ;; PRETTY-STREAM are based on SBCL's pprint.lisp.
  6. ;;
  7. ;; Public domain.
  8. (in-package "SB!PRETTY")
  9. (defstruct (annotation (:include queued-op))
  10. (handler (constantly nil) :type function)
  11. (record))
  12. (defstruct (pretty-stream (:include sb!kernel:ansi-stream
  13. (out #'pretty-out)
  14. (sout #'pretty-sout)
  15. (misc #'pretty-misc))
  16. (:constructor make-pretty-stream (target))
  17. (:copier nil))
  18. ;; Where the output is going to finally go.
  19. (target (missing-arg) :type stream)
  20. ;; Line length we should format to. Cached here so we don't have to keep
  21. ;; extracting it from the target stream.
  22. (line-length (or *print-right-margin*
  23. (sb!impl::line-length target)
  24. default-line-length)
  25. :type column)
  26. ;; A simple string holding all the text that has been output but not yet
  27. ;; printed.
  28. (buffer (make-string initial-buffer-size) :type (simple-array character (*)))
  29. ;; The index into BUFFER where more text should be put.
  30. (buffer-fill-pointer 0 :type index)
  31. ;; Whenever we output stuff from the buffer, we shift the remaining noise
  32. ;; over. This makes it difficult to keep references to locations in
  33. ;; the buffer. Therefore, we have to keep track of the total amount of
  34. ;; stuff that has been shifted out of the buffer.
  35. (buffer-offset 0 :type posn)
  36. ;; The column the first character in the buffer will appear in. Normally
  37. ;; zero, but if we end up with a very long line with no breaks in it we
  38. ;; might have to output part of it. Then this will no longer be zero.
  39. (buffer-start-column (or (sb!impl::charpos target) 0) :type column)
  40. ;; The line number we are currently on. Used for *PRINT-LINES*
  41. ;; abbreviations and to tell when sections have been split across
  42. ;; multiple lines.
  43. (line-number 0 :type index)
  44. ;; the value of *PRINT-LINES* captured at object creation time. We
  45. ;; use this, instead of the dynamic *PRINT-LINES*, to avoid
  46. ;; weirdness like
  47. ;; (let ((*print-lines* 50))
  48. ;; (pprint-logical-block ..
  49. ;; (dotimes (i 10)
  50. ;; (let ((*print-lines* 8))
  51. ;; (print (aref possiblybigthings i) prettystream)))))
  52. ;; terminating the output of the entire logical blockafter 8 lines.
  53. (print-lines *print-lines* :type (or index null) :read-only t)
  54. ;; Stack of logical blocks in effect at the buffer start.
  55. (blocks (list (make-logical-block)) :type list)
  56. ;; Buffer holding the per-line prefix active at the buffer start.
  57. ;; Indentation is included in this. The length of this is stored
  58. ;; in the logical block stack.
  59. (prefix (make-string initial-buffer-size) :type (simple-array character (*)))
  60. ;; Buffer holding the total remaining suffix active at the buffer start.
  61. ;; The characters are right-justified in the buffer to make it easier
  62. ;; to output the buffer. The length is stored in the logical block
  63. ;; stack.
  64. (suffix (make-string initial-buffer-size) :type (simple-array character (*)))
  65. ;; Queue of pending operations. When empty, HEAD=TAIL=NIL. Otherwise,
  66. ;; TAIL holds the first (oldest) cons and HEAD holds the last (newest)
  67. ;; cons. Adding things to the queue is basically (setf (cdr head) (list
  68. ;; new)) and removing them is basically (pop tail) [except that care must
  69. ;; be taken to handle the empty queue case correctly.]
  70. (queue-tail nil :type list)
  71. (queue-head nil :type list)
  72. ;; Block-start queue entries in effect at the queue head.
  73. (pending-blocks nil :type list)
  74. ;; Queue of annotations to the buffer
  75. (annotations-tail nil :type list)
  76. (annotations-head nil :type list))
  77. (defmacro enqueue (stream type &rest args)
  78. (let ((constructor (intern (concatenate 'string
  79. "MAKE-"
  80. (symbol-name type))
  81. "SB-PRETTY")))
  82. (once-only ((stream stream)
  83. (entry `(,constructor :posn
  84. (index-posn
  85. (pretty-stream-buffer-fill-pointer
  86. ,stream)
  87. ,stream)
  88. ,@args))
  89. (op `(list ,entry))
  90. (head `(pretty-stream-queue-head ,stream)))
  91. `(progn
  92. (if ,head
  93. (setf (cdr ,head) ,op)
  94. (setf (pretty-stream-queue-tail ,stream) ,op))
  95. (setf (pretty-stream-queue-head ,stream) ,op)
  96. ,entry))))
  97. ;;;
  98. ;;; New helper functions
  99. ;;;
  100. (defun enqueue-annotation (stream handler record)
  101. (enqueue stream annotation :handler handler
  102. :record record))
  103. (defun re-enqueue-annotation (stream annotation)
  104. (let* ((annotation-cons (list annotation))
  105. (head (pretty-stream-annotations-head stream)))
  106. (if head
  107. (setf (cdr head) annotation-cons)
  108. (setf (pretty-stream-annotations-tail stream) annotation-cons))
  109. (setf (pretty-stream-annotations-head stream) annotation-cons)
  110. nil))
  111. (defun re-enqueue-annotations (stream end)
  112. (loop for tail = (pretty-stream-queue-tail stream) then (cdr tail)
  113. while (and tail (not (eql (car tail) end)))
  114. when (annotation-p (car tail))
  115. do (re-enqueue-annotation stream (car tail))))
  116. (defun dequeue-annotation (stream &key end-posn)
  117. (let ((next-annotation (car (pretty-stream-annotations-tail stream))))
  118. (when next-annotation
  119. (when (or (not end-posn)
  120. (<= (annotation-posn next-annotation) end-posn))
  121. (pop (pretty-stream-annotations-tail stream))
  122. (unless (pretty-stream-annotations-tail stream)
  123. (setf (pretty-stream-annotations-head stream) nil))
  124. next-annotation))))
  125. (defun invoke-annotation (stream annotation truncatep)
  126. (let ((target (pretty-stream-target stream)))
  127. (funcall (annotation-handler annotation)
  128. (annotation-record annotation)
  129. target
  130. truncatep)))
  131. (defun output-buffer-with-annotations (stream end)
  132. (let ((target (pretty-stream-target stream))
  133. (buffer (pretty-stream-buffer stream))
  134. (end-posn (index-posn end stream))
  135. (start 0))
  136. (loop
  137. for annotation = (dequeue-annotation stream :end-posn end-posn)
  138. while annotation
  139. do
  140. (let ((annotation-index (posn-index (annotation-posn annotation)
  141. stream)))
  142. (when (> annotation-index start)
  143. (write-string buffer target :start start
  144. :end annotation-index)
  145. (setf start annotation-index))
  146. (invoke-annotation stream annotation nil)))
  147. (when (> end start)
  148. (write-string buffer target :start start :end end))))
  149. (defun flush-annotations (stream end truncatep)
  150. (let ((end-posn (index-posn end stream)))
  151. (loop
  152. for annotation = (dequeue-annotation stream :end-posn end-posn)
  153. while annotation
  154. do (invoke-annotation stream annotation truncatep))))
  155. ;;;
  156. ;;; Changed functions
  157. ;;;
  158. (defun maybe-output (stream force-newlines-p)
  159. (declare (type pretty-stream stream))
  160. (let ((tail (pretty-stream-queue-tail stream))
  161. (output-anything nil))
  162. (loop
  163. (unless tail
  164. (setf (pretty-stream-queue-head stream) nil)
  165. (return))
  166. (let ((next (pop tail)))
  167. (etypecase next
  168. (newline
  169. (when (ecase (newline-kind next)
  170. ((:literal :mandatory :linear) t)
  171. (:miser (misering-p stream))
  172. (:fill
  173. (or (misering-p stream)
  174. (> (pretty-stream-line-number stream)
  175. (logical-block-section-start-line
  176. (first (pretty-stream-blocks stream))))
  177. (ecase (fits-on-line-p stream
  178. (newline-section-end next)
  179. force-newlines-p)
  180. ((t) nil)
  181. ((nil) t)
  182. (:dont-know
  183. (return))))))
  184. (setf output-anything t)
  185. (output-line stream next)))
  186. (indentation
  187. (unless (misering-p stream)
  188. (set-indentation stream
  189. (+ (ecase (indentation-kind next)
  190. (:block
  191. (logical-block-start-column
  192. (car (pretty-stream-blocks stream))))
  193. (:current
  194. (posn-column
  195. (indentation-posn next)
  196. stream)))
  197. (indentation-amount next)))))
  198. (block-start
  199. (ecase (fits-on-line-p stream (block-start-section-end next)
  200. force-newlines-p)
  201. ((t)
  202. ;; Just nuke the whole logical block and make it look like one
  203. ;; nice long literal. (But don't nuke annotations.)
  204. (let ((end (block-start-block-end next)))
  205. (expand-tabs stream end)
  206. (re-enqueue-annotations stream end)
  207. (setf tail (cdr (member end tail)))))
  208. ((nil)
  209. (really-start-logical-block
  210. stream
  211. (posn-column (block-start-posn next) stream)
  212. (block-start-prefix next)
  213. (block-start-suffix next)))
  214. (:dont-know
  215. (return))))
  216. (block-end
  217. (really-end-logical-block stream))
  218. (tab
  219. (expand-tabs stream next))
  220. (annotation
  221. (re-enqueue-annotation stream next))))
  222. (setf (pretty-stream-queue-tail stream) tail))
  223. output-anything))
  224. (defun output-line (stream until)
  225. (declare (type pretty-stream stream)
  226. (type newline until))
  227. (let* ((target (pretty-stream-target stream))
  228. (buffer (pretty-stream-buffer stream))
  229. (kind (newline-kind until))
  230. (literal-p (eq kind :literal))
  231. (amount-to-consume (posn-index (newline-posn until) stream))
  232. (amount-to-print
  233. (if literal-p
  234. amount-to-consume
  235. (let ((last-non-blank
  236. (position #\space buffer :end amount-to-consume
  237. :from-end t :test #'char/=)))
  238. (if last-non-blank
  239. (1+ last-non-blank)
  240. 0)))))
  241. (output-buffer-with-annotations stream amount-to-print)
  242. (flush-annotations stream amount-to-consume nil)
  243. (let ((line-number (pretty-stream-line-number stream)))
  244. (incf line-number)
  245. (when (and (not *print-readably*)
  246. (pretty-stream-print-lines stream)
  247. (>= line-number (pretty-stream-print-lines stream)))
  248. (write-string " .." target)
  249. (flush-annotations stream
  250. (pretty-stream-buffer-fill-pointer stream)
  251. t)
  252. (let ((suffix-length (logical-block-suffix-length
  253. (car (pretty-stream-blocks stream)))))
  254. (unless (zerop suffix-length)
  255. (let* ((suffix (pretty-stream-suffix stream))
  256. (len (length suffix)))
  257. (write-string suffix target
  258. :start (- len suffix-length)
  259. :end len))))
  260. (throw 'line-limit-abbreviation-happened t))
  261. (setf (pretty-stream-line-number stream) line-number)
  262. (write-char #\newline target)
  263. (setf (pretty-stream-buffer-start-column stream) 0)
  264. (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
  265. (block (first (pretty-stream-blocks stream)))
  266. (prefix-len
  267. (if literal-p
  268. (logical-block-per-line-prefix-end block)
  269. (logical-block-prefix-length block)))
  270. (shift (- amount-to-consume prefix-len))
  271. (new-fill-ptr (- fill-ptr shift))
  272. (new-buffer buffer)
  273. (buffer-length (length buffer)))
  274. (when (> new-fill-ptr buffer-length)
  275. (setf new-buffer
  276. (make-string (max (* buffer-length 2)
  277. (+ buffer-length
  278. (floor (* (- new-fill-ptr buffer-length)
  279. 5)
  280. 4)))))
  281. (setf (pretty-stream-buffer stream) new-buffer))
  282. (replace new-buffer buffer
  283. :start1 prefix-len :start2 amount-to-consume :end2 fill-ptr)
  284. (replace new-buffer (pretty-stream-prefix stream)
  285. :end1 prefix-len)
  286. (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
  287. (incf (pretty-stream-buffer-offset stream) shift)
  288. (unless literal-p
  289. (setf (logical-block-section-column block) prefix-len)
  290. (setf (logical-block-section-start-line block) line-number))))))
  291. (defun output-partial-line (stream)
  292. (let* ((fill-ptr (pretty-stream-buffer-fill-pointer stream))
  293. (tail (pretty-stream-queue-tail stream))
  294. (count
  295. (if tail
  296. (posn-index (queued-op-posn (car tail)) stream)
  297. fill-ptr))
  298. (new-fill-ptr (- fill-ptr count))
  299. (buffer (pretty-stream-buffer stream)))
  300. (when (zerop count)
  301. (error "Output-partial-line called when nothing can be output."))
  302. (output-buffer-with-annotations stream count)
  303. (incf (pretty-stream-buffer-start-column stream) count)
  304. (replace buffer buffer :end1 new-fill-ptr :start2 count :end2 fill-ptr)
  305. (setf (pretty-stream-buffer-fill-pointer stream) new-fill-ptr)
  306. (incf (pretty-stream-buffer-offset stream) count)))
  307. (defun force-pretty-output (stream)
  308. (maybe-output stream nil)
  309. (expand-tabs stream nil)
  310. (re-enqueue-annotations stream nil)
  311. (output-buffer-with-annotations stream
  312. (pretty-stream-buffer-fill-pointer stream)))