github.com/khulnasoft/cli@v0.0.0-20240402070845-01bcad7beefa/cli-plugins/hooks/template.go (about) 1 package hooks 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "strconv" 8 "text/template" 9 10 "github.com/spf13/cobra" 11 ) 12 13 type HookType int 14 15 const ( 16 NextSteps = iota 17 ) 18 19 // HookMessage represents a plugin hook response. Plugins 20 // declaring support for CLI hooks need to print a json 21 // representation of this type when their hook subcommand 22 // is invoked. 23 type HookMessage struct { 24 Type HookType 25 Template string 26 } 27 28 // TemplateReplaceSubcommandName returns a hook template string 29 // that will be replaced by the CLI subcommand being executed 30 // 31 // Example: 32 // 33 // "you ran the subcommand: " + TemplateReplaceSubcommandName() 34 // 35 // when being executed after the command: 36 // `docker run --name "my-container" alpine` 37 // will result in the message: 38 // `you ran the subcommand: run` 39 func TemplateReplaceSubcommandName() string { 40 return hookTemplateCommandName 41 } 42 43 // TemplateReplaceFlagValue returns a hook template string 44 // that will be replaced by the flags value. 45 // 46 // Example: 47 // 48 // "you ran a container named: " + TemplateReplaceFlagValue("name") 49 // 50 // when being executed after the command: 51 // `docker run --name "my-container" alpine` 52 // will result in the message: 53 // `you ran a container named: my-container` 54 func TemplateReplaceFlagValue(flag string) string { 55 return fmt.Sprintf(hookTemplateFlagValue, flag) 56 } 57 58 // TemplateReplaceArg takes an index i and returns a hook 59 // template string that the CLI will replace the template with 60 // the ith argument, after processing the passed flags. 61 // 62 // Example: 63 // 64 // "run this image with `docker run " + TemplateReplaceArg(0) + "`" 65 // 66 // when being executed after the command: 67 // `docker pull alpine` 68 // will result in the message: 69 // "Run this image with `docker run alpine`" 70 func TemplateReplaceArg(i int) string { 71 return fmt.Sprintf(hookTemplateArg, strconv.Itoa(i)) 72 } 73 74 func ParseTemplate(hookTemplate string, cmd *cobra.Command) (string, error) { 75 tmpl := template.New("").Funcs(commandFunctions) 76 tmpl, err := tmpl.Parse(hookTemplate) 77 if err != nil { 78 return "", err 79 } 80 b := bytes.Buffer{} 81 err = tmpl.Execute(&b, cmd) 82 if err != nil { 83 return "", err 84 } 85 return b.String(), nil 86 } 87 88 var ErrHookTemplateParse = errors.New("failed to parse hook template") 89 90 const ( 91 hookTemplateCommandName = "{{.Name}}" 92 hookTemplateFlagValue = `{{flag . "%s"}}` 93 hookTemplateArg = "{{arg . %s}}" 94 ) 95 96 var commandFunctions = template.FuncMap{ 97 "flag": getFlagValue, 98 "arg": getArgValue, 99 } 100 101 func getFlagValue(cmd *cobra.Command, flag string) (string, error) { 102 cmdFlag := cmd.Flag(flag) 103 if cmdFlag == nil { 104 return "", ErrHookTemplateParse 105 } 106 return cmdFlag.Value.String(), nil 107 } 108 109 func getArgValue(cmd *cobra.Command, i int) (string, error) { 110 flags := cmd.Flags() 111 if flags == nil { 112 return "", ErrHookTemplateParse 113 } 114 return flags.Arg(i), nil 115 }