From 4c3f5de78914fd38b4e3c3d46ccd7f777e233c39 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Wed, 18 Dec 2024 10:40:34 -0800 Subject: [PATCH] debug: make ctrl+c copy value(s) in debug views (#236501) Not sure how this ever worked, but it was reported as a bug, and this makes it work. Fixes #232767 --- .../debug/browser/debug.contribution.ts | 12 +++++++ .../contrib/debug/browser/variablesView.ts | 35 ++++++++++++++++--- .../debug/browser/watchExpressionsView.ts | 8 +++-- .../workbench/contrib/debug/common/debug.ts | 5 +++ 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts index 7c501db354f..6033b0cf9b5 100644 --- a/src/vs/workbench/contrib/debug/browser/debug.contribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debug.contribution.ts @@ -63,6 +63,8 @@ import { ReplAccessibilityHelp } from './replAccessibilityHelp.js'; import { ReplAccessibilityAnnouncer } from '../common/replAccessibilityAnnouncer.js'; import { RunAndDebugAccessibilityHelp } from './runAndDebugAccessibilityHelp.js'; import { DebugWatchAccessibilityAnnouncer } from '../common/debugAccessibilityAnnouncer.js'; +import { KeybindingsRegistry, KeybindingWeight } from '../../../../platform/keybinding/common/keybindingsRegistry.js'; +import { FocusedViewContext } from '../../../common/contextkeys.js'; const debugCategory = nls.localize('debugCategory', "Debug"); registerColors(); @@ -206,6 +208,16 @@ registerDebugViewMenuItem(MenuId.DebugWatchContext, REMOVE_WATCH_EXPRESSIONS_COM registerDebugViewMenuItem(MenuId.NotebookVariablesContext, COPY_NOTEBOOK_VARIABLE_VALUE_ID, COPY_NOTEBOOK_VARIABLE_VALUE_LABEL, 20, CONTEXT_VARIABLE_VALUE); +KeybindingsRegistry.registerKeybindingRule({ + id: COPY_VALUE_ID, + weight: KeybindingWeight.WorkbenchContrib, + when: ContextKeyExpr.or( + FocusedViewContext.isEqualTo(WATCH_VIEW_ID), + FocusedViewContext.isEqualTo(VARIABLES_VIEW_ID), + ), + primary: KeyMod.CtrlCmd | KeyCode.KeyC +}); + // Touch Bar if (isMacintosh) { diff --git a/src/vs/workbench/contrib/debug/browser/variablesView.ts b/src/vs/workbench/contrib/debug/browser/variablesView.ts index 222e0a7b57b..16d53c4f87e 100644 --- a/src/vs/workbench/contrib/debug/browser/variablesView.ts +++ b/src/vs/workbench/contrib/debug/browser/variablesView.ts @@ -40,8 +40,9 @@ import { IViewletViewOptions } from '../../../browser/parts/views/viewsViewlet.j import { IViewDescriptorService } from '../../../common/views.js'; import { IEditorService, SIDE_GROUP } from '../../../services/editor/common/editorService.js'; import { IExtensionService } from '../../../services/extensions/common/extensions.js'; +import { IViewsService } from '../../../services/views/common/viewsService.js'; import { IExtensionsWorkbenchService } from '../../extensions/common/extensions.js'; -import { CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_IS_ACCESSED_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_IS_READ_SUPPORTED, CONTEXT_VARIABLES_FOCUSED, DataBreakpointSetType, DebugVisualizationType, IDataBreakpointInfoResponse, IDebugService, IExpression, IScope, IStackFrame, IViewModel, VARIABLES_VIEW_ID } from '../common/debug.js'; +import { CONTEXT_BREAK_WHEN_VALUE_CHANGES_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_IS_ACCESSED_SUPPORTED, CONTEXT_BREAK_WHEN_VALUE_IS_READ_SUPPORTED, CONTEXT_VARIABLES_FOCUSED, DataBreakpointSetType, DebugVisualizationType, IDataBreakpointInfoResponse, IDebugService, IDebugViewWithVariables, IExpression, IScope, IStackFrame, IViewModel, VARIABLES_VIEW_ID, WATCH_VIEW_ID } from '../common/debug.js'; import { getContextForVariable } from '../common/debugContext.js'; import { ErrorScope, Expression, Scope, StackFrame, Variable, VisualizedExpression, getUriForDebugMemory } from '../common/debugModel.js'; import { DebugVisualizer, IDebugVisualizerService } from '../common/debugVisualizers.js'; @@ -61,7 +62,7 @@ interface IVariablesContext { variable: DebugProtocol.Variable; } -export class VariablesView extends ViewPane { +export class VariablesView extends ViewPane implements IDebugViewWithVariables { private updateTreeScheduler: RunOnceScheduler; private needsRefresh = false; @@ -69,6 +70,10 @@ export class VariablesView extends ViewPane { private savedViewState = new Map(); private autoExpandedScopes = new Set(); + public get treeSelection() { + return this.tree.getSelection(); + } + constructor( options: IViewletViewOptions, @IContextMenuService contextMenuService: IContextMenuService, @@ -653,12 +658,34 @@ CommandsRegistry.registerCommand({ description: COPY_VALUE_LABEL, }, id: COPY_VALUE_ID, - handler: async (accessor: ServicesAccessor, arg: Variable | Expression | IVariablesContext, ctx?: (Variable | Expression)[]) => { + handler: async (accessor: ServicesAccessor, arg: Variable | Expression | IVariablesContext | undefined, ctx?: (Variable | Expression)[]) => { + if (!arg) { + const viewService = accessor.get(IViewsService); + const view = viewService.getActiveViewWithId(WATCH_VIEW_ID) || viewService.getActiveViewWithId(VARIABLES_VIEW_ID); + if (view) { + + } + } const debugService = accessor.get(IDebugService); const clipboardService = accessor.get(IClipboardService); let elementContext = ''; let elements: (Variable | Expression)[]; - if (arg instanceof Variable || arg instanceof Expression) { + if (!arg) { + const viewService = accessor.get(IViewsService); + const focusedView = viewService.getFocusedView(); + let view: IDebugViewWithVariables | null | undefined; + if (focusedView?.id === WATCH_VIEW_ID) { + view = viewService.getActiveViewWithId(WATCH_VIEW_ID); + elementContext = 'watch'; + } else if (focusedView?.id === VARIABLES_VIEW_ID) { + view = viewService.getActiveViewWithId(VARIABLES_VIEW_ID); + elementContext = 'variables'; + } + if (!view) { + return; + } + elements = view.treeSelection.filter(e => e instanceof Expression || e instanceof Variable); + } else if (arg instanceof Variable || arg instanceof Expression) { elementContext = 'watch'; elements = ctx ? ctx : []; } else { diff --git a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts index b1b75a73bc0..b325c138b0a 100644 --- a/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts +++ b/src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts @@ -29,7 +29,7 @@ import { IThemeService } from '../../../../platform/theme/common/themeService.js import { ViewAction, ViewPane } from '../../../browser/parts/views/viewPane.js'; import { IViewletViewOptions } from '../../../browser/parts/views/viewsViewlet.js'; import { IViewDescriptorService } from '../../../common/views.js'; -import { CONTEXT_CAN_VIEW_MEMORY, CONTEXT_VARIABLE_IS_READONLY, CONTEXT_WATCH_EXPRESSIONS_EXIST, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_WATCH_ITEM_TYPE, IDebugConfiguration, IDebugService, IExpression, WATCH_VIEW_ID } from '../common/debug.js'; +import { CONTEXT_CAN_VIEW_MEMORY, CONTEXT_VARIABLE_IS_READONLY, CONTEXT_WATCH_EXPRESSIONS_EXIST, CONTEXT_WATCH_EXPRESSIONS_FOCUSED, CONTEXT_WATCH_ITEM_TYPE, IDebugConfiguration, IDebugService, IDebugViewWithVariables, IExpression, WATCH_VIEW_ID } from '../common/debug.js'; import { Expression, Variable, VisualizedExpression } from '../common/debugModel.js'; import { AbstractExpressionDataSource, AbstractExpressionsRenderer, IExpressionTemplateData, IInputBoxOptions, renderViewTree } from './baseDebugView.js'; import { DebugExpressionRenderer } from './debugExpressionRenderer.js'; @@ -40,7 +40,7 @@ const MAX_VALUE_RENDER_LENGTH_IN_VIEWLET = 1024; let ignoreViewUpdates = false; let useCachedEvaluation = false; -export class WatchExpressionsView extends ViewPane { +export class WatchExpressionsView extends ViewPane implements IDebugViewWithVariables { private watchExpressionsUpdatedScheduler: RunOnceScheduler; private needsRefresh = false; @@ -51,6 +51,10 @@ export class WatchExpressionsView extends ViewPane { private menu: IMenu; private expressionRenderer: DebugExpressionRenderer; + public get treeSelection() { + return this.tree.getSelection(); + } + constructor( options: IViewletViewOptions, @IContextMenuService contextMenuService: IContextMenuService, diff --git a/src/vs/workbench/contrib/debug/common/debug.ts b/src/vs/workbench/contrib/debug/common/debug.ts index d5387b10408..c0501554472 100644 --- a/src/vs/workbench/contrib/debug/common/debug.ts +++ b/src/vs/workbench/contrib/debug/common/debug.ts @@ -29,6 +29,7 @@ import { Source } from './debugSource.js'; import { ITaskIdentifier } from '../../tasks/common/tasks.js'; import { LiveTestResult } from '../../testing/common/testResult.js'; import { IEditorService } from '../../../services/editor/common/editorService.js'; +import { IView } from '../../../common/views.js'; export const VIEWLET_ID = 'workbench.view.debug'; @@ -115,6 +116,10 @@ export const INTERNAL_CONSOLE_OPTIONS_SCHEMA = { description: nls.localize('internalConsoleOptions', "Controls when the internal Debug Console should open.") }; +export interface IDebugViewWithVariables extends IView { + readonly treeSelection: IExpression[]; +} + // raw export interface IRawModelUpdate {