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  }