diff --git a/package.json b/package.json index 1f1d40868afc..5afa6ff42ae3 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,7 @@ { "id": "python.selectInterpreter", "title": "Select a Python Interpreter", - "description": "Choose which Python interpreter/environment you want to use for your Python project.\n[Select Python Interpreter](command:python.setInterpreter)\n**Tip**: Run the ``Python: Select Interpreter`` command in the [Command Palette](command:workbench.action.showCommands).\nReload the window if you installed Python but don't see it in the list (``Developer: Reload Window`` command). ", + "description": "Choose which Python interpreter/environment you want to use for your Python project.\n[Select Python Interpreter](command:python.setInterpreter)\n**Tip**: Run the ``Python: Select Interpreter`` command in the [Command Palette](command:workbench.action.showCommands).", "media": { "svg": "resources/walkthrough/python-interpreter-v2.svg", "altText": "Selecting a python interpreter from the status bar" diff --git a/src/client/common/constants.ts b/src/client/common/constants.ts index 1c1064b77921..6981cf0fa146 100644 --- a/src/client/common/constants.ts +++ b/src/client/common/constants.ts @@ -73,6 +73,7 @@ export namespace Octicons { export const Gear = '$(gear)'; export const Warning = '$(warning)'; export const Error = '$(error)'; + export const Lightbulb = '$(lightbulb)'; } export const DEFAULT_INTERPRETER_SETTING = 'python'; diff --git a/src/client/interpreter/configuration/interpreterSelector/commands/setInterpreter.ts b/src/client/interpreter/configuration/interpreterSelector/commands/setInterpreter.ts index d1be191ebfe2..f344a85765ae 100644 --- a/src/client/interpreter/configuration/interpreterSelector/commands/setInterpreter.ts +++ b/src/client/interpreter/configuration/interpreterSelector/commands/setInterpreter.ts @@ -15,6 +15,7 @@ import { IPlatformService } from '../../../../common/platform/types'; import { IConfigurationService, IPathUtils, Resource } from '../../../../common/types'; import { getIcon } from '../../../../common/utils/icons'; import { Common, InterpreterQuickPickList } from '../../../../common/utils/localize'; +import { noop } from '../../../../common/utils/misc'; import { IMultiStepInput, IMultiStepInputFactory, @@ -80,6 +81,14 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand { alwaysShow: true, }; + private wasNoPythonInstalledItemClicked = false; + + private readonly tipToReloadWindow: ISpecialQuickPickItem = { + label: `${Octicons.Lightbulb} Reload the window if you installed Python but don't see it`, + detail: `Click to run \`Developer: Reload Window\` command`, + alwaysShow: true, + }; + constructor( @inject(IApplicationShell) applicationShell: IApplicationShell, @inject(IPathUtils) pathUtils: IPathUtils, @@ -171,7 +180,10 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand { sendTelemetryEvent(EventName.SELECT_INTERPRETER_ENTER_OR_FIND); return this._enterOrBrowseInterpreterPath(input, state, suggestions); } else if (selection.label === this.noPythonInstalled.label) { - this.commandManager.executeCommand(Commands.InstallPython); + this.commandManager.executeCommand(Commands.InstallPython).then(noop, noop); + this.wasNoPythonInstalledItemClicked = true; + } else if (selection.label === this.tipToReloadWindow.label) { + this.commandManager.executeCommand('workbench.action.reloadWindow').then(noop, noop); } else { sendTelemetryEvent(EventName.SELECT_INTERPRETER_SELECTED, undefined, { action: 'selected' }); state.path = (selection as IInterpreterQuickPickItem).path; @@ -302,6 +314,12 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand { if (noPyIndex !== -1) { updatedItems.splice(noPyIndex, 1); } + const tryReloadIndex = updatedItems.findIndex( + (item) => isSpecialQuickPickItem(item) && item.label === this.tipToReloadWindow.label, + ); + if (tryReloadIndex !== -1) { + updatedItems.splice(tryReloadIndex, 1); + } if (areItemsGrouped) { addSeparatorIfApplicable( updatedItems, @@ -340,6 +358,9 @@ export class SetInterpreterCommand extends BaseInterpreterSelectorCommand { }); } else { items.push(this.noPythonInstalled); + if (this.wasNoPythonInstalledItemClicked) { + items.push(this.tipToReloadWindow); + } } } } diff --git a/src/test/configuration/interpreterSelector/commands/setInterpreter.unit.test.ts b/src/test/configuration/interpreterSelector/commands/setInterpreter.unit.test.ts index d51e81365015..ef73ef4cec04 100644 --- a/src/test/configuration/interpreterSelector/commands/setInterpreter.unit.test.ts +++ b/src/test/configuration/interpreterSelector/commands/setInterpreter.unit.test.ts @@ -135,6 +135,12 @@ suite('Set Interpreter Command', () => { alwaysShow: true, }; + const tipToReloadWindow = { + label: `${Octicons.Lightbulb} Reload the window if you installed Python but don't see it`, + detail: `Click to run \`Developer: Reload Window\` command`, + alwaysShow: true, + }; + const refreshedItem: IInterpreterQuickPickItem = { description: interpreterPath, detail: '', @@ -322,6 +328,26 @@ suite('Set Interpreter Command', () => { commandManager.verifyAll(); }); + test('Picker should reload window if corresponding item is selected', async () => { + const state: InterpreterStateArgs = { path: 'some path', workspace: undefined }; + const multiStepInput = TypeMoq.Mock.ofType>(); + multiStepInput + .setup((i) => i.showQuickPick(TypeMoq.It.isAny())) + .returns(() => Promise.resolve((tipToReloadWindow as unknown) as QuickPickItem)); + interpreterSelector.reset(); + interpreterSelector + .setup((i) => i.getSuggestions(TypeMoq.It.isAny(), TypeMoq.It.isAny())) + .returns(() => []); + commandManager + .setup((c) => c.executeCommand('workbench.action.reloadWindow')) + .returns(() => Promise.resolve()) + .verifiable(TypeMoq.Times.once()); + + await setInterpreterCommand._pickInterpreter(multiStepInput.object, state); + + commandManager.verifyAll(); + }); + test('Items displayed should be grouped if no refresh is going on', async () => { const state: InterpreterStateArgs = { path: 'some path', workspace: undefined }; const multiStepInput = TypeMoq.Mock.ofType>();