climax

package module
v0.0.0-...-9f87fd1 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2020 License: MIT Imports: 6 Imported by: 35

README

Climax

Climax is an alternative CLI that looks like Go command

GoDoc Travis

Climax is a handy alternative CLI (command-line interface) for Go apps. It looks pretty much exactly like the output of the default go command and incorporates some fancy features from it. For instance, Climax does support so-called topics (some sort of Wiki entries for CLI). You can define some annotated use cases of some command that would get displayed in the help section of corresponding command also.

Why creating another CLI?

I didn't like existing solutions (e.g. codegangsta/cli | spf13/cobra) either for bloated codebase (I dislike the huge complex libraries) or poor output style / API. This project is just an another view on the subject, it has slightly different API than, let's say, Cobra; I find it much more convenient.


A sample application output, Climax produces:

Camus is a modern content writing suite.

Usage:

	camus command [arguments]

The commands are:

	init        starts a new project
	new         creates flavored book parts

Use "camus help [command]" for more information about a command.

Additional help topics:

	writing     markdown language cheatsheet
	metadata    intro to yaml-based metadata
	realtime    effective real-time writing

Use "camus help [topic]" for more information about a topic.

Here is an example of a trivial CLI application that does nothing, but provides a single string split-like functionality:

demo := climax.New("demo")
demo.Brief = "Demo is a funky demonstation of Climax capabilities."
demo.Version = "stable"

joinCmd := climax.Command{
	Name:  "join",
	Brief: "merges the strings given",
	Usage: `[-s=] "a few" distinct strings`,
	Help:  `Lorem ipsum dolor sit amet amet sit todor...`,

	Flags: []climax.Flag{
		{
			Name:     "separator",
			Short:    "s",
			Usage:    `--separator="."`,
			Help:     `Put some separating string between all the strings given.`,
			Variable: true,
		},
	},

	Examples: []climax.Example{
		{
			Usecase:     `-s . "google" "com"`,
			Description: `Results in "google.com"`,
		},
	},

	Handle: func(ctx climax.Context) int {
		var separator string
		if sep, ok := ctx.Get("separator"); ok {
			separator = sep
		}

		fmt.Println(strings.Join(ctx.Args, separator))

		return 0
	},
}

demo.AddCommand(joinCmd)
demo.Run()

Have fun!

Documentation

Overview

Package climax is a handy alternative CLI for Go applications. It looks pretty much exactly like the output of the default `go` command and incorporates some cool features from it. For instance, Climax does support so-called topics (some sort of Wiki entries for CLI). You can also define some annotated use cases of some command that would get displayed in the help section of corresponding command.

Climax applications produce this sort of output:

Camus is a modern content writing suite.

Usage:

	camus command [arguments]

The commands are:

	init        starts a new project
	new         creates flavored book parts

Use "camus help [command]" for more information about a command.

Additional help topics:

	writing     markdown language cheatsheet
	metadata    intro to yaml-based metadata
	realtime    effective real-time writing

Use "camus help [topic]" for more information about a topic.
Example (Application)
package main

import (
	"fmt"
	"github.com/tucnak/climax"
	"strings"
)

func main() {
	demo := climax.New("demo")
	demo.Brief = "Demo is a funky demonstation of Climax capabilities."
	demo.Version = "stable"

	joinCmd := climax.Command{
		Name:  "join",
		Brief: "merges the strings given",
		Usage: `[-s=] "a few" distinct strings`,
		Help:  `Lorem ipsum dolor sit amet amet sit todor...`,

		Flags: []climax.Flag{
			{
				Name:     "separator",
				Short:    "s",
				Usage:    `--separator="."`,
				Help:     `Put some separating string between all the strings given.`,
				Variable: true,
			},
		},

		Examples: []climax.Example{
			{
				Usecase:     `-s . "google" "com"`,
				Description: `Results in "google.com"`,
			},
		},

		Handle: func(ctx climax.Context) int {
			var separator string
			if sep, ok := ctx.Get("separator"); ok {
				separator = sep
			}

			fmt.Println(strings.Join(ctx.Args, separator))

			return 0
		},
	}

	demo.AddCommand(joinCmd)
	demo.Run()
}

// Handler accepts a climax.Context object and returns an exitcode integer.
func main(ctx climax.Context) int {
	if len(ctx.Args) < 2 {
		ctx.Log("not enough arguments")

		// with os.Exit(1)
		return 1
	}

	if name, ok := ctx.Get("name"); ok {
		// argument `name` parsed
		fmt.Println(name)

	} else {
		ctx.Log("name not specified")

		return 1
	}

	return 0
}
Output:

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Application

type Application struct {
	Name    string // `go`
	Brief   string // `Go is a tool for managing Go source code.`
	Version string // `1.5`

	Commands []Command
	Topics   []Topic
	Groups   []Group

	// Default is a default handler. It gets executed if there are
	// no command line arguments (except the program name), when
	// otherwise, by default, the help entry is being shown.
	Default CmdHandler
	// contains filtered or unexported fields
}

Application is a main CLI instance.

By default, Climax provides its own implementation of version command, but it will use "version" command instead if you provide one.

func New

func New(name string) *Application

New constructs a new CLI application with a given name. In case of an empty name it will panic.

func (*Application) AddCommand

func (a *Application) AddCommand(command Command)

AddCommand does literally what its name says.

func (*Application) AddGroup

func (a *Application) AddGroup(name string) string

AddGroup adds a new empty, named group.

Pass the returned group name to Command's Group member to make the command part of the group.

func (*Application) AddTopic

func (a *Application) AddTopic(topic Topic)

AddTopic does literally what its name says.

func (*Application) Log

func (a *Application) Log(lines ...interface{})

Log prints the message to stderrr (each argument takes a distinct line).

func (*Application) Run

func (a *Application) Run() int

Run executes a CLI.

Take a note, Run panics if len(os.Args) < 1

type CmdHandler

type CmdHandler func(Context) int

CmdHandler is a handling function type for functions.

Returned integer would be used as application exit status.

type Command

type Command struct {
	// Name is a [A-Za-z_0-9] identifier of up to 11 characters.
	//
	// Keep command names short, reasonable, catchy and
	// easy to type. At best, keep it a single word.
	//
	// Examples: build, list, install
	Name string

	// Brief is a short annotation of action command is capable of.
	//
	// Climax doesn't provide any limitations on the brief string
	// format, however it's highly recommended to keep it a single
	// lowercase phrase of 3-5 words without any punctuation marks.
	//
	// Example: compile packages and dependencies
	Brief string

	// Usage is a generic command use case, suggested by help.
	//
	// This string gets displayed on the usage line of command
	// help entry. You should NOT include command name itself.
	//
	// Example: [-o output] [-i] [build flags] [packages]
	Usage string

	// Help is a detailed command reference displayed after
	// the usage line and before the available flags block
	// of the help entry.
	//
	// Try to stick to the 80 character limit, so it looks fine
	// in the split terminal window.
	Help string

	// The group name this command belongs to.
	Group string

	// Handling, I bet it's pretty straight-forward.
	Handle CmdHandler

	// Flags are command-line options.
	Flags []Flag

	// Examples are annotated tips on command usage.
	Examples []Example
}

Command represents a top-level application subcommand.

func (*Command) AddExample

func (c *Command) AddExample(newExample Example)

AddExample does exactly what its name says.

func (*Command) AddFlag

func (c *Command) AddFlag(newFlag Flag)

AddFlag does literally what its name says.

func (Command) Run

func (c Command) Run(context Context) int

Run executes a command handler and returns corresponding exitcode.

type Context

type Context struct {
	// Real arguments, excluding any option flags and their values.
	//
	// Example:
	//
	//     $ app command --force -s="magic" 42 fairy
	//
	//     []string{"42", "fairy"}
	//
	Args []string

	NonVariable map[string]bool
	Variable    map[string]string
	// contains filtered or unexported fields
}

Context is a set of arguments and options of command call.

func (*Context) Get

func (c *Context) Get(variableFlagName string) (string, bool)

Get returns a value of corresponding variable flag. Second (bool) parameter says whether it's really defined or not.

func (*Context) Is

func (c *Context) Is(flagName string) bool

Is returns true if a flag with corresponding name is defined.

func (*Context) Log

func (c *Context) Log(data ...interface{})

Log prints the message to stderrr (each argument takes a distinct line).

func (Context) String

func (c Context) String() string

type Example

type Example struct {
	// Usecase is a typical use of command.
	//
	// Make sure to omit application and command name here,
	// since Climax appends it by default.
	Usecase string

	// Be descriptive, but keep it under 3-5 sentences.
	Description string
}

Example is an annotated use case of the command.

type Flag

type Flag struct {
	// A flag label without the prefix (--, -, whatever).
	//
	// Flag names can't contain more than 11 alphanumeric characters.
	Name string

	// Usually the first letter of the name.
	//
	// Short names can't contain more than 3 alphanumeric characters.
	Short string

	// Suggested use case, a generic example, showing
	// user how to use the flag.
	//
	// Example: --filter="token"
	Usage string

	// Help is displayed under the corresponding flag's
	// usage in the available commands section of help entry.
	//
	// Example: Limit tool output to tokens given.
	Help string

	// Variable flags have a flag value, non-variable don't.
	//
	// Flag value is a string assigned to particular flag.
	// For instance, --force is a non-variable flag and
	// --filter="token" is a variable flag.
	Variable bool
}

Flag is an optional command-line option.

type Group

type Group struct {
	Name     string
	Commands []*Command
}

Group connects a list of commands with a descriptive string.

The Name is used in the help output to group related commands together.

type Topic

type Topic struct {
	// Name is a [A-Za-z_0-9] identifier of up to 11 characters.
	//
	// Keep topic names short, reasonable, catchy and
	// easy to type. At best, keep it a single word.
	//
	// Examples: buildmode, packages, filetype
	Name string

	// Brief is a short annotation of the topic.
	//
	// Climax doesn't provide any limitations on the brief string
	// format, however it's highly recommended to keep it a single
	// lowercase phrase of 3-5 words without any punctuation marks.
	//
	// Example: description of package lists
	Brief string

	// Text is the actual topic content.
	//
	// Try to stick to the 80 character limit, so it looks fine
	// in the split terminal window.
	Text string
}

Topic is some sort of a concise wiki page.

Jump to

Keyboard shortcuts

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