From 691df8937fd2b875791a086e19a8a74cc21c0b75 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Fri, 7 Feb 2020 12:16:30 -0800 Subject: [PATCH] Display commands when necessary --- news/3 Code Health/8869.md | 1 + package.json | 97 +++++++++++++------ src/client/common/contextKey.ts | 3 + src/client/datascience/constants.ts | 8 +- .../context/activeEditorContext.ts | 39 +++++++- .../interactive-common/interactiveBase.ts | 7 +- .../interactive-ipynb/nativeEditor.ts | 9 +- .../interactive-window/interactiveWindow.ts | 7 +- src/client/datascience/types.ts | 6 ++ src/client/datascience/webViewHost.ts | 16 +-- 10 files changed, 138 insertions(+), 55 deletions(-) create mode 100644 news/3 Code Health/8869.md diff --git a/news/3 Code Health/8869.md b/news/3 Code Health/8869.md new file mode 100644 index 000000000000..ef4e21f338c6 --- /dev/null +++ b/news/3 Code Health/8869.md @@ -0,0 +1 @@ +Display `Commands` related to `Interactive Window` and `Notebooks` only when necessary. diff --git a/package.json b/package.json index ef0e71028624..a9dfd4122b6c 100644 --- a/package.json +++ b/package.json @@ -656,7 +656,7 @@ { "command": "python.datascience.execSelectionInteractive", "group": "Python2", - "when": "editorFocus && editorLangId == python && python.datascience.featureenabled && python.datascience.ownsSelection" + "when": "editorFocus && editorLangId == python && python.datascience.featureenabled && python.datascience.ownsSelection" }, { "when": "editorFocus && editorLangId == python && resourceLangId == jupyter && python.datascience.featureenabled", @@ -770,43 +770,43 @@ "command": "python.datascience.runcurrentcell", "title": "%python.command.python.datascience.runcurrentcell.title%", "category": "Python", - "when": "python.datascience.hascodecells && python.datascience.featureenabled" + "when": "python.datascience.hascodecells && python.datascience.featureenabled && python.datascience.ispythonornativeactive" }, { "command": "python.datascience.runcurrentcelladvance", "title": "%python.command.python.datascience.runcurrentcelladvance.title%", "category": "Python", - "when": "python.datascience.hascodecells && python.datascience.featureenabled" + "when": "python.datascience.hascodecells && python.datascience.featureenabled && python.datascience.ispythonornativeactive" }, { "command": "python.datascience.runcurrentcellandallbelow.palette", "title": "%python.command.python.datascience.runcurrentcellandallbelow.palette.title%", "category": "Python", - "when": "python.datascience.hascodecells && python.datascience.featureenabled" + "when": "python.datascience.hascodecells && python.datascience.featureenabled && python.datascience.ispythonornativeactive" }, { "command": "python.datascience.runallcellsabove.palette", "title": "%python.command.python.datascience.runallcellsabove.palette.title%", "category": "Python", - "when": "python.datascience.hascodecells && python.datascience.featureenabled" + "when": "python.datascience.hascodecells && python.datascience.featureenabled && python.datascience.ispythonornativeactive" }, { "command": "python.datascience.debugcurrentcell.palette", "title": "%python.command.python.datascience.debugcurrentcell.palette.title%", "category": "Python", - "when": "python.datascience.hascodecells && python.datascience.featureenabled" + "when": "editorFocus && editorLangId == python && python.datascience.hascodecells && python.datascience.featureenabled" }, { "command": "python.datascience.showhistorypane", "title": "%python.command.python.datascience.showhistorypane.title%", "category": "Python", - "when": "python.datascience.featureenabled" + "when": "python.datascience.featureenabled && !python.datascience.isinteractiveactive" }, { "command": "python.datascience.runallcells", "title": "%python.command.python.datascience.runallcells.title%", "category": "Python", - "when": "python.datascience.hascodecells && python.datascience.featureenabled" + "when": "python.datascience.hascodecells && python.datascience.featureenabled && python.datascience.ispythonornativeactive" }, { "command": "python.datascience.scrolltocell", @@ -818,25 +818,25 @@ "command": "python.datascience.debugcell", "title": "%python.command.python.datascience.debugcell.title%", "category": "Python", - "when": "python.datascience.hascodecells && python.datascience.featureenabled" + "when": "config.noExists" }, { "command": "python.datascience.runcell", "title": "%python.command.python.datascience.runcell.title%", "category": "Python", - "when": "python.datascience.hascodecells && python.datascience.featureenabled" + "when": "config.noExists" }, { "command": "python.datascience.runFileInteractive", "title": "%python.command.python.datascience.runFileInteractive.title%", "category": "Python", - "when": "python.datascience.featureenabled" + "when": "editorFocus && editorLangId == python && python.datascience.featureenabled" }, { "command": "python.datascience.debugFileInteractive", "title": "%python.command.python.datascience.debugFileInteractive.title%", "category": "Python", - "when": "python.datascience.featureenabled" + "when": "editorFocus && editorLangId == python && python.datascience.featureenabled" }, { "command": "python.datascience.importnotebook", @@ -852,109 +852,109 @@ "command": "python.datascience.exportfileasnotebook", "title": "%python.command.python.datascience.exportfileasnotebook.title%", "category": "Python", - "when": "python.datascience.hascodecells && python.datascience.featureenabled" + "when": "python.datascience.hascodecells && python.datascience.featureenabled && python.datascience.ispythonorinteractiveeactive" }, { "command": "python.datascience.exportfileandoutputasnotebook", "title": "%python.command.python.datascience.exportfileandoutputasnotebook.title%", "category": "Python", - "when": "python.datascience.hascodecells && python.datascience.featureenabled" + "when": "python.datascience.hascodecells && python.datascience.featureenabled && python.datascience.ispythonorinteractiveeactive" }, { "command": "python.datascience.undocells", "title": "%python.command.python.datascience.undocells.title%", "category": "Python", - "when": "python.datascience.haveinteractivecells && python.datascience.featureenabled" + "when": "python.datascience.haveinteractivecells && python.datascience.featureenabled && python.datascience.ispythonorinteractiveeactive" }, { "command": "python.datascience.redocells", "title": "%python.command.python.datascience.redocells.title%", "category": "Python", - "when": "python.datascience.haveredoablecells && python.datascience.featureenabled" + "when": "python.datascience.haveredoablecells && python.datascience.featureenabled && python.datascience.ispythonorinteractiveornativeeactive" }, { "command": "python.datascience.removeallcells", "title": "%python.command.python.datascience.removeallcells.title%", "category": "Python", - "when": "python.datascience.haveinteractivecells && python.datascience.featureenabled" + "when": "python.datascience.haveinteractivecells && python.datascience.featureenabled && python.datascience.ispythonorinteractiveeactive" }, { "command": "python.datascience.interruptkernel", "title": "%python.command.python.datascience.interruptkernel.title%", "category": "Python", - "when": "python.datascience.haveinteractive && python.datascience.featureenabled" + "when": "python.datascience.haveinteractive && python.datascience.featureenabled && python.datascience.ispythonorinteractiveeactive" }, { "command": "python.datascience.restartkernel", "title": "%python.command.python.datascience.restartkernel.title%", "category": "Python", - "when": "python.datascience.haveinteractive && python.datascience.featureenabled" + "when": "python.datascience.haveinteractive && python.datascience.featureenabled && python.datascience.ispythonorinteractiveeactive" }, { "command": "python.datascience.notebookeditor.undocells", "title": "%python.command.python.datascience.undocells.title%", "category": "Python", - "when": "python.datascience.haveinteractivecells && python.datascience.featureenabled" + "when": "python.datascience.haveinteractivecells && python.datascience.featureenabled && python.datascience.isnativeactive" }, { "command": "python.datascience.notebookeditor.redocells", "title": "%python.command.python.datascience.redocells.title%", "category": "Python", - "when": "python.datascience.havenativeredoablecells && python.datascience.featureenabled" + "when": "python.datascience.havenativeredoablecells && python.datascience.featureenabled && python.datascience.isnativeactive" }, { "command": "python.datascience.notebookeditor.removeallcells", "title": "%python.command.python.datascience.notebookeditor.removeallcells.title%", "category": "Python", - "when": "python.datascience.havenativecells && python.datascience.featureenabled" + "when": "python.datascience.havenativecells && python.datascience.featureenabled && python.datascience.isnativeactive" }, { "command": "python.datascience.notebookeditor.interruptkernel", "title": "%python.command.python.datascience.interruptkernel.title%", "category": "Python", - "when": "python.datascience.havenative && python.datascience.featureenabled" + "when": "python.datascience.isnativeactive && python.datascience.featureenabled" }, { "command": "python.datascience.notebookeditor.restartkernel", "title": "%python.command.python.datascience.restartkernel.title%", "category": "Python", - "when": "python.datascience.havenative && python.datascience.featureenabled" + "when": "python.datascience.isnativeactive && python.datascience.featureenabled" }, { "command": "python.datascience.notebookeditor.runallcells", "title": "%python.command.python.datascience.notebookeditor.runallcells.title%", "category": "Python", - "when": "python.datascience.havenative && python.datascience.featureenabled" + "when": "python.datascience.isnativeactive && python.datascience.featureenabled" }, { "command": "python.datascience.notebookeditor.runselectedcell", "title": "%python.command.python.datascience.notebookeditor.runselectedcell.title%", "category": "Python", - "when": "python.datascience.havenative && python.datascience.featureenabled && python.datascience.havecellselected" + "when": "python.datascience.isnativeactive && python.datascience.featureenabled && python.datascience.havecellselected" }, { "command": "python.datascience.notebookeditor.addcellbelow", "title": "%python.command.python.datascience.notebookeditor.addcellbelow.title%", "category": "Python", - "when": "python.datascience.havenative && python.datascience.featureenabled" + "when": "python.datascience.isnativeactive && python.datascience.featureenabled" }, { "command": "python.datascience.expandallcells", "title": "%python.command.python.datascience.expandallcells.title%", "category": "Python", - "when": "python.datascience.haveinteractive && python.datascience.featureenabled" + "when": "python.datascience.isinteractiveactive && python.datascience.featureenabled" }, { "command": "python.datascience.collapseallcells", "title": "%python.command.python.datascience.collapseallcells.title%", "category": "Python", - "when": "python.datascience.haveinteractive && python.datascience.featureenabled" + "when": "python.datascience.isinteractiveactive && python.datascience.featureenabled" }, { "command": "python.datascience.exportoutputasnotebook", "title": "%python.command.python.datascience.exportoutputasnotebook.title%", "category": "Python", - "when": "python.datascience.haveinteractive && python.datascience.featureenabled" + "when": "python.datascience.isinteractiveactive && python.datascience.featureenabled" }, { "command": "python.datascience.runcellandallbelow", @@ -966,16 +966,51 @@ "category": "Python", "when": "config.noExists" }, + { + "command": "python.datascience.debugcontinue", + "category": "Python", + "when": "config.noExists" + }, + { + "command": "python.datascience.debugstop", + "category": "Python", + "when": "config.noExists" + }, + { + "command": "python.datascience.debugstepover", + "category": "Python", + "when": "config.noExists" + }, + { + "command": "python.datascience.debugcell", + "category": "Python", + "when": "config.noExists" + }, { "command": "python.datascience.addcellbelow", "title": "%python.command.python.datascience.addcellbelow.title%", "category": "Python", - "when": "python.datascience.hascodecells && python.datascience.featureenabled" + "when": "python.datascience.hascodecells && python.datascience.featureenabled && python.datascience.ispythonornativeactive" }, { "command": "python.datascience.createnewnotebook", "title": "%python.command.python.datascience.createnewnotebook.title%", "category": "Python" + }, + { + "command": "python.datascience.runtoline", + "category": "Python", + "when": "config.noExists" + }, + { + "command": "python.datascience.runfromline", + "category": "Python", + "when": "config.noExists" + }, + { + "command": "python.datascience.execSelectionInteractive", + "category": "Python", + "when": "editorFocus && editorLangId == python && python.datascience.featureenabled && python.datascience.ownsSelection" } ], "view/title": [ diff --git a/src/client/common/contextKey.ts b/src/client/common/contextKey.ts index a6aa86678c33..96022a3ba3ce 100644 --- a/src/client/common/contextKey.ts +++ b/src/client/common/contextKey.ts @@ -1,6 +1,9 @@ import { ICommandManager } from './application/types'; export class ContextKey { + public get value(): boolean | undefined { + return this.lastValue; + } private lastValue?: boolean; constructor(private name: string, private commandManager: ICommandManager) {} diff --git a/src/client/datascience/constants.ts b/src/client/datascience/constants.ts index 4f59c614cf29..c00b377705de 100644 --- a/src/client/datascience/constants.ts +++ b/src/client/datascience/constants.ts @@ -79,12 +79,16 @@ export namespace EditorContexts { export const HaveInteractiveCells = 'python.datascience.haveinteractivecells'; export const HaveRedoableCells = 'python.datascience.haveredoablecells'; export const HaveInteractive = 'python.datascience.haveinteractive'; - export const IsInteractive = 'python.datascience.isinteractive'; + export const IsInteractiveActive = 'python.datascience.isinteractiveactive'; export const OwnsSelection = 'python.datascience.ownsSelection'; export const HaveNativeCells = 'python.datascience.havenativecells'; export const HaveNativeRedoableCells = 'python.datascience.havenativeredoablecells'; export const HaveNative = 'python.datascience.havenative'; - export const IsNative = 'python.datascience.isnative'; + export const IsNativeActive = 'python.datascience.isnativeactive'; + export const IsInteractiveOrNativeActive = 'python.datascience.isinteractiveornativeactive'; + export const IsPythonOrNativeActive = 'python.datascience.ispythonornativeactive'; + export const IsPythonOrInteractiveActive = 'python.datascience.ispythonorinteractiveeactive'; + export const IsPythonOrInteractiveOrNativeActive = 'python.datascience.ispythonorinteractiveornativeeactive'; export const HaveCellSelected = 'python.datascience.havecellselected'; } diff --git a/src/client/datascience/context/activeEditorContext.ts b/src/client/datascience/context/activeEditorContext.ts index 3fe1802aa596..d19e54a6bc4e 100644 --- a/src/client/datascience/context/activeEditorContext.ts +++ b/src/client/datascience/context/activeEditorContext.ts @@ -4,8 +4,10 @@ 'use strict'; import { inject, injectable } from 'inversify'; +import { TextEditor } from 'vscode'; import { IExtensionSingleActivationService } from '../../activation/types'; -import { ICommandManager } from '../../common/application/types'; +import { ICommandManager, IDocumentManager } from '../../common/application/types'; +import { PYTHON_LANGUAGE } from '../../common/constants'; import { ContextKey } from '../../common/contextKey'; import { IDisposable, IDisposableRegistry } from '../../common/types'; import { EditorContexts } from '../constants'; @@ -14,28 +16,55 @@ import { IInteractiveWindow, IInteractiveWindowProvider, INotebookEditor, INoteb @injectable() export class ActiveEditorContextService implements IExtensionSingleActivationService, IDisposable { private readonly disposables: IDisposable[] = []; + private nativeContext: ContextKey; + private interactiveContext: ContextKey; + private interactiveOrNativeContext: ContextKey; + private pythonOrInteractiveContext: ContextKey; + private pythonOrNativeContext: ContextKey; + private pythonOrInteractiveOrNativeContext: ContextKey; + private isPythonFileActive: boolean = false; constructor( @inject(IInteractiveWindowProvider) private readonly interactiveProvider: IInteractiveWindowProvider, @inject(INotebookEditorProvider) private readonly notebookProvider: INotebookEditorProvider, + @inject(IDocumentManager) private readonly docManager: IDocumentManager, @inject(ICommandManager) private readonly commandManager: ICommandManager, @inject(IDisposableRegistry) disposables: IDisposableRegistry ) { disposables.push(this); + this.nativeContext = new ContextKey(EditorContexts.IsNativeActive, this.commandManager); + this.interactiveContext = new ContextKey(EditorContexts.IsInteractiveActive, this.commandManager); + this.interactiveOrNativeContext = new ContextKey(EditorContexts.IsInteractiveOrNativeActive, this.commandManager); + this.pythonOrNativeContext = new ContextKey(EditorContexts.IsPythonOrNativeActive, this.commandManager); + this.pythonOrInteractiveContext = new ContextKey(EditorContexts.IsPythonOrInteractiveActive, this.commandManager); + this.pythonOrInteractiveOrNativeContext = new ContextKey(EditorContexts.IsPythonOrInteractiveOrNativeActive, this.commandManager); } public dispose() { this.disposables.forEach(item => item.dispose()); } public async activate(): Promise { + this.docManager.onDidChangeActiveTextEditor(this.onDidChangeActiveTextEditor, this, this.disposables); this.interactiveProvider.onDidChangeActiveInteractiveWindow(this.onDidChangeActiveInteractiveWindow, this, this.disposables); this.notebookProvider.onDidChangeActiveNotebookEditor(this.onDidChangeActiveNotebookEditor, this, this.disposables); } private onDidChangeActiveInteractiveWindow(e?: IInteractiveWindow) { - const interactiveContext = new ContextKey(EditorContexts.IsInteractive, this.commandManager); - interactiveContext.set(!!e).ignoreErrors(); + this.interactiveContext.set(!!e).ignoreErrors(); + this.updateMergedContexts(); } private onDidChangeActiveNotebookEditor(e?: INotebookEditor) { - const interactiveContext = new ContextKey(EditorContexts.IsNative, this.commandManager); - interactiveContext.set(!!e).ignoreErrors(); + this.nativeContext.set(!!e).ignoreErrors(); + this.updateMergedContexts(); + } + private onDidChangeActiveTextEditor(e?: TextEditor) { + this.isPythonFileActive = e?.document.languageId === PYTHON_LANGUAGE; + this.updateMergedContexts(); + } + private updateMergedContexts() { + this.interactiveOrNativeContext.set(this.nativeContext.value === true && this.interactiveContext.value === true).ignoreErrors(); + this.pythonOrNativeContext.set(this.nativeContext.value === true || this.isPythonFileActive === true).ignoreErrors(); + this.pythonOrInteractiveContext.set(this.interactiveContext.value === true || this.isPythonFileActive === true).ignoreErrors(); + this.pythonOrInteractiveOrNativeContext + .set(this.nativeContext.value === true || (this.interactiveContext.value === true && this.isPythonFileActive === true)) + .ignoreErrors(); } } diff --git a/src/client/datascience/interactive-common/interactiveBase.ts b/src/client/datascience/interactive-common/interactiveBase.ts index 7c89937cefb9..6a67364b42aa 100644 --- a/src/client/datascience/interactive-common/interactiveBase.ts +++ b/src/client/datascience/interactive-common/interactiveBase.ts @@ -69,7 +69,8 @@ import { INotebookServerOptions, InterruptResult, IStatusProvider, - IThemeFinder + IThemeFinder, + WebViewViewChangeEventArgs } from '../types'; import { WebViewHost } from '../webViewHost'; import { InteractiveWindowMessageListener } from './interactiveWindowMessageListener'; @@ -389,7 +390,7 @@ export abstract class InteractiveBase extends WebViewHost; } + +type WebViewViewState = { + readonly visible: boolean; + readonly active: boolean; +}; +export type WebViewViewChangeEventArgs = { current: WebViewViewState; previous: WebViewViewState }; diff --git a/src/client/datascience/webViewHost.ts b/src/client/datascience/webViewHost.ts index 6cd0ba5131a6..0b518efb098f 100644 --- a/src/client/datascience/webViewHost.ts +++ b/src/client/datascience/webViewHost.ts @@ -16,7 +16,7 @@ import { StopWatch } from '../common/utils/stopWatch'; import { captureTelemetry, sendTelemetryEvent } from '../telemetry'; import { DefaultTheme, Telemetry } from './constants'; import { CssMessages, IGetCssRequest, IGetMonacoThemeRequest, SharedMessages } from './messages'; -import { ICodeCssGenerator, IDataScienceExtraSettings, IThemeFinder } from './types'; +import { ICodeCssGenerator, IDataScienceExtraSettings, IThemeFinder, WebViewViewChangeEventArgs } from './types'; @injectable() // For some reason this is necessary to get the class hierarchy to work. export class WebViewHost implements IDisposable { @@ -144,7 +144,7 @@ export class WebViewHost implements IDisposable { this.messageListener.onMessage(type.toString(), payload); } - protected onViewStateChanged(_visible: boolean, _active: boolean) { + protected onViewStateChanged(_args: WebViewViewChangeEventArgs) { noop(); } @@ -263,11 +263,13 @@ export class WebViewHost implements IDisposable { } private webPanelViewStateChanged = (webPanel: IWebPanel) => { - const isVisible = webPanel.isVisible(); - const isActive = webPanel.isActive(); - this.onViewStateChanged(isVisible, isActive); - this.viewState.visible = isVisible; - this.viewState.active = isActive; + const visible = webPanel.isVisible(); + const active = webPanel.isActive(); + const current = { visible, active }; + const previous = { visible: this.viewState.visible, active: this.viewState.active }; + this.viewState.visible = visible; + this.viewState.active = active; + this.onViewStateChanged({ current, previous }); }; @captureTelemetry(Telemetry.WebviewStyleUpdate)