Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
  • v1.0.0
  • v1.1.0
  • v1.1.1
  • v1.10.0
  • v1.10.1
  • v1.10.2
  • v1.11.0
  • v1.12.0
  • v1.13.0
  • v1.13.1
  • v1.13.2
  • v1.14.0
  • v1.15.0
  • v1.16.0
  • v1.16.1
  • v1.16.2
  • v1.16.3
  • v1.16.4
  • v1.16.5
  • v1.2.0
  • v1.2.1
  • v1.2.2
  • v1.2.3
  • v1.3.0
  • v1.3.1
  • v1.4.0
  • v1.5.0
  • v1.6.0
  • v1.7.0
  • v1.8.0
  • v1.8.1
  • v1.8.2
  • v1.8.3
  • v1.9.0
35 results

Target

Select target project
  • oss/libraries/go/application/xflags
1 result
Select Git revision
  • master
  • v1.0.0
  • v1.1.0
  • v1.1.1
  • v1.10.0
  • v1.10.1
  • v1.10.2
  • v1.11.0
  • v1.12.0
  • v1.13.0
  • v1.13.1
  • v1.13.2
  • v1.14.0
  • v1.15.0
  • v1.16.0
  • v1.16.1
  • v1.16.2
  • v1.16.3
  • v1.16.4
  • v1.16.5
  • v1.2.0
  • v1.2.1
  • v1.2.2
  • v1.2.3
  • v1.3.0
  • v1.3.1
  • v1.4.0
  • v1.5.0
  • v1.6.0
  • v1.7.0
  • v1.8.0
  • v1.8.1
  • v1.8.2
  • v1.8.3
  • v1.9.0
35 results
Show changes
Commits on Source (3)
<a name="v1.11.0"></a>
## [v1.11.0] - 2022-10-19
### Add Features
- feat improve the help output
<a name="v1.10.2"></a>
## [v1.10.2] - 2022-10-16
### Bug Fixes
......@@ -129,6 +135,7 @@
<a name="v1.0.0"></a>
## v1.0.0 - 2022-10-04
[v1.11.0]: https://gitlab.schukai.com/oss/libraries/go/application/xflags/compare/v1.10.2...v1.11.0
[v1.10.2]: https://gitlab.schukai.com/oss/libraries/go/application/xflags/compare/v1.10.1...v1.10.2
[v1.10.1]: https://gitlab.schukai.com/oss/libraries/go/application/xflags/compare/v1.10.0...v1.10.1
[v1.10.0]: https://gitlab.schukai.com/oss/libraries/go/application/xflags/compare/v1.9.0...v1.10.0
......
/**
* Copyright (c) 2009 The Go Authors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/
package xflags
// this file contain adapted standard function from flag.go
import (
"flag"
"fmt"
"reflect"
"strings"
)
func getFlagTable(f *flag.FlagSet) []string {
var isZeroValueErrs []error
result := []string{}
f.VisitAll(func(f *flag.Flag) {
var b strings.Builder
fmt.Fprintf(&b, " -%s", f.Name) // Two spaces before -; see next two comments.
name, usage := flag.UnquoteUsage(f)
if len(name) > 0 {
b.WriteString(" ")
b.WriteString(name)
}
// Boolean flags of one ASCII letter are so common we
// treat them specially, putting their usage on the same line.
if b.Len() <= 4 { // space, space, '-', 'x'.
b.WriteString("\t")
} else {
// Four spaces before the tab triggers good alignment
// for both 4- and 8-space tab stops.
b.WriteString("\n \t")
}
b.WriteString(strings.ReplaceAll(usage, "\n", "\n \t"))
// Print the default value only if it differs to the zero value
// for this flag type.
if isZero, err := isZeroValue(f, f.DefValue); err != nil {
isZeroValueErrs = append(isZeroValueErrs, err)
} else if !isZero {
if _, ok := f.Value.(*stringValue); ok {
// put quotes on the value
fmt.Fprintf(&b, " (default %q)", f.DefValue)
} else {
fmt.Fprintf(&b, " (default %v)", f.DefValue)
}
}
result = append(result, b.String())
})
// If calling String on any zero flag.Values triggered a panic, print
// the messages after the full set of defaults so that the programmer
// knows to fix the panic.
if errs := isZeroValueErrs; len(errs) > 0 {
fmt.Fprintln(f.Output())
for _, err := range errs {
result = append(result, err.Error())
}
}
return result
}
// isZeroValue determines whether the string represents the zero
// value for a flag.
func isZeroValue(f *flag.Flag, value string) (ok bool, err error) {
// Build a zero value of the flag's Value type, and see if the
// result of calling its String method equals the value passed in.
// This works unless the Value type is itself an interface type.
typ := reflect.TypeOf(f.Value)
var z reflect.Value
if typ.Kind() == reflect.Pointer {
z = reflect.New(typ.Elem())
} else {
z = reflect.Zero(typ)
}
// Catch panics calling the String method, which shouldn't prevent the
// usage message from being printed, but that we should report to the
// user so that they know to fix their code.
defer func() {
if e := recover(); e != nil {
if typ.Kind() == reflect.Pointer {
typ = typ.Elem()
}
err = fmt.Errorf("panic calling String method on zero %v for flag %s: %v", typ, f.Name, e)
}
}()
return value == z.Interface().(flag.Value).String(), nil
}
// -- string Value
type stringValue string
func newStringValue(val string, p *string) *stringValue {
*p = val
return (*stringValue)(p)
}
func (s *stringValue) Set(val string) error {
*s = stringValue(val)
return nil
}
func (s *stringValue) Get() any { return string(*s) }
func (s *stringValue) String() string { return string(*s) }
package xflags
import (
"strings"
)
func (c *cmd[C]) getCommandLevel() (*cmd[C], []string) {
result := c
path := []string{}
path = append(path, c.name)
for _, c := range c.commands {
if c.flagSet.Parsed() {
var p []string
result, p = c.getCommandLevel()
path = append(path, p...)
break
}
}
return result, path
}
// Help returns the help text for the command
func (s *Settings[C]) Help() string {
cmd, path := s.command.getCommandLevel()
h := strings.Join(path, " ")
var help string
help = "Usage: " + h + " "
g := getFlagTable(cmd.settings.command.flagSet)
if len(g) > 0 {
help += "[global options] "
}
if len(cmd.commands) > 0 {
help += "[command] "
}
help += "[arguments]"
help += "\n"
if len(g) > 0 {
help += "\nGlobal Options:\n"
help += strings.Join(g, "\n") + "\n"
}
if len(cmd.commands) > 0 {
for _, c := range cmd.commands {
help += "\nCommand: " + c.name + "\n"
//help += fmt.Sprintf(" %s\t%s", c.name, c.tagMapping[tagDescription])
s := getFlagTable(c.flagSet)
if len(s) > 0 {
help += "\nOptions:\n"
help += strings.Join(s, "\n") + "\n"
}
}
}
return help
}
package xflags
import (
"github.com/stretchr/testify/assert"
"testing"
)
type CmdTestHelp1 struct {
A bool `short:"a" description:"Message A"`
Sub1 struct {
B bool `short:"b" description:"Message B"`
Sub2 struct {
C bool `short:"c" description:"Message C"`
Sub3 struct {
D bool `short:"d" description:"Message D"`
} `command:"sub3"`
Sub4 struct {
E bool `short:"e" description:"Message E"`
} `command:"sub4"`
} `command:"sub2"`
} `command:"sub1"`
aa int `short:"x" description:"Message X"`
}
func TestGetHelp(t *testing.T) {
tables := []struct {
name string
args []string
substring string
}{
{"test1", []string{"sub1", "--help"}, "Usage: test1 sub1 [global options] [command] [arguments]"},
{"test1", []string{"xsd", "help"}, "Usage: test1 [global options] [command] [arguments]"},
{"test2", []string{"sub1", "sub2"}, "Usage: test2 sub1 sub2 [global options] [command] [arguments]"},
}
for _, table := range tables {
t.Run(table.name, func(t *testing.T) {
s := New(table.name, CmdTestHelp1{})
s.Parse(table.args)
help := s.Help()
assert.NotEmpty(t, help)
assert.Contains(t, help, table.substring)
})
}
}
{"version":"1.10.2"}
{"version":"1.11.0"}