github.com/kristofferahl/go-centry@v1.5.0/cmd/centry/commands.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "sort" 6 "strings" 7 8 "github.com/kristofferahl/go-centry/internal/pkg/cmd" 9 "github.com/kristofferahl/go-centry/internal/pkg/config" 10 "github.com/kristofferahl/go-centry/internal/pkg/shell" 11 "github.com/sirupsen/logrus" 12 "github.com/urfave/cli/v2" 13 ) 14 15 func withCommandDefaults(c *cli.Command) *cli.Command { 16 if c.CustomHelpTemplate == "" { 17 c.CustomHelpTemplate = commandHelpTemplate 18 } 19 c.HideHelpCommand = true 20 return c 21 } 22 23 func registerInternalCommands(runtime *Runtime) { 24 context := runtime.context 25 26 if context.executor == CLI { 27 serveCmd := &ServeCommand{ 28 Manifest: context.manifest, 29 Log: context.log.GetLogger().WithFields(logrus.Fields{ 30 "command": "serve", 31 }), 32 } 33 generateMarkdownCmd := &GenerateMarkdownCommand{ 34 CLI: runtime.cli, 35 Manifest: context.manifest, 36 Log: context.log.GetLogger().WithFields(logrus.Fields{ 37 "command": "generate-markdown", 38 }), 39 } 40 internalCmd := withCommandDefaults(&cli.Command{ 41 Name: "internal", 42 Usage: "Internal centry commands", 43 UsageText: "", 44 Hidden: context.manifest.Config.HideInternalCommands, 45 Subcommands: []*cli.Command{ 46 serveCmd.ToCLICommand(), 47 generateMarkdownCmd.ToCLICommand(), 48 }, 49 }) 50 runtime.cli.Commands = append(runtime.cli.Commands, internalCmd) 51 } 52 } 53 54 func registerManifestCommands(runtime *Runtime, options *cmd.OptionsSet) { 55 context := runtime.context 56 57 for _, cmd := range context.manifest.Commands { 58 cmd := cmd 59 60 if context.commandEnabledFunc != nil && context.commandEnabledFunc(cmd) == false { 61 continue 62 } 63 64 script := createScript(cmd, context) 65 66 funcs, err := script.Functions() 67 if err != nil { 68 context.log.GetLogger().WithFields(logrus.Fields{ 69 "command": cmd.Name, 70 }).Errorf("failed to parse script functions. %v", err) 71 } else { 72 for _, fn := range funcs { 73 fn := fn 74 cmd := cmd 75 namespace := script.FunctionNamespace(cmd.Name) 76 77 if fn.Name != cmd.Name && strings.HasPrefix(fn.Name, namespace) == false { 78 continue 79 } 80 81 cmdDescription := cmd.Description 82 if fn.Description != "" { 83 cmd.Description = fn.Description 84 } 85 86 cmdHelp := cmd.Help 87 if fn.Help != "" { 88 cmd.Help = fn.Help 89 } 90 91 scriptCmd := &ScriptCommand{ 92 Context: context, 93 Log: context.log.GetLogger().WithFields(logrus.Fields{}), 94 GlobalOptions: options, 95 Command: cmd, 96 Script: script, 97 Function: *fn, 98 } 99 cliCmd := scriptCmd.ToCLICommand() 100 101 cmdKeyParts := scriptCmd.GetCommandInvocationPath() 102 103 var root *cli.Command 104 for depth, cmdKeyPart := range cmdKeyParts { 105 if depth == 0 { 106 if getCommand(runtime.cli.Commands, cmdKeyPart) == nil { 107 if depth == len(cmdKeyParts)-1 { 108 // add destination command 109 runtime.cli.Commands = append(runtime.cli.Commands, cliCmd) 110 } else { 111 // add placeholder 112 runtime.cli.Commands = append(runtime.cli.Commands, withCommandDefaults(&cli.Command{ 113 Name: cmdKeyPart, 114 Usage: cmdDescription, 115 UsageText: cmdHelp, 116 Action: nil, 117 })) 118 } 119 } 120 root = getCommand(runtime.cli.Commands, cmdKeyPart) 121 } else { 122 if getCommand(root.Subcommands, cmdKeyPart) == nil { 123 if depth == len(cmdKeyParts)-1 { 124 // add destination command 125 root.Subcommands = append(root.Subcommands, cliCmd) 126 } else { 127 // add placeholder 128 root.Subcommands = append(root.Subcommands, withCommandDefaults(&cli.Command{ 129 Name: cmdKeyPart, 130 Usage: "...", 131 UsageText: "", 132 Action: nil, 133 })) 134 } 135 } 136 root = getCommand(root.Subcommands, cmdKeyPart) 137 } 138 } 139 140 runtime.events = append(runtime.events, fmt.Sprintf("registered command \"%s\"", scriptCmd.GetCommandInvocation())) 141 } 142 } 143 } 144 } 145 146 func getCommand(commands []*cli.Command, name string) *cli.Command { 147 for _, c := range commands { 148 if c.HasName(name) { 149 return c 150 } 151 } 152 153 return nil 154 } 155 156 func sortCommands(commands []*cli.Command) { 157 sort.Slice(commands, func(i, j int) bool { 158 return commands[i].Name < commands[j].Name 159 }) 160 } 161 162 func createScript(cmd config.Command, context *Context) shell.Script { 163 return &shell.BashScript{ 164 BasePath: context.manifest.BasePath, 165 Path: cmd.Path, 166 Log: context.log.GetLogger().WithFields(logrus.Fields{ 167 "script": cmd.Path, 168 }), 169 } 170 }