CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-github-ajalt--clikt-jvm

Multiplatform command line interface parsing for Kotlin

Pending
Overview
Eval results
Files

arguments.mddocs/

Arguments

Positional argument parsing with type conversion and validation. Arguments are processed in order and support optional, multiple, and paired value patterns.

Capabilities

Argument Declaration

Create positional arguments using the argument() function with support for help text and completion.

/**
 * Create a positional argument
 * @param name Argument name for help display
 * @param help Help text for the argument
 * @param helpTags Extra help formatter information
 * @param completionCandidates Completion candidates
 */
fun CliktCommand.argument(
    name: String = "",
    help: String = "",
    helpTags: Map<String, String> = emptyMap(),
    completionCandidates: CompletionCandidates? = null
): RawArgument

Usage Examples:

class MyCommand : CliktCommand() {
    // Basic argument
    private val filename by argument(name = "FILE", help = "Input file to process")
    
    // Argument with completion
    private val hostname by argument(
        name = "HOST",
        help = "Target hostname",
        completionCandidates = CompletionCandidates.Hostname
    )
}

Type Conversion

Convert argument values to specific types with built-in converters.

/**
 * Convert argument value using custom conversion function
 */
fun <T : Any> RawArgument.convert(
    conversion: ArgValueConverter<String, T>
): ProcessedArgument<T, T>

/** Convert to Int */
fun RawArgument.int(): ProcessedArgument<Int, Int>

/** Convert to Long */
fun RawArgument.long(): ProcessedArgument<Long, Long>

/** Convert to Float */
fun RawArgument.float(): ProcessedArgument<Float, Float>

/** Convert to Double */
fun RawArgument.double(): ProcessedArgument<Double, Double>

/** Convert to Boolean */
fun RawArgument.boolean(): ProcessedArgument<Boolean, Boolean>

/** Convert to Enum */
fun <T : Enum<T>> RawArgument.enum(): ProcessedArgument<T, T>

/** Convert using choice map */
fun <T : Any> RawArgument.choice(choices: Map<String, T>): ProcessedArgument<T, T>

/** Convert using string choices */
fun RawArgument.choice(vararg choices: String): ProcessedArgument<String, String>

Usage Examples:

class MyCommand : CliktCommand() {
    // Numeric arguments
    private val port by argument(name = "PORT", help = "Port number").int()
    private val ratio by argument(name = "RATIO", help = "Ratio value").double()
    
    // Enum argument
    enum class Operation { ADD, SUBTRACT, MULTIPLY, DIVIDE }
    private val operation by argument(name = "OP", help = "Operation to perform").enum<Operation>()
    
    // Choice argument
    private val format by argument(name = "FORMAT", help = "Output format")
        .choice("json", "xml", "yaml")
    
    // Custom conversion
    private val date by argument(name = "DATE", help = "Date in ISO format")
        .convert { LocalDate.parse(it) }
    
    override fun run() {
        echo("Port: $port")
        echo("Operation: $operation")
        echo("Format: $format")
        echo("Date: $date")
    }
}

Value Processing

Process argument values with optional, multiple, and paired value patterns.

/** Make argument optional */
fun <T : Any> ProcessedArgument<T, T>.optional(): ProcessedArgument<T?, T>

/** Accept multiple values */
fun <T : Any> ProcessedArgument<T, T>.multiple(): ProcessedArgument<List<T>, T>

/** Convert multiple values to Set */
fun <T : Any> ProcessedArgument<List<T>, T>.unique(): ProcessedArgument<Set<T>, T>

/** Accept exactly 2 values */
fun <T : Any> ProcessedArgument<T, T>.pair(): ProcessedArgument<Pair<T, T>, T>

/** Accept exactly 3 values */
fun <T : Any> ProcessedArgument<T, T>.triple(): ProcessedArgument<Triple<T, T, T>, T>

/** Provide default value */
fun <T : Any> ProcessedArgument<T, T>.default(value: T): ArgumentDelegate<T>

/** Provide lazy default value */
fun <T : Any> ProcessedArgument<T, T>.defaultLazy(value: () -> T): ArgumentDelegate<T>

Usage Examples:

class MyCommand : CliktCommand() {
    // Optional argument
    private val inputFile by argument(name = "INPUT", help = "Input file").optional()
    
    // Multiple arguments
    private val files by argument(name = "FILES", help = "Files to process").multiple()
    private val uniqueNames by argument(name = "NAMES", help = "Unique names").multiple().unique()
    
    // Paired arguments
    private val coordinates by argument(name = "X Y", help = "X Y coordinates").int().pair()
    
    // Triple arguments
    private val rgb by argument(name = "R G B", help = "RGB color values").int().triple()
    
    // Default value
    private val outputFile by argument(name = "OUTPUT", help = "Output file")
        .default("output.txt")
    
    override fun run() {
        echo("Input file: $inputFile")
        echo("Files: $files")
        echo("Coordinates: $coordinates")
        echo("RGB: $rgb")
        echo("Output file: $outputFile")
    }
}

Validation

Validate argument values with custom validators and built-in checks.

/**
 * Validate argument value
 * @param validator Custom validation function
 */
fun <AllT, ValueT> ProcessedArgument<AllT, ValueT>.validate(
    validator: ArgValidator<AllT>
): ArgumentDelegate<AllT>

/**
 * Check argument value with boolean condition
 * @param message Error message if check fails
 * @param validator Boolean check function
 */
fun <AllT, ValueT> ProcessedArgument<AllT, ValueT>.check(
    message: String,
    validator: (AllT) -> Boolean
): ArgumentDelegate<AllT>

Usage Examples:

class MyCommand : CliktCommand() {
    // Custom validation
    private val port by argument(name = "PORT", help = "Port number").int().validate {
        require(it in 1..65535) { "Port must be between 1 and 65535" }
    }
    
    // Boolean check
    private val percentage by argument(name = "PERCENT", help = "Percentage value")
        .int().check("Must be 0-100") { it in 0..100 }
    
    // Validate multiple values
    private val files by argument(name = "FILES", help = "Input files").multiple()
        .validate { fileList ->
            require(fileList.isNotEmpty()) { "At least one file must be specified" }
        }
    
    override fun run() {
        echo("Port: $port")
        echo("Percentage: $percentage")
        echo("Files: $files")
    }
}

Help Text

Add or modify help text for arguments.

/**
 * Add help text to processed argument
 * @param help Help text for the argument
 */
fun <AllT, ValueT> ProcessedArgument<AllT, ValueT>.help(help: String): ProcessedArgument<AllT, ValueT>

Usage Examples:

class MyCommand : CliktCommand() {
    private val count by argument()
        .int()
        .help("Number of items to process (must be positive)")
        .check("Must be positive") { it > 0 }
    
    private val files by argument()
        .multiple()
        .help("List of files to process (at least one required)")
        .validate { require(it.isNotEmpty()) { "At least one file required" } }
}

Argument Value Patterns

Single Required Argument

class MyCommand : CliktCommand() {
    private val filename by argument(name = "FILE", help = "Input file")
    
    override fun run() {
        echo("Processing file: $filename")
    }
}

Optional Argument

class MyCommand : CliktCommand() {
    private val outputFile by argument(name = "OUTPUT", help = "Output file").optional()
    
    override fun run() {
        val output = outputFile ?: "default.txt"
        echo("Output file: $output")
    }
}

Multiple Arguments

class MyCommand : CliktCommand() {
    private val inputFiles by argument(name = "FILES", help = "Input files").multiple()
    
    override fun run() {
        if (inputFiles.isEmpty()) {
            echo("No files specified")
        } else {
            echo("Processing ${inputFiles.size} files:")
            inputFiles.forEach { echo("  - $it") }
        }
    }
}

Mixed Argument Types

class MyCommand : CliktCommand() {
    private val operation by argument(name = "OPERATION", help = "Operation to perform")
        .choice("copy", "move", "delete")
    private val source by argument(name = "SOURCE", help = "Source file")
    private val destination by argument(name = "DEST", help = "Destination file").optional()
    
    override fun run() {
        when (operation) {
            "copy", "move" -> {
                requireNotNull(destination) { "Destination required for $operation" }
                echo("$operation $source to $destination")
            }
            "delete" -> {
                echo("Deleting $source")
            }
        }
    }
}

Argument Interfaces

/**
 * Base argument interface
 */
interface Argument {
    /** The metavar for this argument */
    val name: String
    
    /** The number of values that this argument takes (negative indicates variable number) */
    val nvalues: Int
    
    /** If true, an error will be thrown if this argument is not given */
    val required: Boolean
    
    /** The description of this argument */
    fun getArgumentHelp(context: Context): String
    
    /** Extra information about this argument to pass to the help formatter */
    val helpTags: Map<String, String>
    
    /** Optional set of strings to use when the user invokes shell autocomplete */
    val completionCandidates: CompletionCandidates
    
    /** Information about this argument for the help output */
    fun parameterHelp(context: Context): ParameterHelp.Argument?
    
    /** Called after this command's argv is parsed to transform and store the argument's value */
    fun finalize(context: Context, values: List<String>)
    
    /** Called after all parameters have been finalized to perform validation */
    fun postValidate(context: Context)
}

/**
 * Argument property delegate interface
 */
interface ArgumentDelegate<out T> : Argument, ReadOnlyProperty<CliktCommand, T>, PropertyDelegateProvider<CliktCommand, ReadOnlyProperty<CliktCommand, T>> {
    /** The value for this argument */
    val value: T
    
    override fun getValue(thisRef: CliktCommand, property: KProperty<*>): T = value
}

/**
 * Raw unprocessed argument
 */
interface RawArgument : Argument

/**
 * Argument with processed values
 */
interface ProcessedArgument<out AllT, out ValueT> : Argument

Type Aliases

typealias ArgValueConverter<InT, ValueT> = ArgumentTransformContext.(InT) -> ValueT
typealias ArgValueTransformer<T> = ArgValueConverter<String, T>
typealias ArgValidator<T> = ArgumentTransformContext.(T) -> Unit

Install with Tessl CLI

npx tessl i tessl/maven-com-github-ajalt--clikt-jvm

docs

arguments.md

configuration-sources.md

core-commands.md

exceptions.md

index.md

options.md

parameter-groups.md

parameter-types.md

shell-completion.md

testing-utilities.md

tile.json