diff --git a/cmd/tools/vbug.v b/cmd/tools/vbug.v index b9a234219bfa71..0b4bbe50be62ee 100644 --- a/cmd/tools/vbug.v +++ b/cmd/tools/vbug.v @@ -1,8 +1,15 @@ -import net.urllib import os +import term import readline +import net.urllib -const vroot = @VMODROOT +fn elog(msg string) { + eprintln(term.ecolorize(term.gray, msg)) +} + +fn olog(msg string) { + println(term.colorize(term.green, msg)) +} // get output from `v doctor` fn get_vdoctor_output(is_verbose bool) string { @@ -10,55 +17,64 @@ fn get_vdoctor_output(is_verbose bool) string { verbose_flag := if is_verbose { '-v' } else { '' } result := os.execute('${os.quoted_path(vexe)} ${verbose_flag} doctor') if result.exit_code != 0 { - eprintln('unable to get `v doctor` output: ${result.output}') + elog('> unable to get `v doctor` output: ${result.output}') return '' } return result.output } -// get output from `./v -g -o vdbg cmd/v && ./vdbg file.v` -fn get_v_build_output(is_verbose bool, is_yes bool, file_path string) string { +fn runv(label string, user_cmd string) os.Result { + mut result := os.Result{} + elog('> ${label} using: ${term.ecolorize(term.magenta, user_cmd)}') + result = os.execute(user_cmd) + print(result.output) + return result +} + +// get output from `./v -g -o vdbg cmd/v && ./vdbg -user_args run file.v` +fn get_v_build_output(is_verbose bool, is_yes bool, file_path string, user_args string, generated_file string) string { + mut result := os.Result{} mut vexe := os.getenv('VEXE') + // prepare a V compiler with -g to have better backtraces if possible wd := os.getwd() + vroot := @VMODROOT os.chdir(vroot) or {} verbose_flag := if is_verbose { '-v' } else { '' } vdbg_path := $if windows { '${vroot}/vdbg.exe' } $else { '${vroot}/vdbg' } vdbg_compilation_cmd := '${os.quoted_path(vexe)} ${verbose_flag} -g -o ${os.quoted_path(vdbg_path)} cmd/v' - vdbg_result := os.execute(vdbg_compilation_cmd) + result = runv('Prepare vdbg', vdbg_compilation_cmd) os.chdir(wd) or {} - if vdbg_result.exit_code == 0 { + + if result.exit_code == 0 { vexe = vdbg_path } else { - eprintln('unable to compile V in debug mode: ${vdbg_result.output}\ncommand: ${vdbg_compilation_cmd}\n') + elog('> unable to compile V in debug mode: ${result.output}\ncommand: ${vdbg_compilation_cmd}\n') } - mut result := os.execute('${os.quoted_path(vexe)} ${verbose_flag} ${os.quoted_path(file_path)}') + result = runv('Compile', '${os.quoted_path(vexe)} ${verbose_flag} ${user_args} ${os.quoted_path(file_path)}') defer { os.rm(vdbg_path) or { if is_verbose { - eprintln('unable to delete `vdbg`: ${err}') + elog('> unable to delete `vdbg`: ${err}') } } } if result.exit_code == 0 { defer { - mut generated_file := file_path.all_before_last('.') - $if windows { - generated_file += '.exe' - } os.rm(generated_file) or { if is_verbose { - eprintln('unable to delete generated file: ${err}') + elog('> unable to delete generated file: ${err}') } } } run := is_yes || ask('It looks like the compilation went well, do you want to run the file?') if run { - result = os.execute('${os.quoted_path(vexe)} ${verbose_flag} run ${os.quoted_path(file_path)}') + result = runv('Run', generated_file) if result.exit_code == 0 && !is_yes { - confirm_or_exit('It looks like the file ran correctly as well, are you sure you want to continue?') + elog('> The file ran correctly as well.') + confirm_or_exit('Are you sure you want to continue?') } } } @@ -66,7 +82,7 @@ fn get_v_build_output(is_verbose bool, is_yes bool, file_path string) string { } fn ask(msg string) bool { - prompt := os.input_opt('${msg} [Y/n] ') or { 'y' } + prompt := os.input_opt(term.colorize(term.bright_white, '${msg} [Y/n] ')) or { 'y' } return prompt == '' || prompt[0].ascii_str().to_lower() != 'n' } @@ -77,59 +93,68 @@ fn confirm_or_exit(msg string) { } fn main() { + unbuffer_stdout() + mut compiler_args := []string{} mut file_path := '' - mut is_verbose := false - mut is_yes := false - for arg in os.args[2..] { - match arg { - '-v' { - is_verbose = true - } - '-y' { - is_yes = true + is_verbose := '-v' in os.args + is_yes := '-y' in os.args + + for arg in os.args[1..] { + if arg == 'bug' { + continue + } + if arg.ends_with('.v') || arg.ends_with('.vsh') || arg.ends_with('.vv') { + if file_path != '' { + elog('> v bug: only one V file can be submitted') + exit(1) } - else { - if !arg.ends_with('.v') && !arg.ends_with('.vsh') && !arg.ends_with('.vv') { - eprintln('unknown argument: `${arg}`') - exit(1) - } - if file_path != '' { - eprintln('only one V file can be submitted') - exit(1) - } - file_path = arg + file_path = arg + } else { + if arg !in ['-y', '-v'] { + compiler_args << arg } } } + if file_path == '' { - eprintln('v bug: no v file listed to report') + elog('> v bug: no v file listed to report') exit(1) } + os.unsetenv('VCOLORS') // collect error information // output from `v doctor` vdoctor_output := get_vdoctor_output(is_verbose) // file content file_content := os.read_file(file_path) or { - eprintln('unable to get file "${file_path}" content: ${err}') + elog('> unable to get file "${file_path}" content: ${err}') '' } - // output from `./v -g -o vdbg cmd/v && ./vdbg file.v` - build_output := get_v_build_output(is_verbose, is_yes, file_path) + + user_args := compiler_args.join(' ') + mut generated_file := file_path.all_before_last('.') + if os.user_os() == 'windows' { + generated_file += '.exe' + } + build_output := get_v_build_output(is_verbose, is_yes, file_path, user_args, generated_file) + // ask the user if he wants to submit even after an error if !is_yes && (vdoctor_output == '' || file_content == '' || build_output == '') { - confirm_or_exit('An error occurred retrieving the information, do you want to continue?') + elog('> Error while retrieving the information.') + confirm_or_exit('Do you want to continue?') } expected_result := readline.read_line('What did you expect to see? ') or { // Ctrl-C was pressed - eprintln('\nCanceled') + elog('\nCanceled') exit(1) } // open prefilled issue creation page, or print link as a fallback if !is_yes && vdoctor_output.contains('behind V master') { - confirm_or_exit('It looks like your installation of V is outdated, we advise you to run `v up` before submitting an issue. Are you sure you want to continue?') + olog('> It looks like your installation of V is outdated.') + olog('> We advise you to run `v up` before submitting an issue.') + confirm_or_exit('Are you sure you want to continue?') } // When updating this template, make sure to update `.github/ISSUE_TEMPLATE/bug_report.md` too @@ -140,30 +165,33 @@ ${vdoctor_output} ``` **What did you do?** -`./v -g -o vdbg cmd/v && ./vdbg ${file_path}` +`./v -g -o vdbg cmd/v && ./vdbg ${user_args} ${file_path} && ${generated_file}` {file_content} +**What did you see instead?** +``` +${build_output}``` + **What did you expect to see?** ${expected_result} -**What did you see instead?** -``` -${build_output}```' +' mut encoded_body := urllib.query_escape(raw_body.replace_once('{file_content}', '```v\n${file_content}\n```')) mut generated_uri := 'https://github.com/vlang/v/issues/new?labels=Bug&body=${encoded_body}' if generated_uri.len > 8192 { // GitHub doesn't support URLs longer than 8192 characters encoded_body = urllib.query_escape(raw_body.replace_once('{file_content}', 'See attached file `${file_path}`')) generated_uri = 'https://github.com/vlang/v/issues/new?labels=Bug&body=${encoded_body}' - println('Your file is too big to be submitted. Head over to the following URL and attach your file.') - println(generated_uri) + elog('> Your file is too big to be submitted.') + elog('> Go to the following URL, and attach your file:') + olog(generated_uri) } else { os.open_uri(generated_uri) or { if is_verbose { - eprintln(err) + elog(err.str()) } - println(generated_uri) + olog(generated_uri) } } }