summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2018-08-23 22:07:13 +0200
committerAnna Henningsen <anna@addaleax.net>2018-09-01 00:13:23 +0200
commitc8880ea27645aec31ef9dd5687c57747f338d67f (patch)
tree6c0bae2ba0dc4377a8d111e2890563860e3c6acb /lib
parente812be4a55915575fc1afce739848026a48b781e (diff)
downloadandroid-node-v8-c8880ea27645aec31ef9dd5687c57747f338d67f.tar.gz
android-node-v8-c8880ea27645aec31ef9dd5687c57747f338d67f.tar.bz2
android-node-v8-c8880ea27645aec31ef9dd5687c57747f338d67f.zip
cli: generate --help text in JS
Instead of having a custom, static, hand-written string that is being printed to stdout when `--help` is present, generate it in JS when requested. PR-URL: https://github.com/nodejs/node/pull/22490 Reviewed-By: Michaƫl Zasso <targos@protonmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/internal/bootstrap/node.js5
-rw-r--r--lib/internal/print_help.js151
2 files changed, 156 insertions, 0 deletions
diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js
index 30b177c5a4..069c8bc997 100644
--- a/lib/internal/bootstrap/node.js
+++ b/lib/internal/bootstrap/node.js
@@ -105,6 +105,11 @@
NativeModule.require('internal/inspector_async_hook').setup();
}
+ if (internalBinding('options').getOptions('--help')) {
+ NativeModule.require('internal/print_help').print(process.stdout);
+ return;
+ }
+
if (isMainThread) {
mainThreadSetup.setupChildProcessIpcChannel();
}
diff --git a/lib/internal/print_help.js b/lib/internal/print_help.js
new file mode 100644
index 0000000000..9d14671973
--- /dev/null
+++ b/lib/internal/print_help.js
@@ -0,0 +1,151 @@
+'use strict';
+const { internalBinding } = require('internal/bootstrap/loaders');
+const { getOptions, types } = internalBinding('options');
+
+const typeLookup = [];
+for (const key of Object.keys(types))
+ typeLookup[types[key]] = key;
+
+// Environment variables are parsed ad-hoc throughout the code base,
+// so we gather the documentation here.
+const { hasIntl, hasSmallICU, hasNodeOptions } = process.binding('config');
+const envVars = new Map([
+ ['NODE_DEBUG', { helpText: "','-separated list of core modules that " +
+ 'should print debug information' }],
+ ['NODE_DEBUG_NATIVE', { helpText: "','-separated list of C++ core debug " +
+ 'categories that should print debug output' }],
+ ['NODE_DISABLE_COLORS', { helpText: 'set to 1 to disable colors in ' +
+ 'the REPL' }],
+ ['NODE_EXTRA_CA_CERTS', { helpText: 'path to additional CA certificates ' +
+ 'file' }],
+ ['NODE_NO_WARNINGS', { helpText: 'set to 1 to silence process warnings' }],
+ ['NODE_PATH', { helpText: `'${require('path').delimiter}'-separated list ` +
+ 'of directories prefixed to the module search path' }],
+ ['NODE_PENDING_DEPRECATION', { helpText: 'set to 1 to emit pending ' +
+ 'deprecation warnings' }],
+ ['NODE_PRESERVE_SYMLINKS', { helpText: 'set to 1 to preserve symbolic ' +
+ 'links when resolving and caching modules' }],
+ ['NODE_REDIRECT_WARNINGS', { helpText: 'write warnings to path instead ' +
+ 'of stderr' }],
+ ['NODE_REPL_HISTORY', { helpText: 'path to the persistent REPL ' +
+ 'history file' }],
+ ['OPENSSL_CONF', { helpText: 'load OpenSSL configuration from file' }]
+].concat(hasIntl ? [
+ ['NODE_ICU_DATA', { helpText: 'data path for ICU (Intl object) data' +
+ hasSmallICU ? '' : ' (will extend linked-in data)' }]
+] : []).concat(hasNodeOptions ? [
+ ['NODE_OPTIONS', { helpText: 'set CLI options in the environment via a ' +
+ 'space-separated list' }]
+] : []));
+
+
+function indent(text, depth) {
+ return text.replace(/^/gm, ' '.repeat(depth));
+}
+
+function fold(text, width) {
+ return text.replace(new RegExp(`([^\n]{0,${width}})( |$)`, 'g'),
+ (_, newLine, end) => newLine + (end === ' ' ? '\n' : ''));
+}
+
+function getArgDescription(type) {
+ switch (typeLookup[type]) {
+ case 'kNoOp':
+ case 'kV8Option':
+ case 'kBoolean':
+ break;
+ case 'kHostPort':
+ return '[host:]port';
+ case 'kInteger':
+ case 'kString':
+ case 'kStringList':
+ return '...';
+ case undefined:
+ break;
+ default:
+ require('assert').fail(`unknown option type ${type}`);
+ }
+}
+
+function format({ options, aliases = new Map(), firstColumn, secondColumn }) {
+ let text = '';
+
+ for (const [
+ name, { helpText, type, value }
+ ] of [...options.entries()].sort()) {
+ if (!helpText) continue;
+
+ let displayName = name;
+ const argDescription = getArgDescription(type);
+ if (argDescription)
+ displayName += `=${argDescription}`;
+
+ for (const [ from, to ] of aliases) {
+ // For cases like e.g. `-e, --eval`.
+ if (to[0] === name && to.length === 1) {
+ displayName = `${from}, ${displayName}`;
+ }
+
+ // For cases like `--inspect-brk[=[host:]port]`.
+ const targetInfo = options.get(to[0]);
+ const targetArgDescription =
+ targetInfo ? getArgDescription(targetInfo.type) : '...';
+ if (from === `${name}=`) {
+ displayName += `[=${targetArgDescription}]`;
+ } else if (from === `${name} <arg>`) {
+ displayName += ` [${targetArgDescription}]`;
+ }
+ }
+
+ let displayHelpText = helpText;
+ if (value === true) {
+ // Mark boolean options we currently have enabled.
+ // In particular, it indicates whether --use-openssl-ca
+ // or --use-bundled-ca is the (current) default.
+ displayHelpText += ' (currently set)';
+ }
+
+ text += displayName;
+ if (displayName.length >= firstColumn)
+ text += '\n' + ' '.repeat(firstColumn);
+ else
+ text += ' '.repeat(firstColumn - displayName.length);
+
+ text += indent(fold(displayHelpText, secondColumn),
+ firstColumn).trimLeft() + '\n';
+ }
+
+ return text;
+}
+
+function print(stream) {
+ const { options, aliases } = getOptions();
+
+ // TODO(addaleax): Allow a bit of expansion depending on `stream.columns`
+ // if it is set.
+ const firstColumn = 28;
+ const secondColumn = 40;
+
+ options.set('-', { helpText: 'script read from stdin (default; ' +
+ 'interactive mode if a tty)' });
+ options.set('--', { helpText: 'indicate the end of node options' });
+ stream.write(
+ 'Usage: node [options] [ -e script | script.js | - ] [arguments]\n' +
+ ' node inspect script.js [arguments]\n\n' +
+ 'Options:\n');
+ stream.write(indent(format({
+ options, aliases, firstColumn, secondColumn
+ }), 2));
+
+ stream.write('\nEnvironment variables:\n');
+
+ stream.write(format({
+ options: envVars, firstColumn, secondColumn
+ }));
+
+ stream.write('\nDocumentation can be found at https://nodejs.org/\n');
+}
+
+module.exports = {
+ print
+};