<commit_before>/*
* Copyright 2015 <NAME>
*
* 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 gocli

import (
	"errors"
	"fmt"
	"strings"
)

// A Command represents a CLI command.
type Command struct {
	// Name of command.
	Name string
	// Short help for command.
	Short string
	// Long help for command.
	Long string
	// Run is a function that is executed at user call.
	Run func(cmd *Command, args []string)
	// Load is a function that is executed when a parent command is called.
	Load func(cmd *Command)

	childs Commands
	parent *Command
	exit   *Command
	help   *Command
}

// A Commands is a slice of Command pointers
type Commands []*Command

// RecurseGet represents an interaction from RecurseParent.
// The successful returns true whether the value was got successfully.
type RecurseGet func(cmd *Command, first, last bool) (successful bool)

// AddChild adds one or more child commands.
func (c *Command) AddChild(cmds ...*Command) {
	for _, v := range cmds {
		if v == c {
			panic("Command can't be a child of itself")
		}

		v.parent = c
		c.childs = append(c.childs, v)
	}
}

// Execute an interactive CLI until users exits.
func (c *Command) Execute() error {
	if c.Run != nil && len(c.childs) != 0 {
		return errors.New("Current command should not define an action and has childs")
	}
	if c.Load != nil && c.Run != nil {
		return errors.New("Only Run or Load functions should be defined, not both")
	}

	if c.Load != nil {
		c.Load(c)
	}
	if c.Run == nil && len(c.childs) == 0 {
		return errors.New("Current command has neither action and childs")
	}

	if !RecurseParents(c, func(cmd *Command, first, last bool) bool {
		if cmd.exit != nil {
			c.exit = cmd.exit
			c.AddChild(cmd.exit)
			return true
		}
		return false
	}) {
		ExitCommand(c)
	}
	if !RecurseParents(c, func(cmd *Command, first, last bool) bool {
		if cmd.help != nil {
			c.help = cmd.help
			c.AddChild(cmd.exit)
			return true
		}
		return false
	}) {
		HelpCommand(c)
	}

	for {
		if c.parent == nil {
			fmt.Printf("%s>", c.Name)
		} else {
			prompt := ""
			RecurseParents(c, func(cmd *Command, first, last bool) bool {
				if first {
					prompt = fmt.Sprintf("%s)>", cmd.Name)
					return false
				}
				if last {
					prompt = fmt.Sprintf("%s(%s", cmd.Name, prompt)
					return false
				}
				prompt = fmt.Sprintf("%s/%s", cmd.Name, prompt)
				return false
			})<commit_msg>Fixed name typo<commit_after>/*
* Copyright 2015 <NAME>
*
* 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 gocli

import (
	"errors"
	"fmt"
	"strings"
)

// A Command represents a CLI command.
type Command struct {
	// Name of command.
	Name string
	// Short help for command.
	Short string
	// Long help for command.
	Long string
	// Run is a function that is executed at user call.
	Run func(cmd *Command, args []string)
	// Load is a function that is executed when a parent command is called.
	Load func(cmd *Command)

	childs Commands
	parent *Command
	exit   *Command
	help   *Command
}

// A Commands is a slice of Command pointers
type Commands []*Command

// RecurseGet represents an interaction from RecurseParent.
// The successful returns true whether the value was got successfully.
type RecurseGet func(cmd *Command, first, last bool) (successful bool)

// AddChild adds one or more child commands.
func (c *Command) AddChild(cmds ...*Command) {
	for _, v := range cmds {
		if v == c {
			panic("Command can't be a child of itself")
		}

		v.parent = c
		c.childs = append(c.childs, v)
	}
}

// Execute an interactive CLI until users exits.
func (c *Command) Execute() error {
	if c.Run != nil && len(c.childs) != 0 {
		return errors.New("Current command should not define an action and has childs")
	}
	if c.Load != nil && c.Run != nil {
		return errors.New("Only Run or Load functions should be defined, not both")
	}

	if c.Load != nil {
		c.Load(c)
	}
	if c.Run == nil && len(c.childs) == 0 {
		return errors.New("Current command has neither action and childs")
	}

	if !RecurseParents(c, func(cmd *Command, first, last bool) bool {
		if cmd.exit != nil {
			c.exit = cmd.exit
			c.AddChild(cmd.exit)
			return true
		}
		return false
	}) {
		ExitCommand(c)
	}
	if !RecurseParents(c, func(cmd *Command, first, last bool) bool {
		if cmd.help != nil {
			c.help = cmd.help
			c.AddChild(cmd.help)
			return true
		}
		return false
	}) {
		HelpCommand(c)
	}

	for {
		if c.parent == nil {
			fmt.Printf("%s>", c.Name)
		} else {
			prompt := ""
			RecurseParents(c, func(cmd *Command, first, last bool) bool {
				if first {
					prompt = fmt.Sprintf("%s)>", cmd.Name)
					return false
				}
				if last {
					prompt = fmt.Sprintf("%s(%s", cmd.Name, prompt)
					return false
				}
				prompt = fmt.Sprintf("%s/%s", cmd.Name, prompt)
				return false
			})
{'fraction_non_alphanumeric': 0.11474269819193324, 'fraction_numerical': 0.0034770514603616135, 'mean_word_length': 3.147801009372747, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2670265', 'n_tokens_mistral': 2034, 'n_tokens_neox': 1835, 'n_words': 712}