<commit_before>Start
=====

Start Go command line apps with ease


Status
------
v0.1.0-alpha.
Most of this README is not implemented yet. I use it as a functional specification.


Executive Summary
-----------------

The *start* package for Go provides two basic features for command line applications:

1. Read your application settings transparently from either  
	- command line flags,  
	- environment variables,  
	- config file entries,  
	- or hardcoded defaults  
(in this order).

2. Parse commands and subcommands. This includes:
	- Mapping commands and subcommands to functions.
	- Providing an auto-generated help command for every command and subcommand.


Motivation
----------

I built the *start* package mainly because existing flag packages do not provide any option for getting default values from environment variables or from a config file (let alone in a transparent way). And I decided to include command and subcommand parsing as well, making this package a complete "starter kit".


Installation
------------

    go get github.com/christophberger/start
    
Usage
-----

    import (
        "github.com/christophberger/start"
    )


### Define application settings:

Define your application settings like you would define flags with the flag or [pflag](https://github.com/ogier/pflag) packages:

	var ip *int = start.Int("intname", "n", 1234, "help message")
	var sp *string = start.String("strname", "s", "default", "help message")
	var bp *bool = start.Bool("boolname", "b", "help message") // default is false if boolean flag is missing

	var flagvar int
	flag.IntVar(&flagvar, "flagname", 1234, "help message")

Then (optionally, if not using commands as well) call 
	
	start.Parse()

(instead of pflag.Parse()) to initialize each variable from these sources, in the given order:

1. From a commandline flag of the long or short name.
2. From an environment variable named as <APPLICATION>_<LONGNAME>, if the commandline flag does not exist. (<APPLICATION> is the executable's name, and <LONGNAME> is the flag's long name.)
3. From an entry in the config file, if the environment variable does not exist.
4. From the default value if the config file entry does not exist.

This way, you are free to decide whether to use a config file, environment variables, flags, or any combination of these. For example, let's assume you want to implement an HTTP server. Some of the settings will depend on the environment (development, test, or production), such as the HTTP port. Using enviornment variables, you can define, for example, port 8080 on the test server, and port 80 on the production server. Other settings will be the same across environments, so put them into the config file. And finally, you can overwrite any default setting at any time via command line flags. 

And best of all, each setting has the same name in the config file, for the environment variable, and for the command line flag (but the latter can also have a short form).


### Define commands:

Use Command() to define a new command. Pass the name, a sort and a long help message, and the function to call.

	start.Command("command", "short help message", "long help for 'help command'", commandFunc)

The function commandFunc has no parameters. It can get the command line via `flag.Args()` or `flag.Arg(n)`, where n is between 0 and `flag.NArg()-1`.

Define subcommands in the same way through SubCommand:

	start.SubCommand("parent", "command", "short help", "long help", commandFunc)

The parent command then needs no own commandFunc:

	start.Command("parent", "short help", "long help")

If you specify one, it will only be invoked if no subcommand is used.

For evaluating the command line, call

	start.Up()

This method calls `start.Parse()` and then executes the given command.


### Notes about the config file

By default, *start* looks for a configuration file in the following places:

* In the path defined through the environment variable <APPLICATION>_CFGPATH<commit_msg>Markdown fix, added caveat when using strange executable names<commit_after>Start
=====

Start Go command line apps with ease


Status
------
v0.1.0-alpha.
Most of this README is not implemented yet. I use it as a functional specification.


Executive Summary
-----------------

The *start* package for Go provides two basic features for command line applications:

1. Read your application settings transparently from either  
	- command line flags,  
	- environment variables,  
	- config file entries,  
	- or hardcoded defaults  
(in this order).

2. Parse commands and subcommands. This includes:
	- Mapping commands and subcommands to functions.
	- Providing an auto-generated help command for every command and subcommand.


Motivation
----------

I built the *start* package mainly because existing flag packages do not provide any option for getting default values from environment variables or from a config file (let alone in a transparent way). And I decided to include command and subcommand parsing as well, making this package a complete "starter kit".


Installation
------------

    go get github.com/christophberger/start
    
Usage
-----

    import (
        "github.com/christophberger/start"
    )


### Define application settings:

Define your application settings like you would define flags with the flag or [pflag](https://github.com/ogier/pflag) packages:

	var ip *int = start.Int("intname", "n", 1234, "help message")
	var sp *string = start.String("strname", "s", "default", "help message")
	var bp *bool = start.Bool("boolname", "b", "help message") // default is false if boolean flag is missing

	var flagvar int
	flag.IntVar(&flagvar, "flagname", 1234, "help message")

Then (optionally, if not using commands as well) call 
	
	start.Parse()

(instead of pflag.Parse()) to initialize each variable from these sources, in the given order:

1. From a commandline flag of the long or short name.
2. From an environment variable named as &lt;APPLICATION&gt;_&lt;LONGNAME&gt;, if the commandline flag does not exist. (<APPLICATION> is the executable's name, and <LONGNAME> is the flag's long name.) [1]
3. From an entry in the config file, if the environment variable does not exist.
4. From the default value if the config file entry does not exist.

This way, you are free to decide whether to use a config file, environment variables, flags, or any combination of these. For example, let's assume you want to implement an HTTP server. Some of the settings will depend on the environment (development, test, or production), such as the HTTP port. Using enviornment variables, you can define, for example, port 8080 on the test server, and port 80 on the production server. Other settings will be the same across environments, so put them into the config file. And finally, you can overwrite any default setting at any time via command line flags. 

And best of all, each setting has the same name in the config file, for the environment variable, and for the command line flag (but the latter can also have a short form).

[1] Warning: If your application name contains characters other than a-zA-Z0-9_, then <APPLICATION> must be set to the application name where all special characters are replaced by an underscore. For example: If your executable is named "start.test", then the environment variable is expected to read START_TEST_CFGPATH.

### Define commands:

Use Command() to define a new command. Pass the name, a sort and a long help message, and the function to call.

	start.Command("command", "short help message", "long help for 'help command'", commandFunc)

The function commandFunc has no parameters. It can get the command line via `flag.Args()` or `flag.Arg(n)`, where n is between 0 and `flag.NArg()-1`.

Define subcommands in the same way through SubCommand:

	start.SubCommand("parent", "command", "short help", "long help", commandFunc)

The parent command then needs no own commandFunc:

	start.Command("parent", "short help", "long help")

If you specify one, it will only be invoked if no subcommand is used.

For evaluating the command line, call

	start.Up()

This method calls `start.Parse()` and then executes the given command.


### Notes about the config file

By default, *start* looks for a configuration file in the following places:

* In the path defined through the environment variable <APPLICATION>_CFGPATH
{'fraction_non_alphanumeric': 0.08275614998805828, 'fraction_numerical': 0.006448531167900645, 'mean_word_length': 4.002986857825568, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, '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': '545056', 'n_tokens_mistral': 2234, 'n_tokens_neox': 2117, 'n_words': 1188}