[doc] Report undocumented value expression functions
in the manpage and texinfo manual.
This commit is contained in:
parent
19f4f587f0
commit
11a01f1b5a
4 changed files with 90 additions and 24 deletions
|
|
@ -8020,13 +8020,13 @@ functions and variables below:
|
|||
@defun abs value
|
||||
@defunx U value
|
||||
Return the absolute value of the given @var{value}, e.g. @var{amount}.
|
||||
@end defun
|
||||
@smallexample @c command:3406FC1
|
||||
$ ledger -f expr.dat --format "%(account) %(abs(amount))\n" reg assets
|
||||
@end smallexample
|
||||
@smallexample @c output:3406FC1
|
||||
Assets:Cash ¤ 123,45
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun amount_expr
|
||||
@value{FIXME:UNDOCUMENTED}
|
||||
|
|
@ -8038,7 +8038,6 @@ codes to display it in the given @var{color} if @var{bool} is true. It
|
|||
typically checks the value of the option @option{--color}. Since ANSI escape
|
||||
codes include non-printable character sequences, such as escape @kbd{^[}
|
||||
the following example may not appear as the final result on the commandline.
|
||||
@end defun
|
||||
@smallexample @c command:4D836EE,with_input:3406FC1
|
||||
$ ledger -f expr.dat --format "%(ansify_if(account, blue, options.color))\n" reg
|
||||
@end smallexample
|
||||
|
|
@ -8046,10 +8045,10 @@ $ ledger -f expr.dat --format "%(ansify_if(account, blue, options.color))\n" reg
|
|||
[34mAssets:Cash[0m
|
||||
[34mExpenses:Office Supplies[0m
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun ceiling value
|
||||
Return the next integer of @var{value} toward @math{+}infinity.
|
||||
@end defun
|
||||
@smallexample @c command:FF9C18C,with_input:3406FC1
|
||||
$ ledger -f expr.dat --format "%(account) %(ceiling(amount))\n" reg
|
||||
@end smallexample
|
||||
|
|
@ -8057,6 +8056,7 @@ $ ledger -f expr.dat --format "%(account) %(ceiling(amount))\n" reg
|
|||
Assets:Cash ¤ -123,00
|
||||
Expenses:Office Supplies ¤ 124,00
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defvar code
|
||||
Return the transaction code, the string between the parenthesis after the date.
|
||||
|
|
@ -8102,7 +8102,6 @@ $ ledger -f expr.dat --format "%(date) %(account)\n" reg assets
|
|||
|
||||
@defun floor value
|
||||
Return the next integer of @var{value} toward @math{-}infinity.
|
||||
@end defun
|
||||
@smallexample @c command:4FDC7C5,with_input:3406FC1
|
||||
$ ledger -f expr.dat --format "%(account) %(floor(amount))\n" reg
|
||||
@end smallexample
|
||||
|
|
@ -8110,6 +8109,7 @@ $ ledger -f expr.dat --format "%(account) %(floor(amount))\n" reg
|
|||
Assets:Cash ¤ -124,00
|
||||
Expenses:Office Supplies ¤ 123,00
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun format
|
||||
@value{FIXME:UNDOCUMENTED}
|
||||
|
|
@ -8118,13 +8118,13 @@ Expenses:Office Supplies ¤ 123,00
|
|||
@defun format_date date format
|
||||
Return the @var{date} as a string using @var{format}. See strftime (3)
|
||||
for format string details.
|
||||
@end defun
|
||||
@smallexample @c command:9605B13,with_input:3406FC1
|
||||
$ ledger -f expr.dat --format "%(format_date(date, '%A, %B %d. %Y'))\n" reg assets
|
||||
@end smallexample
|
||||
@smallexample @c output:9605B13
|
||||
Friday, January 16. 2015
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun format_datetime
|
||||
@value{FIXME:UNDOCUMENTED}
|
||||
|
|
@ -8151,7 +8151,6 @@ If @var{right_justify=true} then the field is right justify within
|
|||
the width of the field. If it is @var{false}, then the field is left
|
||||
justified and padded to the full width of the field. If
|
||||
@var{colorize} is true, then ledger will honor color settings.
|
||||
@end defun
|
||||
@smallexample @c command:082FB27,with_input:3406FC1
|
||||
$ ledger -f expr.dat --format "»%(justify(account, 30, 30, true))«\n" reg
|
||||
@end smallexample
|
||||
|
|
@ -8159,6 +8158,7 @@ $ ledger -f expr.dat --format "»%(justify(account, 30, 30, true))«\n" reg
|
|||
» Assets:Cash«
|
||||
» Expenses:Office Supplies«
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun market
|
||||
@defunx P
|
||||
|
|
@ -8189,7 +8189,6 @@ true $
|
|||
|
||||
@defun percent value_a value_b
|
||||
Return the percentage of @var{value_a} in relation to @var{value_b} (used as 100%)
|
||||
@end defun
|
||||
@smallexample @c command:04959BF,with_input:3406FC1
|
||||
$ ledger -f expr.dat --format "%(percent(amount, 200))\n" reg
|
||||
@end smallexample
|
||||
|
|
@ -8197,6 +8196,7 @@ $ ledger -f expr.dat --format "%(percent(amount, 200))\n" reg
|
|||
-61.73%
|
||||
61.73%
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun print
|
||||
@value{FIXME:UNDOCUMENTED}
|
||||
|
|
@ -8208,7 +8208,6 @@ $ ledger -f expr.dat --format "%(percent(amount, 200))\n" reg
|
|||
|
||||
@defun quoted expression
|
||||
Surround @var{expression} with double-quotes.
|
||||
@end defun
|
||||
@smallexample @c command:EAD8AA7,with_input:3406FC1
|
||||
$ ledger -f expr.dat --format "%(quoted(account)) %(quoted(amount))\n" reg
|
||||
@end smallexample
|
||||
|
|
@ -8216,6 +8215,7 @@ $ ledger -f expr.dat --format "%(quoted(account)) %(quoted(amount))\n" reg
|
|||
"Assets:Cash" "¤ -123,45"
|
||||
"Expenses:Office Supplies" "¤ 123,45"
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun round
|
||||
@value{FIXME:UNDOCUMENTED}
|
||||
|
|
@ -8227,7 +8227,6 @@ $ ledger -f expr.dat --format "%(quoted(account)) %(quoted(amount))\n" reg
|
|||
|
||||
@defun roundto value n
|
||||
Return @var{value} rounded to @var{n} digits. Does not affect formatting.
|
||||
@end defun
|
||||
@smallexample @c command:B4DFB9F,with_input:3406FC1
|
||||
$ ledger -f expr.dat --format "%(account) %(roundto(amount, 1))\n" reg
|
||||
@end smallexample
|
||||
|
|
@ -8235,6 +8234,7 @@ $ ledger -f expr.dat --format "%(account) %(roundto(amount, 1))\n" reg
|
|||
Assets:Cash ¤ -123,40
|
||||
Expenses:Office Supplies ¤ 123,50
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun scrub
|
||||
@value{FIXME:UNDOCUMENTED}
|
||||
|
|
@ -8272,7 +8272,6 @@ Expenses:Office Supplies ¤ 123,50
|
|||
@defun to_int value
|
||||
@defunx int value
|
||||
Return the integer value for @var{value}.
|
||||
@end defun
|
||||
@smallexample @c command:0B0CBA1,with_input:3406FC1
|
||||
$ ledger -f expr.dat --format "%(1 + to_int('1'))\n%(2,5 + int(2,5))\n" reg assets
|
||||
@end smallexample
|
||||
|
|
@ -8280,6 +8279,7 @@ $ ledger -f expr.dat --format "%(1 + to_int('1'))\n%(2,5 + int(2,5))\n" reg asse
|
|||
2
|
||||
4.5
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun to_mask
|
||||
@value{FIXME:UNDOCUMENTED}
|
||||
|
|
@ -8314,13 +8314,13 @@ $ ledger -f expr.dat --now 2015/01/01 --format "%(today)\n" reg assets
|
|||
|
||||
@defun trim value
|
||||
Trim leading and trailing whitespace from @var{value}.
|
||||
@end defun
|
||||
@smallexample @c command:377BBAB,with_input:3406FC1
|
||||
$ ledger -f expr.dat --format "»%(trim(' Trimmed '))«\n" reg assets
|
||||
@end smallexample
|
||||
@smallexample @c output:377BBAB
|
||||
»Trimmed«
|
||||
@end smallexample
|
||||
@end defun
|
||||
|
||||
@defun truncated
|
||||
@value{FIXME:UNDOCUMENTED}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class CheckManpage (CheckOptions):
|
|||
def __init__(self, args):
|
||||
CheckOptions.__init__(self, args)
|
||||
self.option_pattern = '\.It Fl \\\\-([-A-Za-z]+)'
|
||||
self.function_pattern = '\.It Fn ([-A-Za-z_]+)'
|
||||
self.source_file = join(self.source, 'doc', 'ledger.1')
|
||||
self.source_type = 'manpage'
|
||||
|
||||
|
|
|
|||
|
|
@ -22,16 +22,21 @@ class CheckOptions (object):
|
|||
self.ledger = os.path.abspath(args.ledger)
|
||||
self.source = os.path.abspath(args.source)
|
||||
|
||||
self.missing_baseline_tests = set()
|
||||
self.missing_options = set()
|
||||
self.unknown_options = set()
|
||||
self.missing_functions = set()
|
||||
self.unknown_functions = set()
|
||||
|
||||
def find_options(self, filename):
|
||||
regex = re.compile(self.option_pattern)
|
||||
def find_pattern(self, filename, pattern):
|
||||
regex = re.compile(pattern)
|
||||
return {match.group(1) for match in {regex.match(line) for line in open(filename)} if match}
|
||||
|
||||
def find_options(self, filename):
|
||||
return self.find_pattern(filename, self.option_pattern)
|
||||
|
||||
def find_functions(self, filename):
|
||||
return self.find_pattern(filename, self.function_pattern)
|
||||
def find_alternates(self):
|
||||
regex = re.compile(r'OPT_ALT\([^,]*,\s*([^)]+?)_?\)');
|
||||
command = shlex.split('grep --no-filename OPT_ALT')
|
||||
for source_file in ['session', 'report']:
|
||||
command.append(os.path.join(self.source, 'src', '%s.cc' % source_file))
|
||||
|
|
@ -39,6 +44,8 @@ class CheckOptions (object):
|
|||
output = subprocess.check_output(command).split('\n');
|
||||
except subprocess.CalledProcessError:
|
||||
output = ''
|
||||
|
||||
regex = re.compile(r'OPT_ALT\([^,]*,\s*([^)]+?)_?\)');
|
||||
alternates = {match.group(1).replace('_', '-') for match in {regex.search(line) for line in output} if match}
|
||||
return alternates
|
||||
|
||||
|
|
@ -49,22 +56,43 @@ class CheckOptions (object):
|
|||
ledger_options = {match.group(1).replace('_', '-') for match in {regex.search(line.decode()) for line in pipe.stderr} if match}
|
||||
return ledger_options
|
||||
|
||||
def ledger_functions(self):
|
||||
command = shlex.split('grep --no-filename fn_ %s' % (os.path.join(self.source, 'src', 'report.h')))
|
||||
try:
|
||||
output = subprocess.check_output(command).split('\n');
|
||||
except subprocess.CalledProcessError:
|
||||
output = ''
|
||||
|
||||
regex = re.compile(r'fn_([^(]+)\(');
|
||||
functions = {match.group(1) for match in {regex.search(line) for line in output} if match}
|
||||
return functions
|
||||
|
||||
def main(self):
|
||||
options = self.find_options(self.source_file)
|
||||
|
||||
for option in self.ledger_options():
|
||||
if option not in options:
|
||||
self.missing_options.add(option)
|
||||
else:
|
||||
options.remove(option)
|
||||
|
||||
known_alternates = self.find_alternates()
|
||||
self.unknown_options = {option for option in options if option not in known_alternates}
|
||||
|
||||
if len(self.missing_options):
|
||||
print("Missing %s entries for:%s%s\n" % (self.source_type, self.sep, self.sep.join(sorted(list(self.missing_options)))))
|
||||
if len(self.unknown_options):
|
||||
print("%s entry for unknown options:%s%s" % (self.source_type, self.sep, self.sep.join(sorted(list(self.unknown_options)))))
|
||||
functions = self.find_functions(self.source_file)
|
||||
for function in self.ledger_functions():
|
||||
if function not in functions:
|
||||
self.missing_functions.add(function)
|
||||
else:
|
||||
functions.remove(function)
|
||||
known_functions = ['tag', 'has_tag']
|
||||
self.unknown_functions = {function for function in functions if function not in known_functions}
|
||||
|
||||
errors = len(self.missing_options) + len(self.unknown_options)
|
||||
if len(self.missing_options):
|
||||
print("Missing %s option entries for:%s%s\n" % (self.source_type, self.sep, self.sep.join(sorted(list(self.missing_options)))))
|
||||
if len(self.unknown_options):
|
||||
print("%s entry for unknown options:%s%s\n" % (self.source_type, self.sep, self.sep.join(sorted(list(self.unknown_options)))))
|
||||
if len(self.missing_functions):
|
||||
print("Missing %s function entries for:%s%s\n" % (self.source_type, '\n ', '\n '.join(sorted(list(self.missing_functions)))))
|
||||
if len(self.unknown_functions):
|
||||
print("%s entry for unknown functions:%s%s\n" % (self.source_type, '\n ', '\n '.join(sorted(list(self.unknown_functions)))))
|
||||
errors = len(self.missing_options) + len(self.unknown_options) + len(self.missing_functions) + len(self.unknown_functions)
|
||||
return errors
|
||||
|
|
|
|||
|
|
@ -16,10 +16,47 @@ from CheckOptions import CheckOptions
|
|||
class CheckTexinfo (CheckOptions):
|
||||
def __init__(self, args):
|
||||
CheckOptions.__init__(self, args)
|
||||
self.option_pattern = '@item --([-A-Za-z]+).*@c option'
|
||||
self.option_pattern = '^@item\s+--([-A-Za-z]+)'
|
||||
self.function_pattern = '^@defun\s+([-A-Za-z_]+)'
|
||||
self.source_file = join(self.source, 'doc', 'ledger3.texi')
|
||||
self.source_type = 'texinfo'
|
||||
|
||||
|
||||
def find_functions(self, filename):
|
||||
functions = set()
|
||||
state_normal = 0
|
||||
state_function = 1
|
||||
state = state_normal
|
||||
function = None
|
||||
fun_doc = str()
|
||||
fun_example = False
|
||||
item_regex = re.compile(self.function_pattern)
|
||||
itemx_regex = re.compile('^@defunx')
|
||||
example_regex = re.compile('^@smallexample\s+@c\s+command:')
|
||||
fix_regex = re.compile('FIX')
|
||||
comment_regex = re.compile('^\s*@c')
|
||||
for line in open(filename):
|
||||
line = line.strip()
|
||||
if state == state_normal:
|
||||
match = item_regex.match(line)
|
||||
if match:
|
||||
state = state_function
|
||||
function = match.group(1)
|
||||
elif state == state_function:
|
||||
if line == '@end defun':
|
||||
if function and fun_example and len(fun_doc) and not fix_regex.search(fun_doc):
|
||||
functions.add(function)
|
||||
state = state_normal
|
||||
fun_example = None
|
||||
fun_doc = str()
|
||||
elif itemx_regex.match(line):
|
||||
continue
|
||||
elif example_regex.match(line):
|
||||
fun_example = True
|
||||
elif not comment_regex.match(line):
|
||||
fun_doc += line
|
||||
return functions
|
||||
|
||||
def find_options(self, filename):
|
||||
options = set()
|
||||
state_normal = 0
|
||||
|
|
@ -27,7 +64,7 @@ class CheckTexinfo (CheckOptions):
|
|||
state = state_normal
|
||||
option = None
|
||||
opt_doc = str()
|
||||
item_regex = re.compile('^@item --([-A-Za-z]+)')
|
||||
item_regex = re.compile(self.option_pattern)
|
||||
itemx_regex = re.compile('^@itemx')
|
||||
fix_regex = re.compile('FIX')
|
||||
comment_regex = re.compile('^\s*@c')
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue