1
1
import * as vscode from 'vscode' ;
2
2
import * as settings from './configSettings' ;
3
- import { createDeferred , isNotInstalledError } from './helpers' ;
4
- import { execPythonFile , getFullyQualifiedPythonInterpreterPath } from './utils' ;
5
3
import * as os from 'os' ;
4
+ import { isNotInstalledError } from './helpers' ;
5
+ import { execPythonFile , getFullyQualifiedPythonInterpreterPath } from './utils' ;
6
6
import { Documentation } from './constants' ;
7
7
8
8
export enum Product {
@@ -86,9 +86,6 @@ export const Linters: Product[] = [
86
86
Product . pydocstyle
87
87
] ;
88
88
89
- const Formatters : Product [ ] = [ Product . autopep8 , Product . yapf ] ;
90
- const TestFrameworks : Product [ ] = [ Product . pytest , Product . nosetest , Product . unittest ] ;
91
-
92
89
const ProductNames = new Map < Product , string > ( ) ;
93
90
ProductNames . set ( Product . autopep8 , 'autopep8' ) ;
94
91
ProductNames . set ( Product . flake8 , 'flake8' ) ;
@@ -146,9 +143,9 @@ ProductTypes.set(Product.yapf, ProductType.Formatter);
146
143
ProductTypes . set ( Product . rope , ProductType . RefactoringLibrary ) ;
147
144
148
145
export class Installer implements vscode . Disposable {
149
- private static terminal : vscode . Terminal ;
146
+ private static terminal : vscode . Terminal | undefined | null ;
150
147
private disposables : vscode . Disposable [ ] = [ ] ;
151
- constructor ( private outputChannel : vscode . OutputChannel = null ) {
148
+ constructor ( private outputChannel ? : vscode . OutputChannel ) {
152
149
this . disposables . push ( vscode . window . onDidCloseTerminal ( term => {
153
150
if ( term === Installer . terminal ) {
154
151
Installer . terminal = null ;
@@ -158,46 +155,65 @@ export class Installer implements vscode.Disposable {
158
155
public dispose ( ) {
159
156
this . disposables . forEach ( d => d . dispose ( ) ) ;
160
157
}
158
+ public shouldDisplayPrompt ( product : Product ) {
159
+ const productName = ProductNames . get ( product ) ! ;
160
+ return settings . PythonSettings . getInstance ( ) . disablePromptForFeatures . indexOf ( productName ) === - 1 ;
161
+ }
161
162
162
- promptToInstall ( product : Product ) : Thenable < any > {
163
- const productType = ProductTypes . get ( product ) ;
163
+ async promptToInstall ( product : Product ) {
164
+ const productType = ProductTypes . get ( product ) ! ;
164
165
const productTypeName = ProductTypeNames . get ( productType ) ;
165
- const productName = ProductNames . get ( product ) ;
166
+ const productName = ProductNames . get ( product ) ! ;
167
+
168
+ if ( ! this . shouldDisplayPrompt ( product ) ) {
169
+ const message = `${ productTypeName } '${ productName } ' not installed.` ;
170
+ if ( this . outputChannel ) {
171
+ this . outputChannel . appendLine ( message ) ;
172
+ }
173
+ else {
174
+ console . warn ( message ) ;
175
+ }
176
+ return ;
177
+ }
166
178
167
179
const installOption = 'Install ' + productName ;
168
180
const disableOption = 'Disable ' + productTypeName ;
169
- const disableOptionGlobally = `Disable ${ productTypeName } globally ` ;
181
+ const dontShowAgain = `Don't show this prompt again ` ;
170
182
const alternateFormatter = product === Product . autopep8 ? 'yapf' : 'autopep8' ;
171
183
const useOtherFormatter = `Use '${ alternateFormatter } ' formatter` ;
172
184
const options = [ ] ;
173
185
options . push ( installOption ) ;
174
186
if ( productType === ProductType . Formatter ) {
175
- options . push ( ...[ installOption , useOtherFormatter ] ) ;
187
+ options . push ( ...[ useOtherFormatter ] ) ;
176
188
}
177
189
if ( SettingToDisableProduct . has ( product ) ) {
178
- options . push ( ...[ disableOption , disableOptionGlobally ] ) ;
190
+ options . push ( ...[ disableOption , dontShowAgain ] ) ;
179
191
}
180
192
return vscode . window . showErrorMessage ( `${ productTypeName } ${ productName } is not installed` , ...options ) . then ( item => {
181
193
switch ( item ) {
182
194
case installOption : {
183
195
return this . install ( product ) ;
184
196
}
185
- case disableOptionGlobally :
186
197
case disableOption : {
187
- const global = item === disableOptionGlobally ;
188
198
if ( Linters . indexOf ( product ) >= 0 ) {
189
- return disableLinter ( product , global ) ;
199
+ return disableLinter ( product ) ;
190
200
}
191
201
else {
192
202
const pythonConfig = vscode . workspace . getConfiguration ( 'python' ) ;
193
- const settingToDisable = SettingToDisableProduct . get ( product ) ;
194
- return pythonConfig . update ( settingToDisable , false , global ) ;
203
+ const settingToDisable = SettingToDisableProduct . get ( product ) ! ;
204
+ return pythonConfig . update ( settingToDisable , false ) ;
195
205
}
196
206
}
197
207
case useOtherFormatter : {
198
208
const pythonConfig = vscode . workspace . getConfiguration ( 'python' ) ;
199
209
return pythonConfig . update ( 'formatting.provider' , alternateFormatter ) ;
200
210
}
211
+ case dontShowAgain : {
212
+ const pythonConfig = vscode . workspace . getConfiguration ( 'python' ) ;
213
+ const features = pythonConfig . get ( 'disablePromptForFeatures' , [ ] as string [ ] ) ;
214
+ features . push ( productName ) ;
215
+ return pythonConfig . update ( 'disablePromptForFeatures' , features , true ) ;
216
+ }
201
217
case 'Help' : {
202
218
return Promise . resolve ( ) ;
203
219
}
@@ -215,7 +231,7 @@ export class Installer implements vscode.Disposable {
215
231
return Promise . resolve ( ) ;
216
232
}
217
233
218
- let installArgs = ProductInstallScripts . get ( product ) ;
234
+ let installArgs = ProductInstallScripts . get ( product ) ! ;
219
235
let pipIndex = installArgs . indexOf ( 'pip' ) ;
220
236
if ( pipIndex > 0 ) {
221
237
installArgs = installArgs . slice ( ) ;
@@ -228,8 +244,8 @@ export class Installer implements vscode.Disposable {
228
244
if ( this . outputChannel && installArgs [ 0 ] === '-m' ) {
229
245
// Errors are just displayed to the user
230
246
this . outputChannel . show ( ) ;
231
- return execPythonFile ( settings . PythonSettings . getInstance ( ) . pythonPath , installArgs , vscode . workspace . rootPath , true , ( data ) => {
232
- this . outputChannel . append ( data ) ;
247
+ return execPythonFile ( settings . PythonSettings . getInstance ( ) . pythonPath , installArgs , vscode . workspace . rootPath ! , true , ( data ) => {
248
+ this . outputChannel ! . append ( data ) ;
233
249
} ) ;
234
250
}
235
251
else {
@@ -249,8 +265,8 @@ export class Installer implements vscode.Disposable {
249
265
installScript = `${ pythonPath } ${ installScript } ` ;
250
266
}
251
267
}
252
- Installer . terminal . sendText ( installScript ) ;
253
- Installer . terminal . show ( false ) ;
268
+ Installer . terminal ! . sendText ( installScript ) ;
269
+ Installer . terminal ! . show ( false ) ;
254
270
} ) ;
255
271
}
256
272
}
@@ -266,7 +282,7 @@ export class Installer implements vscode.Disposable {
266
282
267
283
export function disableLinter ( product : Product , global ?: boolean ) {
268
284
const pythonConfig = vscode . workspace . getConfiguration ( 'python' ) ;
269
- const settingToDisable = SettingToDisableProduct . get ( product ) ;
285
+ const settingToDisable = SettingToDisableProduct . get ( product ) ! ;
270
286
if ( vscode . workspace . rootPath ) {
271
287
return pythonConfig . update ( settingToDisable , false , global ) ;
272
288
}
@@ -275,12 +291,12 @@ export function disableLinter(product: Product, global?: boolean) {
275
291
}
276
292
}
277
293
278
- function isProductInstalled ( product : Product ) : Promise < boolean | undefined > {
294
+ async function isProductInstalled ( product : Product ) : Promise < boolean | undefined > {
279
295
if ( ! ProductExecutableAndArgs . has ( product ) ) {
280
296
return ;
281
297
}
282
- const prodExec = ProductExecutableAndArgs . get ( product ) ;
283
- return execPythonFile ( prodExec . executable , prodExec . args . concat ( [ '--version' ] ) , vscode . workspace . rootPath , false )
298
+ const prodExec = ProductExecutableAndArgs . get ( product ) ! ;
299
+ return execPythonFile ( prodExec . executable , prodExec . args . concat ( [ '--version' ] ) , vscode . workspace . rootPath ! , false )
284
300
. then ( ( ) => {
285
301
return true ;
286
302
} ) . catch ( reason => {
@@ -289,6 +305,6 @@ function isProductInstalled(product: Product): Promise<boolean | undefined> {
289
305
}
290
306
291
307
function uninstallproduct ( product : Product ) : Promise < any > {
292
- const uninstallArgs = ProductUninstallScripts . get ( product ) ;
293
- return execPythonFile ( 'python' , uninstallArgs , vscode . workspace . rootPath , false ) ;
294
- }
308
+ const uninstallArgs = ProductUninstallScripts . get ( product ) ! ;
309
+ return execPythonFile ( 'python' , uninstallArgs , vscode . workspace . rootPath ! , false ) ;
310
+ }
0 commit comments