1
0
This commit is contained in:
Jon Michael Aanes 2017-10-09 13:05:28 +02:00
parent 1781f8267a
commit 7dca1a697d
3 changed files with 84 additions and 19 deletions

View File

@ -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,

View File

@ -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',

View File

@ -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