Change:
<!-- Do Not Delete This! featurerequesttemplate --<!-- Please read our Rules of Conduct: --<!-- Please search existing issues to avoid creating duplicates. --<!-- Describe the feature you'd like. --During debugging there is the option to copy the value from a watch variable. VSCode by default allows to inspect arrays. I can select with shift click a range of values within the array and they are highlighted. Pressing 'copy value' however, will only copy the value of the array that the mouse is hovering. It could be nice that if several values are highlighted all those values are copied into the clipboard. ! As a use case, I work with numerical methods and exporting those vector values to excel allows me to quickly validate that some operations are computed correctly, evolution of values during the solving phase, etc. Moreover, from the point of view of UX, in my humil opinion, it makes more sense that if multiple values are highlighted, all of them are copied to the clipboard, separated by n. Just a small suggestion, Thanks in advance, vscode is awesome
this feature request makes sense. I guess you would expect that each value is followed by a new line to distnguish between them? This is doable, assigning to next milestone to look into it then.
Yes, I suggested new line because it seems reasonable as it copy pastes well to excel and notepad and it resembles the structure you are 'seeing' in the screen. Thanks for answering so fast
Adding help wanted in case somebody from the community wants to help here. Code pointer The command should be changed that as arguments it gets an array of selected expressions. Might be a bit tricky for first time contributors to get 100% right.
I'll work on this

Discussion:
import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { localize } from 'vs/nls'; import { Codicon } from 'vs/base/common/codicons'; <ins> import { coalesce } from 'vs/base/common/arrays'; </ins> const $ = dom.$; let forgetScopes = true;

export const COPY_VALUE_ID = 'workbench.debug.viewlet.action.copyValue'; CommandsRegistry.registerCommand({ id: COPY_VALUE_ID, <del> handler: async (accessor: ServicesAccessor, element: Variable | Expression | unknown) => { </del> <ins> handler: async (accessor: ServicesAccessor, arg: Variable | Expression | unknown, ctx?: (Variable | Expression)[]) => { </ins> const debugService = accessor.get(IDebugService); const clipboardService = accessor.get(IClipboardService); let elementContext = ''; <del> if (element instanceof Variable || element instanceof Expression) { </del> <ins> let elements: (Variable | Expression)[]; if (arg instanceof Variable || arg instanceof Expression) { </ins> elementContext = 'watch'; <ins> elements = ctx ? ctx : []; </ins> } else { <del> element = variableInternalContext; </del> elementContext = 'variables'; <ins> elements = variableInternalContext ? [variableInternalContext] : []; </ins> } const stackFrame = debugService.getViewModel().focusedStackFrame; const session = debugService.getViewModel().focusedSession; <del> if (!stackFrame || !session || !(element instanceof Variable || element instanceof Expression)) { </del> <ins> if (!stackFrame || !session || elements.length === 0) { </ins> return; } <del> const context = session.capabilities.supportsClipboardContext ? 'clipboard' : elementContext; const toEvaluate = element instanceof Variable ? (element.evaluateName || element.value) : element.name; </del> <ins> const evalContext = session.capabilities.supportsClipboardContext ? 'clipboard' : elementContext; const toEvaluate = elements.map(element => element instanceof Variable ? (element.evaluateName || element.value) : element.name); </ins> try { <del> const evaluation = await session.evaluate(toEvaluate, stackFrame.frameId, context); if (evaluation) { clipboardService.writeText(evaluation.body.result); </del> <ins> const evaluations = await Promise.all(toEvaluate.map(expr => session.evaluate(expr, stackFrame.frameId, evalContext))); const result = coalesce(evaluations).map(evaluation => evaluation.body.result); if (result.length) { clipboardService.writeText(result.join('n')); </ins> } } catch (e) { <del> if (element instanceof Variable || element instanceof Expression) { clipboardService.writeText(element.value); } </del> <ins> const result = elements.map(element => element.value); clipboardService.writeText(result.join('n')); </ins> } } });

private onContextMenu(e: ITreeContextMenuEvent<IExpression>): void { const element = e.element; <ins> const selection = this.tree.getSelection(); </ins> this.watchItemType.set(element instanceof Expression ? 'expression' : element instanceof Variable ? 'variable' : undefined); const actions: IAction[] = []; <del> const actionsDisposable = createAndFillInContextMenuActions(this.menu, { arg: element, shouldForwardArgs: false }, actions); </del> <ins> const actionsDisposable = createAndFillInContextMenuActions(this.menu, { arg: element, shouldForwardArgs: true }, actions); </ins> this.contextMenuService.showContextMenu({ getAnchor: () => e.anchor, getActions: () => actions, <del> getActionsContext: () => element, </del> <ins> getActionsContext: () => element && selection.includes(element) ? selection : element ? [element] : [], </ins> onHide: () => dispose(actionsDisposable) }); }