diff --git a/analyze_structure.lua b/analyze_structure.lua index 93bbcb4..b891941 100644 --- a/analyze_structure.lua +++ b/analyze_structure.lua @@ -38,6 +38,7 @@ local SIMPLE_VALUE_TYPES = { } local SHORT_STRING_MAX_LEN = 7 +local MINIMUM_NUMBER_OF_SET_ELEMENTS = 2 -------------------------------------------------------------------------------- @@ -83,14 +84,27 @@ local function largest_number_index (t) return max_index end -local function nr_elements_in_map (t) +local function nr_elements_in_table (t) local k, count = nil, -1 repeat k, count = next(t, k), count + 1 - until not k + until k == nil return count end +local function nr_elements_in_seq (t) + local i, last_elem_i, nr_elems, has_holes = 0, 0, 0, false + while i <= last_elem_i + 2 do + i = i + 1 + if t[i] ~= nil then + last_elem_i, nr_elems = i, nr_elems + 1 + else + has_holes = true + end + end + return nr_elems, has_holes +end + -------------------------------------------------------------------------------- local function contains_only_nice_string_keys (t) @@ -119,19 +133,6 @@ local function contains_only_nice_number_indexes (t) return #t > 0 end -local function has_seq (t) - if not contains_only_nice_number_indexes(t) then return false end - -- Contain list of keys - local keys = {[0] = 0} - for i, _ in pairs(t) do keys[#keys+1] = i end - table.sort(keys) - -- Check to see that no indice jumps more than 2 - for indice_i = 1, #keys do - if keys[indice_i - 1] < keys[indice_i] - 2 then return false end - end - return true, (#keys ~= keys[#keys]) -end - local function is_set (t) -- Predicate: Does t contain only boolean values. local value_types = get_value_types(t) @@ -202,12 +203,14 @@ local function get_table_info (t) local key_types = get_key_types(t) local info = {} - info.has_seq, info.has_holes = has_seq(t) - info.has_map = key_types.nr_types > (key_types.number and 1 or 0) - info.is_set = is_set(t) + info.nr_elems = nr_elements_in_table(t) + info.seq_elems, info.has_holes = nr_elements_in_seq(t) + info.map_elems = info.nr_elems - info.seq_elems + info.has_seq = info.seq_elems > 0 + info.has_map = info.map_elems > 0 + info.is_set = is_set(t) and info.nr_elems >= MINIMUM_NUMBER_OF_SET_ELEMENTS info.is_tabular = is_tabular(t) - info.is_short = is_short_table(t) - info.nr_elems = nr_elements_in_map(t) -- TODO: Use this for something. + info.is_short = is_short_table(t) -- TODO: Remove this. It's not used for anything. -- Determine type of table if not info.has_seq and not info.has_map then info.type = TABLE_TYPE.EMPTY @@ -251,4 +254,4 @@ end -------------------------------------------------------------------------------- -return analyze_structure +return { analyze_structure, get_table_info } diff --git a/pretty.lua b/pretty.lua index 0238616..1beefbc 100644 --- a/pretty.lua +++ b/pretty.lua @@ -2,7 +2,7 @@ -- Ensure loading library, if it exists, no matter where pretty.lua was loaded from. -- Load the library component -local format_number, format_function, analyze_structure, TABLE_TYPE +local format_number, format_function, analyze_structure, get_table_info, TABLE_TYPE do local thispath = ... and select('1', ...):match('.+%.') or '' @@ -13,7 +13,7 @@ do -- Load other stuff local was_loaded was_loaded, analyze_structure = pcall(require, thispath..'analyze_structure') - print(was_loaded, analyze_structure) + analyze_structure, get_table_info = analyze_structure[1], analyze_structure[2] assert(was_loaded, '[pretty]: Could not load vital library: analyze_structure') was_loaded, TABLE_TYPE = pcall(require, thispath..'table_type') assert(was_loaded, '[pretty]: Could not load vital library: table_type') @@ -333,12 +333,12 @@ local TABLE_TYPE_TO_PAIR_FORMAT = { local function format_map (t, options, depth, l) -- NOTE: Assumes that the input table was pre-checked with `is_single_line_table()` - local table_type = l.info[t] and l.info[t].type or get_table_type(t) -- FIXME: This is a temp fix + local table_info = l.info[t] or get_table_info(t) local key_value_pairs = get_key_value_pairs_in_proper_order(t) - if table_type == TABLE_TYPE.SEQUENCE and l.info[t].has_holes then + if table_info.type == TABLE_TYPE.SEQUENCE and l.info[t].has_holes then fill_holes_in_key_value_pairs(key_value_pairs) end - local pair_format_func = TABLE_TYPE_TO_PAIR_FORMAT[table_type] + local pair_format_func = TABLE_TYPE_TO_PAIR_FORMAT[table_info.type] local start_of_table_i = #l + 1 l[#l+1] = '{' diff --git a/test/test_analyze_structure.lua b/test/test_analyze_structure.lua index 82d321e..7fb98c6 100644 --- a/test/test_analyze_structure.lua +++ b/test/test_analyze_structure.lua @@ -1,7 +1,7 @@ local SUITE = require('TestSuite').new('analyze_structure') SUITE:setEnviroment { - analyze_structure = require('analyze_structure'), + analyze_structure = require('analyze_structure')[1], TABLE_TYPE = require('table_type') } @@ -55,6 +55,24 @@ SUITE:addTest('Pure Map', function () assert(table_info.has_map == true) end) +SUITE:addTest('Boolean set', function () + local input = { [true] = true, [false] = false } + local table_info = analyze_structure(input)[input] + + assert(table_info.type == TABLE_TYPE.SET, 'Returned bad type: '..table_info.type) + assert(table_info.has_seq == false) + assert(table_info.has_map == true) +end) + +SUITE:addTest('A Mixed table', function () + local input = { 300, [300] = 1 } + local table_info = analyze_structure(input)[input] + + assert(table_info.has_seq == true) + assert(table_info.has_map == true) + assert(table_info.type == TABLE_TYPE.MIXED, 'Returned bad type: '..table_info.type) +end) + SUITE:addTest('String Map', function () local input = { a = 1, b = 2, c = 3 } local table_info = analyze_structure(input)[input] diff --git a/test/test_pretty.lua b/test/test_pretty.lua index f513cc5..4ae1db1 100644 --- a/test/test_pretty.lua +++ b/test/test_pretty.lua @@ -192,11 +192,6 @@ format_test { expect = '{ [false] = false, [true] = true }', } -format_test { - input = { [100] = 'Hi', [300] = 'Hello' }, - expect = '{ [100] = \'Hi\', [300] = \'Hello\' }', -} - format_test { -- Order does not matter input = { b = 1, a = 2 }, expect = '{ a = 2, b = 1 }', @@ -225,9 +220,14 @@ format_test { expect = '{\n\ta = { 1, 2, 3 },\n\tb = { 4, 5, 6 }\n}', } +format_test { + input = { [100] = 'Hi', [300] = 'Hello' }, + expect = '{ [100] = \'Hi\', [300] = \'Hello\' }', +} + format_test { input = { 'Hi', [300] = 'Hello' }, - expect = '{\n\t[1] = \'Hi\',\n\t[300] = \'Hello\'\n}', + expect = '{ [1] = \'Hi\', [300] = \'Hello\' }', } format_test {