// Copyright 2013-2023 The Cobra Authors
//
// 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.

// Commands similar to git, go tools and other modern CLI tools
// inspired by go, go-Commander, gh and subcommand

package cobra

import (
	
	
	
	
	
	
	
	
	
)

var templateFuncs = template.FuncMap{
	"trim":                    strings.TrimSpace,
	"trimRightSpace":          trimRightSpace,
	"trimTrailingWhitespaces": trimRightSpace,
	"appendIfNotPresent":      appendIfNotPresent,
	"rpad":                    rpad,
	"gt":                      Gt,
	"eq":                      Eq,
}

var initializers []func()
var finalizers []func()

const (
	defaultPrefixMatching   = false
	defaultCommandSorting   = true
	defaultCaseInsensitive  = false
	defaultTraverseRunHooks = false
)

// EnablePrefixMatching allows setting automatic prefix matching. Automatic prefix matching can be a dangerous thing
// to automatically enable in CLI tools.
// Set this to true to enable it.
var EnablePrefixMatching = defaultPrefixMatching

// EnableCommandSorting controls sorting of the slice of commands, which is turned on by default.
// To disable sorting, set it to false.
var EnableCommandSorting = defaultCommandSorting

// EnableCaseInsensitive allows case-insensitive commands names. (case sensitive by default)
var EnableCaseInsensitive = defaultCaseInsensitive

// EnableTraverseRunHooks executes persistent pre-run and post-run hooks from all parents.
// By default this is disabled, which means only the first run hook to be found is executed.
var EnableTraverseRunHooks = defaultTraverseRunHooks

// MousetrapHelpText enables an information splash screen on Windows
// if the CLI is started from explorer.exe.
// To disable the mousetrap, just set this variable to blank string ("").
// Works only on Microsoft Windows.
var MousetrapHelpText = `This is a command line tool.

You need to open cmd.exe and run it from there.
`

// MousetrapDisplayDuration controls how long the MousetrapHelpText message is displayed on Windows
// if the CLI is started from explorer.exe. Set to 0 to wait for the return key to be pressed.
// To disable the mousetrap, just set MousetrapHelpText to blank string ("").
// Works only on Microsoft Windows.
var MousetrapDisplayDuration = 5 * time.Second

// AddTemplateFunc adds a template function that's available to Usage and Help
// template generation.
func ( string,  interface{}) {
	templateFuncs[] = 
}

// AddTemplateFuncs adds multiple template functions that are available to Usage and
// Help template generation.
func ( template.FuncMap) {
	for ,  := range  {
		templateFuncs[] = 
	}
}

// OnInitialize sets the passed functions to be run when each command's
// Execute method is called.
func ( ...func()) {
	initializers = append(initializers, ...)
}

// OnFinalize sets the passed functions to be run when each command's
// Execute method is terminated.
func ( ...func()) {
	finalizers = append(finalizers, ...)
}

// FIXME Gt is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra.

// Gt takes two types and checks whether the first type is greater than the second. In case of types Arrays, Chans,
// Maps and Slices, Gt will compare their lengths. Ints are compared directly while strings are first parsed as
// ints and then compared.
func ( interface{},  interface{}) bool {
	var ,  int64
	 := reflect.ValueOf()

	switch .Kind() {
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
		 = int64(.Len())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		 = .Int()
	case reflect.String:
		, _ = strconv.ParseInt(.String(), 10, 64)
	}

	 := reflect.ValueOf()

	switch .Kind() {
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
		 = int64(.Len())
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		 = .Int()
	case reflect.String:
		, _ = strconv.ParseInt(.String(), 10, 64)
	}

	return  > 
}

// FIXME Eq is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra.

// Eq takes two types and checks whether they are equal. Supported types are int and string. Unsupported types will panic.
func ( interface{},  interface{}) bool {
	 := reflect.ValueOf()
	 := reflect.ValueOf()

	switch .Kind() {
	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
		panic("Eq called on unsupported type")
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return .Int() == .Int()
	case reflect.String:
		return .String() == .String()
	}
	return false
}

func trimRightSpace( string) string {
	return strings.TrimRightFunc(, unicode.IsSpace)
}

// FIXME appendIfNotPresent is unused by cobra and should be removed in a version 2. It exists only for compatibility with users of cobra.

// appendIfNotPresent will append stringToAppend to the end of s, but only if it's not yet present in s.
func appendIfNotPresent(,  string) string {
	if strings.Contains(, ) {
		return 
	}
	return  + " " + 
}

// rpad adds padding to the right of a string.
func rpad( string,  int) string {
	 := fmt.Sprintf("%%-%ds", )
	return fmt.Sprintf(, )
}

// tmpl executes the given template text on data, writing the result to w.
func tmpl( io.Writer,  string,  interface{}) error {
	 := template.New("top")
	.Funcs(templateFuncs)
	template.Must(.Parse())
	return .Execute(, )
}

// ld compares two strings and returns the levenshtein distance between them.
func ld(,  string,  bool) int {
	if  {
		 = strings.ToLower()
		 = strings.ToLower()
	}
	 := make([][]int, len()+1)
	for  := range  {
		[] = make([]int, len()+1)
		[][0] = 
	}
	for  := range [0] {
		[0][] = 
	}
	for  := 1;  <= len(); ++ {
		for  := 1;  <= len(); ++ {
			if [-1] == [-1] {
				[][] = [-1][-1]
			} else {
				 := [-1][]
				if [][-1] <  {
					 = [][-1]
				}
				if [-1][-1] <  {
					 = [-1][-1]
				}
				[][] =  + 1
			}
		}

	}
	return [len()][len()]
}

func stringInSlice( string,  []string) bool {
	for ,  := range  {
		if  ==  {
			return true
		}
	}
	return false
}

// CheckErr prints the msg with the prefix 'Error:' and exits with error code 1. If the msg is nil, it does nothing.
func ( interface{}) {
	if  != nil {
		fmt.Fprintln(os.Stderr, "Error:", )
		os.Exit(1)
	}
}

// WriteStringAndCheck writes a string into a buffer, and checks if the error is not nil.
func ( io.StringWriter,  string) {
	,  := .WriteString()
	CheckErr()
}