tools: turn `v -watch` into a `v watch` sub-command, so that it can have its own options

pull/9911/head
Delyan Angelov 2021-04-28 12:23:23 +03:00
parent e4a2d1b239
commit 626517f5f7
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
4 changed files with 51 additions and 18 deletions

View File

@ -3,6 +3,7 @@ module main
import os import os
import time import time
import term import term
import flag
const scan_timeout_s = 5 * 60 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. // workers, thus it does not leak much.
// //
// b) A worker process, doing the actual monitoring/polling. // 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 // 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. // 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)) } mut context := unsafe { &Context(voidptr(&ccontext)) }
context.pid = os.getpid() context.pid = os.getpid()
context.vexe = os.getenv('VEXE') context.vexe = os.getenv('VEXE')
context.is_worker = os.args.contains('-vwatchworker')
context.clear_terminal = os.getenv('VWATCH_CLEAR_TERMINAL') != '' mut fp := flag.new_flag_parser(os.args[1..])
context.add_files = os.getenv('VWATCH_ADD_FILES').split(',') fp.application('v watch')
context.ignore_exts = os.getenv('VWATCH_IGNORE_EXTENSIONS').split(',') if os.args[1] == 'watch' {
context.opts = os.args[1..].filter(it != '-vwatchworker') 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.pid: $context.pid')
context.elog('>>> context.vexe: $context.vexe') context.elog('>>> context.vexe: $context.vexe')
context.elog('>>> context.opts: $context.opts') context.elog('>>> context.opts: $context.opts')
context.elog('>>> context.is_worker: $context.is_worker') 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 { if context.is_worker {
context.worker_main() context.worker_main()
} else { } else {
@ -277,8 +301,8 @@ fn main() {
fn (mut context Context) manager_main() { fn (mut context Context) manager_main() {
myexecutable := os.executable() myexecutable := os.executable()
mut worker_opts := ['-vwatchworker'] mut worker_opts := ['--vwatchworker']
worker_opts << context.opts worker_opts << os.args[2..]
for { for {
mut worker_process := os.new_process(myexecutable) mut worker_process := os.new_process(myexecutable)
worker_process.set_args(worker_opts) worker_process.set_args(worker_opts)

View File

@ -35,6 +35,7 @@ const (
'up', 'up',
'vet', 'vet',
'wipe-cache', 'wipe-cache',
'watch',
] ]
list_of_flags_that_allow_duplicates = ['cc', 'd', 'define', 'cf', 'cflags'] 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..] args_and_flags := util.join_env_vflags_and_os_args()[1..]
prefs, command := pref.parse_args(external_tools, args_and_flags) 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 { if prefs.is_verbose {
// println('args= ') // println('args= ')
// println(args) // QTODO // println(args) // QTODO

View File

@ -65,6 +65,7 @@ pub mut:
application_description string application_description string
min_free_args int min_free_args int
args_description string args_description string
allow_unknown_args bool // whether passing undescribed arguments is allowed
} }
[unsafe] [unsafe]
@ -123,6 +124,14 @@ pub fn (mut fs FlagParser) skip_executable() {
fs.args.delete(0) 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 // private helper to register a flag
fn (mut fs FlagParser) add_flag(name string, abbr byte, usage string, desc string) { fn (mut fs FlagParser) add_flag(name string, abbr byte, usage string, desc string) {
fs.flags << Flag{ 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. // defined on the command line. If additional flags are found, i.e.
// (things starting with '--' or '-'), it returns an error. // (things starting with '--' or '-'), it returns an error.
pub fn (fs FlagParser) finalize() ?[]string { pub fn (fs FlagParser) finalize() ?[]string {
for a in fs.args { if !fs.allow_unknown_args {
if (a.len >= 2 && a[..2] == '--') || (a.len == 2 && a[0] == `-`) { for a in fs.args {
return IError(&UnkownFlagError{ if (a.len >= 2 && a[..2] == '--') || (a.len == 2 && a[0] == `-`) {
msg: 'Unknown flag `$a`' return IError(&UnkownFlagError{
}) msg: 'Unknown flag `$a`'
})
}
} }
} }
if fs.args.len < fs.min_free_args && fs.min_free_args > 0 { if fs.args.len < fs.min_free_args && fs.min_free_args > 0 {

View File

@ -84,7 +84,6 @@ pub mut:
output_mode OutputMode = .stdout output_mode OutputMode = .stdout
// verbosity VerboseLevel // verbosity VerboseLevel
is_verbose bool is_verbose bool
is_watch bool // -watch mode, implemented by cmd/tools/watch.v
// nofmt bool // disable vfmt // nofmt bool // disable vfmt
is_test bool // `v test string_test.v` is_test bool // `v test string_test.v`
is_script bool // single file mode (`v program.v`), main function can be skipped 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 res.skip_warnings = true
} }
'-watch' { '-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' { '-print-v-files' {
res.print_v_files = true res.print_v_files = true