Skip to content

Commit

Permalink
shy, cli: switch from flag.FlagParser to flag.to_*[T]() compile t…
Browse files Browse the repository at this point in the history
…ime flag parsing
  • Loading branch information
larpon committed Jul 30, 2024
1 parent 52c3be1 commit d0e3e6d
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 98 deletions.
12 changes: 6 additions & 6 deletions cli/cli.v
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,30 @@ pub const exe_version = version()
pub const exe_name = os.file_name(os.executable())
pub const exe_short_name = os.file_name(os.executable()).replace('.exe', '')
pub const exe_dir = os.dir(os.real_path(os.executable()))
pub const exe_args_description = 'input
or: shy <sub-command> [options] input'
pub const exe_description = 'Usage: shy [options] input
or: shy <sub-command> [options] input
pub const exe_description = 'shy is a module and tool made with love.
Description: shy is a module and tool made with love.
It is primarily aimed at V developers roaming the creative corners of coding.
shy can compile, package and deploy V apps for a wide range of platforms like:
Linux, macOS, Windows, Android and HTML5 (WASM).
The following does the same as if they were passed to the "v" compiler:
The following does the same as if they were passed to the `v` command:
Flags:
-autofree, -gc <type>, -g, -cg, -prod, -showcc
Sub-commands:
run Run the V code
export Export shy based project
doctor Display useful info about your system for bug reports'
doctor Display useful info about the system'

pub const exe_git_hash = shy_commit_hash()
pub const work_directory = shy_tmp_work_dir()
pub const cache_directory = shy_cache_dir()
pub const rip_vflags = ['-autofree', '-gc', '-g', '-cg', '-prod', 'run', '-showcc']
pub const subcmds = ['complete', 'test-cleancode', 'export']
pub const subcmds = ['complete', 'doctor', 'export', 'test-cleancode']
pub const accepted_input_files = ['.v']

pub const shy_env_vars = [
Expand Down
78 changes: 21 additions & 57 deletions cli/options.v
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,24 @@ import flag
pub struct Options {
pub:
// These fields would make little sense to change during a run
verbosity int
work_dir string = work_directory
verbosity int @[only: v; repeats; xdoc: 'Verbosity level 1-3']
work_dir string = work_directory @[xdoc: 'Directory to use for temporary work files']
//
run bool
parallel bool = true // Run, what can be run, in parallel
cache bool // defaults to false in os.args/flag parsing phase
gl_version string = '3'
nocache bool @[xdoc: 'Do not use caching']
// Detected environment
dump_usage bool
run bool @[ignore]
dump_usage bool @[long: help; short: h; xdoc: 'Show this help message and exit']
pub mut:
// I/O
input string
output string
additional_args []string // additional_args passed via os.args
is_prod bool
c_flags []string // flags passed to the C compiler(s)
v_flags []string // flags passed to the V compiler
assets_extra []string // list of (extra) paths to assets dirs to include
libs_extra []string
input string @[tail]
output string @[short: o; xdoc: 'Path to output (dir/file)']
// additional_args []string // additional_args passed via os.args
is_prod bool
c_flags []string @[long: cflag; short: c; xdoc: 'Additional flags for the C compiler']
v_flags []string @[long: flag; short: f; xdoc: 'Additional flags for the V compiler']
assets_extra []string @[long: asset; short: a; xdoc: 'Asset dir(s) to include in build']
libs_extra []string @[long: libs; short: l; xdoc: 'Lib dir(s) to include in build']
version bool @[xdoc: 'Output version information and exit']
}

// options_from_env returns an `Option` struct filled with flags set via
Expand All @@ -35,7 +34,7 @@ pub fn options_from_env(defaults Options) !Options {
if env_flags != '' {
mut flags := [os.args[0]]
flags << string_to_args(env_flags)!
opts, _ := args_to_options(flags, defaults)!
opts := args_to_options(flags, defaults)!
return opts
}
return defaults
Expand Down Expand Up @@ -85,13 +84,12 @@ pub fn (opt &Options) uses_gc() bool {

// args_to_options returns an `Option` merged from (CLI/Shell) `arguments` using `defaults` as
// values where no value can be obtained from `arguments`.
pub fn args_to_options(arguments []string, defaults Options) !(Options, &flag.FlagParser) {
pub fn args_to_options(arguments []string, defaults Options) !Options {
mut args := arguments.clone()

// Indentify special flags in args before passing them on
mut v_flags := []string{}
mut cmd_flags := []string{}
// Indentify special flags in args before FlagParser ruin them.
// E.g. the -autofree flag will result in dump_usage being called for some weird reason???
for special_flag in rip_vflags {
if special_flag in args {
if special_flag == '-gc' {
Expand All @@ -107,41 +105,7 @@ pub fn args_to_options(arguments []string, defaults Options) !(Options, &flag.Fl
}
}

mut fp := flag.new_flag_parser(args)
fp.application(exe_short_name)
fp.version(version_full())
fp.description(exe_description)
fp.arguments_description(exe_args_description)

fp.skip_executable()

mut verbosity := fp.int_opt('verbosity', `v`, 'Verbosity level 1-3') or { defaults.verbosity }
if ('-v' in args || 'verbosity' in args) && verbosity == 0 {
verbosity = 1
}

mut opt := Options{
assets_extra: fp.string_multi('assets', `a`, 'Asset dir(s) to include in build')
libs_extra: fp.string_multi('libs', `l`, 'Lib dir(s) to include in build')
v_flags: fp.string_multi('flag', `f`, 'Additional flags for the V compiler')
c_flags: fp.string_multi('cflag', `c`, 'Additional flags for the C compiler')
gl_version: fp.string('gl', 0, defaults.gl_version, 'GL(ES) version to use from any of 2,3,es2,es3')
//
run: 'run' in cmd_flags
dump_usage: fp.bool('help', `h`, defaults.dump_usage, 'Show this help message and exit')
cache: !fp.bool('nocache', 0, defaults.cache, 'Do not use build cache')
//
output: fp.string('output', `o`, defaults.output, 'Path to output (dir/file)')
//
verbosity: verbosity
parallel: !fp.bool('no-parallel', 0, false, 'Do not run tasks in parallel.')
//
work_dir: defaults.work_dir
}

opt.additional_args = fp.finalize() or {
return error('${@FN}: flag parser failed finalizing: ${err}')
}
mut opt, _ := flag.using(defaults, args)!

mut c_flags := []string{}
c_flags << opt.c_flags
Expand All @@ -160,7 +124,7 @@ pub fn args_to_options(arguments []string, defaults Options) !(Options, &flag.Fl
}
opt.v_flags = v_flags

return opt, fp
return opt
}

// shy_v builds `opt.input` as `v` would have done normally, except
Expand All @@ -172,7 +136,7 @@ pub fn (opt &Options) shy_v() ! {
mut v_cmd := [
v_exe,
]
if !opt.cache {
if opt.nocache {
v_cmd << '-nocache'
}
if opt.is_prod {
Expand Down Expand Up @@ -200,7 +164,7 @@ pub fn (opt &Options) shy_v() ! {
if opt.run {
v_compile_opt := VCompileOptions{
verbosity: opt.verbosity
cache: opt.cache
cache: !opt.nocache
flags: opt.v_flags
work_dir: os.join_path(opt.work_dir, 'v')
input: opt.input
Expand Down
14 changes: 8 additions & 6 deletions cli/utils.v
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,16 @@ fn version() string {
}

// run_subcommand runs any sub-command detected in `args`.
pub fn run_subcommand(args []string) ! {
nocache := args.contains('--nocache')
for subcmd in subcmds {
if subcmd in args {
// First encountered known sub-command is executed on the spot.
launch_cmd(args[args.index(subcmd)..], nocache)!
pub fn run_subcommand(args []string, opts Options) ! {
if args.len > 1 && !args[1].starts_with('-') && args[1] in subcmds {
sub_command := args[1]
if sub_command == 'doctor' {
doctor(opts)
exit(0)
}
// First encountered known sub-command is executed on the spot.
launch_cmd(args[args.index(sub_command)..], opts.nocache)!
exit(0)
}
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/export/export.v
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ pub fn (opt &Options) to_export_options() export.Options {
verbosity: opt.verbosity
work_dir: opt.work_dir
parallel: opt.parallel
cache: opt.cache
cache: !opt.nocache
gl_version: gl_version
format: format
input: opt.input
Expand Down
45 changes: 17 additions & 28 deletions shy.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,27 @@
// that can be found in the LICENSE file.
module main

import os
import flag
import term
import shy.cli

const c_embedded_shy_sixel_logo = $embed_file('assets/images/shy.six')

fn main() {
// Run any sub-commands on the spot if found in args
cli.run_subcommand(os.args) or {
eprintln(err)
exit(1)
}
args := arguments()

// Collect user flags in an extended manner.
// Start with defaults -> merge over SHY_FLAGS -> merge over cmdline flags -> merge .shy entries.
mut opt := cli.Options{}
mut fp := &flag.FlagParser(unsafe { nil })

opt = cli.options_from_env(opt) or {
eprintln('Error while parsing `SHY_FLAGS`: ${err}')
eprintln('Use `${cli.exe_short_name} -h` to see all flags')
exit(1)
}

opt, fp = cli.args_to_options(os.args, opt) or {
eprintln('Error while parsing `os.args`: ${err}')
opt = cli.args_to_options(args, opt) or {
eprintln('Error while parsing arguments: ${err}')
eprintln('Use `${cli.exe_short_name} -h` to see all flags')
exit(1)
}
Expand All @@ -37,36 +32,30 @@ fn main() {
if term.supports_sixel() {
println(c_embedded_shy_sixel_logo.to_bytes().bytestr())
}
println(fp.usage())
println(flag.to_doc[cli.Options](
name: cli.exe_short_name
version: '${cli.exe_version} (${cli.exe_git_hash})'
description: cli.exe_description
options: flag.DocOptions{
compact: true
}
)!)
exit(0)
}

// All flags after this requires an input argument
if fp.args.len == 0 {
if args.len == 1 {
eprintln('No arguments given')
eprintln('Use `shy -h` to see all flags')
exit(1)
}

// TODO
if opt.additional_args.len > 1 {
if opt.additional_args[0] == 'xxx' {
// xxx_arg := opt.additional_args[1]
exit(1)
}
}

// Call the doctor at this point
if opt.additional_args.len > 0 {
if opt.additional_args[0] == 'doctor' {
cli.doctor(opt)
exit(0)
}
// Run any sub-commands if found on the spot if found in args
cli.run_subcommand(args, opt) or {
eprintln(err)
exit(1)
}

input := fp.args.last()
opt.input = input

cli.validate_input(opt.input)!

opt.extend_from_dot_shy() or {
Expand Down

0 comments on commit d0e3e6d

Please sign in to comment.