Skip to content

Commit

Permalink
Context menu enhancements
Browse files Browse the repository at this point in the history
Enhances the memory webview to  properly support context menu actions contributed via `webview/context` contribution point. This includes
- Augmenting the webview components with `data-vscode-context` custom data properties.
 These properties are used to provide additional context info (as JSON string). The composed context is then available in `when` conditions from `webview/context` contributions and as command argument when executing the associated command.

Provides the following context menu enhancements outlined in eclipse-cdt-cloud#51
- Copy selection
- Quick access to window configuration by
  - providing show/hide entries for variable & ascii column
  - show/hide for radix prefix
  - `Show advanced Options` command to show the advanced settings overlay
 - Allow contributions from other extensions
  • Loading branch information
tortmayr committed Mar 6, 2024
1 parent 7b4c3bf commit 36a5d1e
Show file tree
Hide file tree
Showing 11 changed files with 341 additions and 19 deletions.
83 changes: 83 additions & 0 deletions package.json
Expand Up @@ -81,6 +81,48 @@
"command": "memory-inspector.show-variable",
"title": "Show in Memory Inspector",
"category": "Memory"
},
{
"command": "memory-inspector.show-variables-column",
"title": "Show Variables Column",
"category": "Memory",
"enablement": "webviewId === memory-inspector.memory"
},
{
"command": "memory-inspector.hide-variables-column",
"title": "Hide Variables Column",
"category": "Memory",
"enablement": "webviewId === memory-inspector.memory"
},
{
"command": "memory-inspector.show-ascii-column",
"title": "Show ASCII Column",
"category": "Memory",
"enablement": "webviewId === memory-inspector.memory"
},
{
"command": "memory-inspector.hide-ascii-column",
"title": "Hide ASCII Column",
"category": "Memory",
"enablement": "webviewId === memory-inspector.memory"
},
{
"command": "memory-inspector.show-radix-prefix",
"title": "Show Radix Prefix",
"category": "Memory",
"enablement": "webviewId === memory-inspector.memory"
},
{
"command": "memory-inspector.hide-radix-prefix",
"title": "Hide Radix Prefix",
"category": "Memory",
"enablement": "webviewId === memory-inspector.memory"
},
{
"command": "memory-inspector.show-advanced-display-options",
"title": "Advanced Display Options",
"category": "Memory",
"enablement": "webviewId === memory-inspector.memory"
}
],
"menus": {
Expand All @@ -105,6 +147,47 @@
"command": "memory-inspector.show-variable",
"when": "canViewMemory && memory-inspector.canRead"
}
],
"webview/context": [
{
"command": "memory-inspector.show-variables-column",
"title": "Show Variables Column",
"group": "display@1",
"when": "webviewId === memory-inspector.memory && !(visibleColumns =~ /\\|variables\\|/)"
},
{
"command": "memory-inspector.hide-variables-column",
"title": "Hide Variables Column",
"group": "display@1",
"when": "webviewId === memory-inspector.memory && visibleColumns =~ /\\|variables\\|/"
},
{
"command": "memory-inspector.show-ascii-column",
"title": "Show ASCII Column",
"group": "display@2",
"when": "webviewId === memory-inspector.memory && !(visibleColumns =~ /\\|ascii\\|/)"
},
{
"command": "memory-inspector.hide-ascii-column",
"title": "Hide ASCII Column",
"group": "display@2",
"when": "webviewId === memory-inspector.memory && visibleColumns =~ /\\|ascii\\|/"
},
{
"command": "memory-inspector.show-radix-prefix",
"group": "display@3",
"when": "webviewId === memory-inspector.memory && !showRadixPrefix"
},
{
"command": "memory-inspector.hide-radix-prefix",
"group": "display@3",
"when": "webviewId === memory-inspector.memory && showRadixPrefix"
},
{
"command": "memory-inspector.show-advanced-display-options",
"group": "display@4",
"when": "webviewId === memory-inspector.memory"
}
]
},
"customEditors": [
Expand Down
11 changes: 11 additions & 0 deletions src/common/messaging.ts
Expand Up @@ -31,3 +31,14 @@ export const setOptionsType: RequestType<Partial<DebugProtocol.ReadMemoryArgumen
export const readMemoryType: RequestType<DebugProtocol.ReadMemoryArguments, MemoryReadResult> = { method: 'readMemory' };
export const writeMemoryType: RequestType<DebugProtocol.WriteMemoryArguments, MemoryWriteResult> = { method: 'writeMemory' };
export const getVariables: RequestType<DebugProtocol.ReadMemoryArguments, VariableRange[]> = { method: 'getVariables' };

export const showAdvancedDisplayConfigurationType: NotificationType<void> = { method: 'showAdvancedOptions' };
export const getWebviewSelectionType: RequestType<void, WebviewSelection> = { method: 'getWebviewSelection' };

export interface WebviewSelection {
selectedCell?: {
column: string
value: string
}
textSelection?: string;
}
59 changes: 55 additions & 4 deletions src/plugin/memory-webview-main.ts
Expand Up @@ -31,6 +31,9 @@ import {
setMemoryViewSettingsType,
resetMemoryViewSettingsType,
setTitleType,
showAdvancedDisplayConfigurationType as showAdvancedOptionsConfigurationType,
getWebviewSelectionType,
WebviewSelection,
} from '../common/messaging';
import { MemoryProvider } from './memory-provider';
import { outputChannelLogger } from './logger';
Expand All @@ -49,6 +52,12 @@ enum RefreshEnum {
on = 1
}

export interface WebviewMenuContext {
messageParticipant: WebviewIdMessageParticipant,
visibleColumns: string,
showRadixPrefix: boolean,
}

const isMemoryVariable = (variable: Variable): variable is Variable => variable && !!(variable as Variable).memoryReference;
const CONFIGURABLE_COLUMNS = [
manifest.CONFIG_SHOW_ASCII_COLUMN,
Expand All @@ -59,6 +68,14 @@ export class MemoryWebview implements vscode.CustomReadonlyEditorProvider {
public static ViewType = `${manifest.PACKAGE_NAME}.memory`;
public static ShowCommandType = `${manifest.PACKAGE_NAME}.show`;
public static VariableCommandType = `${manifest.PACKAGE_NAME}.show-variable`;
public static ShowAsciiColumnCommandType = `${manifest.PACKAGE_NAME}.show-ascii-column`;
public static HideAsciiColumnCommandType = `${manifest.PACKAGE_NAME}.hide-ascii-column`;
public static ShowVariablesColumnCommandType = `${manifest.PACKAGE_NAME}.show-variables-column`;
public static HideVariablesColumnCommandType = `${manifest.PACKAGE_NAME}.hide-variables-column`;
public static ShowRadixPrefixCommandType = `${manifest.PACKAGE_NAME}.show-radix-prefix`;
public static HideRadixPrefixCommandType = `${manifest.PACKAGE_NAME}.hide-radix-prefix`;
public static ShowAdvancedDisplayConfigurationCommandType = `${manifest.PACKAGE_NAME}.show-advanced-display-options`;
public static GetWebviewSelectionCommandType = `${manifest.PACKAGE_NAME}.get-webview-selection`;

protected messenger: Messenger;
protected refreshOnStop: RefreshEnum;
Expand All @@ -77,6 +94,10 @@ export class MemoryWebview implements vscode.CustomReadonlyEditorProvider {
}

public activate(context: vscode.ExtensionContext): void {
const getVisibleColumns =
(columnContext: string): string[] =>
columnContext.substring(1, columnContext.length - 1).split('|');

context.subscriptions.push(
vscode.window.registerCustomEditorProvider(manifest.EDITOR_NAME, this),
vscode.commands.registerCommand(MemoryWebview.ShowCommandType, () => this.show()),
Expand All @@ -85,7 +106,29 @@ export class MemoryWebview implements vscode.CustomReadonlyEditorProvider {
if (isMemoryVariable(variable)) {
this.show({ memoryReference: variable.memoryReference.toString() });
}
})
}),
vscode.commands.registerCommand(MemoryWebview.ShowVariablesColumnCommandType, (ctx: WebviewMenuContext) => {
this.setMemoryViewSettings(ctx.messageParticipant, { visibleColumns: [...getVisibleColumns(ctx.visibleColumns), 'variables'] });
}),
vscode.commands.registerCommand(MemoryWebview.HideVariablesColumnCommandType, (ctx: WebviewMenuContext) => {
this.setMemoryViewSettings(ctx.messageParticipant, { visibleColumns: getVisibleColumns(ctx.visibleColumns).filter(column => column !== 'variables') });
}),
vscode.commands.registerCommand(MemoryWebview.ShowAsciiColumnCommandType, (ctx: WebviewMenuContext) => {
this.setMemoryViewSettings(ctx.messageParticipant, { visibleColumns: [...getVisibleColumns(ctx.visibleColumns), 'ascii'] });
}),
vscode.commands.registerCommand(MemoryWebview.HideAsciiColumnCommandType, (ctx: WebviewMenuContext) => {
this.setMemoryViewSettings(ctx.messageParticipant, { visibleColumns: getVisibleColumns(ctx.visibleColumns).filter(column => column !== 'ascii') });
}),
vscode.commands.registerCommand(MemoryWebview.ShowRadixPrefixCommandType, (ctx: WebviewMenuContext) => {
this.setMemoryViewSettings(ctx.messageParticipant, { showRadixPrefix: true, visibleColumns: getVisibleColumns(ctx.visibleColumns) });
}),
vscode.commands.registerCommand(MemoryWebview.HideRadixPrefixCommandType, (ctx: WebviewMenuContext) => {
this.setMemoryViewSettings(ctx.messageParticipant, { showRadixPrefix: false, visibleColumns: getVisibleColumns(ctx.visibleColumns) });
}),
vscode.commands.registerCommand(MemoryWebview.ShowAdvancedDisplayConfigurationCommandType, async (ctx: WebviewMenuContext) => {
this.messenger.sendNotification(showAdvancedOptionsConfigurationType, ctx.messageParticipant, undefined);
}),
vscode.commands.registerCommand(MemoryWebview.GetWebviewSelectionCommandType, (ctx: WebviewMenuContext) => this.getWebviewSelection(ctx.messageParticipant))
);
};

Expand Down Expand Up @@ -213,10 +256,14 @@ export class MemoryWebview implements vscode.CustomReadonlyEditorProvider {
}

protected setInitialSettings(webviewParticipant: WebviewIdMessageParticipant, title: string): void {
this.messenger.sendNotification(setMemoryViewSettingsType, webviewParticipant, this.getMemoryViewSettings(title));
this.setMemoryViewSettings(webviewParticipant, this.getMemoryViewSettings(webviewParticipant, title));
}

protected getMemoryViewSettings(title: string): MemoryViewSettings {
protected setMemoryViewSettings(webviewParticipant: WebviewIdMessageParticipant, settings: Partial<MemoryViewSettings>): void {
this.messenger.sendNotification(setMemoryViewSettingsType, webviewParticipant, settings);
}

protected getMemoryViewSettings(messageParticipant: WebviewIdMessageParticipant, title: string): MemoryViewSettings {
const memoryInspectorConfiguration = vscode.workspace.getConfiguration(manifest.PACKAGE_NAME);
const bytesPerWord = memoryInspectorConfiguration.get<number>(manifest.CONFIG_BYTES_PER_WORD, manifest.DEFAULT_BYTES_PER_WORD);
const wordsPerGroup = memoryInspectorConfiguration.get<number>(manifest.CONFIG_WORDS_PER_GROUP, manifest.DEFAULT_WORDS_PER_GROUP);
Expand All @@ -227,7 +274,7 @@ export class MemoryWebview implements vscode.CustomReadonlyEditorProvider {
.map(columnId => columnId.replace('columns.', ''));
const addressRadix = memoryInspectorConfiguration.get<number>(manifest.CONFIG_ADDRESS_RADIX, manifest.DEFAULT_ADDRESS_RADIX);
const showRadixPrefix = memoryInspectorConfiguration.get<boolean>(manifest.CONFIG_SHOW_RADIX_PREFIX, manifest.DEFAULT_SHOW_RADIX_PREFIX);
return { title, bytesPerWord, wordsPerGroup, groupsPerRow, scrollingBehavior, visibleColumns, addressRadix, showRadixPrefix };
return { messageParticipant, title, bytesPerWord, wordsPerGroup, groupsPerRow, scrollingBehavior, visibleColumns, addressRadix, showRadixPrefix };
}

protected async readMemory(request: DebugProtocol.ReadMemoryArguments): Promise<MemoryReadResult> {
Expand All @@ -254,4 +301,8 @@ export class MemoryWebview implements vscode.CustomReadonlyEditorProvider {
return [];
}
}

protected getWebviewSelection(webviewParticipant: WebviewIdMessageParticipant): Promise<WebviewSelection> {
return this.messenger.sendRequest(getWebviewSelectionType, webviewParticipant, undefined);
}
}
10 changes: 8 additions & 2 deletions src/webview/columns/address-column.tsx
Expand Up @@ -16,8 +16,9 @@

import React, { ReactNode } from 'react';
import { BigIntMemoryRange, getAddressString, getRadixMarker } from '../../common/memory-range';
import { ColumnContribution, ColumnFittingType } from './column-contribution-service';
import { Memory, MemoryDisplayConfiguration } from '../utils/view-types';
import { createVscodeContext } from '../utils/vscode-contexts';
import { ColumnContribution, ColumnFittingType } from './column-contribution-service';

export class AddressColumn implements ColumnContribution {
static ID = 'address';
Expand All @@ -29,7 +30,12 @@ export class AddressColumn implements ColumnContribution {
fittingType: ColumnFittingType = 'content-width';

render(range: BigIntMemoryRange, _: Memory, options: MemoryDisplayConfiguration): ReactNode {
return <span className='memory-start-address'>
const cellContext = {
address: getAddressString(range.startAddress, options.addressRadix),
radix: getRadixMarker(options.addressRadix),

};
return <span className='memory-start-address' {...createVscodeContext(cellContext)}>
{options.showRadixPrefix && <span className='radix-prefix'>{getRadixMarker(options.addressRadix)}</span>}
<span className='address'>{getAddressString(range.startAddress, options.addressRadix)}</span>
</span>;
Expand Down

0 comments on commit 36a5d1e

Please sign in to comment.