suzume

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 6, 2026 License: MIT Imports: 14 Imported by: 0

README

Suzume CLI Framework

Suzume は Go 言語でコマンドラインアプリケーションを構築するためのフレームワークです。

Suzume の特徴

Suzume は一つのコマンドを定義するシンプルなプロジェクトからサブコマンドを持つ複雑なプロジェクトまで、規模を問わないコマンドアプリケーションの構築を容易にサポートします。

例として、簡単な通知を行うコマンドを定義するコードは以下のようになります。

package main

import (
    "fmt"
    "github.com/Luke256/suzume"
)

func main() {
    cmd, err := suzume.NewCommand("notify", "Greet and notify tasks", func(name string, tasks int) error {
        fmt.Printf("Hello, %s! You have %d tasks to complete today.\n", name, tasks)
        return nil
    })
    if err != nil {
        panic(err)
    }

    cmd.Run() // go run main.go Alice 5
}

非常にシンプルながら、Cobra や urfave/cli といった他の CLI フレームワークと比較して少ないコードで同様の機能を実現できます。 Suzume は以下の特徴により、Go 言語での CLI アプリケーション開発をよりシンプルかつ効率的にします。

  • スケール性 : 軽量なアプリケーションはシンプルなコードで構築でき、必要に応じてサブコマンドや追加の機能を簡単に追加できます
  • シンプルなコマンド定義 : コマンドの引数やオプションを関数のシグネチャや構造体のタグから推測するため、コードが非常にクリーンになります
  • 独自型のサポート : TextUnmarshaler を実装する独自の型をコマンド引数やオプションとして使用できます
  • 明示的なデフォルト値 : コマンド引数やオプションのデフォルト値を明示的に指定できるため、コードの可読性が向上します
  • ヘルプの自動生成 : コマンドの説明や引数、オプションの情報から自動的にヘルプメッセージを生成します
  • 軽量な依存関係 : Suzume は標準ライブラリのみで構築され、プロジェクト全体の依存関係を最小限に抑えます

インストール

go get github.com/Luke256/suzume

コマンドの定義

コマンドは suzume.NewCommand 関数を使用して定義する方法と、 suzume.UseCommand 関数を使用して構造体から定義する方法の2通りがあります。

suzume.NewCommand を使用したコマンド定義

suzume.NewCommand を用いると、コマンド名と説明、そしてコマンドの実装を一度に定義できます。コマンドの引数は関数のシグネチャから自動的に推測されます。

cmd, err := suzume.NewCommand("greet", "Greet someone", func(name string, num int) error {
    println("Hello,", name, "you have", num, "messages.")
    return nil
})

コマンドは cmd.Run() を呼び出すことで実行できます。また、cmd.Run("Luke", "5")のように引数を直接渡すことも可能です。

コマンドを cmd.RunAndExit() で実行すると、コマンドがエラーを返した場合にプロセスが終了コード1で終了します。

suzume.UseCommand を使用したコマンド定義

suzume.UseCommand を使用すると、より詳細なコマンド定義が可能になります。

まず、suzume.Runner を実装する構造体を定義します。この構造体のフィールドはコマンドの引数やオプションを表し、タグを使用してコマンドライン引数やオプションの情報を指定します。

type GreetCommand struct {
    Name string `cli:"0" usage:"Name of the person to greet"`
    Num  int    `cli:"num" short:"n" usage:"Number of messages"`
}

func (c GreetCommand) Run(ctx context.Context) error {
    println("Hello,", c.Name, "you have", c.Num, "messages.")
    return nil
}

Suzumeで使用される構造体タグは次の通りです:

  • cli:"0" : 引数の位置を指定します。整数は引数の位置を表し、0は最初の引数を意味します。非整数値はオプションを表します。
  • short:"n" : オプションの短い形式を指定します。この場合、-nNum フィールドを指定できます。
  • usage:"..." : 引数やオプションの説明を指定します。

次に、suzume.UseCommand を使用してコマンドを定義します。

cmd, err := suzume.UseCommand[GreetCommand]("greet", "Greet someone")

引数に対してデフォルト値を明示的に指定する場合、suzume.Defaulter を実装することで可能になります。

func (r GreetCommand) Default() GreetCommand {
	return GreetCommand{
		Num: 5,
	}
}

[!Important] Run() 及び Default() メソッドは、構造体のレシーバーで定義してください。

[!Note] Bool 型のフィールドはすべてフラグとして処理されますが、--flag=falseのように明示的に値を指定した場合、その値が使用されます。

サブコマンドの定義

サブコマンドを作成するには、suzume.NewApp を使用してアプリケーションを作成し、AddCommand メソッドでコマンドを追加します。

cmd1, _ := suzume.NewCommand("foo", "bar", func() error {
    // do something
    return nil
})

cmd2, _ := suzume.NewCommand("hoge", "fuga", func() error {
    // do something
    return nil
})

app := suzume.NewApp("myapp", "My CLI Application")
app.AddCommand(cmd1) // myapp foo
app.AddCommand(cmd2) // myapp hoge
app.Run()

[!Important] アプリケーションは0個以上のコマンドと0個以上のサブアプリケーションを持つことができますが、アプリケーション自体はコマンドとして実行できません。これは、アプリケーションをサブコマンドのハブとして設計するための意図的な制約です。もしアプリケーション自体が実行能力を持ってしまうと、myapp subcmd のようなコマンドの subcmd 部分が引数であるのか、サブコマンドであるのかの区別がつかなくなってしまいます。

サブコマンドのネスト

サブコマンドはさらにサブコマンドを持つことができます。これにより、複雑なコマンド階層を構築することが可能になります。

root := suzume.NewApp("root", "Root Command")
sub1 := suzume.NewApp("sub1", "Sub Command 1")
cmd, _ := suzume.NewCommand("cmd", "A command", func() error {
    // do something
    return nil
})
sub1.AddCommand(cmd) // root sub1 cmd
root.AddApp(sub1)
root.Run() // go run main.go sub1 cmd

Config

ログの出力先などの設定は、SetConfig メソッドを使用して行います。

cmd.SetConfig(suzume.Config{
    Log:        os.Stdout,
    ErrorLog:   os.Stderr,
})

デフォルトでは、ログは標準出力に、エラーログは標準エラー出力に出力されます。 また SetConfig で明示的に設定されない限り、コマンドやアプリケーションは親の設定を継承します。

ヘルプの自動生成

Suzume はコマンドの説明や引数、オプションの情報から自動的にヘルプメッセージを生成します。ユーザーは --help -h オプションを使用してヘルプを表示できます。また、アプリケーションに対しては help サブコマンドも自動的に追加されます。

(これはどのサブコマンドよりも優先されるため、help という名前のサブコマンドを定義することはできません)

例:

$ go run main.go --help
mycli

A simple CLI application

Usage:
  mycli [command] [args...]

Commands:
  greet                Greet someone
  help                 Show this help message

ライセンス

Suzume は MIT ライセンスのもとで公開されています。

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrCommandNotFound = errors.New("Command not found")
)
View Source
var (
	ErrInvalidArgument = errors.New("invalid argument")
)

Functions

This section is empty.

Types

type App

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

App represents a CLI application that can contain commands and sub-applications.

func NewApp

func NewApp(name, description string) *App

NewApp creates a new App with the given name and description, and initializes it with the default configuration.

func (*App) AddApp

func (app *App) AddApp(subApp *App)

AddApp adds a sub-application to the application. If the sub-application is nil, it is ignored.

func (*App) AddCommand

func (app *App) AddCommand(cmd *Command)

AddCommand adds a command to the application. If the command is nil, it is ignored.

func (*App) Alias

func (app *App) Alias(name string) *App

Alias adds an alias for the application. If the alias name is empty, it is ignored.

func (*App) Run

func (app *App) Run(args ...string) error

Run executes the application with a background context and the given arguments.

func (*App) RunAndExit

func (app *App) RunAndExit(args ...string)

RunAndExit executes the application with a background context and the given arguments and exits the process with code 1 if an error occurs.

func (*App) RunContext added in v0.1.0

func (app *App) RunContext(ctx context.Context, args ...string) error

RunContext executes the application with the given context and arguments. It first checks if the arguments indicate that the help message should be shown, then it tries to find a matching command or sub-application to execute. If no matching command or sub-application is found, it returns an error.

func (*App) RunContextAndExit added in v0.1.0

func (app *App) RunContextAndExit(ctx context.Context, args ...string)

RunContextAndExit executes the application with the given context and arguments and exits the process with code 1 if an error occurs.

func (*App) SetConfig

func (app *App) SetConfig(config Config)

SetConfig sets the configuration for the application. This configuration will be inherited by sub-applications and commands unless they have their own configuration set.

type Command

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

Command represents a command in the CLI application, including its name, description, handler function, argument specifications, and configuration.

func MustNewCommand added in v0.1.0

func MustNewCommand(name, description string, runFunc any) *Command

MustNewCommand is a helper function that creates a new Command and panics if an error occurs. It is useful for cases where the command definition is static and should not fail at runtime.

func MustUseCommand added in v0.1.0

func MustUseCommand[T Runner](name, description string) *Command

MustUseCommand is a helper function that creates a new Command based on a Runner type and panics if an error occurs. It is useful for cases where the command definition is static and should not fail at runtime.

func NewCommand

func NewCommand(name, description string, runFunc any) (*Command, error)

NewCommand creates a new Command with the given name, description, and handler function. The handler function can be any function that takes zero or more arguments and returns an error.

func UseCommand

func UseCommand[T Runner](name, description string) (*Command, error)

UseCommand creates a new Command based on a Runner type. It uses reflection to create a handler function that calls the Run method of the Runner, and it generates argument specifications based on the fields of the Runner struct.

func (*Command) Alias

func (cmd *Command) Alias(name string) *Command

Alias adds an alias for the command. If the alias name is empty, it is ignored.

func (*Command) Run

func (cmd *Command) Run(args ...string) error

Run executes the command with a background context and the given arguments.

func (*Command) RunAndExit

func (cmd *Command) RunAndExit(args ...string)

RunAndExit executes the command with a background context and the given arguments and exits the program with a non-zero status code if an error occurs.

func (*Command) RunContext added in v0.1.0

func (cmd *Command) RunContext(ctx context.Context, args ...string) error

RunContext executes the command with the given context and arguments.

func (*Command) RunContextAndExit added in v0.1.0

func (cmd *Command) RunContextAndExit(ctx context.Context, args ...string)

RunContextAndExit executes the command with the given context and arguments and exits the program with a non-zero status code if an error occurs.

func (*Command) SetConfig

func (cmd *Command) SetConfig(config Config)

SetConfig sets the configuration for the command. This configuration will be used when the command is executed, and it can override the configuration inherited from the parent application.

type Config

type Config struct {

	// Log is the destination for log output. By default, it is set to os.Stdout.
	Log io.Writer

	// ErrorLog is the destination for error output. By default, it is set to os.Stderr.
	ErrorLog io.Writer
	// contains filtered or unexported fields
}

Config represents the configuration for an application or command, including settings for log output and error output.

type Defaulter

type Defaulter[T Runner] interface {
	Default() T
}

Defaulter is an interface that defines a Default method, which can be used to provide default values for command arguments.

type Runner

type Runner interface {
	Run(context.Context) error
}

Runner is an interface that defines a Run method, which is used for commands that can be executed.

Jump to

Keyboard shortcuts

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