moon

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 19, 2026 License: MIT Imports: 8 Imported by: 0

README

Moon

Docker Image CI

A minimal POSIX-compliant command-line parser for Go. Moon lets you design CLI applications with support for flags, subcommands, positional arguments, and help generation.

Installation

Moon can be added to any Go project using go get.

go get github.com/meowdhavan/moon

Usage

Moon is very much inspired by Cobra, and many of their commands will look similar.

Example

It is recommended to define the commands in their own dedicated package (cmd, by convention):

package cmd

import (
	"fmt"
	"github.com/meowdhavan/moon"
)

var (
	name    string
	age     int
	verbose bool
	files   []string
)

var RootCmd = &moon.Command{
	Name:       "greet",
	AboutShort: "A simple CLI application to greet people.",
	Run: func() {
		fmt.Printf("Hello %s, you are %d years old.\n", name, age)
		fmt.Printf("Processing %d files.\n", len(files))
	},
}

func init() {
	RootCmd.Flags().String(&name, "name", "n", "Your name", moon.Env("GREET_NAME"), moon.Required())
	RootCmd.Flags().Int(&age, "age", "a", "Your age", moon.Default("18"))

	RootCmd.VarArgs().String(&files, "files", "List of files to process")
}

...and execute the application within main():

package main

import (
	".../cmd"
	"github.com/meowdhavan/moon"
)

func main() {
	m := moon.NewMoon(cmd.RootCmd)
	m.Execute()
}

Running the Example

Print the Autogenerated Help
go run main.go --help

Output:

greet - A simple CLI application to greet people.

Usage:
    greet [FLAGS] <...files>

Flags:
    -n, --name  Your name [required] [env: GREET_NAME]
    -a, --age   Your age [default: 18]
    -h, --help  Show help message
Run with Flags
go run main.go --name Alice --age 25 file1.txt file2.txt

Output:

Hello Alice, you are 25 years old.
Processing 2 files.
Use Short Flags and Default Values
go run main.go -n Bob

Output:

Hello Bob, you are 18 years old.
Processing 0 files.

Advanced Usage

Options

When defining flags or positional arguments, you can pass optional modifiers to customize their behavior:

  • moon.Alias("alias_name"): Sets an alias for the flag.
  • moon.Env("ENV_VAR"): Falls back to reading from an environment variable.
  • moon.Default("value"): Sets a default value if the flag is not provided. Due to current limitations, the provided value must be a string, irrespective of the type of the flag/argument.
  • moon.Required(): Marks the flag or argument as required. If no value is provided and no fallback is available, an error is shown and the application is halted.

Subcommands

Subcommands are just like any other command. They must be attached to their parent with the Subcommand() method.

var srvCmd = &moon.Command{
	Name:       "serve",
	AboutShort: "Start the server",
	Run: func() {
		fmt.Println("Starting server...")
	},
}

var port int

func init() {
	srvCmd.Flags().Int(&port, "port", "p", "PORT", moon.Env("SERVER_PORT"), moon.Required())

	rootCmd.Subcommand(srvCmd)
}

Supported Types

Flags and arguments in Moon are strongly typed. The following configurations are currently supported:

  • Flags (Flags() / GlobalFlags()):

    • String, Int, Bool
    • MultiString, MultiInt, MultiBool (e.g., -vvv or multiple -f declarations)
  • Positional Arguments (PosArgs()):

    • String, Int, Bool
  • Variadic Arguments (VarArgs()):

    • String, Int (Captures all trailing arguments, must be at the end)

Validator

Note that it is possible to incorrectly configure Moon. For example,

  • Mark a flag/argument as required, as well as provide a default value for it.
  • Provide the same short flag name for two different flags.
  • Have a command as a subcommand of itself.
  • Provide positional arguments as well as subcommands to a command.
  • ...and much more

Since this is not checked during compile time, this will not result in a compilation failure. However, this may lead to unintended effects.

Scenarios like these can be avoided with the help of Validate(). This function returns a slice of errors that provides all incorrect configurations in the application (if there are any, that is).

The application can have a test function that runs this method and ensures that the resulting slice is empty. The test may be run in a CI/CD pipeline.

License

This project is licensed under the MIT License.

Documentation

Index

Constants

View Source
const (
	// StyleBold is a [Style] applies bold formatting.
	StyleBold = iota
	// StyleUnderline is a [Style] applies underline formatting.
	StyleUnderline
	// StyleUppercase is a [Style] converts text to uppercase.
	StyleUppercase
)

Variables

This section is empty.

Functions

func Alias

func Alias(alias string) variableProperty

Alias adds an alias name to the Variable.

Aliases must not be present in positional arguments (PosArg) or variadic arguments (VarArgs). Is is only meant to be used on flags (Flag).

Example:

cmd.Flags().String(&name, "name", "n", "Your name", moon.Alias("first-name"))

func Default

func Default(defaultVal string) variableProperty

Default specifies a default value if the Variable is not provided. Due to current limitations, this value must be provided as a string.

If a Variable has a Default value, it should not be Required.

Example:

cmd.Flags().Int(&port, "port", "p", "Port to listen on", moon.Default("8080"))

func Env

func Env(env string) variableProperty

Env specifies an environment variable as a fallback to the Variable. If no flag is passed, the value in the provided environment variable will be used if present.

Example:

cmd.Flags().String(&token, "token", "t", "API Token", moon.Env("API_TOKEN"))

func Required

func Required() variableProperty

Required marks the Variable as mandatory. If the value for this variable is not supplied and there are no fallback values, an error will be reported.

If a Variable is Required, it should not have a Default value.

Example:

cmd.Flags().String(&config, "file", "f", "File to compile", moon.Required())

Types

type Command

type Command struct {
	Name         string
	Version      string
	Aliases      []string
	AboutShort   string
	AboutLong    string
	Run          func()
	SuppressHelp bool
	// contains filtered or unexported fields
}

Command represents a command or subcommand in the application's CLI. It acts as the core building block for your CLI application. Each command can hold its own set of flags (Flag), and either positional arguments (PosArg), variadic arguments (VarArgs), or subcommands (Command).

Example:

rootCmd := &moon.Command{
	Name:       "app",
	Version:    "1.0.0",
	AboutShort: "A sample CLI application",
	Run: func() {
		fmt.Println("Running app...")
	},
}

func (*Command) Flags

func (c *Command) Flags() *flagCollection

Flags returns a collection to define local flags (Flag). Local flags are only available on this specific command.

Example:

var verbose bool
cmd.Flags().Bool(&verbose, "verbose", "v", "Enable verbose output")

func (*Command) GlobalFlags

func (c *Command) GlobalFlags() *flagCollection

GlobalFlags returns a collection to define global flags (Flag). Global flags are available on this command and all of its subcommands.

Example:

var configPath string
cmd.GlobalFlags().String(&configPath, "config", "c", "Path to config file")

func (*Command) PosArgs

func (c *Command) PosArgs() *posArgCollection

PosArgs returns a collection to define positional arguments (PosArg) for this command. Positional arguments are parsed in the order they are defined. However, the required ones are always parsed before the optional ones, regardless of their order of definition.

If a command has positional arguments (PosArg), it should not have subcommands (Command). If a command has optional positional arguments, it should not have variadic arguments (VarArgs). Variadic positional arguments are allowed with required positional arguments.

Example:

var input string
cmd.PosArgs().String(&input, "input", "Input file path", moon.Required())

func (*Command) Subcommand

func (c *Command) Subcommand(s *Command)

Subcommand adds a subcommand to this command.

If a command has subcommands, it should not have positional arguments (PosArg) or variadic arguments (VarArgs).

Example:

sub := &moon.Command{Name: "serve"}
rootCmd.Subcommand(sub)

func (*Command) VarArgs

func (c *Command) VarArgs() *varArgs

VarArgs returns a collection to define variadic arguments (VarArgs) for this command. Variadic arguments capture all remaining positional arguments provided.

If a command has variadic arguments, it should not have subcommands (Command) or optional positional arguments (PosArg). Required positional arguments are allowed.

Example:

var files []string
cmd.VarArgs().String(&files, "files", "List of files to process")

type DefaultPrinter

type DefaultPrinter struct {
	SuppressWarnings bool
	IndentLength     int
	HelperMaxLength  int
	HeadingStyle     []Style
	FocusStyle       []Style
}

DefaultPrinter provides default terminal output formatting for commands and help menus. You can customize its properties to change the style of the generated help text.

func (*DefaultPrinter) Focus

func (p *DefaultPrinter) Focus(s string) string

Focus formats the given string using the FocusStyle rules.

func (*DefaultPrinter) Heading

func (p *DefaultPrinter) Heading(s string) string

Heading formats the given string using the HeadingStyle rules.

type Flag

type Flag struct {
	Variable
	// contains filtered or unexported fields
}

Flag represents a command-line flag (e.g., --xyz or -x) with its parsed value and properties. Flags can be either local to a specific command or global across all subcommands.

type Moon

type Moon struct {
	RootCmd *Command
	Printer Printer
}

Moon is the main application struct that manages the root command and printing. It serves as the entry point for executing the application.

func NewMoon

func NewMoon(rootCmd *Command) *Moon

NewMoon initializes a new Moon application with the given root command and the default Printer. It also recursively sets up standard flags like help and version for all subcommands.

Example:

rootCmd := &moon.Command{Name: "app"}
app := moon.NewMoon(rootCmd)
app.Execute()

func (*Moon) Execute

func (m *Moon) Execute()

Execute parses the command-line arguments and runs the appropriate command. It handles help, version output, parsing errors, and command execution. In the case there are errors during parsing, they will be printed out along with the usage instructions, and the application will be halted.

func (*Moon) Validate

func (m *Moon) Validate() []error

Validate checks the entire command tree for configuration errors. It verifies that there are no conflicting flag names, no subcommand loops, and no invalid combinations of positional arguments, variadic arguments, and subcommands. It returns a slice of all validation errors encountered.

Example:

app := moon.NewMoon(rootCmd)
errs := app.Validate()
if len(errs) > 0 {
	for _, err := range errs {
		fmt.Println("Validation error:", err)
	}
	os.Exit(1)
}

type PosArg

type PosArg struct {
	Variable
}

PosArg represents a positional argument parsed from the command line. There are two types of PorArg: required and optional. The required PosArgs are always parsed first.

type Printer

type Printer interface {
	// contains filtered or unexported methods
}

Printer defines the interface for formatting and printing command outputs, such as versions, help menus, warnings, and usage details. This interface can be implemented to provide custom formatting for the CLI.

type Style

type Style int

Style represents an ANSI text styling option. It is used to customize the appearance of terminal output.

type VarArgs

type VarArgs struct {
	Variable
}

VarArgs represents the variadic arguments parsed from the command line.

type Variable

type Variable struct {
	// contains filtered or unexported fields
}

Variable represents an entity that can contain a value. It is the common base for Flag, PosArg, and VarArgs. It holds metadata such as name, aliases, description, and fallback values.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL