Skip to content

Commit

Permalink
src: port --bash-completion to C++
Browse files Browse the repository at this point in the history
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 BethGriggs committed Feb 6, 2020
1 parent 4f95213 commit 715c158
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 39 deletions.
29 changes: 0 additions & 29 deletions lib/internal/main/print_bash_completion.js

This file was deleted.

1 change: 0 additions & 1 deletion node.gyp
Expand Up @@ -139,7 +139,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',
Expand Down
15 changes: 12 additions & 3 deletions src/node.cc
Expand Up @@ -400,9 +400,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");
Expand Down Expand Up @@ -875,6 +872,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();
Expand Down Expand Up @@ -944,6 +947,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();
Expand Down
39 changes: 39 additions & 0 deletions src/node_options.cc
Expand Up @@ -4,6 +4,8 @@
#include "env-inl.h"
#include "node_binding.h"

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

using v8::Boolean;
Expand Down Expand Up @@ -847,6 +849,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) {
Expand Down
2 changes: 2 additions & 0 deletions src/node_options.h
Expand Up @@ -255,6 +255,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,
Expand Down Expand Up @@ -438,6 +439,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>;
Expand Down
22 changes: 16 additions & 6 deletions test/parallel/test-bash-completion.js
Expand Up @@ -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 715c158

Please sign in to comment.