1
- const { spawn } = require ( 'child_process ' )
1
+ const spawn = require ( '@npmcli/promise-spawn ' )
2
2
const path = require ( 'path' )
3
3
const openUrl = require ( '../utils/open-url.js' )
4
4
const { promisify } = require ( 'util' )
@@ -14,19 +14,26 @@ const BaseCommand = require('../base-command.js')
14
14
const manNumberRegex = / \. ( \d + ) ( \. [ ^ / \\ ] * ) ? $ /
15
15
// Searches for the "npm-" prefix in page names, to prefer those.
16
16
const manNpmPrefixRegex = / \/ n p m - /
17
+ // hardcoded names for mansections
18
+ // XXX: these are used in the docs workspace and should be exported
19
+ // from npm so section names can changed more easily
20
+ const manSectionNames = {
21
+ 1 : 'commands' ,
22
+ 5 : 'configuring-npm' ,
23
+ 7 : 'using-npm' ,
24
+ }
17
25
18
26
class Help extends BaseCommand {
19
27
static description = 'Get help on npm'
20
28
static name = 'help'
21
29
static usage = [ '<term> [<terms..>]' ]
22
30
static params = [ 'viewer' ]
23
- static ignoreImplicitWorkspace = true
24
31
25
32
async completion ( opts ) {
26
33
if ( opts . conf . argv . remain . length > 2 ) {
27
34
return [ ]
28
35
}
29
- const g = path . resolve ( __dirname , '../../ man/man[0-9]/*.[0-9]' )
36
+ const g = path . resolve ( this . npm . npmRoot , 'man/man[0-9]/*.[0-9]' )
30
37
const files = await glob ( globify ( g ) )
31
38
32
39
return Object . keys ( files . reduce ( function ( acc , file ) {
@@ -40,10 +47,7 @@ class Help extends BaseCommand {
40
47
async exec ( args ) {
41
48
// By default we search all of our man subdirectories, but if the user has
42
49
// asked for a specific one we limit the search to just there
43
- let manSearch = 'man*'
44
- if ( / ^ \d + $ / . test ( args [ 0 ] ) ) {
45
- manSearch = `man${ args . shift ( ) } `
46
- }
50
+ const manSearch = / ^ \d + $ / . test ( args [ 0 ] ) ? `man${ args . shift ( ) } ` : 'man*'
47
51
48
52
if ( ! args . length ) {
49
53
return this . npm . output ( await this . npm . usage )
@@ -54,20 +58,18 @@ class Help extends BaseCommand {
54
58
return this . helpSearch ( args )
55
59
}
56
60
57
- let section = this . npm . deref ( args [ 0 ] ) || args [ 0 ]
58
-
59
- // support `npm help package.json`
60
- section = section . replace ( '.json' , '-json' )
61
+ // `npm help package.json`
62
+ const arg = ( this . npm . deref ( args [ 0 ] ) || args [ 0 ] ) . replace ( '.json' , '-json' )
61
63
62
- const manroot = path . resolve ( __dirname , '..' , '..' , 'man' )
63
64
// find either section.n or npm-section.n
64
- const f = ` ${ manroot } /${ manSearch } /?(npm-)${ section } .[0-9]*`
65
- let mans = await glob ( globify ( f ) )
66
- mans = mans . sort ( ( a , b ) => {
65
+ const f = globify ( path . resolve ( this . npm . npmRoot , `man /${ manSearch } /?(npm-)${ arg } .[0-9]*`) )
66
+
67
+ const [ man ] = await glob ( f ) . then ( r => r . sort ( ( a , b ) => {
67
68
// Prefer the page with an npm prefix, if there's only one.
68
69
const aHasPrefix = manNpmPrefixRegex . test ( a )
69
70
const bHasPrefix = manNpmPrefixRegex . test ( b )
70
71
if ( aHasPrefix !== bHasPrefix ) {
72
+ /* istanbul ignore next */
71
73
return aHasPrefix ? - 1 : 1
72
74
}
73
75
@@ -76,6 +78,7 @@ class Help extends BaseCommand {
76
78
const aManNumberMatch = a . match ( manNumberRegex )
77
79
const bManNumberMatch = b . match ( manNumberRegex )
78
80
if ( aManNumberMatch ) {
81
+ /* istanbul ignore next */
79
82
if ( ! bManNumberMatch ) {
80
83
return - 1
81
84
}
@@ -88,77 +91,41 @@ class Help extends BaseCommand {
88
91
}
89
92
90
93
return localeCompare ( a , b )
91
- } )
92
- const man = mans [ 0 ]
94
+ } ) )
93
95
94
- if ( man ) {
95
- await this . viewMan ( man )
96
- } else {
97
- return this . helpSearch ( args )
98
- }
96
+ return man ? this . viewMan ( man ) : this . helpSearch ( args )
99
97
}
100
98
101
99
helpSearch ( args ) {
102
100
return this . npm . exec ( 'help-search' , args )
103
101
}
104
102
105
103
async viewMan ( man ) {
106
- const env = { }
107
- Object . keys ( process . env ) . forEach ( function ( i ) {
108
- env [ i ] = process . env [ i ]
109
- } )
110
104
const viewer = this . npm . config . get ( 'viewer' )
111
105
112
- const opts = {
113
- env,
114
- stdio : 'inherit' ,
106
+ if ( viewer === 'browser' ) {
107
+ return openUrl ( this . npm , this . htmlMan ( man ) , 'help available at the following URL' , true )
115
108
}
116
109
117
- let bin = 'man'
118
- const args = [ ]
119
- switch ( viewer ) {
120
- case 'woman' :
121
- bin = 'emacsclient'
122
- args . push ( '-e' , `(woman-find-file '${ man } ')` )
123
- break
124
-
125
- case 'browser' :
126
- await openUrl ( this . npm , this . htmlMan ( man ) , 'help available at the following URL' , true )
127
- return
128
-
129
- default :
130
- args . push ( man )
131
- break
110
+ let args = [ 'man' , [ man ] ]
111
+ if ( viewer === 'woman' ) {
112
+ args = [ 'emacsclient' , [ '-e' , `(woman-find-file '${ man } ')` ] ]
132
113
}
133
114
134
- const proc = spawn ( bin , args , opts )
135
- return new Promise ( ( resolve , reject ) => {
136
- proc . on ( 'exit' , ( code ) => {
137
- if ( code ) {
138
- return reject ( new Error ( `help process exited with code: ${ code } ` ) )
139
- }
140
-
141
- return resolve ( )
142
- } )
115
+ return spawn ( ...args , { stdio : 'inherit' } ) . catch ( err => {
116
+ if ( err . code ) {
117
+ throw new Error ( `help process exited with code: ${ err . code } ` )
118
+ } else {
119
+ throw err
120
+ }
143
121
} )
144
122
}
145
123
146
124
// Returns the path to the html version of the man page
147
125
htmlMan ( man ) {
148
- let sect = man . match ( manNumberRegex ) [ 1 ]
126
+ const sect = manSectionNames [ man . match ( manNumberRegex ) [ 1 ] ]
149
127
const f = path . basename ( man ) . replace ( manNumberRegex , '' )
150
- switch ( sect ) {
151
- case '1' :
152
- sect = 'commands'
153
- break
154
- case '5' :
155
- sect = 'configuring-npm'
156
- break
157
- case '7' :
158
- sect = 'using-npm'
159
- break
160
- }
161
- return 'file:///' + path . resolve ( __dirname , '..' , '..' , 'docs' , 'output' , sect , f + '.html' )
128
+ return 'file:///' + path . resolve ( this . npm . npmRoot , `docs/output/${ sect } /${ f } .html` )
162
129
}
163
130
}
164
131
module . exports = Help
0 commit comments