Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/commands/help.js')
-rw-r--r--lib/commands/help.js163
1 files changed, 163 insertions, 0 deletions
diff --git a/lib/commands/help.js b/lib/commands/help.js
new file mode 100644
index 000000000..5b6a87bfc
--- /dev/null
+++ b/lib/commands/help.js
@@ -0,0 +1,163 @@
+const { spawn } = require('child_process')
+const path = require('path')
+const openUrl = require('../utils/open-url.js')
+const { promisify } = require('util')
+const glob = promisify(require('glob'))
+const localeCompare = require('@isaacs/string-locale-compare')('en')
+
+const BaseCommand = require('../base-command.js')
+
+// Strips out the number from foo.7 or foo.7. or foo.7.tgz
+// We don't currently compress our man pages but if we ever did this would
+// seemlessly continue supporting it
+const manNumberRegex = /\.(\d+)(\.[^/\\]*)?$/
+
+class Help extends BaseCommand {
+ /* istanbul ignore next - see test/lib/load-all-commands.js */
+ static get description () {
+ return 'Get help on npm'
+ }
+
+ /* istanbul ignore next - see test/lib/load-all-commands.js */
+ static get name () {
+ return 'help'
+ }
+
+ /* istanbul ignore next - see test/lib/load-all-commands.js */
+ static get usage () {
+ return ['<term> [<terms..>]']
+ }
+
+ /* istanbul ignore next - see test/lib/load-all-commands.js */
+ static get params () {
+ return ['viewer']
+ }
+
+ async completion (opts) {
+ if (opts.conf.argv.remain.length > 2)
+ return []
+ const g = path.resolve(__dirname, '../man/man[0-9]/*.[0-9]')
+ const files = await glob(g)
+
+ return Object.keys(files.reduce(function (acc, file) {
+ file = path.basename(file).replace(/\.[0-9]+$/, '')
+ file = file.replace(/^npm-/, '')
+ acc[file] = true
+ return acc
+ }, { help: true }))
+ }
+
+ async exec (args) {
+ // By default we search all of our man subdirectories, but if the user has
+ // asked for a specific one we limit the search to just there
+ let manSearch = 'man*'
+ if (/^\d+$/.test(args[0]))
+ manSearch = `man${args.shift()}`
+
+ if (!args.length)
+ return this.npm.output(await this.npm.usage)
+
+ // npm help foo bar baz: search topics
+ if (args.length > 1)
+ return this.helpSearch(args)
+
+ let section = this.npm.deref(args[0]) || args[0]
+
+ // support `npm help package.json`
+ section = section.replace('.json', '-json')
+
+ const manroot = path.resolve(__dirname, '..', 'man')
+ // find either section.n or npm-section.n
+ const f = `${manroot}/${manSearch}/?(npm-)${section}.[0-9]*`
+ let mans = await glob(f)
+ mans = mans.sort((a, b) => {
+ // Because of the glob we know the manNumberRegex will pass
+ const aManNumber = a.match(manNumberRegex)[1]
+ const bManNumber = b.match(manNumberRegex)[1]
+
+ // man number sort first so that 1 aka commands are preferred
+ if (aManNumber !== bManNumber)
+ return aManNumber - bManNumber
+
+ return localeCompare(a, b)
+ })
+ const man = mans[0]
+
+ if (man)
+ await this.viewMan(man)
+ else
+ return this.helpSearch(args)
+ }
+
+ helpSearch (args) {
+ return new Promise((resolve, reject) => {
+ this.npm.commands['help-search'](args, (err) => {
+ // This would only error if args was empty, which it never is
+ /* istanbul ignore next */
+ if (err)
+ return reject(err)
+
+ resolve()
+ })
+ })
+ }
+
+ async viewMan (man) {
+ const env = {}
+ Object.keys(process.env).forEach(function (i) {
+ env[i] = process.env[i]
+ })
+ const viewer = this.npm.config.get('viewer')
+
+ const opts = {
+ env,
+ stdio: 'inherit',
+ }
+
+ let bin = 'man'
+ const args = []
+ switch (viewer) {
+ case 'woman':
+ bin = 'emacsclient'
+ args.push('-e', `(woman-find-file '${man}')`)
+ break
+
+ case 'browser':
+ await openUrl(this.npm, this.htmlMan(man), 'help available at the following URL')
+ return
+
+ default:
+ args.push(man)
+ break
+ }
+
+ const proc = spawn(bin, args, opts)
+ return new Promise((resolve, reject) => {
+ proc.on('exit', (code) => {
+ if (code)
+ return reject(new Error(`help process exited with code: ${code}`))
+
+ return resolve()
+ })
+ })
+ }
+
+ // Returns the path to the html version of the man page
+ htmlMan (man) {
+ let sect = man.match(manNumberRegex)[1]
+ const f = path.basename(man).replace(manNumberRegex, '')
+ switch (sect) {
+ case '1':
+ sect = 'commands'
+ break
+ case '5':
+ sect = 'configuring-npm'
+ break
+ case '7':
+ sect = 'using-npm'
+ break
+ }
+ return 'file://' + path.resolve(__dirname, '..', 'docs', 'output', sect, f + '.html')
+ }
+}
+module.exports = Help