Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
help.js114 linesDownload Raw Back to commands
1const spawn = require('@npmcli/promise-spawn')
2const path = require('node:path')
3const { openUrl } = require('../utils/open-url.js')
4const { glob } = require('glob')
5const { output, input } = require('proc-log')
6const localeCompare = require('@isaacs/string-locale-compare')('en')
7const { deref } = require('../utils/cmd-list.js')
8const BaseCommand = require('../base-cmd.js')
9
10const globify = pattern => pattern.split('\\').join('/')
11
12// Strips out the number from foo.7 or foo.7. or foo.7.tgz
13// We don't currently compress our man pages but if we ever did this would seamlessly continue supporting it
14const manNumberRegex = /\.(\d+)(\.[^/\\]*)?$/
15// hardcoded names for man sections
16// XXX: these are used in the docs workspace and should be exported from npm so section names can changed more easily
17const manSectionNames = {
18  1: 'commands',
19  5: 'configuring-npm',
20  7: 'using-npm',
21}
22
23class Help extends BaseCommand {
24  static description = 'Get help on npm'
25  static name = 'help'
26  static usage = ['<term> [<terms..>]']
27  static params = ['viewer']
28
29  static async completion (opts, npm) {
30    if (opts.conf.argv.remain.length > 2) {
31      return []
32    }
33    const g = path.resolve(npm.npmRoot, 'man/man[0-9]/*.[0-9]')
34    let files = await glob(globify(g))
35    // preserve glob@8 behavior
36    files = files.sort((a, b) => a.localeCompare(b, 'en'))
37
38    return Object.keys(files.reduce(function (acc, file) {
39      file = path.basename(file).replace(/\.[0-9]+$/, '')
40      file = file.replace(/^npm-/, '')
41      acc[file] = true
42      return acc
43    }, { help: true }))
44  }
45
46  async exec (args) {
47    // 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
48    const manSearch = /^\d+$/.test(args[0]) ? `man${args.shift()}` : 'man*'
49
50    if (!args.length) {
51      return output.standard(this.npm.usage)
52    }
53
54    // npm help foo bar baz: search topics
55    if (args.length > 1) {
56      return this.helpSearch(args)
57    }
58
59    // `npm help package.json`
60    const arg = (deref(args[0]) || args[0]).replace('.json', '-json')
61
62    // find either section.n or npm-section.n
63    const f = globify(path.resolve(this.npm.npmRoot, `man/${manSearch}/?(npm-)${arg}.[0-9]*`))
64
65    const [man] = await glob(f).then(r => r.sort((a, b) => {
66      // Because the glob is (subtly) different from manNumberRegex, we can't rely on it passing.
67      const aManNumberMatch = a.match(manNumberRegex)?.[1] || 999
68      const bManNumberMatch = b.match(manNumberRegex)?.[1] || 999
69      if (aManNumberMatch !== bManNumberMatch) {
70        return aManNumberMatch - bManNumberMatch
71      }
72      return localeCompare(a, b)
73    }))
74
75    return man ? this.viewMan(man) : this.helpSearch(args)
76  }
77
78  helpSearch (args) {
79    return this.npm.exec('help-search', args)
80  }
81
82  async viewMan (man) {
83    const viewer = this.npm.config.get('viewer')
84
85    if (viewer === 'browser') {
86      return openUrl(this.npm, this.htmlMan(man), 'help available at the following URL', true)
87    }
88
89    let args = ['man', [man]]
90    if (viewer === 'woman') {
91      args = ['emacsclient', ['-e', `(woman-find-file '${man}')`]]
92    }
93
94    try {
95      await input.start(() => spawn(...args, { stdio: 'inherit' }))
96    } catch (err) {
97      if (err.code) {
98        throw new Error(`help process exited with code: ${err.code}`)
99      } else {
100        throw err
101      }
102    }
103  }
104
105  // Returns the path to the html version of the man page
106  htmlMan (man) {
107    const sect = manSectionNames[man.match(manNumberRegex)[1]]
108    const f = path.basename(man).replace(manNumberRegex, '')
109    return 'file:///' + path.resolve(this.npm.npmRoot, `docs/output/${sect}/${f}.html`)
110  }
111}
112
113module.exports = Help
114 
codekingpro/portable-devtools · Team Ai