vlib: cli module
parent
8c7f5d5cd8
commit
597a6fead2
|
@ -1,3 +1,4 @@
|
||||||
|
/cli
|
||||||
/hello_world
|
/hello_world
|
||||||
/json
|
/json
|
||||||
/links_scraper
|
/links_scraper
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
module main
|
||||||
|
|
||||||
|
import (
|
||||||
|
cli
|
||||||
|
os
|
||||||
|
)
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mut cmd := cli.Command{
|
||||||
|
name: 'cli',
|
||||||
|
description: 'An example of the cli library',
|
||||||
|
version: '1.0.0',
|
||||||
|
}
|
||||||
|
|
||||||
|
mut greet_cmd := cli.Command{
|
||||||
|
name: 'greet',
|
||||||
|
description: 'Prints greeting in different languages',
|
||||||
|
execute: greet_func,
|
||||||
|
}
|
||||||
|
greet_cmd.add_flag(cli.Flag{
|
||||||
|
flag: .string,
|
||||||
|
required: true,
|
||||||
|
name: 'language',
|
||||||
|
abbrev: 'l',
|
||||||
|
description: 'Language of the message'
|
||||||
|
})
|
||||||
|
greet_cmd.add_flag(cli.Flag{
|
||||||
|
flag: .int,
|
||||||
|
name: 'times',
|
||||||
|
value: '3',
|
||||||
|
description: 'Number of times the message gets printed'
|
||||||
|
})
|
||||||
|
|
||||||
|
cmd.add_command(greet_cmd)
|
||||||
|
cmd.parse(os.args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn greet_func(cmd cli.Command) {
|
||||||
|
language := cmd.flags.get_string('language') or { panic('failed to get \'language\' flag: $err') }
|
||||||
|
times := cmd.flags.get_int('times') or { panic('failed to get \'times\' flag: $err') }
|
||||||
|
|
||||||
|
for i := 0; i < times; i++ {
|
||||||
|
match language {
|
||||||
|
'english' { println('Hello World') }
|
||||||
|
'german' { println('Hallo Welt') }
|
||||||
|
'dutch' { println('Hallo Wereld') }
|
||||||
|
else { println('unsupported language') }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
module cli
|
||||||
|
|
||||||
|
pub struct Command {
|
||||||
|
pub mut:
|
||||||
|
name string
|
||||||
|
description string
|
||||||
|
version string
|
||||||
|
execute fn(cmd Command)
|
||||||
|
|
||||||
|
disable_help bool
|
||||||
|
disable_version bool
|
||||||
|
|
||||||
|
parent &Command
|
||||||
|
commands []Command
|
||||||
|
flags []Flag
|
||||||
|
args []string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (cmd Command) full_name() string {
|
||||||
|
if isnil(cmd.parent) {
|
||||||
|
return cmd.name
|
||||||
|
}
|
||||||
|
return cmd.parent.full_name() + ' ${cmd.name}'
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (cmd Command) root() Command {
|
||||||
|
if isnil(cmd.parent) {
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
return cmd.parent.root()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (cmd mut Command) add_command(command Command) {
|
||||||
|
cmd.commands << command
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (cmd mut Command) add_flag(flag Flag) {
|
||||||
|
cmd.flags << flag
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (cmd mut Command) parse(args []string) {
|
||||||
|
cmd.add_default_flags()
|
||||||
|
cmd.add_default_commands()
|
||||||
|
|
||||||
|
cmd.args = args.right(1)
|
||||||
|
for i := 0; i < cmd.commands.len; i++ {
|
||||||
|
cmd.commands[i].parent = cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.parse_flags()
|
||||||
|
cmd.parse_commands()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (cmd mut Command) add_default_flags() {
|
||||||
|
if !cmd.disable_help && !cmd.flags.contains('help') && !cmd.flags.contains('h') {
|
||||||
|
cmd.add_flag(help_flag())
|
||||||
|
}
|
||||||
|
if !cmd.disable_version && cmd.version != '' && !cmd.flags.contains('version') && !cmd.flags.contains('v') {
|
||||||
|
cmd.add_flag(version_flag())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (cmd mut Command) add_default_commands() {
|
||||||
|
if !cmd.disable_help && !cmd.commands.contains('help') {
|
||||||
|
cmd.add_command(help_cmd())
|
||||||
|
}
|
||||||
|
if !cmd.disable_version && cmd.version != '' && !cmd.commands.contains('version') {
|
||||||
|
cmd.add_command(version_cmd())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (cmd mut Command) parse_flags() {
|
||||||
|
for {
|
||||||
|
if cmd.args.len < 1 || !cmd.args[0].starts_with('-') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
mut found := false
|
||||||
|
for i := 0; i < cmd.flags.len; i++ {
|
||||||
|
mut flag := &cmd.flags[i]
|
||||||
|
if flag.matches(cmd.args) {
|
||||||
|
found = true
|
||||||
|
mut args := flag.parse(cmd.args) or { // TODO: fix once options types can be assigned to struct variables
|
||||||
|
println('failed to parse flag ${cmd.args[0]}: ${err}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
cmd.args = args
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
println('invalid flag: ${cmd.args[0]}')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (cmd mut Command) parse_commands() {
|
||||||
|
flags := cmd.flags
|
||||||
|
global_flags := flags.filter(it.global) // TODO: fix once filter can be applied to struct variable
|
||||||
|
|
||||||
|
cmd.check_help_flag()
|
||||||
|
cmd.check_version_flag()
|
||||||
|
|
||||||
|
for i := 0; i < cmd.args.len; i++ {
|
||||||
|
arg := cmd.args[i]
|
||||||
|
for j := 0; j < cmd.commands.len; j++ {
|
||||||
|
mut command := cmd.commands[j]
|
||||||
|
if command.name == arg {
|
||||||
|
for flag in global_flags {
|
||||||
|
command.add_flag(flag)
|
||||||
|
}
|
||||||
|
command.parse(cmd.args.right(i))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no further command was found execute current command
|
||||||
|
if int(cmd.execute) == 0 {
|
||||||
|
if !cmd.disable_help {
|
||||||
|
help_cmd := cmd.commands.get('help') or { return } // ignore error and handle command normally
|
||||||
|
execute := help_cmd.execute
|
||||||
|
execute(help_cmd)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cmd.check_required_flags()
|
||||||
|
|
||||||
|
execute := cmd.execute
|
||||||
|
execute(cmd) // TODO: fix once higher order function can be execute on struct variable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (cmd mut Command) check_help_flag() {
|
||||||
|
if cmd.disable_help {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cmd.flags.contains('help') {
|
||||||
|
help_flag := cmd.flags.get_bool('help') or { return } // ignore error and handle command normally
|
||||||
|
if help_flag {
|
||||||
|
help_cmd := cmd.commands.get('help') or { return } // ignore error and handle command normally
|
||||||
|
execute := help_cmd.execute
|
||||||
|
execute(help_cmd)
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (cmd mut Command) check_version_flag() {
|
||||||
|
if cmd.disable_version {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cmd.version != '' && cmd.flags.contains('version') {
|
||||||
|
version_flag := cmd.flags.get_bool('version') or { return } // ignore error and handle command normally
|
||||||
|
if version_flag {
|
||||||
|
version_cmd := cmd.commands.get('version') or { return } // ignore error and handle command normally
|
||||||
|
execute := version_cmd.execute
|
||||||
|
execute(version_cmd)
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (cmd mut Command) check_required_flags() {
|
||||||
|
for flag in cmd.flags {
|
||||||
|
if flag.required && flag.value == '' {
|
||||||
|
full_name := cmd.full_name()
|
||||||
|
println('flag \'${flag.name}\' is required by \'${full_name}\'')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (cmds []Command) contains(name string) bool {
|
||||||
|
for cmd in cmds {
|
||||||
|
if cmd.name == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (cmds []Command) get(name string) ?Command {
|
||||||
|
for cmd in cmds {
|
||||||
|
if cmd.name == name {
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error('command \'${name}\' not found.')
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
import cli
|
||||||
|
|
||||||
|
fn test_if_command_parses_empty_args() {
|
||||||
|
mut cmd := cli.Command{
|
||||||
|
name: 'command',
|
||||||
|
execute: empty_func,
|
||||||
|
}
|
||||||
|
cmd.parse(['command'])
|
||||||
|
assert cmd.name == 'command'
|
||||||
|
&& compare_arrays(cmd.args, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_command_parses_args() {
|
||||||
|
mut cmd := cli.Command{
|
||||||
|
name: 'command',
|
||||||
|
execute: empty_func,
|
||||||
|
}
|
||||||
|
cmd.parse(['command', 'arg0', 'arg1'])
|
||||||
|
|
||||||
|
assert cmd.name == 'command'
|
||||||
|
&& compare_arrays(cmd.args, ['arg0', 'arg1'])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_subcommands_parse_args() {
|
||||||
|
mut cmd := cli.Command{
|
||||||
|
name: 'command',
|
||||||
|
}
|
||||||
|
subcmd := cli.Command{
|
||||||
|
name: 'subcommand',
|
||||||
|
execute: empty_func,
|
||||||
|
}
|
||||||
|
cmd.add_command(subcmd)
|
||||||
|
cmd.parse(['command', 'subcommand', 'arg0', 'arg1'])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_subcommands_parse_args_func(cmd cli.Command) {
|
||||||
|
assert cmd.name == 'subcommand'
|
||||||
|
&& compare_arrays(cmd.args, ['arg0', 'arg1'])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_command_has_default_help_subcommand() {
|
||||||
|
mut cmd := cli.Command{
|
||||||
|
name: 'command',
|
||||||
|
}
|
||||||
|
cmd.parse(['command'])
|
||||||
|
|
||||||
|
assert has_command(cmd, 'help')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_command_has_default_version_subcommand_if_version_is_set() {
|
||||||
|
mut cmd := cli.Command{
|
||||||
|
name: 'command',
|
||||||
|
version: '1.0.0',
|
||||||
|
}
|
||||||
|
cmd.parse(['command'])
|
||||||
|
|
||||||
|
assert has_command(cmd, 'version')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_flag_gets_set() {
|
||||||
|
mut cmd := cli.Command{
|
||||||
|
name: 'command',
|
||||||
|
execute: if_flag_gets_set_func,
|
||||||
|
}
|
||||||
|
cmd.add_flag(cli.Flag{
|
||||||
|
flag: .string
|
||||||
|
name: 'flag'
|
||||||
|
})
|
||||||
|
cmd.parse(['command', '--flag', 'value'])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_flag_gets_set_func(cmd cli.Command) {
|
||||||
|
flag := cmd.flags.get_string('flag') or { panic(err) }
|
||||||
|
assert flag == 'value'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_flag_gets_set_with_abbrev() {
|
||||||
|
mut cmd := cli.Command{
|
||||||
|
name: 'command',
|
||||||
|
execute: if_flag_gets_set_with_abbrev_func,
|
||||||
|
}
|
||||||
|
cmd.add_flag(cli.Flag{
|
||||||
|
flag: .string,
|
||||||
|
name: 'flag',
|
||||||
|
abbrev: 'f',
|
||||||
|
})
|
||||||
|
cmd.parse(['command', '-f', 'value'])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_flag_gets_set_with_abbrev_func(cmd cli.Command) {
|
||||||
|
flag := cmd.flags.get_string('flag') or { panic(err) }
|
||||||
|
assert flag == 'value'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_multiple_flags_get_set() {
|
||||||
|
mut cmd := cli.Command{
|
||||||
|
name: 'command',
|
||||||
|
execute: if_multiple_flags_get_set_func,
|
||||||
|
}
|
||||||
|
cmd.add_flag(cli.Flag{
|
||||||
|
flag: .string
|
||||||
|
name: 'flag'
|
||||||
|
})
|
||||||
|
cmd.add_flag(cli.Flag{
|
||||||
|
flag: .int
|
||||||
|
name: 'value'
|
||||||
|
})
|
||||||
|
cmd.parse(['command', '--flag', 'value', '--value', '42'])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_multiple_flags_get_set_func(cmd cli.Command) {
|
||||||
|
flag := cmd.flags.get_string('flag') or { panic(err) }
|
||||||
|
value := cmd.flags.get_int('value') or { panic(err) }
|
||||||
|
assert flag == 'value'
|
||||||
|
&& value == 42
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_flag_gets_set_in_subcommand() {
|
||||||
|
mut cmd := cli.Command{
|
||||||
|
name: 'command',
|
||||||
|
execute: empty_func,
|
||||||
|
}
|
||||||
|
mut subcmd := cli.Command{
|
||||||
|
name: 'subcommand',
|
||||||
|
execute: if_flag_gets_set_in_subcommand_func
|
||||||
|
}
|
||||||
|
subcmd.add_flag(cli.Flag{
|
||||||
|
flag: .string
|
||||||
|
name: 'flag'
|
||||||
|
})
|
||||||
|
cmd.add_command(subcmd)
|
||||||
|
cmd.parse(['command', 'subcommand', '--flag', 'value'])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_flag_gets_set_in_subcommand_func(cmd cli.Command) {
|
||||||
|
flag := cmd.flags.get_string('flag') or { panic(err) }
|
||||||
|
assert flag == 'value'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_global_flag_gets_set_in_subcommand() {
|
||||||
|
mut cmd := cli.Command{
|
||||||
|
name: 'command',
|
||||||
|
execute: empty_func,
|
||||||
|
}
|
||||||
|
cmd.add_flag(cli.Flag{
|
||||||
|
flag: .string,
|
||||||
|
name: 'flag',
|
||||||
|
global: true,
|
||||||
|
})
|
||||||
|
subcmd := cli.Command{
|
||||||
|
name: 'subcommand',
|
||||||
|
execute: if_global_flag_gets_set_in_subcommand_func,
|
||||||
|
}
|
||||||
|
cmd.add_command(subcmd)
|
||||||
|
cmd.parse(['command', '--flag', 'value', 'subcommand'])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn if_global_flag_gets_set_in_subcommand_func(cmd cli.Command) {
|
||||||
|
flag := cmd.flags.get_string('flag') or { panic(err) }
|
||||||
|
assert flag == 'value'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// helper functions
|
||||||
|
|
||||||
|
fn empty_func(cmd cli.Command) {}
|
||||||
|
|
||||||
|
fn has_command(cmd cli.Command, name string) bool {
|
||||||
|
for subcmd in cmd.commands {
|
||||||
|
if subcmd.name == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_arrays(array0 []string, array1 []string) bool {
|
||||||
|
if array0.len != array1.len {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := 0; i < array0.len; i++ {
|
||||||
|
if array0[i] != array1[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
module cli
|
||||||
|
|
||||||
|
pub enum FlagType {
|
||||||
|
bool
|
||||||
|
int
|
||||||
|
float
|
||||||
|
string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Flag {
|
||||||
|
pub mut:
|
||||||
|
flag FlagType
|
||||||
|
name string
|
||||||
|
abbrev string
|
||||||
|
description string
|
||||||
|
global bool
|
||||||
|
required bool
|
||||||
|
|
||||||
|
value string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (flags []Flag) get_bool(name string) ?bool {
|
||||||
|
flag := flags.get(name) or { return error(err) }
|
||||||
|
if flag.flag != .bool { return error('invalid flag type') }
|
||||||
|
return flag.value == 'true'
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (flags []Flag) get_int(name string) ?int {
|
||||||
|
flag := flags.get(name) or { return error(err) }
|
||||||
|
if flag.flag != .int { return error('invalid flag type') }
|
||||||
|
return flag.value.int()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (flags []Flag) get_float(name string) ?f32 {
|
||||||
|
flag := flags.get(name) or { return error(err) }
|
||||||
|
if flag.flag != .float { return error('invalid flag type') }
|
||||||
|
return flag.value.f32()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (flags []Flag) get_string(name string) ?string {
|
||||||
|
flag := flags.get(name) or { return error(err) }
|
||||||
|
if flag.flag != .string { return error('invalid flag type') }
|
||||||
|
return flag.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse flag value from arguments and return arguments with all consumed element removed
|
||||||
|
fn (flag mut Flag) parse(args []string) ?[]string {
|
||||||
|
if flag.matches(args) {
|
||||||
|
if flag.flag == .bool {
|
||||||
|
new_args := flag.parse_bool(args) or { return error(err) }
|
||||||
|
return new_args
|
||||||
|
} else {
|
||||||
|
new_args := flag.parse_raw(args) or { return error(err) }
|
||||||
|
return new_args
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if first arg matches flag
|
||||||
|
fn (flag mut Flag) matches(args []string) bool {
|
||||||
|
return
|
||||||
|
(flag.name != '' && args[0].starts_with('--${flag.name}')) ||
|
||||||
|
(flag.abbrev != '' && args[0].starts_with('-${flag.abbrev}'))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (flag mut Flag) parse_raw(args []string) ?[]string {
|
||||||
|
if args[0].len > flag.name.len && args[0].contains('=') {
|
||||||
|
println('1')
|
||||||
|
flag.value = args[0].split('=')[1]
|
||||||
|
return args.right(1)
|
||||||
|
} else if args.len >= 2 {
|
||||||
|
flag.value = args[1]
|
||||||
|
return args.right(2)
|
||||||
|
}
|
||||||
|
return error('missing argument for ${flag.name}')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (flag mut Flag) parse_bool(args []string) ?[]string {
|
||||||
|
if args[0].len > flag.name.len && args[0].contains('=') {
|
||||||
|
flag.value = args[0].split('=')[1]
|
||||||
|
return args.right(1)
|
||||||
|
} else if args.len >= 2 {
|
||||||
|
if args[1] in ['true', 'false'] {
|
||||||
|
flag.value = args[1]
|
||||||
|
return args.right(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flag.value = 'true'
|
||||||
|
return args.right(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (flags []Flag) get(name string) ?Flag {
|
||||||
|
for flag in flags {
|
||||||
|
if flag.name == name {
|
||||||
|
return flag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error('flag ${name} not found.')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (flags []Flag) contains(name string) bool {
|
||||||
|
for flag in flags {
|
||||||
|
if flag.name == name || flag.abbrev == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
import cli
|
||||||
|
|
||||||
|
fn test_if_string_flag_parses() {
|
||||||
|
mut flag := cli.Flag{
|
||||||
|
flag: .string,
|
||||||
|
name: 'flag',
|
||||||
|
}
|
||||||
|
|
||||||
|
flag.parse(['--flag', 'value']) or { panic(err) }
|
||||||
|
assert flag.value == 'value'
|
||||||
|
|
||||||
|
flag.parse(['--flag=value']) or { panic(err) }
|
||||||
|
assert flag.value == 'value'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_bool_flag_parses() {
|
||||||
|
mut flag := cli.Flag{
|
||||||
|
flag: .bool,
|
||||||
|
name: 'flag',
|
||||||
|
}
|
||||||
|
|
||||||
|
flag.parse(['--flag']) or { panic(err) }
|
||||||
|
assert flag.value == 'true'
|
||||||
|
|
||||||
|
flag.parse(['--flag', 'true']) or { panic(err) }
|
||||||
|
assert flag.value == 'true'
|
||||||
|
|
||||||
|
flag.parse(['--flag=true']) or { panic(err) }
|
||||||
|
assert flag.value == 'true'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_int_flag_parses() {
|
||||||
|
mut flag := cli.Flag{
|
||||||
|
flag: .int,
|
||||||
|
name: 'flag',
|
||||||
|
}
|
||||||
|
|
||||||
|
flag.parse(['--flag', '42']) or { panic(err) }
|
||||||
|
assert flag.value.int() == 42
|
||||||
|
|
||||||
|
flag.parse(['--flag=42']) or { panic(err) }
|
||||||
|
assert flag.value.int() == 42
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_if_float_flag_parses() {
|
||||||
|
mut flag := cli.Flag{
|
||||||
|
flag: .float,
|
||||||
|
name: 'flag',
|
||||||
|
}
|
||||||
|
|
||||||
|
flag.parse(['--flag', '3.14159']) or { panic(err) }
|
||||||
|
assert flag.value.f32() == 3.14159
|
||||||
|
|
||||||
|
flag.parse(['--flag=3.14159']) or { panic(err) }
|
||||||
|
assert flag.value.f32() == 3.14159
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
module cli
|
||||||
|
|
||||||
|
const (
|
||||||
|
BASE_INDENT = 2
|
||||||
|
ABBREV_INDENT = 5
|
||||||
|
DESCRIPTION_INDENT = 20
|
||||||
|
)
|
||||||
|
|
||||||
|
fn help_flag() Flag {
|
||||||
|
return Flag{
|
||||||
|
flag: .bool,
|
||||||
|
name: 'help',
|
||||||
|
abbrev: 'h',
|
||||||
|
description: 'Prints help information',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn help_cmd() Command {
|
||||||
|
return Command{
|
||||||
|
name: 'help',
|
||||||
|
description: 'Prints help information',
|
||||||
|
execute: help_func,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn help_func(help_cmd cli.Command) {
|
||||||
|
cmd := help_cmd.parent
|
||||||
|
full_name := cmd.full_name()
|
||||||
|
|
||||||
|
mut help := ''
|
||||||
|
help += 'Usage: ${full_name}'
|
||||||
|
if cmd.flags.len > 0 { help += ' [FLAGS]'}
|
||||||
|
if cmd.commands.len > 0 { help += ' [COMMANDS]'}
|
||||||
|
help += '\n\n'
|
||||||
|
|
||||||
|
if cmd.description != '' {
|
||||||
|
help += '${cmd.description}\n\n'
|
||||||
|
}
|
||||||
|
if cmd.flags.len > 0 {
|
||||||
|
help += 'Flags:\n'
|
||||||
|
for flag in cmd.flags {
|
||||||
|
mut flag_name := ''
|
||||||
|
if flag.abbrev != '' {
|
||||||
|
abbrev_indent := ' '.repeat(ABBREV_INDENT-(flag.abbrev.len+1))
|
||||||
|
flag_name = '-${flag.abbrev}${abbrev_indent}--${flag.name}'
|
||||||
|
} else {
|
||||||
|
abbrev_indent := ' '.repeat(ABBREV_INDENT-(flag.abbrev.len))
|
||||||
|
flag_name = '${abbrev_indent}--${flag.name}'
|
||||||
|
}
|
||||||
|
mut required := ''
|
||||||
|
if flag.required {
|
||||||
|
required = ' (required)'
|
||||||
|
}
|
||||||
|
|
||||||
|
base_indent := ' '.repeat(BASE_INDENT)
|
||||||
|
description_indent := ' '.repeat(DESCRIPTION_INDENT-flag_name.len)
|
||||||
|
help += '${base_indent}${flag_name}${description_indent}${flag.description}${required}\n'
|
||||||
|
}
|
||||||
|
help += '\n'
|
||||||
|
}
|
||||||
|
if cmd.commands.len > 0 {
|
||||||
|
help += 'Commands:\n'
|
||||||
|
for command in cmd.commands {
|
||||||
|
base_indent := ' '.repeat(BASE_INDENT)
|
||||||
|
description_indent := ' '.repeat(DESCRIPTION_INDENT-command.name.len)
|
||||||
|
|
||||||
|
help += '${base_indent}${command.name}${description_indent}${command.description}\n'
|
||||||
|
}
|
||||||
|
help += '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
print(help)
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
module cli
|
||||||
|
|
||||||
|
fn version_flag() Flag {
|
||||||
|
return Flag{
|
||||||
|
flag: .bool,
|
||||||
|
name: 'version',
|
||||||
|
abbrev: 'v',
|
||||||
|
description: 'Prints version information',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn version_cmd() Command {
|
||||||
|
return Command{
|
||||||
|
name: 'version'
|
||||||
|
description: 'Prints version information',
|
||||||
|
execute: version_func,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn version_func(version_cmd cli.Command) {
|
||||||
|
cmd := version_cmd.parent
|
||||||
|
version := '${cmd.name} v${cmd.version}'
|
||||||
|
println(version)
|
||||||
|
}
|
Loading…
Reference in New Issue