Skip to content

Commit 8ccb813

Browse files
authored
flag: add DocOptions/Show to FlagParser (#26630)
1 parent bcfc16a commit 8ccb813

3 files changed

Lines changed: 108 additions & 28 deletions

File tree

vlib/flag/flag.v

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,9 @@ pub mut:
9595
application_description string
9696
min_free_args int
9797
args_description string
98-
allow_unknown_args bool // whether passing undescribed arguments is allowed
99-
footers []string // when set, --help will display all the collected footers at the bottom.
98+
allow_unknown_args bool // whether passing undescribed arguments is allowed
99+
footers []string // when set, --help will display all the collected footers at the bottom.
100+
options DocOptions // documentation options
100101
}
101102

102103
// free frees the resources allocated for the given FlagParser instance.
@@ -144,6 +145,9 @@ pub fn new_flag_parser(args []string) &FlagParser {
144145
all_after_dashdash: all_after_dashdash
145146
args: all_before_dashdash
146147
max_free_args: max_args_number
148+
options: DocOptions{
149+
show: ~Show.zero() ^ .name
150+
}
147151
}
148152
}
149153

@@ -548,8 +552,9 @@ pub fn (fs &FlagParser) usage() string {
548552
adesc = ''
549553
}
550554
mut use := []string{}
551-
if fs.application_version != '' {
552-
use << '${fs.application_name} ${fs.application_version}'
555+
if doc_add_name_and_version(fs.application_name, fs.application_version, fs.options, mut
556+
use)
557+
{
553558
use << '${underline}'
554559
}
555560
if fs.usage_examples.len == 0 {
@@ -564,7 +569,7 @@ pub fn (fs &FlagParser) usage() string {
564569
}
565570
}
566571
use << ''
567-
if fs.application_description != '' {
572+
if fs.options.show.has(.description) && fs.application_description != '' {
568573
use << 'Description: ${fs.application_description}'
569574
use << ''
570575
}
@@ -589,8 +594,10 @@ pub fn (fs &FlagParser) usage() string {
589594
use << ''
590595
}
591596
}
592-
if fs.flags.len > 0 {
593-
use << 'Options:'
597+
if fs.options.show.has(.flags) && fs.flags.len > 0 {
598+
if fs.options.show.has(.flags_header) {
599+
use << fs.options.flag_header.trim_space_left()
600+
}
594601
for f in fs.flags {
595602
mut onames := []string{}
596603
if f.abbr != 0 {
@@ -614,8 +621,10 @@ pub fn (fs &FlagParser) usage() string {
614621
use << fdesc
615622
}
616623
}
617-
for footer in fs.footers {
618-
use << footer
624+
if fs.options.show.has(.footer) {
625+
for footer in fs.footers {
626+
use << footer
627+
}
619628
}
620629
return use.join('\n').replace('- ,', ' ')
621630
}

vlib/flag/flag_test.v

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,41 @@ fn test_allow_to_build_usage_message() {
179179
assert all_strings_found
180180
}
181181

182-
fn test_if_no_description_given_usage_message_does_not_contain_descpription() {
182+
fn test_if_app_name_given_but_no_show_usage_message_still_contain_version() {
183183
mut fp := flag.new_flag_parser([])
184184
fp.application('flag_tool')
185185
fp.version('v0.0.0')
186+
fp.description('a description')
186187
fp.bool('a_bool', 0, false, '')
188+
fp.options.show.clear(.name)
189+
assert fp.usage().contains('v0.0.0\n---')
190+
}
191+
192+
fn test_if_version_given_but_no_show_usage_message_does_not_contain_banner() {
193+
mut fp := flag.new_flag_parser([])
194+
fp.application('flag_tool')
195+
fp.version('v0.0.0')
196+
fp.description('a description')
197+
fp.bool('a_bool', 0, false, '')
198+
fp.options.show.clear(.version)
199+
assert !fp.usage().contains('v0.0.0\n---')
200+
}
201+
202+
fn test_if_no_description_given_usage_message_does_not_contain_description() {
203+
mut fp := flag.new_flag_parser([])
204+
fp.application('flag_tool')
205+
fp.version('v0.0.0')
206+
fp.bool('a_bool', 0, false, '')
207+
assert !fp.usage().contains('Description:')
208+
}
209+
210+
fn test_if_description_given_but_no_show_usage_message_does_not_contain_description() {
211+
mut fp := flag.new_flag_parser([])
212+
fp.application('flag_tool')
213+
fp.version('v0.0.0')
214+
fp.description('a description')
215+
fp.bool('a_bool', 0, false, '')
216+
fp.options.show.clear(.description)
187217
assert !fp.usage().contains('Description:')
188218
}
189219

@@ -194,6 +224,34 @@ fn test_if_no_options_given_usage_message_does_not_contain_options() {
194224
assert !fp.usage().contains('Options:')
195225
}
196226

227+
fn test_if_options_given_but_no_show_flag_header_usage_message_does_not_contain_flag_header() {
228+
mut fp := flag.new_flag_parser([])
229+
fp.application('flag_tool')
230+
fp.version('v0.0.0')
231+
fp.int('abc', `a`, 1, '')
232+
fp.options.show.clear(.flags_header)
233+
assert !fp.usage().contains('Options:')
234+
}
235+
236+
fn test_if_options_given_but_no_show_usage_message_does_not_contain_options() {
237+
mut fp := flag.new_flag_parser([])
238+
fp.application('flag_tool')
239+
fp.version('v0.0.0')
240+
fp.int('abc', `a`, 1, '')
241+
fp.options.show.clear(.flags)
242+
assert !fp.usage().contains('Options:')
243+
}
244+
245+
fn test_if_footer_given_but_no_show_usage_message_does_not_contain_footer() {
246+
mut fp := flag.new_flag_parser([])
247+
fp.application('flag_tool')
248+
fp.version('v0.0.0')
249+
fp.int('abc', `a`, 1, '')
250+
fp.footers << 'footer1'
251+
fp.options.show.clear(.footer)
252+
assert !fp.usage().contains('footer1')
253+
}
254+
197255
fn test_default_val_descriptions_for_bools() {
198256
mut fp := flag.new_flag_parser([])
199257
fp.bool('a_bool', `b`, true, '')

vlib/flag/flag_to.v

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -617,14 +617,38 @@ pub fn (mut fm FlagMapper) parse[T]() ! {
617617
}
618618
}
619619

620+
// add name and/or version to doc. Returns true if name or version has been added.
621+
fn doc_add_name_and_version(app_name string, app_version string, options DocOptions, mut docs []string) bool {
622+
mut name_and_version := ''
623+
624+
if options.show.has(.name) && app_name != '' {
625+
name_and_version = app_name
626+
}
627+
628+
if options.show.has(.version) && app_version != '' {
629+
if app_name != '' {
630+
name_and_version = '${app_name} ${app_version}' // Version string is always name + version
631+
} else {
632+
name_and_version = app_version
633+
}
634+
}
635+
636+
if name_and_version != '' {
637+
docs << '${name_and_version}'
638+
639+
return true
640+
}
641+
642+
return false
643+
}
644+
620645
// to_doc returns a "usage" style documentation `string` generated from the internal data structures generated via the `parse()` function.
621646
pub fn (fm FlagMapper) to_doc(dc DocConfig) !string {
622647
mut docs := []string{}
623648

624-
mut name_and_version := ''
649+
mut app_name := ''
625650
// resolve name
626651
if dc.options.show.has(.name) {
627-
mut app_name := ''
628652
// struct `name: x` attribute, if defined
629653
if attr_name := fm.si.attrs['name'] {
630654
app_name = attr_name
@@ -633,13 +657,11 @@ pub fn (fm FlagMapper) to_doc(dc DocConfig) !string {
633657
if dc.name != '' {
634658
app_name = dc.name
635659
}
636-
if app_name != '' {
637-
name_and_version = '${app_name}'
638-
}
639660
}
661+
662+
mut app_version := ''
640663
// resolve version
641664
if dc.options.show.has(.version) {
642-
mut app_version := ''
643665
// struct `version` attribute, if defined
644666
if attr_version := fm.si.attrs['version'] {
645667
app_version = attr_version
@@ -648,19 +670,10 @@ pub fn (fm FlagMapper) to_doc(dc DocConfig) !string {
648670
if dc.version != '' {
649671
app_version = dc.version
650672
}
651-
652-
if app_version != '' {
653-
if name_and_version != '' {
654-
name_and_version = '${name_and_version} ${app_version}'
655-
} else {
656-
name_and_version = '${app_version}'
657-
}
658-
}
659673
}
660674

661-
if name_and_version != '' {
662-
docs << '${name_and_version}'
663-
}
675+
name_and_version := doc_add_name_and_version(app_name, app_version, dc.options, mut
676+
docs)
664677

665678
// Resolve the description if visible
666679
if dc.options.show.has(.description) {
@@ -703,7 +716,7 @@ pub fn (fm FlagMapper) to_doc(dc DocConfig) !string {
703716
}
704717
}
705718

706-
if name_and_version != '' {
719+
if name_and_version {
707720
mut longest_line := 0
708721
for doc_line in docs {
709722
lines := doc_line.split('\n')

0 commit comments

Comments
 (0)