Skip to content
Permalink
Browse files

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

PR-URL: #25901
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
joyeecheung authored and BridgeAR committed Feb 3, 2019
1 parent 1357c97 commit 80732cdf9c4a6beb19226d720ffb20cb505bc6e4
Showing with 69 additions and 39 deletions.
  1. +0 −29 lib/internal/main/print_bash_completion.js
  2. +0 −1 node.gyp
  3. +12 −3 src/node.cc
  4. +39 −0 src/node_options.cc
  5. +2 −0 src/node_options.h
  6. +16 −6 test/parallel/test-bash-completion.js

This file was deleted.

@@ -145,7 +145,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',
@@ -438,9 +438,6 @@ MaybeLocal<Value> 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");
@@ -974,6 +971,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) {
// Doesn't return.
V8::SetFlagsFromString("--help", static_cast<size_t>(6));
@@ -1044,6 +1047,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) {
// Doesn't return.
V8::SetFlagsFromString("--help", static_cast<size_t>(6));
@@ -4,6 +4,8 @@
#include "env-inl.h"
#include "node_binding.h"

#include <errno.h>
#include <sstream>
#include <cstdlib> // strtoul, errno

using v8::Boolean;
@@ -809,6 +811,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<Value>& args) {
@@ -254,6 +254,7 @@ namespace options_parser {
HostPort SplitHostPort(const std::string& arg,
std::vector<std::string>* errors);
void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
std::string GetBashCompletion();

enum OptionType {
kNoOp,
@@ -437,6 +438,7 @@ class OptionsParser {
friend class OptionsParser;

friend void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
friend std::string GetBashCompletion();
};

using StringVector = std::vector<std::string>;
@@ -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)}`);

0 comments on commit 80732cd

Please sign in to comment.
You can’t perform that action at this time.