Function formatting will now automatically pull documentation from a lua file, if it knows where to look.
This commit is contained in:
parent
3bb599e976
commit
9a6a5b4b51
57
function.lua
57
function.lua
|
@ -123,12 +123,23 @@ local function get_function_paramlist_and_body (str, start_line, end_line)
|
|||
local start_line_index = get_line_index(str, start_line)
|
||||
local end_line_index = get_line_index(str, end_line + 1)
|
||||
|
||||
local function_params, function_body = str:sub(start_line_index, end_line_index):match('.*function%s*[a-zA-Z0-9_.]*%s*(%([a-zA-Z0-9_,. \t]*%))[ \t]*(.+)[ \t]*end')
|
||||
local function_params, function_body = str:sub(start_line_index, end_line_index):match('.*%f[%a_]function%f[^%a_]%s*[a-zA-Z0-9_.]*%s*(%([a-zA-Z0-9_,. \t]*%))[ \t]*(.+)[ \t]*end')
|
||||
function_body = function_body:match('^%s*(.-)%s*$')
|
||||
assert(type(function_params) == 'string' and type(function_body) == 'string')
|
||||
return function_params, function_body
|
||||
end
|
||||
|
||||
local function get_function_body_from_file (filename, start_line, end_line)
|
||||
assert(type(filename) == 'string')
|
||||
assert(type(start_line) == 'number')
|
||||
assert(type(end_line) == 'number')
|
||||
|
||||
local file = io.open(filename, 'r')
|
||||
local str = file:read('*all')
|
||||
file:close()
|
||||
return select(2, get_function_paramlist_and_body(str, start_line, end_line))
|
||||
end
|
||||
|
||||
local function get_full_function_str (...)
|
||||
local function_params, function_body = get_function_paramlist_and_body(...)
|
||||
return 'function '..function_params..' '..function_body..' end'
|
||||
|
@ -159,14 +170,20 @@ local function add_indent_to_string (str, indent)
|
|||
assert(type(str) == 'string')
|
||||
assert(type(indent) == 'string')
|
||||
|
||||
local l = {}
|
||||
for line in str:gmatch('[^\n]+', true) do
|
||||
l[#l+1] = indent
|
||||
l[#l+1] = line
|
||||
l[#l+1] = '\n'
|
||||
return indent .. str:gsub('\n', '\n'..indent)
|
||||
end
|
||||
if l[#l] == '\n' then l[#l] = nil end
|
||||
return table.concat(l, '')
|
||||
|
||||
local function get_docs_from_function_body (func_body)
|
||||
assert(type(func_body) == 'string')
|
||||
local doc_lines = {}
|
||||
for line in func_body:gmatch('[^\n]+', true) do
|
||||
if not line:match('^%s*$') then
|
||||
local line_text = line:match('^%s*%-%-%s*(.*)%s*$')
|
||||
if not line_text then break end
|
||||
doc_lines[#doc_lines+1] = line_text
|
||||
end
|
||||
end
|
||||
return table.concat(doc_lines, '\n')
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -215,6 +232,10 @@ return function (value, depth, l, format_value)
|
|||
if info.defined_how == 'string' and l.options.embed_loaded_funcs then
|
||||
-- Function was defined as a string.
|
||||
function_params, function_body = get_function_paramlist_and_body(info.source, info.linedefined, info.lastlinedefined)
|
||||
--elseif info.defined_how == 'file' then
|
||||
--function_body = get_function_body_from_file(info.short_src, info.linedefined, info.lastlinedefined)
|
||||
----print(function_body)
|
||||
--function_body = function_body or '...'
|
||||
end
|
||||
|
||||
if info.builtin and l.options.short_builtins then
|
||||
|
@ -259,17 +280,21 @@ return function (value, depth, l, format_value)
|
|||
end
|
||||
|
||||
-- Doc
|
||||
if info.doc then
|
||||
for doc_line in info.doc:gmatch('[^\n]+') do
|
||||
l[#l+1] = indent
|
||||
l[#l+1] = '-- '
|
||||
|
||||
l[#l+1] = doc_line
|
||||
if not info.doc then
|
||||
local function_body = get_function_body_from_file(info.short_src, info.linedefined, info.lastlinedefined)
|
||||
if function_body then
|
||||
local documentation = get_docs_from_function_body(function_body)
|
||||
info.doc = documentation ~= '' and documentation
|
||||
end
|
||||
end
|
||||
|
||||
if info.doc then
|
||||
l[#l+1] = '\n'
|
||||
l[#l+1] = add_indent_to_string(info.doc, l.options.indent .. '-- ')
|
||||
end
|
||||
|
||||
-- source
|
||||
if not info.builtin then
|
||||
if not info.builtin and not info.doc then
|
||||
l[#l+1] = indent
|
||||
l[#l+1] = ('-- source_file: \'%s\' '):format(info.short_src)
|
||||
if info.linedefined == info.lastlinedefined then
|
||||
|
@ -280,7 +305,7 @@ return function (value, depth, l, format_value)
|
|||
end
|
||||
|
||||
-- upvalues
|
||||
if info.nups > 0 and not info.builtin then
|
||||
if info.nups > 0 and (not info.builtin and not info.doc) then
|
||||
l[#l+1] = indent
|
||||
l[#l+1] = '-- up_values: '
|
||||
format_value(info.ups, depth + 1, l)
|
||||
|
|
|
@ -474,8 +474,8 @@ local KNOWN_OPTIONS = {
|
|||
indent = { type = 'string', default = ' ' },
|
||||
max_depth = { type = 'number', default = math.huge },
|
||||
embed_loaded_funcs = { type = 'boolean', default = false }, -- TODO: Outphase this, in favor of automatically embedding "small enough" functions.
|
||||
recursion = { type = 'string', default = 'ignore', accepted = {['ignore'] = true, ['marked'] = true} },
|
||||
short_builtins = { type = 'boolean', default = false }, -- TODO: Outphase this. Rather automatically use the short versions in places where it would be strange to find the function, like keys, etc.
|
||||
recursion = { type = 'string', default = 'ignore', accepted = {['ignore'] = true, ['marked'] = true} },
|
||||
}
|
||||
|
||||
local function ensure_that_all_options_are_known (options)
|
||||
|
|
|
@ -166,7 +166,7 @@ SUITE:addTest('Recursive Numeration, Simple', function ()
|
|||
input[1] = input
|
||||
local info = analyze_structure(input)
|
||||
|
||||
assert(info[input].marker == 1)
|
||||
assert_equal(1, info[input].marker)
|
||||
end)
|
||||
|
||||
SUITE:addTest('Recursive Numeration, Multiple-appear', function ()
|
||||
|
@ -174,7 +174,7 @@ SUITE:addTest('Recursive Numeration, Multiple-appear', function ()
|
|||
input[1][1] = input[2][1]
|
||||
local info = analyze_structure(input)
|
||||
|
||||
assert(info[input[1][1]].marker == 1)
|
||||
assert_equal(1, info[input[1][1]].marker)
|
||||
end)
|
||||
|
||||
SUITE:addTest('Recursive Numeration, Multiple at once', function ()
|
||||
|
@ -183,8 +183,8 @@ SUITE:addTest('Recursive Numeration, Multiple at once', function ()
|
|||
input[1][2] = input
|
||||
local info = analyze_structure(input)
|
||||
|
||||
assert(type(info[input[1][1]].marker) == 'number')
|
||||
assert(type(info[input].marker) == 'number')
|
||||
assert_equal('number', type(info[input[1][1]].marker))
|
||||
assert_equal('number', type(info[input].marker))
|
||||
end)
|
||||
|
||||
SUITE:addTest('Recursive Numeration, Through Keys', function ()
|
||||
|
@ -192,7 +192,7 @@ SUITE:addTest('Recursive Numeration, Through Keys', function ()
|
|||
input[input] = input
|
||||
local info = analyze_structure(input)
|
||||
|
||||
assert(info[input].marker == 1)
|
||||
assert_equal(1, info[input].marker)
|
||||
end)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -209,7 +209,7 @@ SUITE:addTest('Can count elements, even though metatable.__index throws errors',
|
|||
local input = setmetatable({ 'hi', 'hello' }, {__index = function (_, k) error('Undefined access on key: '..k) end})
|
||||
local info = analyze_structure(input)
|
||||
|
||||
assert_equal(info[input].seq_elems, 2)
|
||||
assert_equal(2, info[input].seq_elems)
|
||||
end)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -219,21 +219,21 @@ SUITE:addTest('Can detect uniform structure', function ()
|
|||
local input = { a = 'b', b = 'a' }
|
||||
local info = analyze_structure(input)
|
||||
|
||||
assert_equal(info[input].is_uniform, true)
|
||||
assert_equal(true, info[input].is_uniform)
|
||||
end)
|
||||
|
||||
SUITE:addTest('Can detect uniform structure with different key value types', function ()
|
||||
local input = { a = 1, b = 4 }
|
||||
local info = analyze_structure(input)
|
||||
|
||||
assert_equal(info[input].is_uniform, true)
|
||||
assert_equal(true, info[input].is_uniform)
|
||||
end)
|
||||
|
||||
SUITE:addTest('Can detect basic non-uniform structure', function ()
|
||||
local input = { a = 'b', b = 5 }
|
||||
local info = analyze_structure(input)
|
||||
|
||||
assert_equal(info[input].is_uniform, false)
|
||||
assert_equal(false, info[input].is_uniform)
|
||||
end)
|
||||
|
||||
SUITE:addTest('Can detect pseudo-uniform structure with nested tables', function ()
|
||||
|
@ -242,14 +242,14 @@ SUITE:addTest('Can detect pseudo-uniform structure with nested tables', function
|
|||
local input = { a = { d = 7 }, b = { p = 3 } }
|
||||
local info = analyze_structure(input)
|
||||
|
||||
assert_equal(info[input].is_uniform, true)
|
||||
assert_equal(true, info[input].is_uniform)
|
||||
end)
|
||||
|
||||
SUITE:addTest('Can detect non-uniform structure with nested tables', function ()
|
||||
local input = { a = { 'a', 'b', 'c' }, b = { p = 3, 'hi' } }
|
||||
local info = analyze_structure(input)
|
||||
|
||||
assert_equal(info[input].is_uniform, false)
|
||||
assert_equal(false, info[input].is_uniform)
|
||||
end)
|
||||
|
||||
-- TODO: Add predicate to check for pseudo-uniformness.
|
||||
|
|
|
@ -119,15 +119,67 @@ format_test {
|
|||
expect = 'function ()\n -- source_file: \'./test/test_function.lua\' [Line: '..func_line..']\n -- up_values: { TEST_UPVALUE = 42 }\n\n ...\nend'
|
||||
}
|
||||
|
||||
local func_line = curline(3)
|
||||
--------------------------------------------------------------------------------
|
||||
-- Elaborate functions with documentation
|
||||
|
||||
format_test {
|
||||
name = 'Elaborate function with documentation',
|
||||
name = 'Basic Func with docs',
|
||||
input = function ()
|
||||
-- Hello World
|
||||
if true then return false end
|
||||
-- This is docs
|
||||
return true
|
||||
end,
|
||||
expect = 'function ()\n -- source_file: \'./test/test_function.lua\' [Lines: '..func_line..' - '..(func_line+1)..']\n -- Hello World\n\n ...\nend',
|
||||
expect = 'function ()\n -- This is docs\n\n ...\nend',
|
||||
}
|
||||
|
||||
format_test {
|
||||
name = 'Comments after other code won\'t be included as docs',
|
||||
input = function ()
|
||||
-- This is also docs
|
||||
if true then return false end
|
||||
-- Some other comment, that won't appear as docs.
|
||||
return true
|
||||
end,
|
||||
expect = 'function ()\n -- This is also docs\n\n ...\nend',
|
||||
}
|
||||
|
||||
format_test {
|
||||
name = 'We can leave a space between doc lines',
|
||||
input = function ()
|
||||
-- This is docs
|
||||
|
||||
-- This is also docs
|
||||
return true
|
||||
end,
|
||||
expect = 'function ()\n -- This is docs\n -- This is also docs\n\n ...\nend',
|
||||
}
|
||||
|
||||
format_test {
|
||||
name = 'We can also leave a line with an empty comment',
|
||||
input = function ()
|
||||
-- This is docs
|
||||
--
|
||||
-- This is also docs
|
||||
return true
|
||||
end,
|
||||
expect = 'function ()\n -- This is docs\n -- \n -- This is also docs\n\n ...\nend',
|
||||
}
|
||||
|
||||
format_test {
|
||||
name = 'No opvalues when docs are there',
|
||||
input = function ()
|
||||
-- This is docs
|
||||
return TEST_UPVALUE
|
||||
end,
|
||||
expect = 'function ()\n -- This is docs\n\n ...\nend',
|
||||
}
|
||||
|
||||
format_test {
|
||||
name = 'Can find docs when body contains the word "function"',
|
||||
input = function ()
|
||||
-- Hi
|
||||
_function()
|
||||
end,
|
||||
expect = 'function ()\n -- Hi\n\n ...\nend',
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
@ -229,6 +281,15 @@ format_test {
|
|||
expect = 'function () ... end',
|
||||
}
|
||||
|
||||
format_test {
|
||||
name = 'Can still find body when body contains the word "function"',
|
||||
single = true,
|
||||
adv_getlocal = true,
|
||||
options = { embed_loaded_funcs = true },
|
||||
input = loadstring('return function () function_body() end')(),
|
||||
expect = 'function () function_body() end',
|
||||
}
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Indent functions nicely
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user