fix: customised usage messages
Add functionality to display the default help message when running spruce without any arguments or when the help flag is used. Customise the help message for the subcommands. Additional changes: - Refactor: move the Runner interface to the internal cmd package - Fix: Add a summary for each of the subcommands. - Refactor: Use string builder to replace string literals. - Perf: Use a switch statement to only create the subcommand that the user calls.
This commit is contained in:
parent
050748d8cd
commit
90638f5569
6 changed files with 118 additions and 35 deletions
|
@ -89,6 +89,29 @@ go install .
|
|||
|
||||
=== Verifying the installation
|
||||
|
||||
Run `spruce` to verify your installation. You should see the usage printed onto your screen.
|
||||
|
||||
[source,console]
|
||||
----
|
||||
$ spruce
|
||||
A tool for building CVs
|
||||
|
||||
Usage:
|
||||
spruce [flags]
|
||||
spruce [command]
|
||||
|
||||
Available Commands:
|
||||
create create a new CV JSON file
|
||||
generate generate a PDF file from an existing CV JSON file
|
||||
version print the application's build information
|
||||
|
||||
Flags:
|
||||
-h, --help
|
||||
print the help message for spruce
|
||||
|
||||
Use "spruce [command] --help" for more information about a command.
|
||||
----
|
||||
|
||||
If you have installed spruce with Mage, you can get the build information to confirm that you have installed the correct version.
|
||||
[source,console]
|
||||
----
|
||||
|
|
51
internal/cmd/cmd.go
Normal file
51
internal/cmd/cmd.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Runner interface {
|
||||
Parse([]string) error
|
||||
Name() string
|
||||
Run() error
|
||||
}
|
||||
|
||||
func SpruceUsage() {
|
||||
usage := `A tool for building CVs
|
||||
|
||||
Usage:
|
||||
spruce [flags]
|
||||
spruce [command]
|
||||
|
||||
Available Commands:
|
||||
create create a new CV JSON file
|
||||
generate generate a PDF file from an existing CV JSON file
|
||||
version print the application's build information
|
||||
|
||||
Flags:
|
||||
-h, --help
|
||||
print the help message for spruce
|
||||
|
||||
Use "spruce [command] --help" for more information about a command.
|
||||
`
|
||||
|
||||
fmt.Print(usage)
|
||||
}
|
||||
|
||||
func usageFunc(name, summary string, flagset *flag.FlagSet) func() {
|
||||
return func() {
|
||||
var b strings.Builder
|
||||
|
||||
w := flag.CommandLine.Output()
|
||||
|
||||
fmt.Fprintf(&b, "%s\n\nUsage:\n spruce %s [flags]\n\nFlags:", summary, name)
|
||||
|
||||
flagset.VisitAll(func(f *flag.Flag) {
|
||||
fmt.Fprintf(&b, "\n --%s\n %s\n", f.Name, f.Usage)
|
||||
})
|
||||
|
||||
fmt.Fprint(w, b.String())
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
type CreateCommand struct {
|
||||
*flag.FlagSet
|
||||
summary string
|
||||
firstName string
|
||||
lastName string
|
||||
jobTitle string
|
||||
|
@ -22,12 +23,15 @@ type CreateCommand struct {
|
|||
func NewCreateCommand() *CreateCommand {
|
||||
cc := CreateCommand{
|
||||
FlagSet: flag.NewFlagSet("create", flag.ExitOnError),
|
||||
summary: "Create a new CV JSON file.",
|
||||
}
|
||||
|
||||
cc.StringVar(&cc.firstName, "first-name", "", "specify your first name")
|
||||
cc.StringVar(&cc.lastName, "last-name", "", "specify your last name")
|
||||
cc.StringVar(&cc.jobTitle, "job-title", "", "specify your preferred job title")
|
||||
cc.StringVar(&cc.filename, "filename", "cv.json", "specify the filename of the created JSON document")
|
||||
cc.StringVar(&cc.filename, "filepath", "cv.json", "specify the path where the CV JSON document should be created.")
|
||||
cc.StringVar(&cc.firstName, "first-name", "", "specify your first name.")
|
||||
cc.StringVar(&cc.jobTitle, "job-title", "", "specify your current job title.")
|
||||
cc.StringVar(&cc.lastName, "last-name", "", "specify your last name.")
|
||||
|
||||
cc.Usage = usageFunc(cc.Name(), cc.summary, cc.FlagSet)
|
||||
|
||||
return &cc
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ var templates embed.FS
|
|||
|
||||
type GenerateCommand struct {
|
||||
*flag.FlagSet
|
||||
summary string
|
||||
input string
|
||||
output string
|
||||
employmentHistory int
|
||||
|
@ -30,12 +31,15 @@ type GenerateCommand struct {
|
|||
func NewGenerateCommand() *GenerateCommand {
|
||||
gc := GenerateCommand{
|
||||
FlagSet: flag.NewFlagSet("generate", flag.ExitOnError),
|
||||
summary: "Generate a PDF file from an existing CV JSON file.",
|
||||
}
|
||||
|
||||
gc.StringVar(&gc.input, "input", "", "specify the CV JSON file that you want to input to the builder.")
|
||||
gc.StringVar(&gc.output, "output", "", "specify the name of the output CV file.")
|
||||
gc.IntVar(&gc.employmentHistory, "employment-history", 10, "show employment history within these number of years.")
|
||||
gc.BoolVar(&gc.verbose, "verbose", false, "set to true to enable verbose logging")
|
||||
gc.BoolVar(&gc.verbose, "verbose", false, "set to true to enable verbose logging.")
|
||||
|
||||
gc.Usage = usageFunc(gc.Name(), gc.summary, gc.FlagSet)
|
||||
|
||||
return &gc
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@ package cmd
|
|||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type VersionCommand struct {
|
||||
*flag.FlagSet
|
||||
summary string
|
||||
fullVersion bool
|
||||
binaryVersion string
|
||||
buildTime string
|
||||
|
@ -21,28 +23,24 @@ func NewVersionCommand(binaryVersion, buildTime, goVersion, gitCommit string) *V
|
|||
buildTime: buildTime,
|
||||
goVersion: goVersion,
|
||||
gitCommit: gitCommit,
|
||||
summary: "Print the application's build information.",
|
||||
}
|
||||
|
||||
vc.BoolVar(&vc.fullVersion, "full", false, "prints the full version")
|
||||
vc.BoolVar(&vc.fullVersion, "full", false, "prints the full build information")
|
||||
|
||||
vc.Usage = usageFunc(vc.Name(), vc.summary, vc.FlagSet)
|
||||
|
||||
return &vc
|
||||
}
|
||||
|
||||
func (v *VersionCommand) Run() error {
|
||||
var version string
|
||||
var b strings.Builder
|
||||
if v.fullVersion {
|
||||
fullVersionFmt := `Spruce
|
||||
Version: %s
|
||||
Git commit: %s
|
||||
Go version: %s
|
||||
Build date: %s
|
||||
`
|
||||
|
||||
version = fmt.Sprintf(fullVersionFmt, v.binaryVersion, v.gitCommit, v.goVersion, v.buildTime)
|
||||
fmt.Fprintf(&b, "Spruce\n Version: %s\n Git commit: %s\n Go version: %s\n Build date: %s\n", v.binaryVersion, v.gitCommit, v.goVersion, v.buildTime)
|
||||
} else {
|
||||
version = v.binaryVersion + "\n"
|
||||
fmt.Fprintln(&b, v.binaryVersion)
|
||||
}
|
||||
|
||||
fmt.Print(version)
|
||||
fmt.Print(b.String())
|
||||
return nil
|
||||
}
|
||||
|
|
39
main.go
39
main.go
|
@ -8,12 +8,6 @@ import (
|
|||
"codeflow.dananglin.me.uk/apollo/spruce/internal/cmd"
|
||||
)
|
||||
|
||||
type Runner interface {
|
||||
Parse([]string) error
|
||||
Name() string
|
||||
Run() error
|
||||
}
|
||||
|
||||
var (
|
||||
binaryVersion string
|
||||
buildTime string
|
||||
|
@ -22,6 +16,13 @@ var (
|
|||
)
|
||||
|
||||
func main() {
|
||||
args := os.Args[1:]
|
||||
|
||||
if len(args) < 1 || args[0] == "--help" || args[0] == "-h" || args[0] == "help" || args[0] == "-help" {
|
||||
cmd.SpruceUsage()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
logOptions := slog.HandlerOptions{
|
||||
AddSource: false,
|
||||
}
|
||||
|
@ -30,23 +31,25 @@ func main() {
|
|||
|
||||
slog.SetDefault(logger)
|
||||
|
||||
commandMap := map[string]Runner{
|
||||
"version": cmd.NewVersionCommand(
|
||||
subcommand := args[0]
|
||||
|
||||
var runner cmd.Runner
|
||||
|
||||
switch subcommand {
|
||||
case "version":
|
||||
runner = cmd.NewVersionCommand(
|
||||
binaryVersion,
|
||||
buildTime,
|
||||
goVersion,
|
||||
gitCommit,
|
||||
),
|
||||
"generate": cmd.NewGenerateCommand(),
|
||||
"create": cmd.NewCreateCommand(),
|
||||
}
|
||||
|
||||
subcommand := os.Args[1]
|
||||
|
||||
runner, ok := commandMap[subcommand]
|
||||
|
||||
if !ok {
|
||||
)
|
||||
case "generate":
|
||||
runner = cmd.NewGenerateCommand()
|
||||
case "create":
|
||||
runner = cmd.NewCreateCommand()
|
||||
default:
|
||||
slog.Error("unknown subcommand", "subcommand", subcommand)
|
||||
cmd.SpruceUsage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue