Skip to content

Commit 112b813

Browse files
goofinatorakamensky
authored andcommitted
Gocyclo on issue 1#2 (akamensky#55)
* reduced gocyclo at argument.go/reduce * reduced gocyclo at argument.go/check * reduced gocyclo at argument.go/setDefault (using reflect to merge most of cases into one) * reduced gocyclo at argument.go/setDefault (filenames processing moved into the functions) * reduced gocyclo at command.go/parse (some blocks of code have been moved into separate functions) * reduced gocyclo at argparse.go/Usage (some blocks of code have been moved into separate functions) * reduced gocyclo at argparse_test.go/TestInternalFunctionParse (cycle on testing table) * reduced gocyclo at argparse_test.go/TestCommandMixedArgs1 (cycle on commands)
1 parent 0d46fd6 commit 112b813

File tree

4 files changed

+323
-290
lines changed

4 files changed

+323
-290
lines changed

argparse.go

Lines changed: 77 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -394,33 +394,11 @@ func (o *Command) Selector(short string, long string, options []string, opts *Op
394394
return &result
395395
}
396396

397-
// Happened shows whether Command was specified on CLI arguments or not. If Command did not "happen", then
398-
// all its descendant commands and arguments are not parsed. Returns a boolean value.
399-
func (o *Command) Happened() bool {
400-
return o.happened
401-
}
402-
403-
// Usage returns a multiline string that is the same as a help message for this Parser or Command.
404-
// Since Parser is a Command as well, they work in exactly same way. Meaning that usage string
405-
// can be retrieved for any level of commands. It will only include information about this Command,
406-
// its sub-commands, current Command arguments and arguments of all preceding commands (if any)
407-
//
397+
// message2String - puts msg in result string
408398
// Accepts an interface that can be error, string or fmt.Stringer that will be prepended to a message.
409399
// All other interface types will be ignored
410-
func (o *Command) Usage(msg interface{}) string {
411-
for _, cmd := range o.commands {
412-
if cmd.Happened() {
413-
return cmd.Usage(msg)
414-
}
415-
}
400+
func message2String(msg interface{}) string {
416401
var result string
417-
// Stay classy
418-
maxWidth := 80
419-
// List of arguments from all preceding commands
420-
arguments := make([]*arg, 0)
421-
// First get line of commands until root
422-
var chain []string
423-
current := o
424402
if msg != nil {
425403
switch msg.(type) {
426404
case subCommandError:
@@ -437,23 +415,33 @@ func (o *Command) Usage(msg interface{}) string {
437415
result = fmt.Sprintf("%s\n", msg.(fmt.Stringer).String())
438416
}
439417
}
418+
return result
419+
}
420+
421+
// getPrecedingCommands - collects info on command chain from root to current (o *Command) and all arguments in this chain
422+
func (o *Command) getPrecedingCommands(chain *[]string, arguments *[]*arg) {
423+
current := o
424+
// Get line of commands until root
440425
for current != nil {
441-
chain = append(chain, current.name)
426+
*chain = append(*chain, current.name)
442427
// Also add arguments
443428
if current.args != nil {
444-
arguments = append(arguments, current.args...)
429+
*arguments = append(*arguments, current.args...)
445430
}
446431
current = current.parent
447432
}
448433
// Reverse the slice
449-
last := len(chain) - 1
450-
for i := 0; i < len(chain)/2; i++ {
451-
chain[i], chain[last-i] = chain[last-i], chain[i]
434+
last := len(*chain) - 1
435+
for i := 0; i < len(*chain)/2; i++ {
436+
(*chain)[i], (*chain)[last-i] = (*chain)[last-i], (*chain)[i]
452437
}
453-
// If this Command has sub-commands we need their list
438+
}
439+
440+
// getSubCommands - collects info on subcommands of current command
441+
func (o *Command) getSubCommands(chain *[]string) []Command {
454442
commands := make([]Command, 0)
455443
if o.commands != nil && len(o.commands) > 0 {
456-
chain = append(chain, "<Command>")
444+
*chain = append(*chain, "<Command>")
457445
for _, v := range o.commands {
458446
// Skip hidden commands
459447
if v.description == DisableDescription {
@@ -462,9 +450,11 @@ func (o *Command) Usage(msg interface{}) string {
462450
commands = append(commands, *v)
463451
}
464452
}
453+
return commands
454+
}
465455

466-
// Build usage description
467-
result += "usage:"
456+
// precedingCommands2Result - puts info about command chain from root to current (o *Command) into result string buffer
457+
func (o *Command) precedingCommands2Result(result string, chain []string, arguments []*arg, maxWidth int) string {
468458
leftPadding := len("usage: " + chain[0] + "")
469459
// Add preceding commands
470460
for _, v := range chain {
@@ -478,12 +468,16 @@ func (o *Command) Usage(msg interface{}) string {
478468
}
479469
result = addToLastLine(result, v.usage(), maxWidth, leftPadding, true)
480470
}
481-
482471
// Add program/Command description to the result
483472
result = result + "\n\n" + strings.Repeat(" ", leftPadding)
484473
result = addToLastLine(result, o.description, maxWidth, leftPadding, true)
485474
result = result + "\n\n"
486475

476+
return result
477+
}
478+
479+
// subCommands2Result - puts info about subcommands of current command into result string buffer
480+
func subCommands2Result(result string, commands []Command, maxWidth int) string {
487481
// Add list of sub-commands to the result
488482
if len(commands) > 0 {
489483
cmdContent := "Commands:\n\n"
@@ -509,8 +503,11 @@ func (o *Command) Usage(msg interface{}) string {
509503
}
510504
result = result + cmdContent + "\n"
511505
}
506+
return result
507+
}
512508

513-
// Add list of arguments to the result
509+
// arguments2Result - puts info about all arguments of current command into result string buffer
510+
func arguments2Result(result string, arguments []*arg, maxWidth int) string {
514511
if len(arguments) > 0 {
515512
argContent := "Arguments:\n\n"
516513
// Get biggest padding
@@ -544,6 +541,51 @@ func (o *Command) Usage(msg interface{}) string {
544541
}
545542
result = result + argContent + "\n"
546543
}
544+
return result
545+
}
546+
547+
// Happened shows whether Command was specified on CLI arguments or not. If Command did not "happen", then
548+
// all its descendant commands and arguments are not parsed. Returns a boolean value.
549+
func (o *Command) Happened() bool {
550+
return o.happened
551+
}
552+
553+
// Usage returns a multiline string that is the same as a help message for this Parser or Command.
554+
// Since Parser is a Command as well, they work in exactly same way. Meaning that usage string
555+
// can be retrieved for any level of commands. It will only include information about this Command,
556+
// its sub-commands, current Command arguments and arguments of all preceding commands (if any)
557+
//
558+
// Accepts an interface that can be error, string or fmt.Stringer that will be prepended to a message.
559+
// All other interface types will be ignored
560+
func (o *Command) Usage(msg interface{}) string {
561+
for _, cmd := range o.commands {
562+
if cmd.Happened() {
563+
return cmd.Usage(msg)
564+
}
565+
}
566+
567+
var result string
568+
// Stay classy
569+
maxWidth := 80
570+
// List of arguments from all preceding commands
571+
arguments := make([]*arg, 0)
572+
// Line of commands until root
573+
var chain []string
574+
575+
// Put message in resultz
576+
result = message2String(msg)
577+
578+
//collect info about Preceding Commands into chain and arguments
579+
o.getPrecedingCommands(&chain, &arguments)
580+
// If this Command has sub-commands we need their list
581+
commands := o.getSubCommands(&chain)
582+
583+
// Build usage description from description of preceding commands chain and each of subcommands
584+
result += "usage:"
585+
result = o.precedingCommands2Result(result, chain, arguments, maxWidth)
586+
result = subCommands2Result(result, commands, maxWidth)
587+
// Add list of arguments to the result
588+
result = arguments2Result(result, arguments, maxWidth)
547589

548590
return result
549591
}

0 commit comments

Comments
 (0)