More properties for configuring usage and help messages

* `usage_margin`: sets margin for the second and following lines of
  usage string.
* `usage_max_width`: sets usage max width for autowrapping.
* `help_usage_margin`: sets margin for element usages in help string.
* `help_description`: sets margin for element descrptions in help string.
This commit is contained in:
Peter Melnichenko
2018-04-08 16:00:42 +03:00
parent a04899a485
commit 8a3faf3a3e
4 changed files with 95 additions and 14 deletions

View File

@@ -16,6 +16,10 @@
* Added `help_vertical_space` property for configuring number of extra * Added `help_vertical_space` property for configuring number of extra
newlines between help strings for different arguments and options in newlines between help strings for different arguments and options in
autogenerated help string. autogenerated help string.
* Added `usage_margin` and `usage_max_width` properties for configuring
usage string autogeneration.
* Added `help_usage_margin` and `help_description_margin` properties
for configuring help string autogeneration.
### Improvements ### Improvements

View File

@@ -463,4 +463,37 @@ Options:
-h, --help Show this help message and exit.]], cmd2:get_help()) -h, --help Show this help message and exit.]], cmd2:get_help())
end) end)
it("allows configuring margins using help_usage_margin and help_description_margin", function()
local parser = Parser "foo"
:help_usage_margin(2)
:help_description_margin(15)
parser:argument "arg1"
:description "Argument number one."
parser:argument "arg2"
:description "Argument number two."
parser:flag "-p"
:description "This is a thing."
parser:option "-f --foo"
:description [[
And this things uses many lines.
Because it has lots of complex behaviour.
That needs documenting.]]
assert.equal([[
Usage: foo [-p] [-f <foo>] [-h] <arg1> <arg2>
Arguments:
arg1 Argument number one.
arg2 Argument number two.
Options:
-p This is a thing.
-f <foo>, And this things uses many lines.
--foo <foo> Because it has lots of complex behaviour.
That needs documenting.
-h, --help Show this help message and exit.]], parser:get_help())
end)
end) end)

View File

@@ -307,4 +307,38 @@ Usage: foo ([--opt1 <opt1>] | [--opt3 <opt3>] | [--opt5 <opt5>])
([<arg4>] | [--opt4 <opt4>])]=], parser:get_usage() ([<arg4>] | [--opt4 <opt4>])]=], parser:get_usage()
) )
end) end)
it("allows configuring usage margin using usage_margin property", function()
local parser = Parser "foo"
:usage_margin(2)
parser:argument "long_argument_name"
parser:argument "very_long_words"
parser:option "--set-important-property"
parser:option "--include"
:args "*"
assert.equals([=[
Usage: foo [--set-important-property <set_important_property>] [-h]
<long_argument_name> <very_long_words> [--include [<include>] ...]]=], parser:get_usage())
end)
it("allows configuring max usage width using usage_max_width property", function()
local parser = Parser "foo"
:usage_max_width(50)
parser:argument "long_argument_name"
parser:argument "very_long_words"
parser:option "--set-important-property"
parser:option "--include"
:args "*"
assert.equals([=[
Usage: foo
[--set-important-property <set_important_property>]
[-h] <long_argument_name> <very_long_words>
[--include [<include>] ...]]=], parser:get_usage())
end)
end) end)

View File

@@ -247,6 +247,10 @@ local Parser = class({
typechecked("action", "function"), typechecked("action", "function"),
typechecked("command_target", "string"), typechecked("command_target", "string"),
typechecked("help_vertical_space", "number"), typechecked("help_vertical_space", "number"),
typechecked("usage_margin", "number"),
typechecked("usage_max_width", "number"),
typechecked("help_usage_margin", "number"),
typechecked("help_description_margin", "number"),
add_help add_help
}) })
@@ -265,6 +269,10 @@ local Command = class({
typechecked("action", "function"), typechecked("action", "function"),
typechecked("command_target", "string"), typechecked("command_target", "string"),
typechecked("help_vertical_space", "number"), typechecked("help_vertical_space", "number"),
typechecked("usage_margin", "number"),
typechecked("usage_max_width", "number"),
typechecked("help_usage_margin", "number"),
typechecked("help_description_margin", "number"),
typechecked("hidden", "boolean"), typechecked("hidden", "boolean"),
add_help add_help
}, Parser) }, Parser)
@@ -638,7 +646,6 @@ function Parser:group(name, ...)
return self return self
end end
local max_usage_width = 70
local usage_welcome = "Usage: " local usage_welcome = "Usage: "
function Parser:get_usage() function Parser:get_usage()
@@ -646,13 +653,15 @@ function Parser:get_usage()
return self._usage return self._usage
end end
local usage_margin = self:_inherit_property("usage_margin", #usage_welcome)
local max_usage_width = self:_inherit_property("usage_max_width", 70)
local lines = {usage_welcome .. self:_get_fullname()} local lines = {usage_welcome .. self:_get_fullname()}
local function add(s) local function add(s)
if #lines[#lines]+1+#s <= max_usage_width then if #lines[#lines]+1+#s <= max_usage_width then
lines[#lines] = lines[#lines] .. " " .. s lines[#lines] = lines[#lines] .. " " .. s
else else
lines[#lines+1] = (" "):rep(#usage_welcome) .. s lines[#lines+1] = (" "):rep(usage_margin) .. s
end end
end end
@@ -773,11 +782,6 @@ function Parser:get_usage()
return table.concat(lines, "\n") return table.concat(lines, "\n")
end end
local margin_len = 3
local margin2_len = 25
local margin = (" "):rep(margin_len)
local margin2 = (" "):rep(margin2_len)
local function split_lines(s) local function split_lines(s)
if s == "" then if s == "" then
return {} return {}
@@ -796,7 +800,7 @@ local function split_lines(s)
return lines return lines
end end
local function get_element_help(element) function Parser:_get_element_help(element)
local label_lines = element:_get_label_lines() local label_lines = element:_get_label_lines()
local description_lines = split_lines(element:_get_description()) local description_lines = split_lines(element:_get_description())
@@ -806,13 +810,19 @@ local function get_element_help(element)
-- If too long, start description after all the label lines. -- If too long, start description after all the label lines.
-- Otherwise, combine label and description lines. -- Otherwise, combine label and description lines.
if #label_lines[1] >= (margin2_len - margin_len) then local usage_margin_len = self:_inherit_property("help_usage_margin", 3)
local usage_margin = (" "):rep(usage_margin_len)
local description_margin_len = self:_inherit_property("help_description_margin", 25)
local description_margin = (" "):rep(description_margin_len)
if #label_lines[1] >= (description_margin_len - usage_margin_len) then
for _, label_line in ipairs(label_lines) do for _, label_line in ipairs(label_lines) do
table.insert(result_lines, margin .. label_line) table.insert(result_lines, usage_margin .. label_line)
end end
for _, description_line in ipairs(description_lines) do for _, description_line in ipairs(description_lines) do
table.insert(result_lines, margin2 .. description_line) table.insert(result_lines, description_margin .. description_line)
end end
else else
for i = 1, math.max(#label_lines, #description_lines) do for i = 1, math.max(#label_lines, #description_lines) do
@@ -822,11 +832,11 @@ local function get_element_help(element)
local line = "" local line = ""
if label_line then if label_line then
line = margin .. label_line line = usage_margin .. label_line
end end
if description_line and description_line ~= "" then if description_line and description_line ~= "" then
line = line .. (" "):rep(margin2_len - #line) .. description_line line = line .. (" "):rep(description_margin_len - #line) .. description_line
end end
table.insert(result_lines, line) table.insert(result_lines, line)
@@ -852,7 +862,7 @@ function Parser:_add_group_help(blocks, added_elements, label, elements)
for _, element in ipairs(elements) do for _, element in ipairs(elements) do
if not element._hidden and not added_elements[element] then if not element._hidden and not added_elements[element] then
added_elements[element] = true added_elements[element] = true
table.insert(buf, get_element_help(element)) table.insert(buf, self:_get_element_help(element))
end end
end end