Make a positional argument optional
Positional arguments are required by default, and their order is the order you declare them. To let one be omitted, mark it .optional().
Use .optional()
import org.draftcode.argot.Arguments
class CopyArgs : Arguments(programName = "copy", description = "Copy a file.") {
val source: String by argument(help = "File to copy")
val destination: String? by argument(help = "Where to put it").optional()
}.optional() makes the property nullable, which is the whole point: the type tells you the value might not be there, so you cannot forget to handle it.
fun destinationOf(args: CopyArgs): String = args.destination ?: "${args.source}.bak"$ copy notes.txt # destination == null
$ copy notes.txt backup.txt # destination == "backup.txt"The help screen shows the difference with brackets:
$ copy --help
Usage: copy <source> [<destination>]
Arguments:
<source> File to copy
<destination> Where to put itOptional ones come last
An optional positional must follow the required ones. copy [<destination>] <source> has no unambiguous reading — given one argument, the parser cannot know which slot it fills — so Argot rejects that arrangement rather than guessing. The name comes from the property, so reordering the declarations reorders the command line.
Capturing the rest
For "one target and then any number of inputs", use .multiple() on the last positional:
class ArchiveArgs : Arguments(programName = "archive", description = "Archive files.") {
val output: String by argument(help = "Archive to create")
val inputs: List<String> by argument(help = "Files to include").multiple().required()
}$ archive out.zip a.txt b.txt c.txt
# output == "out.zip", inputs == ["a.txt", "b.txt", "c.txt"].multiple() alone accepts zero inputs and gives an empty list; adding .required() demands at least one. There can be at most one such trailing positional, and it must be declared last — otherwise everything after it would be unreachable.
In the annotation style
Nullability and List do the same work, so there is nothing extra to write:
@Command(name = "copy", description = "Copy a file.")
data class CopyArgs(
@Argument(help = "File to copy") val source: String,
@Argument(help = "Where to put it") val destination: String?,
)See also
ArgumentBuilderandOptionalArgumentBuilder.- How optionality is inferred for why the property type is the source of truth.