|
1 | 1 | basilisp.pprint
|
2 | 2 | ===============
|
3 | 3 |
|
| 4 | +.. lpy:currentns:: basilisp.pprint |
| 5 | +
|
4 | 6 | .. toctree::
|
5 | 7 | :maxdepth: 2
|
6 | 8 | :caption: Contents:
|
7 | 9 |
|
| 10 | +.. _pretty_printing: |
| 11 | + |
| 12 | +Pretty Printing |
| 13 | +--------------- |
| 14 | + |
| 15 | +Pretty printing built-in data structures is as easy as a call to :lpy:fn:`pprint`. |
| 16 | + |
| 17 | +.. code-block:: |
| 18 | +
|
| 19 | + (require '[basilisp.pprint :as pprint]) |
| 20 | + (pprint/pprint (range 30)) |
| 21 | +
|
| 22 | +The output can be configured using a number of different control variables, which are expressed as dynamic Vars. |
| 23 | + |
| 24 | +- :lpy:var:`*print-base*` |
| 25 | +- :lpy:var:`*print-miser-width*` |
| 26 | +- :lpy:var:`*print-pretty*` |
| 27 | +- :lpy:var:`*print-pprint-dispatch*` |
| 28 | +- :lpy:var:`*print-radix*` |
| 29 | +- :lpy:var:`*print-right-margin*` |
| 30 | +- :lpy:var:`*print-sort-keys*` |
| 31 | +- :lpy:var:`*print-suppress-namespaces*` |
| 32 | + |
| 33 | +You can pretty print the last result from the REPL using the :lpy:fn:`pp` convenience macro. |
| 34 | + |
| 35 | +As an alternative, the :lpy:fn:`write` API enables a more ergonomic API for configuring the printer using keyword arguments rather than dynamic Vars. |
| 36 | + |
| 37 | +.. code-block:: |
| 38 | +
|
| 39 | + (pprint/write (ns-interns 'basilisp.pprint) :sort-keys true) |
| 40 | + ;; {*current-length* #'basilisp.pprint/*current-length* |
| 41 | + ;; ... |
| 42 | + ;; write-out #'basilisp.pprint/write-out} |
| 43 | +
|
| 44 | +.. _custom_pretty_print_dispatch_function: |
| 45 | + |
| 46 | +Custom Pretty Print Dispatch Function |
| 47 | +------------------------------------- |
| 48 | + |
| 49 | +The default dispatch function is :lpy:fn:`simple-dispatch` which can print most builtin Basilisp types. |
| 50 | +Using the builtin macros and utilities, it is possible to create a custom dispatch function. |
| 51 | + |
| 52 | +.. _pretty_printing_concepts: |
| 53 | + |
| 54 | +Pretty Printing Concepts |
| 55 | +^^^^^^^^^^^^^^^^^^^^^^^^ |
| 56 | + |
| 57 | +The pretty printing algorithm used in ``basilisp.pprint`` is based on the XP algorithm defined in Richard Water's 1989 paper "XP: A Common Lisp Pretty Printing System" as adapted in Clojure's ``pprint`` by Tom Faulhaber. |
| 58 | +There are three basic concepts in the XP algorithm which are necessary in order to create a custom dispatch function. |
| 59 | + |
| 60 | +- *Logical blocks* are groups of output that should be treated as a single unit by the pretty printer. |
| 61 | + Logical blocks can nest, so one logical block may contain 0 or more other logical blocks. |
| 62 | + For example, a vector may contain a map; the vector would be a logical block and the map would also be a logical block. |
| 63 | + ``simple-dispatch`` even treats key/value pairs in associative type outputs as a logical block, so they are printed on the same line whenever possible. |
| 64 | + |
| 65 | + A dispatch function can emit a logical block using the :lpy:fn:`pprint-logical-block` macro. |
| 66 | + |
| 67 | +- *Conditional newlines* can be emitted anywhere a newline may need inserted into the output stream. |
| 68 | + Newlines can be one of 3 different types which hints to the pretty printer when a newline should be emitted. |
| 69 | + |
| 70 | + Dispatch functions can emit newlines in any supported style using the :lpy:fn:`pprint-newline` function. |
| 71 | + |
| 72 | + - ``:linear`` style newlines should be emitted whenever the enclosing logical block does not fit on a single line. |
| 73 | + Note that if any linear newline is emitted in a block, every linear newline will be emitted in that block. |
| 74 | + |
| 75 | + - ``:mandatory`` style newlines are emitted in all cases. |
| 76 | + |
| 77 | + - ``:miser`` style newlines are emitted only when the output will occur in the "miser" region as defined by :lpy:var:`*print-miser-width*`. |
| 78 | + This allows additional newlines to be emitted as the output nests closer to the right margin. |
| 79 | + |
| 80 | +- *Indentation* commands indicate how indentation of subsequent lines in a logical block should be defined. |
| 81 | + Indentation may be defined relative to either the starting column of the current logical block or to the current column of the output. |
| 82 | + |
| 83 | + Dispatch functions can control indentation using the :lpy:fn:`pprint-indent` function. |
| 84 | + |
| 85 | +Pretty printing is most useful for viewing large, nested structures in a more human-friendly way. |
| 86 | +To that end, dispatch functions wishing to print any collection may want to use the :lpy:fn:`print-length-loop` macro to loop over the output, respecting the :lpy:var:`basilisp.core/*print-length*` setting. |
| 87 | + |
| 88 | +Dispatch functions which may need to be called on nested elements should use :lpy:fn:`write-out` to ensure that :lpy:var:`basilisp.core/*print-level*` is respected. |
| 89 | +Scalar values can be printed with :lpy:fn:`basilisp.core/pr` or just written directly to :lpy:var:`*out*`. |
| 90 | + |
| 91 | +.. _unimplemented_pprint_features: |
| 92 | + |
| 93 | +Unimplemented Features |
| 94 | +---------------------- |
| 95 | + |
| 96 | +The following features from ``clojure.pprint`` are not currently implemented: |
| 97 | + |
| 98 | +- ``:fill`` newlines |
| 99 | +- ``code-dispatch`` for printing code |
| 100 | +- ``cl-format`` |
| 101 | + |
| 102 | +.. _pprint_references: |
| 103 | + |
| 104 | +References |
| 105 | +---------- |
| 106 | + |
| 107 | +- Tom Faulhaber et al.; ``clojure.pprint`` (`API <https://clojure.github.io/clojure/clojure.pprint-api.html>`_, `Documentation <https://clojure.github.io/clojure/doc/clojure/pprint/PrettyPrinting.html>`_) |
| 108 | +- Oppen, Derek; \"Prettyprinting\"; October 1980 |
| 109 | +- Waters, Richard; \"XP: A Common Lisp Pretty Printing System\"; March 1989 |
| 110 | + |
| 111 | +.. _pprint_api: |
| 112 | + |
| 113 | +API |
| 114 | +--- |
| 115 | + |
8 | 116 | .. autonamespace:: basilisp.pprint
|
9 | 117 | :members:
|
10 |
| - :undoc-members: |
| 118 | + :undoc-members: |
| 119 | + :exclude-members: LogicalBlock, StartBlock, EndBlock, Blob, Newline, Indent, *current-length*, *current-level* |
0 commit comments