{"id":37105480,"url":"https://github.com/eurozulu/commandgo","last_synced_at":"2026-01-14T12:43:36.794Z","repository":{"id":57515592,"uuid":"235468868","full_name":"eurozulu/commandgo","owner":"eurozulu","description":"command line interface object mapper","archived":false,"fork":false,"pushed_at":"2021-07-16T14:02:13.000Z","size":11695,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-06-20T00:27:32.773Z","etag":null,"topics":["args","argument-parser","cli","cmdline","command-line","command-line-tool","commandline","commandline-arguments","decoder","golang","object-mapping","unmarshalling","unnamed-arguments"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eurozulu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-01-22T00:30:35.000Z","updated_at":"2023-11-27T01:04:13.000Z","dependencies_parsed_at":"2022-09-10T17:31:29.719Z","dependency_job_id":null,"html_url":"https://github.com/eurozulu/commandgo","commit_stats":null,"previous_names":["eurozulu/commando","eurozulu/mainline"],"tags_count":34,"template":false,"template_full_name":null,"purl":"pkg:github/eurozulu/commandgo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eurozulu%2Fcommandgo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eurozulu%2Fcommandgo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eurozulu%2Fcommandgo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eurozulu%2Fcommandgo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eurozulu","download_url":"https://codeload.github.com/eurozulu/commandgo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eurozulu%2Fcommandgo/sbom","scorecard":{"id":385134,"data":{"date":"2025-08-11","repo":{"name":"github.com/eurozulu/commandgo","commit":"cbafa71169f401083f933a785a1437edc1139bfd"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T16:24:45.865Z","repository_id":57515592,"created_at":"2025-08-18T16:24:45.865Z","updated_at":"2025-08-18T16:24:45.865Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28420814,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["args","argument-parser","cli","cmdline","command-line","command-line-tool","commandline","commandline-arguments","decoder","golang","object-mapping","unmarshalling","unnamed-arguments"],"created_at":"2026-01-14T12:43:36.146Z","updated_at":"2026-01-14T12:43:36.783Z","avatar_url":"https://github.com/eurozulu.png","language":"Go","readme":"# CommandGo\n### Command line parser - object mapper\n\n* Simplifies writing command line tools by mapping the command line arguments directly into functions and method.  \n* Performs automatic type detection and parsing for all variables, fields and parameters with extendable framework for customised data types.\n* Keeps all flags and commands in one place.  Simple to maintain and IDE friendly.\n* Clean and simple to use.  No interfaces, struct's or types required to learn, just a simple map.\n  \nUnlike many command line parsers, Commandgo does not rely on any interface or predefined structures.  \nIt will map into almost any function/method or variable/field already in your application, so you don't have to maintain\nadditional code for your command line interface.  This works well for existing libraries and tools that require a simple\ncommand line interface applied to it.  Of course you can create one of your own, using generic struct's, functions and variable\nand map into these, but the choice is yours.\n\n##### Goal\nThe goal of this parser is to simplfy the boiler work of mapping command line arguments into your application.  \nThe prime goals are:  \n  \n+ Simplicity.  Interface must be clean, simple and obvious to anyone looking at it.\nNo additional types or interfaces to be imposed on the developer.  They define the code, the framework maps into it.  \n  \n+ Reduce code maintenance\nKeep code relating to the command line to a minimum. Keep the framework in the background.\nSingle point of maintenance.  All commands and flags in one, easily editable place, with direct links (via IDE) to the point thay map to.\nProvide single point of help, easily maintained. (No double changes to text prompts and comments, use the comments!)  \n  \nPartly insprired by [Spring IOC](\"https://www.baeldung.com/inversion-control-and-dependency-injection-in-spring\") from\nthe Java world, structures and parameters can have their values 'injected' into them from an external\nsource, in this case, the command line arguments.\n  \nA large part of the design was to keep the API as simple as possible, so you, the developer, doesn't have a steep learning curve to use the framework.  \nNo complex structures or special interfaces to implement, Commandgo tries to be intuitive and obvious, so anyone should be able to look at your code\nand understand exactly what its doing without having to know or learn the framework behind it.  \nAll the complexities of parsing value types and mapping functions is hidden away leaving the developer with a simple map.  \nThis maps the strings expected in the command line arguments, into their respective locations within your application,\nthose locations being functions, methods, variables or fields.  (known as mapped points)\n  \n### Usage\nTo show an example Commands map, first, here is a fictional \"deployment\" application struct, which performs deployments of code.  \nThis would be your own application code, just an example of something to map into.  \n```\n\ntype EnvironmentType int\nconst (\n\tDEV EnvironmentType = iota\n\tTEST\n\tPROD\n)\n\ntype Deployer struct {\n    // Config file holds the data to connect to the jenkins servers etc.\n    Config        io.ReaderCloser \n    Environment   EnvironmentType\n}\n// DoDeploy performs a deployment of the given project, to the configured servers and returns the version deployed \nfunc (d Deployer) DoDeploy(repoURL *url.URL) (float32, error) {\n   ...\n}\n// DeployedVersion gets the version of the project at the given repo\nfunc (d Deployer) DeployedVersion(repoURL *url.URL) (float32, error) {\n   ...\n}\n\n```  \nTo map a command line interface into this application we might use a map something like this:\n```\nfunc main() {\n    // create our 'app' with its default settings\n    dp := \u0026Deployer{Environment: DEV }\n    \n    cmds := commandgo.Commands{\n        \"deploy\": dp.DoDeploy,\n        \"ver\":    dp.DeployedVersion,\n         \n        \"--config\": \u0026dp.Config,\n        \"--env\":    \u0026dp.Environment,\n    }\n    \n    v, err := cmds.RunArgs()\n    if err != nil {\n        log.FatalLn(err)\n    }\n    \n    fmt.Println(v)\n}\n```\n\n\nAnd that's it!  You have a command line application.\n\nBoth methods require a single URL parameter, returning a float, error so the framework parses the first arg after the 'command' as a url.\nThe two flags are also both parsed into their respective types The 'EnvironmentType' parses as an int.\nThe Config field is defined as an interface `io.ReaderCloser`.  By default, the framework has a custom type of *File, which can handle this type.\nThe *File type parses an argument as a local file path and opens the corrisponding file for that path.  \n  \n\nThe corresponding command line, for a binary named 'myapp', would be:  \n  \n``` \nmyapp ver https://github.com/eurzulu/blabla -config ~/.deploy/config.yaml \n1.2\n\n```  \n``` \nmyapp deploy https://github.com/eurzulu/blabla -config ~/.deploy/config.yaml -env 1\n1.3\n\n```\n\n  \nThis is the simplest example to show how it works.  \nThere's loads more features to help you maintain the most complex of command line parsing needs, from sub maps, default keys and functional flags to \ncustom type mapping and automatic help generation.  \nRead on to discover these and see how commandgo can take the grind work out of writing command line tools and let you focus on what your application does.  \n  \n  \n  \n### Commands\nThe Commands map is the heart of the framework.  It's a simple map using string keys which map to `interface{}` values.  \nA very simple example:   \n```\ncmds := commandgo.Commands { \n      \"mycommand\": MyFunction,  \n      \"-myflag\":   \u0026SomeVariable,\n    }\n ```\nWhere `MyFunction` is an exported function and `SomeVariable` is a variable.\nThe keys are the command line arguments and the `interface{}` value is either a func/method, or pointer to variable/field.    \n  \nNotice the function mapping requires no reference to the functions parameters, return values or their types, as with\nthe variable and its type.  These are all detected and handled for you by the framework.  \n  \nShould `MyFunction` look something like this:  \n`func MyFunction(name string, id int, click *url.URL) (string, error) { ...}`    \nThen the framework will expect three command line arguments following the \"mycommand\" argument, and those arguments must be parsable as:  \nstring, int and a url respectively.  If the wrong amount of arguments is given or they cannot be parsed into these types,\nthe framework reports the error back to the user, informing them of what is required.  \nThis frees the developer of the tedious task of parsing and basic validation.  \nMappings can be to almost any type of function/method or to any variable/struct field.  \n\nThe interface values can be one of three types:\n+ func / method\n+ variable/field pointer\n+ another 'sub' Commands map\n\nA helpful bonus of having the function / variables directly referenced in the map is that most IDE's allow you to click through to the implementation or definition of that item.  \nViewing the Commands map, you see the command being mapped, and a click takes you to the function or field it maps to.\n\n\n#### Mapping points\nMapping points are the values, other than submaps, which keys are mapped to. i.e. func/methods, variable/fields.  \nThese points can be ANY exported point of a library or application or point local to the same package.  \nFor simple tools, your map can often call directly into the library or data model you wish to use,\nwithout the need for an intermedeate structure or interface.  For more complex needs, an intermediate structure can be used, grouping your flags and commands into \ninduvidual structs and performing 'pre-call' or 'post-call' operations, perhaps using flags set as fields etc.  \n  \n\n#### default key\nThe default key is an empty string, when present, gives the Commands a default location to call when no arg-\u003ekey mapping is found.  \nWithout the default key, (the out of the box state) the framework will report a \"missing command\" or \"unknown command\" error when no key is found.  \nWhen present, this key is used when no other matches.  \nAn important note about the default key is how parameters are handled.  Considure a cmd line of:  \n`hello world`  and a map with no matching key but a default key.  The framework will first search for the `hello` key as the command,\nand on failing, revert back to the default.  The `hello` will then revert to being a parameter (rather than a command).  \nWith no default key, it will report `hello` as an unknown command.\nThe same rules apply to the default mapping as any other, in that the arguments must match the mapping points type or signature.\n\n#### Command alias\nTo specifiy more than one command name or flag, simply map two or more entiries with the same value.\n```\ncmd := commandgo.Commands{\n  \"mylongcommandname\" : MyCommands.LongName,\n  \"mlcn\"              : MyCommands.LongName,\n}\n```\nThe Help system detects these multi entries and groups all keys into the same help subject.\n\n#### Submaps\nIn addition to func and vars etc, values may also be other Commands maps, containing their own set of flags and command keys.  \nUsing sub maps commands can be 'chained' into sequences, forming a hierarchy of commands.  \ne.g. `get users accounts`, the `get` is in the 'top' map as a key to another map containing the `users`\nkey mapping to yet another map with the `accounts` key finally mapped to a function/method.  \nEach level of commands has its own set of flags (and alternative commands), only being parsed when that sequence if followed.  \ne.g. if we want a flag to apply to all `users` commands, we place them in the second map.  \nFlags only applying to `account` command, are placed in the last map and so on.  Flags and commands are 'scoped' to the map they're defined in.  \nWhen the final function map is found, all flags should have been assigned at their respective levels.  Remaining flags are considured an error.\n\n\n\nAn example of submaps, here, a mapping of a \"getter\" and \"putter\" structs being used to map commands to get and put resources\nto either external urls, or local files.\n```\nCommmands{\n  \"-verbose\": \u0026Verbose,\n  \"-log\":     \u0026logs.Level,\n  \"about\":    showAbout,\n  \"get\": Commands{\n      \"\":        getter.DoGet,\n      \"later\":   getter.DelayedGet,\n      \"-format\": \u0026getter.OutputFormat,\n  },\n  \"put\": Commands{\n      \"\":         putter.DoPut\n      \"-encrypt\": \u0026putter.Encrypt,\n      \"-key\":     \u0026putter.Key,\n      \"-user\":    \u0026putter.User,\n      \"new\": Commands{ \n          \"\":        builder.Build,\n          \"-name\":   \u0026builder.Name, \n          \"-id\":     \u0026builder.Id, \n          \"-status\": \u0026builder.Status,\n  },\n}\n```    \n  \nIn this example there are five mappings in the 'root' map, two flags (-verbose, -log) and three commands, \"get\", \"put\" \u0026 \"about\".  \nThe top level flag mappings are called global flags, as they are always available to all commands.  These usually map to global variable.   \nRegardless of the command being used, these flags will be parsed from the command line first.  \nOf the three top level commands, two, `get` and `put` map into methods and `about` maps to a global function `showAbout()`.\nThe method mappings are using submaps to define some additional flags that are specific to those commands only.\nIn addition, `put` has a third level command `new`  command which maps yet another submap and to a Builder object for creating new instances.  \ne.g.  \n```myapp put http://myserver/theputtedstuff \"This is the data\" -encrypt -user john -key ~/.ssh/id_rsa.pub```  \nor  \n```mycmd put new -name mynewfile -id \"blabla\" -status draft```\n\nAn example of what this map is mapping into:  \n```\ntype MyPutter struct {\n  Encrypt bool\n  Key *os.File\n  User string\n}\n\nfunc (mg MyGetter) DoGet(url *url.Url) (string, error) {\n  ...\n}\n\nfunc (mg MyGetter) DelayedGet(url *url.Url) (string, error) {\n  ...\n}\n```\nNote the parameters of these function are the types required (URL), which is parsed for you by the framework, from the given command line.  \nCommand lines missing arguments or using malformed arguments for that type are reported as errors automatically by the framework.  \n\n\n### Execution\nOnce a map is created, it can be called using the arguments to be parsed.  \nCommands has two points to call, `Run(args ...string)` and a convienience method `runArgs()` which simply uses the os.Args.  \n\n\n#### Execution order\nOn calling `Run` or `RunArgs` the command line is parsed in the following order:  \n- The Flags are located along with their following values.  \n- Flags are each run, first the assignment mappings, followed by any func mappings.  \n- Finally the command mapping is found and run, using any remaining args (not consumed by flags) as parameters (or values) for the command.\n  \nThe command line is parsed by passing it to each map and sub map, which 'consumes' arguments from it.  Consume meaning they are no longer\nmade available to the following func or assignments.  Think of each mapping taking its arguments from the command line until all thats left\nis a command followed by its parameters.  Each flag takes what it needs and finally the command uses the remaining to set its parameters.\n\nIn the command line, Flags can appear in any order. All flags, with the exception of bool types must have a following\nargument as its value.  \nThis value is converted to the relevant data type for the Field. Booleans MAY have a value, if it is parsable as a bool.\nIf they have a following argument which is not parsable as bool, that value is ignored by the bool flag. Bool flag are\nTrue when they are present, unless they are followed by a 'false' value.\n\n\n\n#### Flags\nA Key may be marked as a 'Flag' by preceeding it with one or more '-' dash characters.  \nFlags are usually optional arguments which can alter the behaviour of the 'main' command.  \nFlag keys are treated with priority when executing the command line.  Non flags, which are not parameter values, are treated as\na command, and executed once.  Flags are ALL executed before the main command is invoked.\nAny name can be mapped to any of these three mappings.\n\n#### Parameters\n\nAll arguments which are not flags or values of flags are classed as unnamed arguments or parameters.  \n`... --myflag myflagvalue unnamed1 -v unnamed2 unnamed3`  \nIn this example there are 3 unnamed values, (Assuming -v maps to a bool)\n\nOnce all flags and their values are removed from the command line, the remaining, unnamed arguments are used to map to\nthe parameters of the method being called, in the order they are presented.  \ne.g. should a method or function have a signature such as:  \n`func (ma Myargs) MyCommand(s string, t time.Time, count int)`  \nIt will require three unnamed parameters in the command line and those parameters must be valid for the data types in\nthat position.  \n`mycommand hello \"1/1/2001T12:00:00\" 4`  \nwill parse correctly.  \n`mycommand \"1/1/2001T12:00:00\" hello 4`  \nwill throw an error of invalid date.\n  \n#### Variadic Parameters\nVariadic parameters are supported.  When present, the command line arguments\nfrom the final position, onwards, are all parsed into a slice of the Variadic type.  \nThese allow the command line to accept zero or more arguments optionaly.  \nVariadic parameters can be of any of the supported data types.  \nA func with a signature such as:\n```\nfunc DoThis(s ...string) {}\n```\nCan accept any command line passed to it as all args are strings already, and all are optional.\n\n\n\n\n  \n### Data Types\nWhen parsing the command line argument strings, the destination of the argument is examinied to determine its type.  \ne.g. \"-myflag\": \u0026SomeFloat  pointing to a float var attempts to parse the string following the -myflag agument, into a float.  \nThis is the same process for function parameters, struct fields and variables.\nWhen mappng to flags, the order of the command line is unimportant, flags can be anywhere in the command line.  \nWhen mapping to functions or methods, the order of the arguments and the count* must match that of the function parameters being called.  \n*unless function/method uses variadic parameters, in which case argument count must only match the non variadic parameters. \n\nMost data types are supported with the exception of channels:  \n+ int, int16, int32 int64, uint8, uint16, uint32, uint64\n+ float32 float64 \n+ bool\n+ string    \n+ slices \n+ maps\n+ struct\n  \n`bool` types are exceptional as they are the only type not requiring a value.  They default to true when no value is provided.  \n`structs` are parsed as json from the command line or, if the struct supports encoding, will be Unmarshalled using that.\n+ Those supporting [encoding.BinaryUnmarshaler](https://golang.org/pkg/encoding/#BinaryUnmarshaler) interface\n+ Those supporting [encoding.TextUnmarshaler](https://golang.org/pkg/encoding/#TextUnmarshaler) interface\n\nAdditional types can be added via the 'CustomType' system.  \n  \n  \n#### Custom Data type  \nData type support can be extended using custom data types to allow mapping into variables or functions which use a specific type.  \nThese types define a specific data type and provide a custom function to parse the string argument into that type.  \nThe framework include three custom types out of the box:  \n+ \\*url.Url\n+ time.Time, time.Duration\n+ \\*os.File  \n  \nCustom types apply to both fields/variable values and func/method parameters.  \nBy specifying a custom type, function parameters and variables of any type which can be mapped directly from the command line and parsed in the required type.\nThe type only has to be \"assignable\", therefore a parameter type of say `io.Reader` will be parsed by the \\*os.File custom type.  \n\nTo define a new custom type use the `values.NewCustomType` method, which accepts a reflect.Type and a ArgValue function.  \nThe ArgValue function is passed a string argument and a reflect.Type of the type required.  \nIt returns an `interface{}, error` of the value it parses the argument into.  \n  \nAs an example of a custom type, take the first example \"deployment\" app above, the EnvironmentType is an `int` const.  \nRather than accept numbers on the command line, we could map this from a more natural string name:  \n```\nett := reflect.TypeOf(EnvironmentType(0))\nvalues.NewCustomType(ett, func(s string, t reflect.Type) (interface{}, error) {\n\tswitch s {\n\tcase \"DEV\":\n\t\treturn DEV, nil\n\tcase \"TEST\":\n\t\treturn TEST, nil\n\tcase \"PROD\":\n\t\treturn PROD, nil\n\tdefault:\n\t    return 0, fmt.Errorf(\"%s is not a known environment\", s)\n\t}\n})\n```  \nThen the flag would be more natural `-env DEV` rather than `-env 0`  \nOnce registered this way, the type will automatically be called on all values which are assignable to `EnvironmentType`.  \n\n\n\n### Help System\nAll command line parsers require a help system to guide the final user about the commands and flags.  \nThe help system is current designed to be open and freely editable by the application designer.\nCustom help can be added or replace any existing help.  \n\nIn line with minimal effort, the help system aims to use Godoc comments to form the help system.  \nThis is still currently under development, but is aimed as a pre-build process, extracting the key mappings from source\nand matching them to the comments they map to.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feurozulu%2Fcommandgo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feurozulu%2Fcommandgo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feurozulu%2Fcommandgo/lists"}