CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-apache-groovy--groovy

Apache Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at improving developer productivity thanks to a concise, familiar and easy to learn syntax.

Pending
Overview
Eval results
Files

cli-interface.mddocs/

Command-Line Interface

CLI building and option parsing utilities for creating robust command-line applications with support for various argument patterns and help text generation.

Capabilities

CliBuilder with Apache Commons CLI

Command-line interface builder using Apache Commons CLI library for robust option parsing.

/**
 * Command-line interface builder using Apache Commons CLI
 */
class CliBuilder {
    /** Create CliBuilder with default settings */
    CliBuilder()
    
    /** Create CliBuilder with usage text */
    CliBuilder(String usage)
    
    /** Parse command-line arguments */
    OptionAccessor parse(String[] args)
    
    /** Parse arguments and handle errors */
    OptionAccessor parse(String[] args, boolean stopAtNonOption)
    
    /** Print usage information */
    void usage()
    
    /** Print usage to specific writer */
    void usage(PrintWriter writer)
    
    /** Print usage to specific writer with width */
    void usage(PrintWriter writer, int width)
    
    /** Set usage text */
    void setUsage(String usage)
    
    /** Set header text */
    void setHeader(String header)
    
    /** Set footer text */
    void setFooter(String footer)
    
    /** Set whether to stop at non-option */
    void setStopAtNonOption(boolean stopAtNonOption)
    
    /** Add option with short name */
    void option(String shortOpt, String description)
    
    /** Add option with long name */
    void longOpt(String longOpt, String description)
    
    /** Add option with argument */
    void optionWithArg(String shortOpt, String longOpt, String description)
    
    /** Add option with optional argument */
    void optionWithOptionalArg(String shortOpt, String longOpt, String description)
}

/**
 * Accessor for parsed command-line options
 */
class OptionAccessor {
    /** Check if option was provided */
    boolean hasOption(String option)
    
    /** Get option value */
    Object getOptionValue(String option)
    
    /** Get option value with default */
    Object getOptionValue(String option, Object defaultValue)
    
    /** Get option values (for options that can appear multiple times) */
    String[] getOptionValues(String option)
    
    /** Get remaining arguments */
    String[] getArgs()
    
    /** Get arguments as list */
    List<String> arguments()
}

Usage Examples:

import groovy.cli.commons.*

// Basic CLI setup
def cli = new CliBuilder(usage: 'myapp [options] <files>')
cli.setHeader('My Application - File Processor')
cli.setFooter('For more information, visit: https://example.com')

// Define options
cli.h(longOpt: 'help', 'Show this help message')
cli.v(longOpt: 'verbose', 'Verbose output')
cli.q(longOpt: 'quiet', 'Quiet mode')
cli.o(longOpt: 'output', args: 1, argName: 'file', 'Output file')
cli.f(longOpt: 'format', args: 1, argName: 'format', 'Output format (xml|json|csv)')
cli.r(longOpt: 'recursive', 'Process directories recursively')
cli.n(longOpt: 'dry-run', 'Show what would be done without actually doing it')

// Parse arguments
def options = cli.parse(args)

if (!options) {
    // Parsing failed
    return
}

if (options.h) {
    cli.usage()
    return
}

// Access options
boolean verbose = options.v
boolean quiet = options.q
boolean recursive = options.r
boolean dryRun = options.n

String outputFile = options.o
String format = options.getOptionValue('f', 'json') // default to 'json'

// Get remaining arguments (files to process)
def files = options.arguments()

if (files.isEmpty()) {
    println "Error: No input files specified"
    cli.usage()
    return
}

// Process based on options
if (verbose && !quiet) {
    println "Processing ${files.size()} files"
    println "Output format: $format"
    if (outputFile) {
        println "Output file: $outputFile"
    }
    if (recursive) {
        println "Recursive processing enabled"
    }
    if (dryRun) {
        println "DRY RUN MODE - no changes will be made"
    }
}

files.each { file ->
    if (verbose && !quiet) {
        println "Processing: $file"
    }
    
    if (!dryRun) {
        // Actually process the file
        processFile(file, format, outputFile, recursive)
    }
}

Advanced Option Configuration

Configure complex option patterns with validation and type conversion.

// Advanced CLI with multiple argument types
def cli = new CliBuilder(usage: 'deploy [options] <environment>')

// String options
cli.u(longOpt: 'user', args: 1, argName: 'username', 'Username for deployment')
cli.p(longOpt: 'password', args: 1, argName: 'password', 'Password (prompt if not provided)')

// Numeric options  
cli.t(longOpt: 'timeout', args: 1, argName: 'seconds', type: Integer, 'Timeout in seconds (default: 300)')
cli.r(longOpt: 'retries', args: 1, argName: 'count', type: Integer, 'Number of retry attempts (default: 3)')

// Multiple values
cli.s(longOpt: 'service', args: Option.UNLIMITED_VALUES, argName: 'service', 'Services to deploy (can be specified multiple times)')
cli.e(longOpt: 'exclude', args: Option.UNLIMITED_VALUES, argName: 'pattern', 'Exclude patterns')

// Optional arguments
cli.c(longOpt: 'config', optionalArg: true, argName: 'file', 'Configuration file (default: config.yml)')

// Boolean flags
cli.f(longOpt: 'force', 'Force deployment even if validation fails')
cli.v(longOpt: 'verbose', 'Verbose output')
cli.q(longOpt: 'quiet', 'Quiet mode')

def options = cli.parse(args)

if (!options || options.arguments().isEmpty()) {
    println "Error: Environment must be specified"
    cli.usage()
    return
}

// Extract values with defaults and validation
String environment = options.arguments()[0]
String user = options.u
String password = options.p
Integer timeout = options.t ? options.t as Integer : 300
Integer retries = options.r ? options.r as Integer : 3
String configFile = options.c ?: 'config.yml'

// Handle multiple values
List<String> services = options.ss ?: []  // Note: multiple values accessed with repeated short option
List<String> excludePatterns = options.es ?: []

// Validation
if (!user) {
    println "Error: Username is required"
    cli.usage()
    return
}

if (timeout < 1 || timeout > 3600) {
    println "Error: Timeout must be between 1 and 3600 seconds"
    return
}

if (!password) {
    // Prompt for password
    print "Password: "
    password = System.console()?.readPassword()?.toString()
    if (!password) {
        println "Error: Password is required"
        return
    }
}

println "Deploying to environment: $environment"
println "User: $user"
println "Timeout: ${timeout}s"
println "Retries: $retries"
println "Config: $configFile"

if (services) {
    println "Services: ${services.join(', ')}"
}
if (excludePatterns) {
    println "Exclude patterns: ${excludePatterns.join(', ')}"
}

CliBuilder with Picocli

Alternative CLI builder using Picocli library for annotation-based configuration.

/**
 * Command-line interface builder using Picocli
 */
class CliBuilder {
    /** Create CliBuilder with Picocli backend */
    CliBuilder()
    
    /** Create with usage text */
    CliBuilder(String usage)
    
    /** Parse arguments */
    Object parse(String[] args)
    
    /** Parse with command object */
    <T> T parse(String[] args, Class<T> commandClass)
    
    /** Set command specification */
    void setSpec(Object spec)
    
    /** Print usage information */
    void usage()
    
    /** Print version information */
    void version()
}

Usage Examples:

import groovy.cli.picocli.*
import picocli.CommandLine.*

// Using annotations for command specification
@Command(name = 'backup', description = 'Backup utility')
class BackupCommand {
    @Option(names = ['-h', '--help'], usageHelp = true, description = 'Show help')
    boolean help
    
    @Option(names = ['-v', '--verbose'], description = 'Verbose output')
    boolean verbose
    
    @Option(names = ['-o', '--output'], paramLabel = 'DIR', description = 'Output directory')
    String outputDir = './backup'
    
    @Option(names = ['-c', '--compress'], description = 'Compress backup files')
    boolean compress
    
    @Option(names = ['-e', '--exclude'], paramLabel = 'PATTERN', description = 'Exclude patterns')
    List<String> excludePatterns = []
    
    @Parameters(paramLabel = 'SOURCE', description = 'Source directories to backup')
    List<String> sources = []
    
    @Spec CommandSpec spec  // Injected by Picocli
    
    void run() {
        if (sources.isEmpty()) {
            throw new ParameterException(spec.commandLine(), "At least one source directory must be specified")
        }
        
        if (verbose) {
            println "Backup configuration:"
            println "  Sources: ${sources.join(', ')}"
            println "  Output: $outputDir"
            println "  Compress: $compress"
            if (excludePatterns) {
                println "  Exclude: ${excludePatterns.join(', ')}"
            }
        }
        
        // Perform backup
        performBackup(sources, outputDir, compress, excludePatterns, verbose)
    }
}

// Use the command
def cli = new CliBuilder()
def command = cli.parse(args, BackupCommand)

if (command) {
    command.run()
}

Subcommands and Command Hierarchies

Create complex CLI applications with subcommands.

// Main command with subcommands
@Command(name = 'myapp', 
         description = 'Multi-purpose application',
         subcommands = [UserCommand, ProjectCommand, ConfigCommand])
class MainCommand implements Runnable {
    @Option(names = ['-h', '--help'], usageHelp = true)
    boolean help
    
    @Option(names = ['-v', '--version'], versionHelp = true)
    boolean version
    
    void run() {
        println "Use 'myapp --help' for available commands"
    }
}

// User management subcommand
@Command(name = 'user', description = 'User management commands')
class UserCommand {
    @Command(name = 'create', description = 'Create a new user')
    void create(
        @Option(names = ['-n', '--name'], required = true) String name,
        @Option(names = ['-e', '--email'], required = true) String email,
        @Option(names = ['-r', '--role']) String role = 'user'
    ) {
        println "Creating user: $name ($email) with role: $role"
        // Implementation here
    }
    
    @Command(name = 'list', description = 'List all users')
    void list(
        @Option(names = ['-f', '--format']) String format = 'table',
        @Option(names = ['-r', '--role']) String roleFilter
    ) {
        println "Listing users (format: $format)"
        if (roleFilter) {
            println "Filtering by role: $roleFilter"
        }
        // Implementation here
    }
    
    @Command(name = 'delete', description = 'Delete a user')
    void delete(@Parameters(paramLabel = 'USER_ID') String userId) {
        println "Deleting user: $userId"
        // Implementation here
    }
}

// Project management subcommand
@Command(name = 'project', description = 'Project management commands')
class ProjectCommand {
    @Command(name = 'init', description = 'Initialize a new project')
    void init(
        @Parameters(paramLabel = 'NAME') String name,
        @Option(names = ['-t', '--template']) String template,
        @Option(names = ['-d', '--directory']) String directory
    ) {
        println "Initializing project: $name"
        if (template) println "Using template: $template"
        if (directory) println "In directory: $directory"
        // Implementation here
    }
    
    @Command(name = 'build', description = 'Build the project')
    void build(
        @Option(names = ['-e', '--environment']) String env = 'development',
        @Option(names = ['-c', '--clean']) boolean clean
    ) {
        if (clean) println "Cleaning build artifacts"
        println "Building project for environment: $env"
        // Implementation here
    }
}

// Usage
def commandLine = new CommandLine(new MainCommand())
commandLine.execute(args)

Error Handling and Validation

Implement robust error handling and input validation.

import picocli.CommandLine.*

class ValidatedCommand {
    @Option(names = ['-p', '--port'], description = 'Server port (1024-65535)')
    void setPort(int port) {
        if (port < 1024 || port > 65535) {
            throw new ParameterException(
                CommandLine.this, 
                "Port must be between 1024 and 65535, got: $port"
            )
        }
        this.port = port
    }
    private int port = 8080
    
    @Option(names = ['-f', '--file'], description = 'Input file')
    void setFile(File file) {
        if (!file.exists()) {
            throw new ParameterException(
                CommandLine.this,
                "File does not exist: ${file.absolutePath}"
            )
        }
        if (!file.canRead()) {
            throw new ParameterException(
                CommandLine.this,
                "Cannot read file: ${file.absolutePath}"
            )
        }
        this.file = file
    }
    private File file
    
    @Option(names = ['-e', '--email'], description = 'Email address')
    void setEmail(String email) {
        if (!email.matches(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) {
            throw new ParameterException(
                CommandLine.this,
                "Invalid email format: $email"
            )
        }
        this.email = email
    }
    private String email
    
    void run() {
        println "Port: $port"
        println "File: ${file?.absolutePath}"
        println "Email: $email"
    }
}

// Custom exception handler
class CustomExceptionHandler implements IExceptionHandler2<List<Object>> {
    List<Object> handleParseException(ParameterException ex, String[] args) {
        System.err.println("Error: ${ex.message}")
        ex.commandLine.usage(System.err)
        return [1] // exit code
    }
    
    List<Object> handleExecutionException(ExecutionException ex, ParseResult parseResult) {
        System.err.println("Execution failed: ${ex.cause?.message}")
        return [2] // exit code
    }
}

// Use with error handling
def commandLine = new CommandLine(new ValidatedCommand())
commandLine.setExceptionHandler(new CustomExceptionHandler())
int exitCode = commandLine.execute(args)
System.exit(exitCode)

Install with Tessl CLI

npx tessl i tessl/maven-org-apache-groovy--groovy

docs

cli-interface.md

collections-utilities.md

core-runtime.md

index.md

json-processing.md

meta-programming.md

script-execution.md

sql-database.md

template-processing.md

xml-processing.md

tile.json