From 3190ae1fe0b7b35a19f185cf94edd59f2888193c Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sun, 3 Feb 2019 11:47:26 +0800 Subject: [PATCH 1/3] src: port --bash-completion to C++ So that it gets handle earlier and faster during the bootstrap process. Drive-by fixes: - Remove `[has_eval_string]` and `[ssl_openssl_cert_store]` from the completion output - Set `kProfProcess` execution mode for `--prof-process` instead of `kPrintBashProcess` which is removed in this patch. - Append new line to the end of the output of --bash-completion --- lib/internal/main/print_bash_completion.js | 29 ---------------- node.gyp | 1 - src/node.cc | 15 +++++++-- src/node_options.cc | 39 ++++++++++++++++++++++ src/node_options.h | 2 ++ 5 files changed, 53 insertions(+), 33 deletions(-) delete mode 100644 lib/internal/main/print_bash_completion.js diff --git a/lib/internal/main/print_bash_completion.js b/lib/internal/main/print_bash_completion.js deleted file mode 100644 index 41ebf0c6063e5f..00000000000000 --- a/lib/internal/main/print_bash_completion.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; -const { options, aliases } = require('internal/options'); - -const { - prepareMainThreadExecution -} = require('internal/bootstrap/pre_execution'); - -function print(stream) { - const all_opts = [...options.keys(), ...aliases.keys()]; - - stream.write(`_node_complete() { - local cur_word options - cur_word="\${COMP_WORDS[COMP_CWORD]}" - if [[ "\${cur_word}" == -* ]] ; then - COMPREPLY=( $(compgen -W '${all_opts.join(' ')}' -- "\${cur_word}") ) - return 0 - else - COMPREPLY=( $(compgen -f "\${cur_word}") ) - return 0 - fi -} -complete -F _node_complete node node_g`); -} - -prepareMainThreadExecution(); - -markBootstrapComplete(); - -print(process.stdout); diff --git a/node.gyp b/node.gyp index 926fe98959c21a..3a201eed4a540d 100644 --- a/node.gyp +++ b/node.gyp @@ -138,7 +138,6 @@ 'lib/internal/main/eval_string.js', 'lib/internal/main/eval_stdin.js', 'lib/internal/main/inspect.js', - 'lib/internal/main/print_bash_completion.js', 'lib/internal/main/print_help.js', 'lib/internal/main/prof_process.js', 'lib/internal/main/repl.js', diff --git a/src/node.cc b/src/node.cc index ac0e7dfce3f058..5110c8b55ccb53 100644 --- a/src/node.cc +++ b/src/node.cc @@ -396,9 +396,6 @@ MaybeLocal StartMainThreadExecution(Environment* env) { return StartExecution(env, "internal/main/print_help"); } - if (per_process::cli_options->print_bash_completion) { - return StartExecution(env, "internal/main/print_bash_completion"); - } if (env->options()->prof_process) { return StartExecution(env, "internal/main/prof_process"); @@ -771,6 +768,12 @@ void Init(int* argc, exit(0); } + if (per_process::cli_options->print_bash_completion) { + std::string completion = options_parser::GetBashCompletion(); + printf("%s\n", completion.c_str()); + exit(0); + } + if (per_process::cli_options->print_v8_help) { V8::SetFlagsFromString("--help", 6); // Doesn't return. UNREACHABLE(); @@ -829,6 +832,12 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) { return result; } + if (per_process::cli_options->print_bash_completion) { + std::string completion = options_parser::GetBashCompletion(); + printf("%s\n", completion.c_str()); + exit(0); + } + if (per_process::cli_options->print_v8_help) { V8::SetFlagsFromString("--help", 6); // Doesn't return. UNREACHABLE(); diff --git a/src/node_options.cc b/src/node_options.cc index a36666c3e0f452..f627c8fc64a9b9 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -4,6 +4,8 @@ #include "env-inl.h" #include "node_binding.h" +#include +#include #include // strtoul, errno using v8::Boolean; @@ -678,6 +680,43 @@ HostPort SplitHostPort(const std::string& arg, ParseAndValidatePort(arg.substr(colon + 1), errors) }; } +std::string GetBashCompletion() { + Mutex::ScopedLock lock(per_process::cli_options_mutex); + const auto& parser = _ppop_instance; + + std::ostringstream out; + + out << "_node_complete() {\n" + " local cur_word options\n" + " cur_word=\"${COMP_WORDS[COMP_CWORD]}\"\n" + " if [[ \"${cur_word}\" == -* ]] ; then\n" + " COMPREPLY=( $(compgen -W '"; + + for (const auto& item : parser.options_) { + if (item.first[0] != '[') { + out << item.first << " "; + } + } + for (const auto& item : parser.aliases_) { + if (item.first[0] != '[') { + out << item.first << " "; + } + } + if (parser.aliases_.size() > 0) { + out.seekp(-1, out.cur); // Strip the trailing space + } + + out << "' -- \"${cur_word}\") )\n" + " return 0\n" + " else\n" + " COMPREPLY=( $(compgen -f \"${cur_word}\") )\n" + " return 0\n" + " fi\n" + "}\n" + "complete -F _node_complete node node_g"; + return out.str(); +} + // Return a map containing all the options and their metadata as well // as the aliases void GetOptions(const FunctionCallbackInfo& args) { diff --git a/src/node_options.h b/src/node_options.h index db564ddb3d3e6d..19b0b51d6a4113 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -224,6 +224,7 @@ namespace options_parser { HostPort SplitHostPort(const std::string& arg, std::vector* errors); void GetOptions(const v8::FunctionCallbackInfo& args); +std::string GetBashCompletion(); enum OptionEnvvarSettings { kAllowedInEnvironment, @@ -412,6 +413,7 @@ class OptionsParser { friend class OptionsParser; friend void GetOptions(const v8::FunctionCallbackInfo& args); + friend std::string GetBashCompletion(); }; using StringVector = std::vector; From bdfabf44fda543c89d3290d9c4ae3f70f572175f Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sun, 12 May 2019 05:14:03 +0800 Subject: [PATCH 2/3] fixup! src: port --bash-completion to C++ --- test/parallel/test-bash-completion.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/parallel/test-bash-completion.js b/test/parallel/test-bash-completion.js index 50378a7b0f8028..ef79e7cd1d41fd 100644 --- a/test/parallel/test-bash-completion.js +++ b/test/parallel/test-bash-completion.js @@ -2,22 +2,32 @@ require('../common'); const assert = require('assert'); const child_process = require('child_process'); +const { inspect } = require('util'); const p = child_process.spawnSync( process.execPath, [ '--completion-bash' ]); assert.ifError(p.error); -assert.ok(p.stdout.toString().includes( - `_node_complete() { + +const output = p.stdout.toString().trim().replace(/\r/g, ''); +console.log(output) + +const prefix = `_node_complete() { local cur_word options cur_word="\${COMP_WORDS[COMP_CWORD]}" if [[ "\${cur_word}" == -* ]] ; then - COMPREPLY=( $(compgen -W '`)); -assert.ok(p.stdout.toString().includes( - `' -- "\${cur_word}") ) + COMPREPLY=( $(compgen -W '`.replace(/\r/g, ''); +const suffix = `' -- "\${cur_word}") ) return 0 else COMPREPLY=( $(compgen -f "\${cur_word}") ) return 0 fi } -complete -F _node_complete node node_g`)); +complete -F _node_complete node node_g`.replace(/\r/g, ''); + +assert.ok( + output.includes(prefix), + `Expect\n\n ${inspect(output)}\n\nto include\n\n${inspect(prefix)}`); +assert.ok( + output.includes(suffix), + `Expect\n\n ${inspect(output)}\n\nto include\n\n${inspect(suffix)}`); From e8986f0423c511f8496cfecb2a7be529bc463772 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Sun, 12 May 2019 16:13:12 +0800 Subject: [PATCH 3/3] fixup! fixup! src: port --bash-completion to C++ --- test/parallel/test-bash-completion.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-bash-completion.js b/test/parallel/test-bash-completion.js index ef79e7cd1d41fd..f6a1cc405eb02c 100644 --- a/test/parallel/test-bash-completion.js +++ b/test/parallel/test-bash-completion.js @@ -9,14 +9,14 @@ const p = child_process.spawnSync( assert.ifError(p.error); const output = p.stdout.toString().trim().replace(/\r/g, ''); -console.log(output) +console.log(output); const prefix = `_node_complete() { local cur_word options cur_word="\${COMP_WORDS[COMP_CWORD]}" if [[ "\${cur_word}" == -* ]] ; then COMPREPLY=( $(compgen -W '`.replace(/\r/g, ''); -const suffix = `' -- "\${cur_word}") ) +const suffix = `' -- "\${cur_word}") ) return 0 else COMPREPLY=( $(compgen -f "\${cur_word}") )