How to actually implement word wrapping?
I copied some code from the tests and got this:
func main() {
cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
funcMap := map[string]interface{}{
"wrapAt": func() int {
return 80
},
}
cli.HelpPrinterCustom(w, templ, data, funcMap)
}
app := &cli.App{...}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
But when I look at the help output, nothing is wrapped. Am I doing this right?
It'd be really nice if this was better documented. Right now there's just has a passing mention of wrapAt in the docs but no examples.
Specifically which content will be wrapped, you can refer to cli.AppHelpTemplate:
https://github.com/urfave/cli/blob/254c38ea72e18e58f2ba8a4e25c7c553f19161e6/template.go#L3-L38
Hi @Dokiys, that's not what I was getting at. I'm saying that how to inject wrapping wasn't documented, nor is what will be wrapped. Looking at a template doesn't really help that much.
Hi @Dokiys, that's not what I was getting at. I'm saying that how to inject wrapping wasn't documented, nor is what will be wrapped. Looking at a template doesn't really help that much.
Hi @autarch I think if you want to custom HelpPrinter by default template and implementation of HelpPrinterCustom, you should know about what its handling. About 'how to inject wrapping', there are notes here: https://github.com/urfave/cli/blob/ca9df40abd0db61673fb645f9826d8fbb061b6bb/help.go#L289-L293
About 'what will be wrapped', you can find in AppHelpTemplate and here:
https://github.com/urfave/cli/blob/ca9df40abd0db61673fb645f9826d8fbb061b6bb/help.go#L52-L53
But I think the method name "wrap" is really confusing.
Hi @autarch
You can try this
package main
import (
"log"
"os"
"github.com/urfave/cli/v2"
)
func main() {
app := &cli.App{
Name: "long",
Usage: "Long command description cli",
Commands: []*cli.Command{
{
Name: "help",
Aliases: []string{"h"},
Action: func(cCtx *cli.Context) error {
_ = ShowAppHelp(cCtx)
return nil
},
},
{
Name: "testing",
Aliases: []string{"t"},
Usage: "aaaaaaaaa aaaaaaaaa aaaaa aaaaaaaaa aaaaaaaaaaaaaaa aaaaa aaaaaaaaaaaa aaa aa aaaaaa aa aaaa",
},
},
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
}
}
func ShowAppHelp(c *cli.Context) error {
template := c.App.CustomAppHelpTemplate
if template == "" {
template = cli.AppHelpTemplate
}
customAppData := func() map[string]interface{} {
return map[string]interface{}{
"wrapAt": func() int {
return 80
},
}
}
cli.HelpPrinterCustom(c.App.Writer, template, c.App, customAppData())
return nil
}
This result will be the following:
NAME:
long - Long command description cli
USAGE:
long command [command options] [arguments...]
COMMANDS:
help, h
testing, t aaaaaaaaa aaaaaaaaa aaaaa aaaaaaaaa aaaaaaaaaaaaaaa aaaaa
aaaaaaaaaaaa aaa aa aaaaaa aa aaaa
Still it doesn't work quite will with Flags since the template doesn't handle flag usage wrapping. To fix it you can use the following template:
var AppHelpTemplate = `NAME:
{{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}
USAGE:
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
VERSION:
{{.Version}}{{end}}{{end}}{{if .Description}}
DESCRIPTION:
{{wrap .Description 3}}{{end}}{{if len .Authors}}
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
{{range $index, $author := .Authors}}{{if $index}}
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
{{.Name}}:{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}}
{{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlagCategories}}
GLOBAL OPTIONS:{{range .VisibleFlagCategories}}
{{if .Name}}{{.Name}}
{{end}}{{range .Flags}}{{$v := offset .Name 6}}{{wrap .Name 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}
{{end}}{{end}}{{else}}{{if .VisibleFlags}}
GLOBAL OPTIONS:
{{range $index, $option := .VisibleFlags}}{{if $index}}
{{end}}{{wrap $option.String 3}}{{end}}{{end}}{{end}}{{if .Copyright}}
COPYRIGHT:
{{wrap .Copyright 3}}{{end}}
`
Cheers,
Documentation added for this.