mirror of
https://github.com/gohugoio/hugo.git
synced 2024-12-12 10:36:20 -05:00
a67650b6f7
Do not offer filenames to arguments not taking one, complete arguments of options taking resource kinds, directory names, --logLevel, release --step, config and new --format. As an internal refactoring, use higher level functions to set flag completions. SetAnnotation works, but is more verbose than alternatives, and uses bash specific wording. While at it, move setting completions next to flag definitions consistently. Remove superfluous --destination completer setting, which is already set elsewhere.
279 lines
8.8 KiB
Go
279 lines
8.8 KiB
Go
// Copyright 2024 The Hugo Authors. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package commands
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/alecthomas/chroma/v2"
|
|
"github.com/alecthomas/chroma/v2/formatters/html"
|
|
"github.com/alecthomas/chroma/v2/styles"
|
|
"github.com/bep/simplecobra"
|
|
"github.com/gohugoio/hugo/common/hugo"
|
|
"github.com/gohugoio/hugo/docshelper"
|
|
"github.com/gohugoio/hugo/helpers"
|
|
"github.com/gohugoio/hugo/hugofs"
|
|
"github.com/gohugoio/hugo/hugolib"
|
|
"github.com/gohugoio/hugo/parser"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/cobra/doc"
|
|
"gopkg.in/yaml.v2"
|
|
)
|
|
|
|
func newGenCommand() *genCommand {
|
|
var (
|
|
// Flags.
|
|
gendocdir string
|
|
genmandir string
|
|
|
|
// Chroma flags.
|
|
style string
|
|
highlightStyle string
|
|
linesStyle string
|
|
)
|
|
|
|
newChromaStyles := func() simplecobra.Commander {
|
|
return &simpleCommand{
|
|
name: "chromastyles",
|
|
short: "Generate CSS stylesheet for the Chroma code highlighter",
|
|
long: `Generate CSS stylesheet for the Chroma code highlighter for a given style. This stylesheet is needed if markup.highlight.noClasses is disabled in config.
|
|
|
|
See https://xyproto.github.io/splash/docs/all.html for a preview of the available styles`,
|
|
|
|
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
|
|
builder := styles.Get(style).Builder()
|
|
if highlightStyle != "" {
|
|
builder.Add(chroma.LineHighlight, highlightStyle)
|
|
}
|
|
if linesStyle != "" {
|
|
builder.Add(chroma.LineNumbers, linesStyle)
|
|
}
|
|
style, err := builder.Build()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
formatter := html.New(html.WithAllClasses(true))
|
|
formatter.WriteCSS(os.Stdout, style)
|
|
return nil
|
|
},
|
|
withc: func(cmd *cobra.Command, r *rootCommand) {
|
|
cmd.ValidArgsFunction = cobra.NoFileCompletions
|
|
cmd.PersistentFlags().StringVar(&style, "style", "friendly", "highlighter style (see https://xyproto.github.io/splash/docs/)")
|
|
_ = cmd.RegisterFlagCompletionFunc("style", cobra.NoFileCompletions)
|
|
cmd.PersistentFlags().StringVar(&highlightStyle, "highlightStyle", "", "style used for highlighting lines (see https://github.com/alecthomas/chroma)")
|
|
_ = cmd.RegisterFlagCompletionFunc("highlightStyle", cobra.NoFileCompletions)
|
|
cmd.PersistentFlags().StringVar(&linesStyle, "linesStyle", "", "style used for line numbers (see https://github.com/alecthomas/chroma)")
|
|
_ = cmd.RegisterFlagCompletionFunc("linesStyle", cobra.NoFileCompletions)
|
|
},
|
|
}
|
|
}
|
|
|
|
newMan := func() simplecobra.Commander {
|
|
return &simpleCommand{
|
|
name: "man",
|
|
short: "Generate man pages for the Hugo CLI",
|
|
long: `This command automatically generates up-to-date man pages of Hugo's
|
|
command-line interface. By default, it creates the man page files
|
|
in the "man" directory under the current directory.`,
|
|
|
|
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
|
|
header := &doc.GenManHeader{
|
|
Section: "1",
|
|
Manual: "Hugo Manual",
|
|
Source: fmt.Sprintf("Hugo %s", hugo.CurrentVersion),
|
|
}
|
|
if !strings.HasSuffix(genmandir, helpers.FilePathSeparator) {
|
|
genmandir += helpers.FilePathSeparator
|
|
}
|
|
if found, _ := helpers.Exists(genmandir, hugofs.Os); !found {
|
|
r.Println("Directory", genmandir, "does not exist, creating...")
|
|
if err := hugofs.Os.MkdirAll(genmandir, 0o777); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
cd.CobraCommand.Root().DisableAutoGenTag = true
|
|
|
|
r.Println("Generating Hugo man pages in", genmandir, "...")
|
|
doc.GenManTree(cd.CobraCommand.Root(), header, genmandir)
|
|
|
|
r.Println("Done.")
|
|
|
|
return nil
|
|
},
|
|
withc: func(cmd *cobra.Command, r *rootCommand) {
|
|
cmd.ValidArgsFunction = cobra.NoFileCompletions
|
|
cmd.PersistentFlags().StringVar(&genmandir, "dir", "man/", "the directory to write the man pages.")
|
|
_ = cmd.MarkFlagDirname("dir")
|
|
},
|
|
}
|
|
}
|
|
|
|
newGen := func() simplecobra.Commander {
|
|
const gendocFrontmatterTemplate = `---
|
|
title: "%s"
|
|
slug: %s
|
|
url: %s
|
|
---
|
|
`
|
|
|
|
return &simpleCommand{
|
|
name: "doc",
|
|
short: "Generate Markdown documentation for the Hugo CLI.",
|
|
long: `Generate Markdown documentation for the Hugo CLI.
|
|
This command is, mostly, used to create up-to-date documentation
|
|
of Hugo's command-line interface for https://gohugo.io/.
|
|
|
|
It creates one Markdown file per command with front matter suitable
|
|
for rendering in Hugo.`,
|
|
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
|
|
cd.CobraCommand.VisitParents(func(c *cobra.Command) {
|
|
// Disable the "Auto generated by spf13/cobra on DATE"
|
|
// as it creates a lot of diffs.
|
|
c.DisableAutoGenTag = true
|
|
})
|
|
if !strings.HasSuffix(gendocdir, helpers.FilePathSeparator) {
|
|
gendocdir += helpers.FilePathSeparator
|
|
}
|
|
if found, _ := helpers.Exists(gendocdir, hugofs.Os); !found {
|
|
r.Println("Directory", gendocdir, "does not exist, creating...")
|
|
if err := hugofs.Os.MkdirAll(gendocdir, 0o777); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
prepender := func(filename string) string {
|
|
name := filepath.Base(filename)
|
|
base := strings.TrimSuffix(name, path.Ext(name))
|
|
url := "/commands/" + strings.ToLower(base) + "/"
|
|
return fmt.Sprintf(gendocFrontmatterTemplate, strings.Replace(base, "_", " ", -1), base, url)
|
|
}
|
|
|
|
linkHandler := func(name string) string {
|
|
base := strings.TrimSuffix(name, path.Ext(name))
|
|
return "/commands/" + strings.ToLower(base) + "/"
|
|
}
|
|
r.Println("Generating Hugo command-line documentation in", gendocdir, "...")
|
|
doc.GenMarkdownTreeCustom(cd.CobraCommand.Root(), gendocdir, prepender, linkHandler)
|
|
r.Println("Done.")
|
|
|
|
return nil
|
|
},
|
|
withc: func(cmd *cobra.Command, r *rootCommand) {
|
|
cmd.ValidArgsFunction = cobra.NoFileCompletions
|
|
cmd.PersistentFlags().StringVar(&gendocdir, "dir", "/tmp/hugodoc/", "the directory to write the doc.")
|
|
_ = cmd.MarkFlagDirname("dir")
|
|
},
|
|
}
|
|
}
|
|
|
|
var docsHelperTarget string
|
|
|
|
newDocsHelper := func() simplecobra.Commander {
|
|
return &simpleCommand{
|
|
name: "docshelper",
|
|
short: "Generate some data files for the Hugo docs.",
|
|
|
|
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
|
|
r.Println("Generate docs data to", docsHelperTarget)
|
|
|
|
var buf bytes.Buffer
|
|
jsonEnc := json.NewEncoder(&buf)
|
|
|
|
configProvider := func() docshelper.DocProvider {
|
|
conf := hugolib.DefaultConfig()
|
|
conf.CacheDir = "" // The default value does not make sense in the docs.
|
|
defaultConfig := parser.NullBoolJSONMarshaller{Wrapped: parser.LowerCaseCamelJSONMarshaller{Value: conf}}
|
|
return docshelper.DocProvider{"config": defaultConfig}
|
|
}
|
|
|
|
docshelper.AddDocProviderFunc(configProvider)
|
|
if err := jsonEnc.Encode(docshelper.GetDocProvider()); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Decode the JSON to a map[string]interface{} and then unmarshal it again to the correct format.
|
|
var m map[string]interface{}
|
|
if err := json.Unmarshal(buf.Bytes(), &m); err != nil {
|
|
return err
|
|
}
|
|
|
|
targetFile := filepath.Join(docsHelperTarget, "docs.yaml")
|
|
|
|
f, err := os.Create(targetFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
yamlEnc := yaml.NewEncoder(f)
|
|
if err := yamlEnc.Encode(m); err != nil {
|
|
return err
|
|
}
|
|
|
|
r.Println("Done!")
|
|
return nil
|
|
},
|
|
withc: func(cmd *cobra.Command, r *rootCommand) {
|
|
cmd.Hidden = true
|
|
cmd.ValidArgsFunction = cobra.NoFileCompletions
|
|
cmd.PersistentFlags().StringVarP(&docsHelperTarget, "dir", "", "docs/data", "data dir")
|
|
},
|
|
}
|
|
}
|
|
|
|
return &genCommand{
|
|
commands: []simplecobra.Commander{
|
|
newChromaStyles(),
|
|
newGen(),
|
|
newMan(),
|
|
newDocsHelper(),
|
|
},
|
|
}
|
|
}
|
|
|
|
type genCommand struct {
|
|
rootCmd *rootCommand
|
|
|
|
commands []simplecobra.Commander
|
|
}
|
|
|
|
func (c *genCommand) Commands() []simplecobra.Commander {
|
|
return c.commands
|
|
}
|
|
|
|
func (c *genCommand) Name() string {
|
|
return "gen"
|
|
}
|
|
|
|
func (c *genCommand) Run(ctx context.Context, cd *simplecobra.Commandeer, args []string) error {
|
|
return nil
|
|
}
|
|
|
|
func (c *genCommand) Init(cd *simplecobra.Commandeer) error {
|
|
cmd := cd.CobraCommand
|
|
cmd.Short = "A collection of several useful generators."
|
|
|
|
cmd.RunE = nil
|
|
return nil
|
|
}
|
|
|
|
func (c *genCommand) PreRun(cd, runner *simplecobra.Commandeer) error {
|
|
c.rootCmd = cd.Root.Command.(*rootCommand)
|
|
return nil
|
|
}
|