func NewStringCmdSetForRunners(cmds ...*CmdWithRunner) (StringCmdSet, error) {
	seenCmdNames := make(map[string]bool)
	var duplicates []string
	duplicatesSet := make(map[string]bool)
	for _, cmd := range cmds {
		cmdName := cmd.cmdName
		if seenCmdNames[cmdName] {
			if !duplicatesSet[cmdName] {
				duplicates = append(duplicates, cmdName)
			}
			duplicatesSet[cmdName] = true
		}
		seenCmdNames[cmdName] = true
	}
	if len(duplicates) > 0 {
		return nil, errors.Errorf("multiple runners provided for commands: %v", duplicates)
	}
	return cmdWithRunnerCmdSet(cmds), nil
}
func NewStringCmdSetForRunners(cmds ...*CmdWithRunner) (StringCmdSet, error) {
	seenCmdNames := make(map[string]bool)
	var duplicates []string
	duplicatesSet := make(map[string]bool)
	for _, cmd := range cmds {
		cmdName := cmd.cmdName
		if seenCmdNames[cmdName] {
			if !duplicatesSet[cmdName] {
				duplicates = append(duplicates, cmdName)
			}
			duplicatesSet[cmdName] = true
		}
		seenCmdNames[cmdName] = true
	}
	if len(duplicates) > 0 {
		return nil, errors.Errorf("multiple runners provided for commands: %v", duplicates)
	}
	return cmdWithRunnerCmdSet(cmds), nil
}
// NewStringCmdSetForRunners creates a new StringCmdSet from the provided cmds (all of which must be non-nil). Returns
// an error if any of the provided commands have the same name.