func (a *Action) Has(index int) bool {
	if len(a.Arguments) <= index {
		return false
	}
	return true
}
Has returns true if an argument with given is exist
package recipe
import (
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"pkg.re/essentialkaos/ek.v12/strutil"
)
const MAX_VAR_NESTING = 32
const TEARDOWN_TAG = "teardown"
type Recipe struct {
	Packages        []string    
	Commands        []*Command  
	File            string      
	Dir             string      
	Delay           float64     
	UnsafeActions   bool        
	RequireRoot     bool        
	FastFinish      bool        
	LockWorkdir     bool        
	Unbuffer        bool        
	HTTPSSkipVerify bool        
	variables map[string]*Variable  
}
type Command struct {
	Actions     []*Action  
	User        string     
	Tag         string     
	Cmdline     string     
	Description string     
	Recipe      *Recipe    
	Line        uint16     
	props map[string]interface{}  
}
type Action struct {
	Arguments []string  
	Name      string    
	Command   *Command  
	Line      uint16    
	Negative  bool      
}
type Variable struct {
	Value      string
	IsReadOnly bool
}
var varRegex = regexp.MustCompile(`\{([a-zA-Z0-9:_-]+)\}`)
var userRegex = regexp.MustCompile(`^([a-zA-Z_0-9\{\}]+):`)
func NewRecipe(file string) *Recipe {
	return &Recipe{
		File:        file,
		LockWorkdir: true,
	}
}
func NewCommand(args []string, line uint16) *Command {
	return parseCommand(args, line)
}
func (r *Recipe) AddCommand(cmd *Command, tag string) {
	cmd.Recipe = r
	cmd.Tag = tag
	if cmd.User != "" {
		r.RequireRoot = true
		if isVariable(cmd.User) {
			cmd.User = renderVars(r, cmd.User)
		}
	}
	if isVariable(cmd.Description) {
		cmd.Description = renderVars(r, cmd.Description)
	}
	r.Commands = append(r.Commands, cmd)
}
func (r *Recipe) AddVariable(name, value string) {
	if r.variables == nil {
		r.variables = make(map[string]*Variable)
	}
	r.variables[name] = &Variable{value, true}
}
func (r *Recipe) SetVariable(name, value string) error {
	if r.variables == nil {
		r.variables = make(map[string]*Variable)
	}
	varInfo, ok := r.variables[name]
	if !ok {
		r.variables[name] = &Variable{value, false}
		return nil
	}
	if !varInfo.IsReadOnly {
		r.variables[name].Value = value
		return nil
	}
	return fmt.Errorf("Can't set read-only variable %s", name)
}
func (r *Recipe) GetVariable(name string) string {
	rtv := getRuntimeVariable(name, r)
	if rtv != "" {
		return rtv
	}
	if r.variables == nil {
		return ""
	}
	varInfo, ok := r.variables[name]
	if !ok {
		return ""
	}
	return varInfo.Value
}
func (r *Recipe) GetPackages() string {
	return strings.Join(r.Packages, " ")
}
func (r *Recipe) HasTeardown() bool {
	for _, c := range r.Commands {
		if c.Tag == TEARDOWN_TAG {
			return true
		}
	}
	return false
}
func (c *Command) AddAction(action *Action) {
	action.Command = c
	c.Actions = append(c.Actions, action)
}
func (c *Command) GetCmdline() string {
	return renderVars(c.Recipe, c.Cmdline)
}
func (c *Command) GetCmdlineArgs() []string {
	return strutil.Fields(c.GetCmdline())
}
func (c *Command) Index() int {
	if c.Recipe == nil {
		return -1
	}
	for index, command := range c.Recipe.Commands {
		if command == c {
			return index
		}
	}
	return -1
}
func (c *Command) SetProp(name string, value interface{}) {
	if c.props == nil {
		c.props = make(map[string]interface{})
	}
	c.props[name] = value
}
func (c *Command) GetProp(name string) interface{} {
	if c.props == nil {
		return ""
	}
	return c.props[name]
}
func (c *Command) HasProp(name string) bool {
	if c.props == nil {
		return false
	}
	_, ok := c.props[name]
	return ok
}
func (a *Action) Index() int {
	if a.Command == nil {
		return -1
	}
	for index, action := range a.Command.Actions {
		if action == a {
			return index
		}
	}
	return -1
}