Skip to content

Commit 1faa5b3

Browse files
committed
help: show usage when help-search finds no results
Fix #1655
1 parent b44768a commit 1faa5b3

File tree

3 files changed

+99
-82
lines changed

3 files changed

+99
-82
lines changed

lib/help-search.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@ const output = require('./utils/output.js')
77
const usageUtil = require('./utils/usage.js')
88
const { promisify } = require('util')
99
const readFile = promisify(fs.readFile)
10+
const didYouMean = require('./utils/did-you-mean.js')
11+
const { cmdList } = require('./utils/cmd-list.js')
1012

1113
const usage = usageUtil('help-search', 'npm help-search <text>')
1214
const completion = require('./utils/completion/none.js')
1315

16+
const npmUsage = require('./utils/npm-usage.js')
17+
1418
const cmd = (args, cb) => helpSearch(args).then(() => cb()).catch(cb)
1519

1620
const helpSearch = async args => {
@@ -26,7 +30,13 @@ const helpSearch = async args => {
2630

2731
const data = await readFiles(files)
2832
const results = await searchFiles(args, data, files)
29-
output(formatResults(args, results))
33+
const formatted = formatResults(args, results)
34+
if (!formatted.trim()) {
35+
npmUsage(false)
36+
} else {
37+
output(formatted)
38+
output(didYouMean(args[0], cmdList))
39+
}
3040
}
3141

3242
const readFiles = async files => {

lib/help.js

Lines changed: 3 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@ help.completion = function (opts, cb) {
66
getSections(cb)
77
}
88

9+
const npmUsage = require('./utils/npm-usage.js')
910
var path = require('path')
1011
var spawn = require('./utils/spawn')
1112
var npm = require('./npm.js')
1213
var log = require('npmlog')
1314
var openUrl = require('./utils/open-url')
1415
var glob = require('glob')
15-
var didYouMean = require('./utils/did-you-mean')
16-
var cmdList = require('./utils/cmd-list').cmdList
17-
var commands = cmdList
1816
var output = require('./utils/output.js')
1917

2018
const usage = require('./utils/usage.js')
@@ -42,7 +40,8 @@ function help (args, cb) {
4240
// npm help <noargs>: show basic usage
4341
if (!section) {
4442
var valid = argv[0] === 'help' ? 0 : 1
45-
return npmUsage(valid, cb)
43+
npmUsage(argv[0] === 'help')
44+
return cb()
4645
}
4746

4847
// npm <command> -h: show command usage
@@ -161,83 +160,6 @@ function htmlMan (man) {
161160
return 'file://' + path.resolve(__dirname, '..', 'docs', 'public', sect, f, 'index.html')
162161
}
163162

164-
function npmUsage (valid, cb) {
165-
npm.config.set('loglevel', 'silent')
166-
log.level = 'silent'
167-
output(`
168-
Usage: npm <command>
169-
170-
npm install install all the dependencies in your project
171-
npm install <foo> add the <foo> dependency to your project
172-
npm test run this project's tests
173-
npm run <foo> run the script named <foo>
174-
npm <command> -h quick help on <command>
175-
npm -l display usage info for all commands
176-
npm help <term> search for help on <term>
177-
npm help npm more involved overview
178-
179-
All commands:
180-
${npm.config.get('long') ? usages() : ('\n ' + wrap(commands))}
181-
182-
Specify configs in the ini-formatted file:
183-
${npm.config.get('userconfig')}
184-
or on the command line via: npm <command> --key=value
185-
186-
More configuration info: npm help config
187-
Configuration fields: npm help 7 config
188-
189-
npm@${npm.version} ${path.dirname(__dirname)}
190-
`)
191-
192-
if (npm.argv.length > 1) {
193-
output(didYouMean(npm.argv[1], commands))
194-
}
195-
196-
cb(valid)
197-
}
198-
199-
function usages () {
200-
// return a string of <command>: <usage>
201-
var maxLen = 0
202-
return commands.reduce(function (set, c) {
203-
set.push([c, require(`./${npm.deref(c)}.js`).usage || ''])
204-
maxLen = Math.max(maxLen, c.length)
205-
return set
206-
}, []).sort((a, b) => {
207-
return a[0].localeCompare(b[0])
208-
}).map(function (item) {
209-
var c = item[0]
210-
var usage = item[1]
211-
return '\n ' +
212-
c + (new Array(maxLen - c.length + 2).join(' ')) +
213-
(usage.split('\n').join('\n' + (new Array(maxLen + 6).join(' '))))
214-
}).join('\n')
215-
}
216-
217-
function wrap (arr) {
218-
var out = ['']
219-
var l = 0
220-
var line
221-
222-
line = process.stdout.columns
223-
if (!line) {
224-
line = 60
225-
} else {
226-
line = Math.min(60, Math.max(line - 16, 24))
227-
}
228-
229-
arr.sort(function (a, b) { return a < b ? -1 : 1 })
230-
.forEach(function (c) {
231-
if (out[l].length + c.length + 2 < line) {
232-
out[l] += ', ' + c
233-
} else {
234-
out[l++] += ','
235-
out[l] = c
236-
}
237-
})
238-
return out.join('\n ').substr(2)
239-
}
240-
241163
function getSections (cb) {
242164
var g = path.resolve(__dirname, '../man/man[0-9]/*.[0-9]')
243165
glob(g, function (er, files) {

lib/utils/npm-usage.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
const npm = require('../npm.js')
2+
const didYouMean = require('./did-you-mean.js')
3+
const { dirname } = require('path')
4+
const output = require('./output.js')
5+
const { cmdList } = require('./cmd-list')
6+
7+
module.exports = (valid = true) => {
8+
npm.config.set('loglevel', 'silent')
9+
npm.log.level = 'silent'
10+
output(`
11+
Usage: npm <command>
12+
13+
npm install install all the dependencies in your project
14+
npm install <foo> add the <foo> dependency to your project
15+
npm test run this project's tests
16+
npm run <foo> run the script named <foo>
17+
npm <command> -h quick help on <command>
18+
npm -l display usage info for all commands
19+
npm help <term> search for help on <term>
20+
npm help npm more involved overview
21+
22+
All commands:
23+
${npm.config.get('long') ? usages() : ('\n ' + wrap(cmdList))}
24+
25+
Specify configs in the ini-formatted file:
26+
${npm.config.get('userconfig')}
27+
or on the command line via: npm <command> --key=value
28+
29+
More configuration info: npm help config
30+
Configuration fields: npm help 7 config
31+
32+
npm@${npm.version} ${dirname(dirname(__dirname))}
33+
`)
34+
35+
if (npm.argv.length >= 1) {
36+
output(didYouMean(npm.argv[0], cmdList))
37+
}
38+
39+
if (!valid) {
40+
process.exitCode = 1
41+
}
42+
}
43+
44+
const wrap = (arr) => {
45+
var out = ['']
46+
var l = 0
47+
var line
48+
49+
line = process.stdout.columns
50+
if (!line) {
51+
line = 60
52+
} else {
53+
line = Math.min(60, Math.max(line - 16, 24))
54+
}
55+
56+
arr.sort(function (a, b) { return a < b ? -1 : 1 })
57+
.forEach(function (c) {
58+
if (out[l].length + c.length + 2 < line) {
59+
out[l] += ', ' + c
60+
} else {
61+
out[l++] += ','
62+
out[l] = c
63+
}
64+
})
65+
return out.join('\n ').substr(2)
66+
}
67+
68+
const usages = () => {
69+
// return a string of <command>: <usage>
70+
var maxLen = 0
71+
return cmdList.reduce(function (set, c) {
72+
set.push([c, require(`./${npm.deref(c)}.js`).usage || ''])
73+
maxLen = Math.max(maxLen, c.length)
74+
return set
75+
}, []).sort((a, b) => {
76+
return a[0].localeCompare(b[0])
77+
}).map(function (item) {
78+
var c = item[0]
79+
var usage = item[1]
80+
return '\n ' +
81+
c + (new Array(maxLen - c.length + 2).join(' ')) +
82+
(usage.split('\n').join('\n' + (new Array(maxLen + 6).join(' '))))
83+
}).join('\n')
84+
}
85+

0 commit comments

Comments
 (0)