diff --git a/pretty.lua b/pretty.lua index de1d4c6..713b8df 100644 --- a/pretty.lua +++ b/pretty.lua @@ -7,32 +7,49 @@ --[=[ Thoughts on displaying tables in an intuitive way. -Lua's table datastructure is likely to be the most consise data structure ever +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, or to -just display those it contains. That is, do we think about `__index` 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 then the output would be cluttered. +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 about the contents. -2. It continues: By representing tables as the pseudo-parsable `{...}`, it's + 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. -3. Special case for 2. 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". -4. Single-line: TODO -5. Multi-line: TODO -6. Format into columns: (like ls) TODO -7. Tabular: TODO -8. Special cases: (Array-tree, Table-Tree, Linked-List) TODO +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 --]=] @@ -56,6 +73,12 @@ We are attempting to cover all Lua features, so please report this bug, so we ca ]] local MAX_WIDTH_FOR_SINGLE_LINE_TABLE = 38 +if io and io.popen then + local f = io.popen "tput cols" + local term_width = f:read '*n' + f:close() +-- if term_width then MAX_WIDTH_FOR_SINGLE_LINE_TABLE = term_width * 3 / 2 end +end local KEY_TYPE_SORT_ORDER = { ['number'] = 0, diff --git a/test/test_cdata.lua b/test/test_cdata.lua index 7fbdff8..0b91f3f 100644 --- a/test/test_cdata.lua +++ b/test/test_cdata.lua @@ -1,8 +1,9 @@ --- Only relevant in LUAJIT. -if type(jit) ~= 'table' then return end - local SUITE = require 'TestSuite' 'cdata' + +-- Only relevant in LUAJIT. +if type(jit) ~= 'table' or true then return SUITE end + SUITE:setEnviroment{ format = require 'pretty', analyze_byte_string = require 'analyze_byte_string', diff --git a/test/test_pretty.lua b/test/test_pretty.lua index 05d9fc5..521c5a3 100644 --- a/test/test_pretty.lua +++ b/test/test_pretty.lua @@ -317,6 +317,42 @@ format_test { expect = '{\n { a = \'hel\', x = { b = \'abc\', c = \'yo\' } },\n { a = \'hi\', x = { b = \'yo\', c = \'abc\' } }\n}', } + +------------------------ + +format_test { + name = 'Pseudo-Tabular style with justification', + input = { + { st = 'ita', tx = 'annah', }, + { st = 'bld', tx = 'tommy', sz = 20 }, + { st = 'unl', tx = 'mike', }, + }, + expect = '{\n { st = \'ita\', tx = \'annah\' },\n { st = \'bld\', tx = \'tommy\', sz = 20 },\n { st = \'unl\', tx = \'mike\' }\n}', +} + +format_test { + name = 'Pseudo-Tabular style with extreme justification', + input = { + { st = 'ita', tx = 'annah', }, + { st = 'bld', tx = 'tommy', sz = 20 }, + { st = 'unl', tx = 'mike', sy = 21 }, + }, + expect = '{\n { st = \'ita\', tx = \'annah\' },\n { st = \'bld\', tx = \'tommy\', sz = 20 },\n { st = \'unl\', tx = \'mike\', sy = 21 }\n}', +} + +format_test { + name = 'Pseudo-Tabular style without justification', + input = { + { st = 'ita', tx = 'annah', sx = 19 }, + { st = 'bld', tx = 'tommy', sz = 20 }, + { st = 'unl', tx = 'mike', sy = 21 }, + { st = 'ita', tx = 'milo' }, + { st = 'bld', tx = 'yota' }, + { st = 'unl', tx = 'kilo' }, + }, + expect = '{\n { st = \'ita\', tx = \'annah\', sx = 19 },\n { st = \'bld\', tx = \'tommy\', sz = 20 },\n { st = \'unl\', tx = \'mike\', sy = 21 },\n { st = \'ita\', tx = \'milo\' },\n { st = \'bld\', tx = \'yota\' },\n { st = \'unl\', tx = \'kilo\' }\n}', +} + -------------------------------------------------------------------------------- -- Table recursion @@ -337,6 +373,11 @@ SUITE:addTest('UseCase: Can print global enviroment', function () assert(true) end) +SUITE:addTest('UseCase: Can print value with __tostring returning unusual values', function () + format( setmetatable({}, {__tostring = function() end}) ) + assert(true) +end) + SUITE:addTest('UseCase: Can load function from file that is shortly deleted', function () local module_name = 'tmp_'..os.time() -- Create module