Modified the sort function signature to also pass the original table, so not only keys are available when sorting, but also the values in the original table.

This commit is contained in:
Thijs Schreijer 2013-02-27 22:31:18 +01:00
parent 16c5599903
commit fff87fea74
2 changed files with 32 additions and 12 deletions

View File

@ -51,13 +51,13 @@ internal function, but set different options by default:
* name (string) -- name; triggers full serialization with self-ref section
* indent (string) -- indentation; triggers long multi-line output
* comment (true/False/maxlevel) -- provide stringified value in a comment (up to maxlevel of depth)
* sortkeys (true/False) -- sort keys
* sparse (true/False) -- force sparse encoding (no nil filling based on #t)
* compact (true/False) -- remove spaces
* fatal (true/False) -- raise fatal error on non-serilizable values
* nocode (true/False) -- disable bytecode serialization for easy comparison
* nohuge (true/False) -- disable checking numbers against undefined and huge values
* comment (true/false/maxlevel) -- provide stringified value in a comment (up to maxlevel of depth)
* sortkeys (true/false/function) -- sort keys
* sparse (true/false) -- force sparse encoding (no nil filling based on #t)
* compact (true/false) -- remove spaces
* fatal (true/false) -- raise fatal error on non-serilizable values
* nocode (true/false) -- disable bytecode serialization for easy comparison
* nohuge (true/false) -- disable checking numbers against undefined and huge values
* maxlevel (number) -- specify max level up to which to expand nested tables
* valignore (table) -- allows to specify a list of values to ignore (as keys)
* keyallow (table) -- allows to specify the list of keys to be serialized. Any keys not in this list are not included in final output (as keys)
@ -72,6 +72,26 @@ line(a, {nocode = true, valignore = {[arrayToIgnore] = true}})
function todiff(a) return dump(a, {nocode = true, indent = ' '}) end
```
## Sorting
A custom sort function can be provided to sort the contents of tables. The function takes 2 parameters, the first being the table (a list) with the keys, the second the original table. It should modify the first table in-place, and return nothing.
For example, the following call will apply a sort function identical to the standard sort, except that it will not distinguish between lower- and uppercase.
```lua
local mysort = function(k, o) -- k=keys, o=original table
local maxn, to = 12, {number = 'a', string = 'b'}
local function padnum(d) return ("%0"..maxn.."d"):format(d) end
local sort = function(a,b)
return ((k[a] and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))):upper()
< ((k[b] and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum))):upper()
end
table.sort(k, sort)
end
local content = { some = 1, input = 2, to = 3, serialize = 4 }
local result = require('serpent').block(content, {sortkeys = mysort})
```
## Formatters
Serpent supports a way to provide a custom formatter that allows to fully

View File

@ -29,12 +29,12 @@ local function s(t, opts)
local plain = type(n) == "string" and n:match("^[%l%u_][%w_]*$") and not keyword[n]
local safe = plain and n or '['..safestr(n)..']'
return (path or '')..(plain and path and '.' or '')..safe, safe end
local alphanumsort = type(opts.sortkeys) == 'function' and opts.sortkeys or function(o, n)
local alphanumsort = type(opts.sortkeys) == 'function' and opts.sortkeys or function(k, o, n) -- k=keys, o=originaltable, n=padding
local maxn, to = tonumber(n) or 12, {number = 'a', string = 'b'}
local function padnum(d) return ("%0"..maxn.."d"):format(d) end
table.sort(o, function(a,b)
return (o[a] and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
< (o[b] and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
table.sort(k, function(a,b)
return (k[a] and 0 or to[type(a)] or 'z')..(tostring(a):gsub("%d+",padnum))
< (k[b] and 0 or to[type(b)] or 'z')..(tostring(b):gsub("%d+",padnum)) end) end
local function val2str(t, name, indent, insref, path, plainindex, level)
local ttype, level = type(t), (level or 0)
local spath, sname = safename(path, name)
@ -63,7 +63,7 @@ local function s(t, opts)
local maxn, o, out = #t, {}, {}
for key = 1, maxn do table.insert(o, key) end
for key in pairs(t) do if not o[key] then table.insert(o, key) end end
if opts.sortkeys then alphanumsort(o, opts.sortkeys) end
if opts.sortkeys then alphanumsort(o, t, opts.sortkeys) end
for n, key in ipairs(o) do
local value, ktype, plainindex = t[key], type(key), n <= maxn and not sparse
if opts.valignore and opts.valignore[value] -- skip ignored values; do nothing