Initial commit
This commit is contained in:
52
skills/cli-patterns/templates/basic-cli.go
Normal file
52
skills/cli-patterns/templates/basic-cli.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := &cli.App{
|
||||
Name: "myapp",
|
||||
Usage: "A simple CLI application",
|
||||
Version: "0.1.0",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "Enable verbose output",
|
||||
EnvVars: []string{"VERBOSE"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Path to config file",
|
||||
EnvVars: []string{"CONFIG_PATH"},
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
verbose := c.Bool("verbose")
|
||||
config := c.String("config")
|
||||
|
||||
if verbose {
|
||||
fmt.Println("Verbose mode enabled")
|
||||
}
|
||||
|
||||
if config != "" {
|
||||
fmt.Printf("Using config: %s\n", config)
|
||||
}
|
||||
|
||||
// Your application logic here
|
||||
fmt.Println("Hello, World!")
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
141
skills/cli-patterns/templates/categories-cli.go
Normal file
141
skills/cli-patterns/templates/categories-cli.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := &cli.App{
|
||||
Name: "myapp",
|
||||
Usage: "CLI tool with categorized commands",
|
||||
Commands: []*cli.Command{
|
||||
// Database category
|
||||
{
|
||||
Name: "create-db",
|
||||
Category: "Database",
|
||||
Usage: "Create a new database",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Creating database...")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "migrate",
|
||||
Category: "Database",
|
||||
Usage: "Run database migrations",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Running migrations...")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "seed",
|
||||
Category: "Database",
|
||||
Usage: "Seed database with test data",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Seeding database...")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
|
||||
// Deploy category
|
||||
{
|
||||
Name: "deploy",
|
||||
Category: "Deploy",
|
||||
Usage: "Deploy application",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "env",
|
||||
Aliases: []string{"e"},
|
||||
Usage: "Target environment",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
env := c.String("env")
|
||||
fmt.Printf("Deploying to %s...\n", env)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "rollback",
|
||||
Category: "Deploy",
|
||||
Usage: "Rollback deployment",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Rolling back...")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
|
||||
// Monitor category
|
||||
{
|
||||
Name: "logs",
|
||||
Category: "Monitor",
|
||||
Usage: "View application logs",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "follow",
|
||||
Aliases: []string{"f"},
|
||||
Usage: "Follow log output",
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
follow := c.Bool("follow")
|
||||
fmt.Println("Fetching logs...")
|
||||
if follow {
|
||||
fmt.Println("Following logs (Ctrl+C to stop)...")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "status",
|
||||
Category: "Monitor",
|
||||
Usage: "Check application status",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Status: Running")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "metrics",
|
||||
Category: "Monitor",
|
||||
Usage: "View application metrics",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Fetching metrics...")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
|
||||
// Config category
|
||||
{
|
||||
Name: "show-config",
|
||||
Category: "Config",
|
||||
Usage: "Show current configuration",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Current configuration:")
|
||||
fmt.Println(" env: production")
|
||||
fmt.Println(" port: 8080")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "set-config",
|
||||
Category: "Config",
|
||||
Usage: "Set configuration value",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Setting configuration...")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
52
skills/cli-patterns/templates/click-basic.py
Normal file
52
skills/cli-patterns/templates/click-basic.py
Normal file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
# Python equivalent using click (similar API to urfave/cli)
|
||||
|
||||
import click
|
||||
|
||||
@click.group()
|
||||
@click.version_option('0.1.0')
|
||||
@click.option('--verbose', '-v', is_flag=True, help='Enable verbose output')
|
||||
@click.option('--config', '-c', envvar='CONFIG_PATH', help='Path to config file')
|
||||
@click.pass_context
|
||||
def cli(ctx, verbose, config):
|
||||
"""A simple CLI application"""
|
||||
ctx.ensure_object(dict)
|
||||
ctx.obj['verbose'] = verbose
|
||||
ctx.obj['config'] = config
|
||||
|
||||
if verbose:
|
||||
click.echo('Verbose mode enabled')
|
||||
|
||||
if config:
|
||||
click.echo(f'Using config: {config}')
|
||||
|
||||
@cli.command()
|
||||
@click.option('--port', '-p', default=8080, help='Port to listen on')
|
||||
@click.pass_context
|
||||
def start(ctx, port):
|
||||
"""Start the service"""
|
||||
if ctx.obj['verbose']:
|
||||
click.echo(f'Starting service on port {port}')
|
||||
else:
|
||||
click.echo(f'Starting on port {port}')
|
||||
|
||||
@cli.command()
|
||||
@click.pass_context
|
||||
def stop(ctx):
|
||||
"""Stop the service"""
|
||||
click.echo('Stopping service...')
|
||||
|
||||
@cli.command()
|
||||
def status():
|
||||
"""Check service status"""
|
||||
click.echo('Service is running')
|
||||
|
||||
@cli.command()
|
||||
@click.argument('key')
|
||||
@click.argument('value')
|
||||
def config(key, value):
|
||||
"""Set configuration value"""
|
||||
click.echo(f'Setting {key} = {value}')
|
||||
|
||||
if __name__ == '__main__':
|
||||
cli(obj={})
|
||||
51
skills/cli-patterns/templates/commander-basic.ts
Normal file
51
skills/cli-patterns/templates/commander-basic.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env node
|
||||
// TypeScript equivalent using commander.js (similar API to urfave/cli)
|
||||
|
||||
import { Command } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name('myapp')
|
||||
.description('A simple CLI application')
|
||||
.version('0.1.0');
|
||||
|
||||
program
|
||||
.option('-v, --verbose', 'Enable verbose output')
|
||||
.option('-c, --config <path>', 'Path to config file', process.env.CONFIG_PATH)
|
||||
.action((options) => {
|
||||
if (options.verbose) {
|
||||
console.log('Verbose mode enabled');
|
||||
}
|
||||
|
||||
if (options.config) {
|
||||
console.log(`Using config: ${options.config}`);
|
||||
}
|
||||
|
||||
console.log('Hello, World!');
|
||||
});
|
||||
|
||||
// Subcommands
|
||||
program
|
||||
.command('start')
|
||||
.description('Start the service')
|
||||
.option('-p, --port <number>', 'Port to listen on', '8080')
|
||||
.action((options) => {
|
||||
console.log(`Starting service on port ${options.port}`);
|
||||
});
|
||||
|
||||
program
|
||||
.command('stop')
|
||||
.description('Stop the service')
|
||||
.action(() => {
|
||||
console.log('Stopping service...');
|
||||
});
|
||||
|
||||
program
|
||||
.command('status')
|
||||
.description('Check service status')
|
||||
.action(() => {
|
||||
console.log('Service is running');
|
||||
});
|
||||
|
||||
program.parse();
|
||||
152
skills/cli-patterns/templates/context-cli.go
Normal file
152
skills/cli-patterns/templates/context-cli.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// AppContext holds shared state across commands
|
||||
type AppContext struct {
|
||||
Config *Config
|
||||
DB *sql.DB
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
// Config represents application configuration
|
||||
type Config struct {
|
||||
Host string
|
||||
Port int
|
||||
Database string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := &cli.App{
|
||||
Name: "context-demo",
|
||||
Usage: "Demonstration of context and state management",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "Enable verbose output",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Path to config file",
|
||||
Value: "config.yaml",
|
||||
},
|
||||
},
|
||||
|
||||
// Initialize shared context
|
||||
Before: func(c *cli.Context) error {
|
||||
verbose := c.Bool("verbose")
|
||||
configPath := c.String("config")
|
||||
|
||||
if verbose {
|
||||
fmt.Printf("Loading config from: %s\n", configPath)
|
||||
}
|
||||
|
||||
// Create application context
|
||||
appCtx := &AppContext{
|
||||
Config: &Config{
|
||||
Host: "localhost",
|
||||
Port: 5432,
|
||||
Database: "mydb",
|
||||
},
|
||||
Verbose: verbose,
|
||||
}
|
||||
|
||||
// Simulate database connection
|
||||
// In real app: appCtx.DB, err = sql.Open("postgres", connStr)
|
||||
if verbose {
|
||||
fmt.Println("Connected to database")
|
||||
}
|
||||
|
||||
// Store context in app metadata
|
||||
c.App.Metadata["ctx"] = appCtx
|
||||
|
||||
return nil
|
||||
},
|
||||
|
||||
// Cleanup shared resources
|
||||
After: func(c *cli.Context) error {
|
||||
if ctx, ok := c.App.Metadata["ctx"].(*AppContext); ok {
|
||||
if ctx.DB != nil {
|
||||
// ctx.DB.Close()
|
||||
if ctx.Verbose {
|
||||
fmt.Println("Database connection closed")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "query",
|
||||
Usage: "Execute a database query",
|
||||
Action: func(c *cli.Context) error {
|
||||
// Retrieve context
|
||||
ctx := c.App.Metadata["ctx"].(*AppContext)
|
||||
|
||||
if ctx.Verbose {
|
||||
fmt.Printf("Connecting to %s:%d/%s\n",
|
||||
ctx.Config.Host,
|
||||
ctx.Config.Port,
|
||||
ctx.Config.Database)
|
||||
}
|
||||
|
||||
fmt.Println("Executing query...")
|
||||
// Use ctx.DB for actual query
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Name: "migrate",
|
||||
Usage: "Run database migrations",
|
||||
Action: func(c *cli.Context) error {
|
||||
// Retrieve context
|
||||
ctx := c.App.Metadata["ctx"].(*AppContext)
|
||||
|
||||
if ctx.Verbose {
|
||||
fmt.Println("Running migrations with context...")
|
||||
}
|
||||
|
||||
fmt.Printf("Migrating database: %s\n", ctx.Config.Database)
|
||||
// Use ctx.DB for migrations
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Name: "status",
|
||||
Usage: "Check database status",
|
||||
Action: func(c *cli.Context) error {
|
||||
// Retrieve context
|
||||
ctx := c.App.Metadata["ctx"].(*AppContext)
|
||||
|
||||
fmt.Printf("Database: %s\n", ctx.Config.Database)
|
||||
fmt.Printf("Host: %s:%d\n", ctx.Config.Host, ctx.Config.Port)
|
||||
fmt.Println("Status: Connected")
|
||||
|
||||
if ctx.Verbose {
|
||||
fmt.Println("Verbose mode: enabled")
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
172
skills/cli-patterns/templates/flags-demo.go
Normal file
172
skills/cli-patterns/templates/flags-demo.go
Normal file
@@ -0,0 +1,172 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := &cli.App{
|
||||
Name: "flags-demo",
|
||||
Usage: "Demonstration of all flag types in urfave/cli",
|
||||
Flags: []cli.Flag{
|
||||
// String flag
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Aliases: []string{"n"},
|
||||
Value: "World",
|
||||
Usage: "Name to greet",
|
||||
EnvVars: []string{"GREETING_NAME"},
|
||||
},
|
||||
|
||||
// Int flag
|
||||
&cli.IntFlag{
|
||||
Name: "count",
|
||||
Aliases: []string{"c"},
|
||||
Value: 1,
|
||||
Usage: "Number of times to repeat",
|
||||
EnvVars: []string{"REPEAT_COUNT"},
|
||||
},
|
||||
|
||||
// Bool flag
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "Enable verbose output",
|
||||
EnvVars: []string{"VERBOSE"},
|
||||
},
|
||||
|
||||
// Int64 flag
|
||||
&cli.Int64Flag{
|
||||
Name: "size",
|
||||
Value: 1024,
|
||||
Usage: "Size in bytes",
|
||||
},
|
||||
|
||||
// Uint flag
|
||||
&cli.UintFlag{
|
||||
Name: "port",
|
||||
Value: 8080,
|
||||
Usage: "Port number",
|
||||
},
|
||||
|
||||
// Float64 flag
|
||||
&cli.Float64Flag{
|
||||
Name: "timeout",
|
||||
Value: 30.0,
|
||||
Usage: "Timeout in seconds",
|
||||
},
|
||||
|
||||
// Duration flag
|
||||
&cli.DurationFlag{
|
||||
Name: "wait",
|
||||
Value: 10 * time.Second,
|
||||
Usage: "Wait duration",
|
||||
},
|
||||
|
||||
// StringSlice flag (multiple values)
|
||||
&cli.StringSliceFlag{
|
||||
Name: "tag",
|
||||
Aliases: []string{"t"},
|
||||
Usage: "Tags (can be specified multiple times)",
|
||||
},
|
||||
|
||||
// IntSlice flag (multiple int values)
|
||||
&cli.IntSliceFlag{
|
||||
Name: "priority",
|
||||
Usage: "Priority values",
|
||||
},
|
||||
|
||||
// Required flag
|
||||
&cli.StringFlag{
|
||||
Name: "token",
|
||||
Usage: "API token (required)",
|
||||
Required: true,
|
||||
EnvVars: []string{"API_TOKEN"},
|
||||
},
|
||||
|
||||
// Flag with default from env
|
||||
&cli.StringFlag{
|
||||
Name: "env",
|
||||
Aliases: []string{"e"},
|
||||
Value: "development",
|
||||
Usage: "Environment name",
|
||||
EnvVars: []string{"ENV", "ENVIRONMENT"},
|
||||
},
|
||||
|
||||
// Hidden flag (not shown in help)
|
||||
&cli.StringFlag{
|
||||
Name: "secret",
|
||||
Usage: "Secret value",
|
||||
Hidden: true,
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
// String flag
|
||||
name := c.String("name")
|
||||
fmt.Printf("Name: %s\n", name)
|
||||
|
||||
// Int flag
|
||||
count := c.Int("count")
|
||||
fmt.Printf("Count: %d\n", count)
|
||||
|
||||
// Bool flag
|
||||
verbose := c.Bool("verbose")
|
||||
if verbose {
|
||||
fmt.Println("Verbose mode: enabled")
|
||||
}
|
||||
|
||||
// Int64 flag
|
||||
size := c.Int64("size")
|
||||
fmt.Printf("Size: %d bytes\n", size)
|
||||
|
||||
// Uint flag
|
||||
port := c.Uint("port")
|
||||
fmt.Printf("Port: %d\n", port)
|
||||
|
||||
// Float64 flag
|
||||
timeout := c.Float64("timeout")
|
||||
fmt.Printf("Timeout: %.2f seconds\n", timeout)
|
||||
|
||||
// Duration flag
|
||||
wait := c.Duration("wait")
|
||||
fmt.Printf("Wait: %s\n", wait)
|
||||
|
||||
// StringSlice flag
|
||||
tags := c.StringSlice("tag")
|
||||
if len(tags) > 0 {
|
||||
fmt.Printf("Tags: %v\n", tags)
|
||||
}
|
||||
|
||||
// IntSlice flag
|
||||
priorities := c.IntSlice("priority")
|
||||
if len(priorities) > 0 {
|
||||
fmt.Printf("Priorities: %v\n", priorities)
|
||||
}
|
||||
|
||||
// Required flag
|
||||
token := c.String("token")
|
||||
fmt.Printf("Token: %s\n", token)
|
||||
|
||||
// Environment flag
|
||||
env := c.String("env")
|
||||
fmt.Printf("Environment: %s\n", env)
|
||||
|
||||
// Greeting logic
|
||||
fmt.Println("\n---")
|
||||
for i := 0; i < count; i++ {
|
||||
fmt.Printf("Hello, %s!\n", name)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
94
skills/cli-patterns/templates/hooks-cli.go
Normal file
94
skills/cli-patterns/templates/hooks-cli.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := &cli.App{
|
||||
Name: "hooks-demo",
|
||||
Usage: "Demonstration of Before/After hooks",
|
||||
|
||||
// Global Before hook - runs before any command
|
||||
Before: func(c *cli.Context) error {
|
||||
fmt.Println("🚀 [GLOBAL BEFORE] Initializing application...")
|
||||
fmt.Println(" - Loading configuration")
|
||||
fmt.Println(" - Setting up connections")
|
||||
return nil
|
||||
},
|
||||
|
||||
// Global After hook - runs after any command
|
||||
After: func(c *cli.Context) error {
|
||||
fmt.Println("✅ [GLOBAL AFTER] Cleaning up...")
|
||||
fmt.Println(" - Closing connections")
|
||||
fmt.Println(" - Saving state")
|
||||
return nil
|
||||
},
|
||||
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "process",
|
||||
Usage: "Process data with hooks",
|
||||
|
||||
// Command-specific Before hook
|
||||
Before: func(c *cli.Context) error {
|
||||
fmt.Println(" [COMMAND BEFORE] Preparing to process...")
|
||||
fmt.Println(" - Validating input")
|
||||
return nil
|
||||
},
|
||||
|
||||
// Command action
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println(" [ACTION] Processing data...")
|
||||
return nil
|
||||
},
|
||||
|
||||
// Command-specific After hook
|
||||
After: func(c *cli.Context) error {
|
||||
fmt.Println(" [COMMAND AFTER] Processing complete!")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Name: "validate",
|
||||
Usage: "Validate configuration",
|
||||
|
||||
Before: func(c *cli.Context) error {
|
||||
fmt.Println(" [COMMAND BEFORE] Starting validation...")
|
||||
return nil
|
||||
},
|
||||
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println(" [ACTION] Validating...")
|
||||
return nil
|
||||
},
|
||||
|
||||
After: func(c *cli.Context) error {
|
||||
fmt.Println(" [COMMAND AFTER] Validation complete!")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Example output when running "hooks-demo process":
|
||||
// 🚀 [GLOBAL BEFORE] Initializing application...
|
||||
// - Loading configuration
|
||||
// - Setting up connections
|
||||
// [COMMAND BEFORE] Preparing to process...
|
||||
// - Validating input
|
||||
// [ACTION] Processing data...
|
||||
// [COMMAND AFTER] Processing complete!
|
||||
// ✅ [GLOBAL AFTER] Cleaning up...
|
||||
// - Closing connections
|
||||
// - Saving state
|
||||
116
skills/cli-patterns/templates/subcommands-cli.go
Normal file
116
skills/cli-patterns/templates/subcommands-cli.go
Normal file
@@ -0,0 +1,116 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := &cli.App{
|
||||
Name: "myapp",
|
||||
Usage: "A CLI tool with subcommands",
|
||||
Version: "0.1.0",
|
||||
Commands: []*cli.Command{
|
||||
{
|
||||
Name: "start",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "Start the service",
|
||||
Flags: []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "port",
|
||||
Aliases: []string{"p"},
|
||||
Value: 8080,
|
||||
Usage: "Port to listen on",
|
||||
EnvVars: []string{"PORT"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "host",
|
||||
Value: "localhost",
|
||||
Usage: "Host to bind to",
|
||||
EnvVars: []string{"HOST"},
|
||||
},
|
||||
},
|
||||
Action: func(c *cli.Context) error {
|
||||
port := c.Int("port")
|
||||
host := c.String("host")
|
||||
fmt.Printf("Starting service on %s:%d\n", host, port)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "stop",
|
||||
Usage: "Stop the service",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Stopping service...")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "restart",
|
||||
Usage: "Restart the service",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Restarting service...")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "status",
|
||||
Usage: "Check service status",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Service is running")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "config",
|
||||
Usage: "Configuration management",
|
||||
Subcommands: []*cli.Command{
|
||||
{
|
||||
Name: "show",
|
||||
Usage: "Show current configuration",
|
||||
Action: func(c *cli.Context) error {
|
||||
fmt.Println("Current configuration:")
|
||||
fmt.Println(" port: 8080")
|
||||
fmt.Println(" host: localhost")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "set",
|
||||
Usage: "Set configuration value",
|
||||
ArgsUsage: "<key> <value>",
|
||||
Action: func(c *cli.Context) error {
|
||||
if c.NArg() < 2 {
|
||||
return fmt.Errorf("usage: config set <key> <value>")
|
||||
}
|
||||
key := c.Args().Get(0)
|
||||
value := c.Args().Get(1)
|
||||
fmt.Printf("Setting %s = %s\n", key, value)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "get",
|
||||
Usage: "Get configuration value",
|
||||
ArgsUsage: "<key>",
|
||||
Action: func(c *cli.Context) error {
|
||||
if c.NArg() < 1 {
|
||||
return fmt.Errorf("usage: config get <key>")
|
||||
}
|
||||
key := c.Args().Get(0)
|
||||
fmt.Printf("%s = <value>\n", key)
|
||||
return nil
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
58
skills/cli-patterns/templates/typer-basic.py
Normal file
58
skills/cli-patterns/templates/typer-basic.py
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
# Modern Python CLI using typer (FastAPI style)
|
||||
|
||||
import typer
|
||||
from typing import Optional
|
||||
from enum import Enum
|
||||
|
||||
app = typer.Typer()
|
||||
|
||||
class Environment(str, Enum):
|
||||
development = "development"
|
||||
staging = "staging"
|
||||
production = "production"
|
||||
|
||||
@app.callback()
|
||||
def main(
|
||||
verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose output"),
|
||||
config: Optional[str] = typer.Option(None, "--config", "-c", envvar="CONFIG_PATH", help="Path to config file")
|
||||
):
|
||||
"""
|
||||
A simple CLI application built with Typer
|
||||
"""
|
||||
if verbose:
|
||||
typer.echo("Verbose mode enabled")
|
||||
|
||||
if config:
|
||||
typer.echo(f"Using config: {config}")
|
||||
|
||||
@app.command()
|
||||
def start(
|
||||
port: int = typer.Option(8080, "--port", "-p", help="Port to listen on"),
|
||||
host: str = typer.Option("localhost", help="Host to bind to"),
|
||||
):
|
||||
"""Start the service"""
|
||||
typer.echo(f"Starting service on {host}:{port}")
|
||||
|
||||
@app.command()
|
||||
def stop():
|
||||
"""Stop the service"""
|
||||
typer.echo("Stopping service...")
|
||||
|
||||
@app.command()
|
||||
def status():
|
||||
"""Check service status"""
|
||||
typer.echo("Service is running")
|
||||
|
||||
@app.command()
|
||||
def deploy(
|
||||
env: Environment = typer.Option(..., "--env", "-e", help="Target environment"),
|
||||
force: bool = typer.Option(False, "--force", help="Force deployment")
|
||||
):
|
||||
"""Deploy to environment"""
|
||||
typer.echo(f"Deploying to {env.value}...")
|
||||
if force:
|
||||
typer.echo("Force flag enabled")
|
||||
|
||||
if __name__ == "__main__":
|
||||
app()
|
||||
Reference in New Issue
Block a user