diff --git a/README.md b/README.md index 8d45422..e69de29 100644 --- a/README.md +++ b/README.md @@ -1,160 +0,0 @@ - -# Pretty # - -`pretty` is an advanced pretty printer for [Lua](lua.org). It's primarily a -debugging tool, aiming for human readability, by detecting pattern in the input -data, and creating an output string utilizing and highlighting those patterns. - -## Code Example - -Setup is simple, use `pretty = require 'pretty'`, and you're good to go. - -```lua -> print(pretty( { 1, 2, 3 } )) -{ 1, 2, 3 } - -> print(pretty( { hello = 'world', num = 42 } )) -{ - num = 42 - hello = 'world' -} - -> print(pretty( { abs = math.abs, max = math.max, some = function() end } )) -{ - abs = builtin function (x) ... end - max = builtin function (x, ...) ... end - some = function () ... end -} - -> print(pretty( math.abs )) -builtin function (x) - -- math.abs - -- Returns the absolute value of x - - ... -end -``` - -## Motivation - -This project is the outcome of my frustration with existing pretty printers, and -a desire to expand upon the pretty printer I developed for -[Xenoterm](https://gitfub.space/takunomi/Xenoterm). The original Xenoterm pretty -printer was much simpler than `pretty` - and the current is even simpler - but -the enhancements I make, when compared to other pretty printers, inspired me to -create `pretty`. - -`pretty` sorts it's priorities like so: - -1. Human readability. -2. Lua-compatible output. -3. Customization. - -I'd rather have good defaults than provide a ton of customization options. If an -structure avoids easy representation in Lua, I'd rather extend the syntax, than -lose the info. - -Another aspect where `pretty` shines is in exploratory programming, when -attempting to avoid reliance on outside documentation. The amount of information -`pretty` exposes varies by the data you are inspecting. If you're inspecting -a list of functions, their function signatures are visible, but if you're -inspecting a single function, documentation and source location may appear if -available. - -## Features - -- Written in good-old pureblood Lua, with support for PUC Lua 5.0+ and - LuaJIT 2.0+. -- Redefining what it means to be "human readable": - * Is multi-line centric, to aid readablitiy. - * Indention and alignment of keys-value pairs. - * Keys-value pairs are [properly](http://www.davekoelle.com/alphanum.html) - sorted by key type and thereafter alphabetically. - * The format and structure of output changes depending upon the input. - Maps appear differently to deeply nested tables to long sequences - with short strings to short lists. - * Uses the standard `debug` library to gain information about functions - and other advanced structures. - -## Installation - -`pretty` is loadable directly with `require`. Either clone or download this -repository. Where you place it, depends upon what you want to do: - -1. **You want `pretty` in a specific project**: Place the `pretty` folder - somewhere in your project, and `require` it from one of your project files. -2. **You want `pretty` on your system**: Place the `pretty` folder such that - it's visible from your Lua-path. On my system this might be - `/usr/local/share/lua/5.1/`. Now you can `require` it from anywhere. - -## API Documentation - -`pretty` exposes a single function, the `pretty` function itself. It's function -signature is `pretty(value, options)`. `value` can be any Lua value. `options` -must be a table. - -### List of options - -`pretty` is sure to complain if you give it an unknown option, or if you give an -option a bad value. - -- `indent: string`: The string to indent with. Four spaces by default. - -## TODO - -Tasks to be done before `pretty` can be called version 1.0.0, in order of -priority: - -- Add a dedicated unicode submodule, to handle some minor alignment and - character escaping issues. `pretty` should escape all malformed unicode - sequences. -- Align numbers towards right for tabular views. -- Add support for `setmetatable`, and exploring values in metatables. -- Provide nice formatting for `cdata` datatype in LuaJIT. -- Find a better name than `pretty`. -- Enhance internal structure some amount. See `TODO` markers in files. - -It would be nice to have the following, but these are secondary: - -- Add option for colored output. Primarily syntax highlighting, but also - [BlueJ-style](www.bluej.org/about.html) scope highlighting, with some faint - background colors. -- Expand on the comment output in output, for `__tostring` methods, and global - namespaces like `io` or `math`. -- Fit output within a predefined width limit. Default to 80. -- Look into tool for understanding complex structures with recursive - definitions. Whatever modes are thought up, they should be automatic modes, - not an options. Should at least include modes for self-referential tables - and Directed-Acyclic-Graphs. - -## Alternative pretty printers - -`pretty` is large, slow, and requires the debug library to work. It's not -designed for serialization purposes, nor is it concerned with offering the same -level of customization as other libraries do. - -If you want a sleek, fast, customizable or embeddable library, there are -thankfully other options. - -- [inspect.lua](github.com/kikito/inspect.lua): One of the classic debugging - pretty printers. -- [pprint.lua](github.com/jagt/pprint.lua): Reimplementation of `inspect.lua` -- [serpent](github.com/pkulchenko/serpent): Advanced and fast pretty printer. -- [pluto](lua-users.org/wiki/PlutoLibrary): Can serialize arbitrary parts of - Lua, including functions, upvalues, and proper lexical scoping. Not written - in native Lua. -- [binser](github.com/bakpakin/binser): Library for special purpose - serialization. - -Even more are available at [the lua-users wiki](lua-users.org/wiki/TableSerialization). - -## Contact - -The author is available at `jonjmaa (at) gmail.com`. Be sure to send an email if -you have ideas for improvements, or find an issue. - -## License - -The license is the BeerWare license - Please see the -[LICENSE.txt](https://gitfub.space/Jmaa/pretty/blob/master/LICENSE.txt) file for -details. diff --git a/pretty.lua b/pretty.lua index 53de8ce..463c584 100644 --- a/pretty.lua +++ b/pretty.lua @@ -1,57 +1,197 @@ - --- pretty.pretty --- Main module of the `pretty` library. - --- TODO: Maybe move table formatting into its own file? - - ---[=[ Thoughts on displaying tables in an intuitive way. - -Lua's table data-structure is likely to be the most concise data structure ever -invented. (If not, please send me a link!) Lists, maps, objects, classes, -proxies, etc. This obviously brings about it some difficulty when attempting to -represent these tables. What do we want to highlight, and what do we choose to -avoid? - -One notable issue is whether to show every key that a table answers (to lift -some Smalltalk terms) to, or to just display those it contains. That is, do we -think about `__index` in the table's metatable and what it returns, or do we -ignore `__index`? For cases where `__index` is a function, we cannot say -anything about the keys that the table answers to. If `__index` is a table, we -have a better idea, but it would be cluttered to display both types of keys side -by side. - -1. Native representation: Lua's native representation includes the type and - address of the table. It allows for distinguishing between unique tables, - but won't tell us anything about the contents. -2. Omission: By representing tables as the pseudo-parsable `{...}`, it's - clear we are talking about a table. We disregard the ability to - distinguish between tables. -2A. If the table is empty, we could represent it as `{}`. But what if the table - has a metatable with `__index` defined? We could continue to represent it as - `{}`, but `{...}` would be more "honest". -3. Single-line: TODO -4. Multi-line: TODO -5. Columns: For some highly-regular structures, like lists of short strings, - giving each string it's own line would be too long, but formatting them as a - single-line list would be too cluttered. Thus we can take inspiration from - the classic `ls` unix tool, and place the output into columns, to help guide - the eyes. -6. Tabular: Other structures are formatted like actual tables of data, e.g. a - sequence of tuples, like one would see in an SQL database. For these - structures it's an obvious choice to align them based on the keys. -7. Pseudo-Tabular: Some structures are almost tabular, e.g. they are sequences - of tuples, but some of the tuples differ in their structure. For these - structures it's still useful to tabulate the keys that all tuples share. To - do this we should sort the key order descending by the number of tuples with - the key. - But what do we do about the the outlier keys? We can either justify the - entire table, and give specific spots for the outlier keys, thereby - significantly increasing the size of the table, or we can leave the table - unjustified, abandoning it's eye-guiding attributes. -8. Special cases: (Array-tree, Table-Tree, Linked-List, Predictive Sequences) TODO - ---]=] +--- Pretty +-- +-- `pretty` is an advanced pretty printer for [Lua](lua.org). It's primarily a +-- debugging tool, aiming for human readability, by detecting pattern in the input +-- data, and creating an output string utilizing and highlighting those patterns. +-- +-- ## Code Example +-- +-- Setup is simple, use `pretty = require 'pretty'`, and you're good to go. +-- +-- ```lua +-- > print(pretty( { 1, 2, 3 } )) +-- { 1, 2, 3 } +-- +-- > print(pretty( { hello = 'world', num = 42 } )) +-- { +-- num = 42 +-- hello = 'world' +-- } +-- +-- > print(pretty( { abs = math.abs, max = math.max, some = function() end } )) +-- { +-- abs = builtin function (x) ... end +-- max = builtin function (x, ...) ... end +-- some = function () ... end +-- } +-- +-- > print(pretty( math.abs )) +-- builtin function (x) +-- -- math.abs +-- -- Returns the absolute value of x +-- +-- ... +-- end +-- ``` +-- +-- ## Motivation +-- +-- This project is the outcome of my frustration with existing pretty printers, and +-- a desire to expand upon the pretty printer I developed for +-- [Xenoterm](https://gitfub.space/takunomi/Xenoterm). The original Xenoterm pretty +-- printer was much simpler than `pretty` - and the current is even simpler - but +-- the enhancements I make, when compared to other pretty printers, inspired me to +-- create `pretty`. +-- +-- `pretty` sorts it's priorities like so: +-- +-- 1. Human readability. +-- 2. Lua-compatible output. +-- 3. Customization. +-- +-- I'd rather have good defaults than provide a ton of customization options. If an +-- structure avoids easy representation in Lua, I'd rather extend the syntax, than +-- lose the info. +-- +-- Another aspect where `pretty` shines is in exploratory programming, when +-- attempting to avoid reliance on outside documentation. The amount of information +-- `pretty` exposes varies by the data you are inspecting. If you're inspecting +-- a list of functions, their function signatures are visible, but if you're +-- inspecting a single function, documentation and source location may appear if +-- available. +-- +-- ## Features +-- +-- - Written in good-old pureblood Lua, with support for PUC Lua 5.0+ and +-- LuaJIT 2.0+. +-- - Redefining what it means to be "human readable": +-- * Is multi-line centric, to aid readablitiy. +-- * Indention and alignment of keys-value pairs. +-- * Keys-value pairs are [properly](http://www.davekoelle.com/alphanum.html) +-- sorted by key type and thereafter alphabetically. +-- * The format and structure of output changes depending upon the input. +-- Maps appear differently to deeply nested tables to long sequences +-- with short strings to short lists. +-- * Uses the standard `debug` library to gain information about functions +-- and other advanced structures. +-- +-- ## Installation +-- +-- `pretty` is loadable directly with `require`. Either clone or download this +-- repository. Where you place it, depends upon what you want to do: +-- +-- 1. **You want `pretty` in a specific project**: Place the `pretty` folder +-- somewhere in your project, and `require` it from one of your project files. +-- 2. **You want `pretty` on your system**: Place the `pretty` folder such that +-- it's visible from your Lua-path. On my system this might be +-- `/usr/local/share/lua/5.1/`. Now you can `require` it from anywhere. +-- +-- ## API Documentation +-- +-- `pretty` exposes a single function, the `pretty` function itself. It's function +-- signature is `pretty(value, options)`. `value` can be any Lua value. `options` +-- must be a table. +-- +-- ### List of options +-- +-- `pretty` is sure to complain if you give it an unknown option, or if you give an +-- option a bad value. +-- +-- - `indent: string`: The string to indent with. Four spaces by default. +-- +-- ## TODO +-- +-- Tasks to be done before `pretty` can be called version 1.0.0, in order of +-- priority: +-- +-- - Add a dedicated unicode submodule, to handle some minor alignment and +-- character escaping issues. `pretty` should escape all malformed unicode +-- sequences. +-- - Align numbers towards right for tabular views. +-- - Add support for `setmetatable`, and exploring values in metatables. +-- - Provide nice formatting for `cdata` datatype in LuaJIT. +-- - Find a better name than `pretty`. +-- - Enhance internal structure some amount. See `TODO` markers in files. +-- +-- It would be nice to have the following, but these are secondary: +-- +-- - Add option for colored output. Primarily syntax highlighting, but also +-- [BlueJ-style](www.bluej.org/about.html) scope highlighting, with some faint +-- background colors. +-- - Expand on the comment output in output, for `__tostring` methods, and global +-- namespaces like `io` or `math`. +-- - Fit output within a predefined width limit. Default to 80. +-- - Look into tool for understanding complex structures with recursive +-- definitions. Whatever modes are thought up, they should be automatic modes, +-- not an options. Should at least include modes for self-referential tables +-- and Directed-Acyclic-Graphs. +-- +-- ## Alternative pretty printers +-- +-- `pretty` is large, slow, and requires the debug library to work. It's not +-- designed for serialization purposes, nor is it concerned with offering the same +-- level of customization as other libraries do. +-- +-- If you want a sleek, fast, customizable or embeddable library, there are +-- thankfully other options. +-- +-- - [inspect.lua](github.com/kikito/inspect.lua): One of the classic debugging +-- pretty printers. +-- - [pprint.lua](github.com/jagt/pprint.lua): Reimplementation of `inspect.lua` +-- - [serpent](github.com/pkulchenko/serpent): Advanced and fast pretty printer. +-- - [pluto](lua-users.org/wiki/PlutoLibrary): Can serialize arbitrary parts of +-- Lua, including functions, upvalues, and proper lexical scoping. Not written +-- in native Lua. +-- - [binser](github.com/bakpakin/binser): Library for special purpose +-- serialization. +-- +-- Even more are available at [the lua-users wiki](lua-users.org/wiki/TableSerialization). +-- +-- ## Thoughts on displaying tables in an intuitive way. +-- +-- Lua's table data-structure is likely to be the most concise data structure ever +-- invented. (If not, please send me a link!) Lists, maps, objects, classes, +-- proxies, etc. This obviously brings about it some difficulty when attempting to +-- represent these tables. What do we want to highlight, and what do we choose to +-- avoid? +-- +-- One notable issue is whether to show every key that a table answers (to lift +-- some Smalltalk terms) to, or to just display those it contains. That is, do we +-- think about `__index` in the table's metatable and what it returns, or do we +-- ignore `__index`? For cases where `__index` is a function, we cannot say +-- anything about the keys that the table answers to. If `__index` is a table, we +-- have a better idea, but it would be cluttered to display both types of keys side +-- by side. +-- +-- 1. Native representation: Lua's native representation includes the type and +-- address of the table. It allows for distinguishing between unique tables, +-- but won't tell us anything about the contents. +-- 2. Omission: By representing tables as the pseudo-parsable `{...}`, it's +-- clear we are talking about a table. We disregard the ability to +-- distinguish between tables. +-- 2A. If the table is empty, we could represent it as `{}`. But what if the table +-- has a metatable with `__index` defined? We could continue to represent it as +-- `{}`, but `{...}` would be more "honest". +-- 3. Single-line: TODO +-- 4. Multi-line: TODO +-- 5. Columns: For some highly-regular structures, like lists of short strings, +-- giving each string it's own line would be too long, but formatting them as a +-- single-line list would be too cluttered. Thus we can take inspiration from +-- the classic `ls` unix tool, and place the output into columns, to help guide +-- the eyes. +-- 6. Tabular: Other structures are formatted like actual tables of data, e.g. a +-- sequence of tuples, like one would see in an SQL database. For these +-- structures it's an obvious choice to align them based on the keys. +-- 7. Pseudo-Tabular: Some structures are almost tabular, e.g. they are sequences +-- of tuples, but some of the tuples differ in their structure. For these +-- structures it's still useful to tabulate the keys that all tuples share. To +-- do this we should sort the key order descending by the number of tuples with +-- the key. +-- But what do we do about the the outlier keys? We can either justify the +-- entire table, and give specific spots for the outlier keys, thereby +-- significantly increasing the size of the table, or we can leave the table +-- unjustified, abandoning it's eye-guiding attributes. +-- 8. Special cases: (Array-tree, Table-Tree, Linked-List, Predictive Sequences) TODO -------------------------------------------------------------------------------- -- Import files