Skip to content

Commit 403c84a

Browse files
joyeecheungBridgeAR
authored andcommitted
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>
1 parent 486ffa2 commit 403c84a

File tree

6 files changed

+69
-39
lines changed

6 files changed

+69
-39
lines changed

lib/internal/main/print_bash_completion.js

-29
This file was deleted.

node.gyp

-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@
145145
'lib/internal/main/eval_string.js',
146146
'lib/internal/main/eval_stdin.js',
147147
'lib/internal/main/inspect.js',
148-
'lib/internal/main/print_bash_completion.js',
149148
'lib/internal/main/print_help.js',
150149
'lib/internal/main/prof_process.js',
151150
'lib/internal/main/repl.js',

src/node.cc

+12-3
Original file line numberDiff line numberDiff line change
@@ -438,9 +438,6 @@ MaybeLocal<Value> StartMainThreadExecution(Environment* env) {
438438
return StartExecution(env, "internal/main/print_help");
439439
}
440440

441-
if (per_process::cli_options->print_bash_completion) {
442-
return StartExecution(env, "internal/main/print_bash_completion");
443-
}
444441

445442
if (env->options()->prof_process) {
446443
return StartExecution(env, "internal/main/prof_process");
@@ -974,6 +971,12 @@ void Init(int* argc,
974971
exit(0);
975972
}
976973

974+
if (per_process::cli_options->print_bash_completion) {
975+
std::string completion = options_parser::GetBashCompletion();
976+
printf("%s\n", completion.c_str());
977+
exit(0);
978+
}
979+
977980
if (per_process::cli_options->print_v8_help) {
978981
// Doesn't return.
979982
V8::SetFlagsFromString("--help", static_cast<size_t>(6));
@@ -1044,6 +1047,12 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) {
10441047
return result;
10451048
}
10461049

1050+
if (per_process::cli_options->print_bash_completion) {
1051+
std::string completion = options_parser::GetBashCompletion();
1052+
printf("%s\n", completion.c_str());
1053+
exit(0);
1054+
}
1055+
10471056
if (per_process::cli_options->print_v8_help) {
10481057
// Doesn't return.
10491058
V8::SetFlagsFromString("--help", static_cast<size_t>(6));

src/node_options.cc

+39
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include "env-inl.h"
55
#include "node_binding.h"
66

7+
#include <errno.h>
8+
#include <sstream>
79
#include <cstdlib> // strtoul, errno
810

911
using v8::Boolean;
@@ -809,6 +811,43 @@ HostPort SplitHostPort(const std::string& arg,
809811
ParseAndValidatePort(arg.substr(colon + 1), errors) };
810812
}
811813

814+
std::string GetBashCompletion() {
815+
Mutex::ScopedLock lock(per_process::cli_options_mutex);
816+
const auto& parser = _ppop_instance;
817+
818+
std::ostringstream out;
819+
820+
out << "_node_complete() {\n"
821+
" local cur_word options\n"
822+
" cur_word=\"${COMP_WORDS[COMP_CWORD]}\"\n"
823+
" if [[ \"${cur_word}\" == -* ]] ; then\n"
824+
" COMPREPLY=( $(compgen -W '";
825+
826+
for (const auto& item : parser.options_) {
827+
if (item.first[0] != '[') {
828+
out << item.first << " ";
829+
}
830+
}
831+
for (const auto& item : parser.aliases_) {
832+
if (item.first[0] != '[') {
833+
out << item.first << " ";
834+
}
835+
}
836+
if (parser.aliases_.size() > 0) {
837+
out.seekp(-1, out.cur); // Strip the trailing space
838+
}
839+
840+
out << "' -- \"${cur_word}\") )\n"
841+
" return 0\n"
842+
" else\n"
843+
" COMPREPLY=( $(compgen -f \"${cur_word}\") )\n"
844+
" return 0\n"
845+
" fi\n"
846+
"}\n"
847+
"complete -F _node_complete node node_g";
848+
return out.str();
849+
}
850+
812851
// Return a map containing all the options and their metadata as well
813852
// as the aliases
814853
void GetOptions(const FunctionCallbackInfo<Value>& args) {

src/node_options.h

+2
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ namespace options_parser {
254254
HostPort SplitHostPort(const std::string& arg,
255255
std::vector<std::string>* errors);
256256
void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
257+
std::string GetBashCompletion();
257258

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

439440
friend void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
441+
friend std::string GetBashCompletion();
440442
};
441443

442444
using StringVector = std::vector<std::string>;

test/parallel/test-bash-completion.js

+16-6
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,32 @@
22
require('../common');
33
const assert = require('assert');
44
const child_process = require('child_process');
5+
const { inspect } = require('util');
56

67
const p = child_process.spawnSync(
78
process.execPath, [ '--completion-bash' ]);
89
assert.ifError(p.error);
9-
assert.ok(p.stdout.toString().includes(
10-
`_node_complete() {
10+
11+
const output = p.stdout.toString().trim().replace(/\r/g, '');
12+
console.log(output);
13+
14+
const prefix = `_node_complete() {
1115
local cur_word options
1216
cur_word="\${COMP_WORDS[COMP_CWORD]}"
1317
if [[ "\${cur_word}" == -* ]] ; then
14-
COMPREPLY=( $(compgen -W '`));
15-
assert.ok(p.stdout.toString().includes(
16-
`' -- "\${cur_word}") )
18+
COMPREPLY=( $(compgen -W '`.replace(/\r/g, '');
19+
const suffix = `' -- "\${cur_word}") )
1720
return 0
1821
else
1922
COMPREPLY=( $(compgen -f "\${cur_word}") )
2023
return 0
2124
fi
2225
}
23-
complete -F _node_complete node node_g`));
26+
complete -F _node_complete node node_g`.replace(/\r/g, '');
27+
28+
assert.ok(
29+
output.includes(prefix),
30+
`Expect\n\n ${inspect(output)}\n\nto include\n\n${inspect(prefix)}`);
31+
assert.ok(
32+
output.includes(suffix),
33+
`Expect\n\n ${inspect(output)}\n\nto include\n\n${inspect(suffix)}`);

0 commit comments

Comments
 (0)