func handleSubCommand(commandFlag *flag.FlagSet, commandOutputFlag string, ds datasource.DataSource, r renderer.Renderer, args []string) (string, error) {
	err := commandFlag.Parse(args[2:])
	if err != nil {
		return "", err
	}
	command := args[1]
	if commandOutputFlag == "json" {
		r = &renderer.JSONRenderer{}
	}
	return executeCommand(ds, r, command, commandFlag.Args())
}
handleSubCommand handles calls to subcommands
package main
import (
	"bufio"
	"flag"
	"fmt"
	"github.com/fatih/color"
	"github.com/kardianos/osext"
	homedir "github.com/mitchellh/go-homedir"
	"github.com/zupzup/calories/command"
	"github.com/zupzup/calories/datasource"
	"github.com/zupzup/calories/renderer"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)
const VERSION = "1.0.0"
const configFile string = ".caloriesconf"
const defaultDBFile string = "calories.db"
var commandFlag = flag.NewFlagSet("", flag.ExitOnError)
var (
	weightFlag        float64
	heightFlag        float64
	activityFlag      float64
	birthDayFlag      string
	genderFlag        string
	unitFlag          string
	dateFlag          string
	yesFlag           bool
	commandOutputFlag string
	positionFlag      int
	fileFlag          string
	defaultDateFlag string
	weekFlag        bool
	monthFlag       bool
	histFlag        int
	commandsFlag    bool
	outputFlag      string
	versionFlag     bool
)
func init() {
	commandFlag.Float64Var(&weightFlag, "weight", -1, "your weight")
	commandFlag.Float64Var(&weightFlag, "w", -1, "your weight (shorthand)")
	commandFlag.Float64Var(&heightFlag, "height", -1, "your height")
	commandFlag.Float64Var(&heightFlag, "h", -1, "your height (shorthand)")
	commandFlag.Float64Var(&activityFlag, "activity", -1, "your activity multiplier")
	commandFlag.Float64Var(&activityFlag, "a", -1, "your activity multiplier (shorthand)")
	commandFlag.StringVar(&birthDayFlag, "birthday", "", "your birthday (dd.mm.yyyy)")
	commandFlag.StringVar(&birthDayFlag, "b", "", "your birthday (dd.mm.yyyy) (shorthand)")
	commandFlag.StringVar(&genderFlag, "gender", "male", "your gender")
	commandFlag.StringVar(&genderFlag, "g", "male", "your gender (shorthand)")
	commandFlag.StringVar(&unitFlag, "unit", "metric", "your preferred unit system (metric | imperial)")
	commandFlag.StringVar(&unitFlag, "u", "metric", "your preferred unit system (metric | imperial) (shorthand)")
	commandFlag.StringVar(&dateFlag, "date", "", "date to add an entry on")
	commandFlag.StringVar(&dateFlag, "d", "", "date to add an entry on (shorthand)")
	commandFlag.BoolVar(&yesFlag, "yes", false, "skip confirmations")
	commandFlag.BoolVar(&yesFlag, "y", false, "skip confirmations (shorthand)")
	commandFlag.StringVar(&commandOutputFlag, "output", "terminal", "output format (terminal | json)")
	commandFlag.StringVar(&commandOutputFlag, "o", "terminal", "output format (terminal | json) (shorthand)")
	commandFlag.IntVar(&positionFlag, "position", -1, "position of the entry to clear (1-n)")
	commandFlag.IntVar(&positionFlag, "p", -1, "position of the entry to clear (1-n) (shorthand)")
	commandFlag.StringVar(&fileFlag, "file", "", "file to export to / import from")
	commandFlag.StringVar(&fileFlag, "f", "", "file to export to / import from (shorthand)")
	flag.StringVar(&defaultDateFlag, "date", "", "date to show")
	flag.StringVar(&defaultDateFlag, "d", "", "date to show (shorthand)")
	flag.BoolVar(&weekFlag, "week", false, "show current week")
	flag.BoolVar(&weekFlag, "w", false, "show current week (shorthand)")
	flag.BoolVar(&monthFlag, "month", false, "show current month")
	flag.BoolVar(&monthFlag, "m", false, "show current month (shorthand)")
	flag.IntVar(&histFlag, "hist", 0, "length of history to show")
	flag.IntVar(&histFlag, "h", 0, "length of history to show (shorthand)")
	flag.BoolVar(&commandsFlag, "commands", false, "show list of commands")
	flag.BoolVar(&commandsFlag, "c", false, "show list of commands (shorthand)")
	flag.BoolVar(&versionFlag, "version", false, "show version")
	flag.BoolVar(&versionFlag, "v", false, "show version (shorthand)")
	flag.StringVar(&outputFlag, "output", "terminal", "output format (terminal | json)")
	flag.StringVar(&outputFlag, "o", "terminal", "output format (terminal | json) (shorthand)")
}
func main() {
	flag.Parse()
	var r renderer.Renderer
	r = &renderer.TerminalRenderer{}
	ds := &datasource.BoltDataSource{}
	folder, err := osext.ExecutableFolder()
	if err != nil {
		fatalError(r, fmt.Errorf("error reading folder containing the calories binary, %v", err))
	}
	var configFile = filepath.Join(folder, configFile)
	config, err := ioutil.ReadFile(configFile)
	if err != nil {
		asciilogo()
		if os.IsNotExist(err) {
			configToSet, configErr := createConfig(config, folder, defaultDBFile)
			if configErr != nil {
				fatalError(r, configErr)
			}
			config = []byte(configToSet)
		} else {
			fatalError(r, fmt.Errorf("error reading config file at %s, %v", configFile, err))
		}
	}
	dbString := string(config)
	close, err := ds.Setup(dbString)
	if err != nil {
		fatalError(r, fmt.Errorf("could not connect to database at %s, if you want to set a new database file, please use the 'calories db' command, %v", dbString, err))
	}
	defer func() {
		closeErr := close()
		if closeErr != nil {
			fatalError(r, closeErr)
		}
	}()
	if len(flag.Args()) > 0 {
		res, err := handleSubCommand(commandFlag, commandOutputFlag, ds, r, os.Args)
		if err != nil {
			fatalError(r, err)
		}
		fmt.Fprintln(color.Output, res)
	} else {
		res, err := handleNoSubCommand(commandsFlag, outputFlag, ds, r, os.Args)
		if err != nil {
			fatalError(r, err)
		}
		fmt.Fprintln(color.Output, res)
	}
}