Merge pull request #193420 from microsoft/merogge/comment-help

add comment widget help dialog
This commit is contained in:
Megan Rogge
2023-09-21 08:51:13 -07:00
committed by GitHub
9 changed files with 255 additions and 113 deletions
@@ -12,12 +12,14 @@ import { IAccessibleViewService, AccessibleViewService } from 'vs/workbench/cont
import { UnfocusedViewDimmingContribution } from 'vs/workbench/contrib/accessibility/browser/unfocusedViewDimmingContribution';
import { EditorAccessibilityHelpContribution, HoverAccessibleViewContribution, InlineCompletionsAccessibleViewContribution, NotificationAccessibleViewContribution } from 'vs/workbench/contrib/accessibility/browser/accessibilityContributions';
import { AccessibilityStatus } from 'vs/workbench/contrib/accessibility/browser/accessibilityStatus';
import { CommentsAccessibilityHelpContribution } from 'vs/workbench/contrib/comments/browser/comments.contribution';
registerAccessibilityConfiguration();
registerSingleton(IAccessibleViewService, AccessibleViewService, InstantiationType.Delayed);
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(EditorAccessibilityHelpContribution, LifecyclePhase.Eventually);
workbenchRegistry.registerWorkbenchContribution(CommentsAccessibilityHelpContribution, LifecyclePhase.Eventually);
workbenchRegistry.registerWorkbenchContribution(UnfocusedViewDimmingContribution, LifecyclePhase.Restored);
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
@@ -43,7 +43,8 @@ export const enum AccessibilityVerbositySettingId {
Editor = 'accessibility.verbosity.editor',
Hover = 'accessibility.verbosity.hover',
Notification = 'accessibility.verbosity.notification',
EmptyEditorHint = 'accessibility.verbosity.emptyEditorHint'
EmptyEditorHint = 'accessibility.verbosity.emptyEditorHint',
Comments = 'accessibility.verbosity.comments'
}
export const enum AccessibleViewProviderId {
@@ -57,7 +58,8 @@ export const enum AccessibleViewProviderId {
Editor = 'editor',
Hover = 'hover',
Notification = 'notification',
EmptyEditorHint = 'emptyEditorHint'
EmptyEditorHint = 'emptyEditorHint',
Comments = 'comments'
}
const baseProperty: object = {
@@ -110,6 +112,10 @@ const configuration: IConfigurationNode = {
[AccessibilityVerbositySettingId.EmptyEditorHint]: {
description: localize('verbosity.emptyEditorHint', 'Provide information about relevant actions in an empty text editor.'),
...baseProperty
},
[AccessibilityVerbositySettingId.Comments]: {
description: localize('verbosity.comments', 'Provide information about actions that can be taken in the comment widget or in a file which contains comments.'),
...baseProperty
}
}
};
@@ -37,7 +37,10 @@ import { ThemeIcon } from 'vs/base/common/themables';
import { Codicon } from 'vs/base/common/codicons';
import { InlineCompletionsController } from 'vs/editor/contrib/inlineCompletions/browser/inlineCompletionsController';
import { InlineCompletionContextKeys } from 'vs/editor/contrib/inlineCompletions/browser/inlineCompletionContextKeys';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys';
import { CommentAccessibilityHelpNLS } from 'vs/workbench/contrib/comments/browser/comments.contribution';
import { CommentCommandId } from 'vs/workbench/contrib/comments/common/commentCommandIds';
export class EditorAccessibilityHelpContribution extends Disposable {
static ID: 'editorAccessibilityHelpContribution';
@@ -66,7 +69,8 @@ class AccessibilityHelpProvider implements IAccessibleContentProvider {
verbositySettingKey = AccessibilityVerbositySettingId.Editor;
constructor(
private readonly _editor: ICodeEditor,
@IKeybindingService private readonly _keybindingService: IKeybindingService
@IKeybindingService private readonly _keybindingService: IKeybindingService,
@IContextKeyService private readonly _contextKeyService: IContextKeyService
) {
}
@@ -96,6 +100,15 @@ class AccessibilityHelpProvider implements IAccessibleContentProvider {
}
}
const editorContext = this._contextKeyService.getContext(this._editor.getDomNode()!);
if (editorContext.getValue<boolean>(CommentContextKeys.activeEditorHasCommentingRange.key)) {
content.push(this._descriptionForCommand(CommentCommandId.Add, CommentAccessibilityHelpNLS.addComment, CommentAccessibilityHelpNLS.addCommentNoKb));
content.push(this._descriptionForCommand(CommentCommandId.NextThread, CommentAccessibilityHelpNLS.nextCommentThreadKb, CommentAccessibilityHelpNLS.nextCommentThreadNoKb));
content.push(this._descriptionForCommand(CommentCommandId.PreviousThread, CommentAccessibilityHelpNLS.previousCommentThreadKb, CommentAccessibilityHelpNLS.previousCommentThreadNoKb));
content.push(this._descriptionForCommand(CommentCommandId.NextRange, CommentAccessibilityHelpNLS.nextRange, CommentAccessibilityHelpNLS.nextRangeNoKb));
content.push(this._descriptionForCommand(CommentCommandId.PreviousRange, CommentAccessibilityHelpNLS.previousRange, CommentAccessibilityHelpNLS.previousRangeNoKb));
}
if (options.get(EditorOption.stickyScroll).enabled) {
content.push(this._descriptionForCommand('editor.action.focusStickyScroll', AccessibilityHelpNLS.stickScrollKb, AccessibilityHelpNLS.stickScrollNoKb));
}
@@ -31,6 +31,10 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { registerNavigableContainer } from 'vs/workbench/browser/actions/widgetNavigationCommands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { COMMENTS_SECTION, ICommentsConfiguration } from 'vs/workbench/contrib/comments/common/commentsConfiguration';
import { localize } from 'vs/nls';
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands';
export const COMMENTEDITOR_DECORATION_KEY = 'commenteditordecoration';
@@ -45,6 +49,7 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
private _threadIsEmpty: IContextKey<boolean>;
private _styleElement: HTMLStyleElement;
private _commentThreadContextValue: IContextKey<string | undefined>;
private _focusedContextKey: IContextKey<boolean>;
private _onDidResize = new Emitter<dom.Dimension>();
onDidResize = this._onDidResize.event;
@@ -53,7 +58,6 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
get commentThread() {
return this._commentThread;
}
constructor(
readonly container: HTMLElement,
private _owner: string,
@@ -71,12 +75,14 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
},
@ICommentService private commentService: ICommentService,
@IContextMenuService contextMenuService: IContextMenuService,
@IConfigurationService private configurationService: IConfigurationService
@IConfigurationService private configurationService: IConfigurationService,
@IKeybindingService private _keybindingService: IKeybindingService
) {
super();
this._threadIsEmpty = CommentContextKeys.commentThreadIsEmpty.bindTo(this._contextKeyService);
this._threadIsEmpty.set(!_commentThread.comments || !_commentThread.comments.length);
this._focusedContextKey = CommentContextKeys.commentFocused.bindTo(this._contextKeyService);
this._commentMenus = this.commentService.getCommentMenus(this._owner);
@@ -111,7 +117,13 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
}
}
}));
this._register(tracker.onDidFocus(() => this._focusedContextKey.set(true)));
this._register(tracker.onDidBlur(() => this._focusedContextKey.reset()));
this._register(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(AccessibilityVerbositySettingId.Comments)) {
this._setAriaLabel();
}
}));
this._body = this._scopedInstantiationService.createInstance(
CommentThreadBody,
this._owner,
@@ -124,7 +136,7 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
this
) as unknown as CommentThreadBody<T>;
this._register(this._body);
this._setAriaLabel();
this._styleElement = dom.createStyleSheet(this.container);
@@ -141,6 +153,21 @@ export class CommentThreadWidget<T extends IRange | ICellRange = IRange> extends
this.currentThreadListeners();
}
private _setAriaLabel(): void {
let ariaLabel = localize('commentLabel', "Comment");
let keybinding: string | undefined;
const verbose = this.configurationService.getValue(AccessibilityVerbositySettingId.Comments);
if (verbose) {
keybinding = this._keybindingService.lookupKeybinding(AccessibilityCommandId.OpenAccessibilityHelp, this._contextKeyService)?.getLabel() ?? undefined;
}
if (keybinding) {
ariaLabel = localize('commentLabelWithKeybinding', "{0}, use ({1}) for accessibility help", ariaLabel, keybinding);
} else {
ariaLabel = localize('commentLabelWithKeybindingNoKeybinding', "{0}, run the command Open Accessibility Help which is currently not triggerable via keybinding.", ariaLabel);
}
this._body.container.ariaLabel = ariaLabel;
}
private updateCurrentThread(hasMouse: boolean, hasFocus: boolean) {
if (hasMouse || hasFocus) {
this.commentService.setCurrentCommentThread(this.commentThread);
@@ -9,6 +9,17 @@ import { Registry } from 'vs/platform/registry/common/platform';
import 'vs/workbench/contrib/comments/browser/commentsEditorContribution';
import { ICommentService, CommentService } from 'vs/workbench/contrib/comments/browser/commentService';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { ctxCommentEditorFocused } from 'vs/workbench/contrib/comments/browser/simpleCommentEditor';
import * as strings from 'vs/base/common/strings';
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
import { AccessibleViewType, IAccessibleContentProvider, IAccessibleViewOptions, IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView';
import { AccessibilityHelpAction } from 'vs/workbench/contrib/accessibility/browser/accessibleViewActions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { Disposable } from 'vs/base/common/lifecycle';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys';
import { CommentCommandId } from 'vs/workbench/contrib/comments/common/commentCommandIds';
Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).registerConfiguration({
id: 'comments',
@@ -54,3 +65,63 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
});
registerSingleton(ICommentService, CommentService, InstantiationType.Delayed);
export namespace CommentAccessibilityHelpNLS {
export const escape = nls.localize('escape', "Dismiss the comment widget via Escape.");
export const nextRange = nls.localize('next', "Navigate to the next commenting range via ({0}).");
export const nextRangeNoKb = nls.localize('nextNoKb', "Run the command: Go to Next Commenting Range, which is currently not triggerable via keybinding.");
export const previousRange = nls.localize('previous', "Navigate to the previous comment range via ({0}).");
export const previousRangeNoKb = nls.localize('previousNoKb', "Run the command: Go to Previous Commenting Range, which is currently not triggerable via keybinding.");
export const nextCommentThreadKb = nls.localize('nextCommentThreadKb', "Navigate to the next comment thread via ({0}).");
export const nextCommentThreadNoKb = nls.localize('nextCommentThreadNoKb', "Run the command: Go to Next Comment Thread, which is currently not triggerable via keybinding.");
export const previousCommentThreadKb = nls.localize('previousCommentThreadKb', "Navigate to the previous comment thread via ({0}).");
export const previousCommentThreadNoKb = nls.localize('previousCommentThreadNoKb', "Run the command: Go to Previous Comment Thread, which is currently not triggerable via keybinding.");
export const addComment = nls.localize('addComment', "Add a comment via ({0}).");
export const addCommentNoKb = nls.localize('addCommentNoKb', "Add a comment via the command: Add Comment on Current Selection, which is currently not triggerable via keybinding.");
export const submitComment = nls.localize('submitComment', "Submit the comment via ({0}).");
export const submitCommentNoKb = nls.localize('submitCommentNoKb', "Submit the comment by navigating with tab to the button, as it's currently not triggerable via keybinding.");
}
export class CommentsAccessibilityHelpContribution extends Disposable {
static ID: 'commentsAccessibilityHelpContribution';
constructor() {
super();
this._register(AccessibilityHelpAction.addImplementation(110, 'comments', accessor => {
const instantiationService = accessor.get(IInstantiationService);
const accessibleViewService = accessor.get(IAccessibleViewService);
accessibleViewService.show(instantiationService.createInstance(CommentsAccessibilityHelpProvider));
return true;
}, ContextKeyExpr.or(ctxCommentEditorFocused, CommentContextKeys.commentFocused)));
}
}
export class CommentsAccessibilityHelpProvider implements IAccessibleContentProvider {
verbositySettingKey: AccessibilityVerbositySettingId = AccessibilityVerbositySettingId.Comments;
options: IAccessibleViewOptions = { type: AccessibleViewType.Help };
private _element: HTMLElement | undefined;
constructor(
@IKeybindingService private readonly _keybindingService: IKeybindingService
) {
}
private _descriptionForCommand(commandId: string, msg: string, noKbMsg: string): string {
const kb = this._keybindingService.lookupKeybinding(commandId);
if (kb) {
return strings.format(msg, kb.getAriaLabel());
}
return strings.format(noKbMsg, commandId);
}
provideContent(): string {
this._element = document.activeElement as HTMLElement;
const content: string[] = [];
content.push(CommentAccessibilityHelpNLS.escape);
content.push(this._descriptionForCommand(CommentCommandId.Add, CommentAccessibilityHelpNLS.addComment, CommentAccessibilityHelpNLS.addCommentNoKb));
content.push(this._descriptionForCommand(CommentCommandId.NextRange, CommentAccessibilityHelpNLS.nextRange, CommentAccessibilityHelpNLS.nextRangeNoKb));
content.push(this._descriptionForCommand(CommentCommandId.PreviousRange, CommentAccessibilityHelpNLS.previousRange, CommentAccessibilityHelpNLS.previousRangeNoKb));
content.push(this._descriptionForCommand(CommentCommandId.Submit, CommentAccessibilityHelpNLS.submitComment, CommentAccessibilityHelpNLS.submitCommentNoKb));
return content.join('\n\n');
}
onClose(): void {
this._element?.focus();
}
}
@@ -40,6 +40,9 @@ import { ICursorSelectionChangedEvent } from 'vs/editor/common/cursorEvents';
import { CommentsPanel } from 'vs/workbench/contrib/comments/browser/commentsView';
import { status } from 'vs/base/browser/ui/aria/aria';
import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys';
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
import { AccessibilityCommandId } from 'vs/workbench/contrib/accessibility/common/accessibilityCommands';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
export const ID = 'editor.contrib.review';
@@ -380,7 +383,8 @@ export class CommentController implements IEditorContribution {
@IViewsService private readonly viewsService: IViewsService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IContextKeyService contextKeyService: IContextKeyService,
@IEditorService private readonly editorService: IEditorService
@IEditorService private readonly editorService: IEditorService,
@IKeybindingService private readonly keybindingService: IKeybindingService
) {
this._commentInfos = [];
this._commentWidgets = [];
@@ -848,7 +852,17 @@ export class CommentController implements IEditorContribution {
if (this._commentInfos.some(commentInfo => commentInfo.commentingRanges.ranges.length > 0 || commentInfo.commentingRanges.fileComments)) {
this._hasRespondedToEditorChange = true;
this._activeEditorHasCommentingRange.set(true);
status(nls.localize('hasCommentRanges', "Editor has commenting ranges."));
const verbose = this.configurationService.getValue(AccessibilityVerbositySettingId.Comments);
if (verbose) {
const keybinding = this.keybindingService.lookupKeybinding(AccessibilityCommandId.OpenAccessibilityHelp)?.getAriaLabel();
if (keybinding) {
status(nls.localize('hasCommentRangesKb', "Editor has commenting ranges, run the command Open Accessibility Help ({0}), for more information.", keybinding));
} else {
status(nls.localize('hasCommentRangesNoKb', "Editor has commenting ranges, run the command Open Accessibility Help, which is currently not triggerable via keybinding, for more information."));
}
} else {
status(nls.localize('hasCommentRanges', "Editor has commenting ranges."));
}
} else {
this._activeEditorHasCommentingRange.set(false);
}
@@ -5,8 +5,8 @@
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import 'vs/css!./media/review';
import { IActiveCodeEditor, ICodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, EditorContributionInstantiation, registerEditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { IActiveCodeEditor, isCodeEditor, isDiffEditor } from 'vs/editor/browser/editorBrowser';
import { EditorContributionInstantiation, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import * as nls from 'vs/nls';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
@@ -21,101 +21,91 @@ import { CommentController, ID } from 'vs/workbench/contrib/comments/browser/com
import { IRange, Range } from 'vs/editor/common/core/range';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys';
export class NextCommentThreadAction extends EditorAction {
constructor() {
super({
id: 'editor.action.nextCommentThreadAction',
label: nls.localize('nextCommentThreadAction', "Go to Next Comment Thread"),
alias: 'Go to Next Comment Thread',
precondition: undefined,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyMod.Alt | KeyCode.F9,
weight: KeybindingWeight.EditorContrib
}
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
const controller = CommentController.get(editor);
controller?.nextCommentThread();
}
}
export class PreviousCommentThreadAction extends EditorAction {
constructor() {
super({
id: 'editor.action.previousCommentThreadAction',
label: nls.localize('previousCommentThreadAction', "Go to Previous Comment Thread"),
alias: 'Go to Previous Comment Thread',
precondition: undefined,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F9,
weight: KeybindingWeight.EditorContrib
}
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
const controller = CommentController.get(editor);
controller?.previousCommentThread();
}
}
import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { accessibilityHelpIsShown, accessibleViewCurrentProviderId, AccessibleViewProviderId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
import { CommentCommandId } from 'vs/workbench/contrib/comments/common/commentCommandIds';
registerEditorContribution(ID, CommentController, EditorContributionInstantiation.AfterFirstRender);
registerEditorAction(NextCommentThreadAction);
registerEditorAction(PreviousCommentThreadAction);
export class NextCommentingRangeAction extends EditorAction {
constructor() {
super({
id: 'editor.action.goToNextCommentingRange',
label: nls.localize('goToNextCommentingRange', "Go to Next Commenting Range"),
alias: 'Go to Next Commenting Range',
precondition: CommentContextKeys.WorkspaceHasCommenting,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.DownArrow),
weight: KeybindingWeight.EditorContrib
}
});
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CommentCommandId.NextThread,
handler: async (accessor, args?: { range: IRange; fileComment: boolean }) => {
const activeEditor = getActiveEditor(accessor);
if (!activeEditor) {
return Promise.resolve();
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
const controller = CommentController.get(editor);
controller?.nextCommentingRange();
}
}
const controller = CommentController.get(activeEditor);
if (!controller) {
return Promise.resolve();
}
controller.nextCommentThread();
},
weight: KeybindingWeight.EditorContrib,
when: EditorContextKeys.focus,
primary: KeyMod.Alt | KeyCode.F9,
});
export class PreviousCommentingRangeAction extends EditorAction {
constructor() {
super({
id: 'editor.action.goToPreviousCommentingRange',
label: nls.localize('goToPreviousCommentingRange', "Go to Previous Commenting Range"),
alias: 'Go to Next Commenting Range',
precondition: CommentContextKeys.WorkspaceHasCommenting,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.UpArrow),
weight: KeybindingWeight.EditorContrib
}
});
}
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CommentCommandId.PreviousThread,
handler: async (accessor, args?: { range: IRange; fileComment: boolean }) => {
const activeEditor = getActiveEditor(accessor);
if (!activeEditor) {
return Promise.resolve();
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
const controller = CommentController.get(editor);
controller?.previousCommentingRange();
}
}
const controller = CommentController.get(activeEditor);
if (!controller) {
return Promise.resolve();
}
controller.previousCommentThread();
},
weight: KeybindingWeight.EditorContrib,
when: EditorContextKeys.focus,
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.F9
});
registerEditorAction(NextCommentingRangeAction);
registerEditorAction(PreviousCommentingRangeAction);
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CommentCommandId.NextRange,
handler: async (accessor, args?: { range: IRange; fileComment: boolean }) => {
const activeEditor = getActiveEditor(accessor);
if (!activeEditor) {
return Promise.resolve();
}
const controller = CommentController.get(activeEditor);
if (!controller) {
return Promise.resolve();
}
controller.nextCommentingRange();
},
when: ContextKeyExpr.and(CONTEXT_ACCESSIBILITY_MODE_ENABLED, ContextKeyExpr.or(EditorContextKeys.focus, CommentContextKeys.commentFocused, ContextKeyExpr.and(accessibilityHelpIsShown, accessibleViewCurrentProviderId.isEqualTo(AccessibleViewProviderId.Comments)))),
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.DownArrow),
weight: KeybindingWeight.EditorContrib
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: CommentCommandId.PreviousRange,
handler: async (accessor, args?: { range: IRange; fileComment: boolean }) => {
const activeEditor = getActiveEditor(accessor);
if (!activeEditor) {
return Promise.resolve();
}
const controller = CommentController.get(activeEditor);
if (!controller) {
return Promise.resolve();
}
controller.previousCommentingRange();
},
when: ContextKeyExpr.and(CONTEXT_ACCESSIBILITY_MODE_ENABLED, ContextKeyExpr.or(EditorContextKeys.focus, CommentContextKeys.commentFocused, ContextKeyExpr.and(accessibilityHelpIsShown, accessibleViewCurrentProviderId.isEqualTo(AccessibleViewProviderId.Comments)))),
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.UpArrow),
weight: KeybindingWeight.EditorContrib
});
const TOGGLE_COMMENTING_COMMAND = 'workbench.action.toggleCommenting';
CommandsRegistry.registerCommand({
id: TOGGLE_COMMENTING_COMMAND,
id: CommentCommandId.ToggleCommenting,
handler: (accessor) => {
const commentService = accessor.get(ICommentService);
const enable = commentService.isCommentingEnabled;
@@ -125,16 +115,15 @@ CommandsRegistry.registerCommand({
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: TOGGLE_COMMENTING_COMMAND,
id: CommentCommandId.ToggleCommenting,
title: nls.localize('comments.toggleCommenting', "Toggle Editor Commenting"),
category: 'Comments',
},
when: CommentContextKeys.WorkspaceHasCommenting
});
const ADD_COMMENT_COMMAND = 'workbench.action.addComment';
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: ADD_COMMENT_COMMAND,
id: CommentCommandId.Add,
handler: async (accessor, args?: { range: IRange; fileComment: boolean }) => {
const activeEditor = getActiveEditor(accessor);
if (!activeEditor) {
@@ -161,16 +150,15 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: ADD_COMMENT_COMMAND,
id: CommentCommandId.Add,
title: nls.localize('comments.addCommand', "Add Comment on Current Selection"),
category: 'Comments'
},
when: CommentContextKeys.activeCursorHasCommentingRange
});
const COLLAPSE_ALL_COMMENT_COMMAND = 'workbench.action.collapseAllComments';
CommandsRegistry.registerCommand({
id: COLLAPSE_ALL_COMMENT_COMMAND,
id: CommentCommandId.CollapseAll,
handler: (accessor) => {
return getActiveController(accessor)?.collapseAll();
}
@@ -178,16 +166,15 @@ CommandsRegistry.registerCommand({
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: COLLAPSE_ALL_COMMENT_COMMAND,
id: CommentCommandId.CollapseAll,
title: nls.localize('comments.collapseAll', "Collapse All Comments"),
category: 'Comments'
},
when: CommentContextKeys.WorkspaceHasCommenting
});
const EXPAND_ALL_COMMENT_COMMAND = 'workbench.action.expandAllComments';
CommandsRegistry.registerCommand({
id: EXPAND_ALL_COMMENT_COMMAND,
id: CommentCommandId.ExpandAll,
handler: (accessor) => {
return getActiveController(accessor)?.expandAll();
}
@@ -195,16 +182,15 @@ CommandsRegistry.registerCommand({
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: EXPAND_ALL_COMMENT_COMMAND,
id: CommentCommandId.ExpandAll,
title: nls.localize('comments.expandAll', "Expand All Comments"),
category: 'Comments'
},
when: CommentContextKeys.WorkspaceHasCommenting
});
const EXPAND_UNRESOLVED_COMMENT_COMMAND = 'workbench.action.expandUnresolvedComments';
CommandsRegistry.registerCommand({
id: EXPAND_UNRESOLVED_COMMENT_COMMAND,
id: CommentCommandId.ExpandUnresolved,
handler: (accessor) => {
return getActiveController(accessor)?.expandUnresolved();
}
@@ -212,7 +198,7 @@ CommandsRegistry.registerCommand({
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: EXPAND_UNRESOLVED_COMMENT_COMMAND,
id: CommentCommandId.ExpandUnresolved,
title: nls.localize('comments.expandUnresolved', "Expand Unresolved Comments"),
category: 'Comments'
},
@@ -220,7 +206,7 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'workbench.action.submitComment',
id: CommentCommandId.Submit,
weight: KeybindingWeight.EditorContrib,
primary: KeyMod.CtrlCmd | KeyCode.Enter,
when: ctxCommentEditorFocused,
@@ -233,7 +219,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'workbench.action.hideComment',
id: CommentCommandId.Hide,
weight: KeybindingWeight.EditorContrib,
primary: KeyCode.Escape,
secondary: [KeyMod.Shift | KeyCode.Escape],
@@ -0,0 +1,18 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export const enum CommentCommandId {
Add = 'workbench.action.addComment',
NextThread = 'editor.action.nextCommentThreadAction',
PreviousThread = 'editor.action.previousCommentThreadAction',
NextRange = 'editor.action.nextCommentingRange',
PreviousRange = 'editor.action.previousCommentingRange',
ToggleCommenting = 'workbench.action.toggleCommenting',
Submit = 'editor.action.submitComment',
Hide = 'workbench.action.hideComment',
CollapseAll = 'workbench.action.collapseAllComments',
ExpandAll = 'workbench.action.expandAllComments',
ExpandUnresolved = 'workbench.action.expandUnresolvedComments'
}
@@ -53,4 +53,9 @@ export namespace CommentContextKeys {
* The comment controller id associated with a comment thread.
*/
export const commentControllerContext = new RawContextKey<string>('commentController', undefined, { type: 'string', description: nls.localize('commentController', "The comment controller id associated with a comment thread") });
/**
* The comment widget is focused.
*/
export const commentFocused = new RawContextKey<boolean>('commentFocused', false, { type: 'boolean', description: nls.localize('commentFocused', "Set when the comment is focused") });
}