diff --git a/cmd/tools/vwatch.v b/cmd/tools/vwatch.v index e6f78b4e23..563995b5ed 100644 --- a/cmd/tools/vwatch.v +++ b/cmd/tools/vwatch.v @@ -3,6 +3,7 @@ module main import os import time import term +import flag const scan_timeout_s = 5 * 60 @@ -37,7 +38,7 @@ const max_scan_cycles = scan_timeout_s * scan_frequency_hz // workers, thus it does not leak much. // // b) A worker process, doing the actual monitoring/polling. -// NB: *workers are started with the -vwatchworker option* +// NB: *workers are started with the --vwatchworker option* // // Worker processes will run for a limited number of iterations, then // they will do exit(255), and then the parent will start a new worker. @@ -259,15 +260,38 @@ fn main() { mut context := unsafe { &Context(voidptr(&ccontext)) } context.pid = os.getpid() context.vexe = os.getenv('VEXE') - context.is_worker = os.args.contains('-vwatchworker') - context.clear_terminal = os.getenv('VWATCH_CLEAR_TERMINAL') != '' - context.add_files = os.getenv('VWATCH_ADD_FILES').split(',') - context.ignore_exts = os.getenv('VWATCH_IGNORE_EXTENSIONS').split(',') - context.opts = os.args[1..].filter(it != '-vwatchworker') + + mut fp := flag.new_flag_parser(os.args[1..]) + fp.application('v watch') + if os.args[1] == 'watch' { + fp.skip_executable() + } + fp.version('0.0.2') + fp.description('Collect all .v files needed for a compilation, then re-run the compilation when any of the source changes.') + fp.arguments_description('[--clear] [--ignore .db] [--add /path/to/a/file.v] [run] program.v') + fp.allow_unknown_args() + fp.limit_free_args_to_at_least(1) + context.is_worker = fp.bool('vwatchworker', 0, false, 'Internal flag. Used to distinguish vwatch manager and worker processes.') + context.clear_terminal = fp.bool('clear', `c`, false, 'Clears the terminal before each re-run.') + context.add_files = fp.string('add', `a`, '', 'Add more files to be watched. Useful with `v watch -add=/tmp/feature.v run cmd/v /tmp/feature.v`, when you want to change *both* the compiler, and the feature.v file.').split(',') + context.ignore_exts = fp.string('ignore', `i`, '', 'Ignore files having these extensions. Useful with `v watch -ignore=.db run server.v`, if your server writes to an sqlite.db file in the same folder.').split(',') + show_help := fp.bool('help', `h`, false, 'Show this help screen.') + if show_help { + println(fp.usage()) + exit(0) + } + remaining_options := fp.finalize() or { + eprintln('Error: $err') + exit(1) + } + context.opts = remaining_options context.elog('>>> context.pid: $context.pid') context.elog('>>> context.vexe: $context.vexe') context.elog('>>> context.opts: $context.opts') context.elog('>>> context.is_worker: $context.is_worker') + context.elog('>>> context.clear_terminal: $context.clear_terminal') + context.elog('>>> context.add_files: $context.add_files') + context.elog('>>> context.ignore_exts: $context.ignore_exts') if context.is_worker { context.worker_main() } else { @@ -277,8 +301,8 @@ fn main() { fn (mut context Context) manager_main() { myexecutable := os.executable() - mut worker_opts := ['-vwatchworker'] - worker_opts << context.opts + mut worker_opts := ['--vwatchworker'] + worker_opts << os.args[2..] for { mut worker_process := os.new_process(myexecutable) worker_process.set_args(worker_opts) diff --git a/cmd/v/v.v b/cmd/v/v.v index 7621f0ad68..730252c360 100644 --- a/cmd/v/v.v +++ b/cmd/v/v.v @@ -35,6 +35,7 @@ const ( 'up', 'vet', 'wipe-cache', + 'watch', ] list_of_flags_that_allow_duplicates = ['cc', 'd', 'define', 'cf', 'cflags'] ) @@ -69,9 +70,6 @@ fn main() { } args_and_flags := util.join_env_vflags_and_os_args()[1..] prefs, command := pref.parse_args(external_tools, args_and_flags) - if prefs.is_watch { - util.launch_tool(prefs.is_verbose, 'vwatch', os.args[1..].filter(it != '-watch')) - } if prefs.is_verbose { // println('args= ') // println(args) // QTODO diff --git a/vlib/flag/flag.v b/vlib/flag/flag.v index e285cc3130..baa56f9027 100644 --- a/vlib/flag/flag.v +++ b/vlib/flag/flag.v @@ -65,6 +65,7 @@ pub mut: application_description string min_free_args int args_description string + allow_unknown_args bool // whether passing undescribed arguments is allowed } [unsafe] @@ -123,6 +124,14 @@ pub fn (mut fs FlagParser) skip_executable() { fs.args.delete(0) } +// allow_unknown_args - if your program has sub commands, that have +// their own arguments, you can call .allow_unknown_args(), so that +// the subcommand arguments (which generally are not known to your +// parent program), will not cause the validation in .finalize() to fail. +pub fn (mut fs FlagParser) allow_unknown_args() { + fs.allow_unknown_args = true +} + // private helper to register a flag fn (mut fs FlagParser) add_flag(name string, abbr byte, usage string, desc string) { fs.flags << Flag{ @@ -495,11 +504,13 @@ pub fn (fs FlagParser) usage() string { // defined on the command line. If additional flags are found, i.e. // (things starting with '--' or '-'), it returns an error. pub fn (fs FlagParser) finalize() ?[]string { - for a in fs.args { - if (a.len >= 2 && a[..2] == '--') || (a.len == 2 && a[0] == `-`) { - return IError(&UnkownFlagError{ - msg: 'Unknown flag `$a`' - }) + if !fs.allow_unknown_args { + for a in fs.args { + if (a.len >= 2 && a[..2] == '--') || (a.len == 2 && a[0] == `-`) { + return IError(&UnkownFlagError{ + msg: 'Unknown flag `$a`' + }) + } } } if fs.args.len < fs.min_free_args && fs.min_free_args > 0 { diff --git a/vlib/v/pref/pref.v b/vlib/v/pref/pref.v index 5f3090f1f9..f99baef2ea 100644 --- a/vlib/v/pref/pref.v +++ b/vlib/v/pref/pref.v @@ -84,7 +84,6 @@ pub mut: output_mode OutputMode = .stdout // verbosity VerboseLevel is_verbose bool - is_watch bool // -watch mode, implemented by cmd/tools/watch.v // nofmt bool // disable vfmt is_test bool // `v test string_test.v` is_script bool // single file mode (`v program.v`), main function can be skipped @@ -447,7 +446,8 @@ pub fn parse_args(known_external_commands []string, args []string) (&Preferences res.skip_warnings = true } '-watch' { - res.is_watch = true + eprintln('The -watch option is deprecated. Please use the watch command `v watch file.v` instead.') + exit(1) } '-print-v-files' { res.print_v_files = true