mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
vlib: cli module
This commit is contained in:
parent
8c7f5d5cd8
commit
597a6fead2
1
examples/.gitignore
vendored
1
examples/.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/cli
|
||||
/hello_world
|
||||
/json
|
||||
/links_scraper
|
||||
|
50
examples/cli.v
Normal file
50
examples/cli.v
Normal file
@ -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') }
|
||||
}
|
||||
}
|
||||
}
|
190
vlib/cli/command.v
Normal file
190
vlib/cli/command.v
Normal file
@ -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.')
|
||||
}
|
187
vlib/cli/command_test.v
Normal file
187
vlib/cli/command_test.v
Normal file
@ -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
|
||||
}
|
110
vlib/cli/flag.v
Normal file
110
vlib/cli/flag.v
Normal file
@ -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
|
||||
}
|
56
vlib/cli/flag_test.v
Normal file
56
vlib/cli/flag_test.v
Normal file
@ -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
|
||||
}
|
73
vlib/cli/help.v
Normal file
73
vlib/cli/help.v
Normal file
@ -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)
|
||||
}
|
24
vlib/cli/version.v
Normal file
24
vlib/cli/version.v
Normal file
@ -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
Block a user