config/template.go
func ParseTemplateConfig(s string) (*TemplateConfig, error) {
	if len(strings.TrimSpace(s)) < 1 {
		return nil, ErrTemplateStringEmpty
	}

	var source, destination, command string
	parts := configTemplateRe.FindAllString(s, -1)

	switch len(parts) {
	case 1:
		source = parts[0]
	case 2:
		source, destination = parts[0], parts[1]
	case 3:
		source, destination, command = parts[0], parts[1], parts[2]
	default:
		source, destination = parts[0], parts[1]
		command = strings.Join(parts[2:], ":")
	}

	var sourcePtr, destinationPtr, commandPtr *string
	if source != "" {
		sourcePtr = String(source)
	}
	if destination != "" {
		destinationPtr = String(destination)
	}
	if command != "" {
		commandPtr = String(command)
	}

	return &TemplateConfig{
		Source:      sourcePtr,
		Destination: destinationPtr,
		Command:     commandPtr,
	}, nil
}
func ParseTemplateConfig(s string) (*TemplateConfig, error) {
	if len(strings.TrimSpace(s)) < 1 {
		return nil, ErrTemplateStringEmpty
	}

	var source, destination, command string
	parts := configTemplateRe.FindAllString(s, -1)

	switch len(parts) {
	case 1:
		source = parts[0]
	case 2:
		source, destination = parts[0], parts[1]
	case 3:
		source, destination, command = parts[0], parts[1], parts[2]
	default:
		source, destination = parts[0], parts[1]
		command = strings.Join(parts[2:], ":")
	}

	var sourcePtr, destinationPtr, commandPtr *string
	if source != "" {
		sourcePtr = String(source)
	}
	if destination != "" {
		destinationPtr = String(destination)
	}
	if command != "" {
		commandPtr = String(command)
	}

	return &TemplateConfig{
		Source:      sourcePtr,
		Destination: destinationPtr,
		Command:     commandPtr,
	}, nil
}
// ParseTemplateConfig parses a string in the form source:destination:command
// into a TemplateConfig.