From 4f3043630dcc080b8205ba2e38555ff71f656876 Mon Sep 17 00:00:00 2001 From: Megan Rogge Date: Tue, 7 Jan 2025 18:12:56 -0600 Subject: [PATCH] add chat edits a11y help (#237439) --- .../browser/actions/chatAccessibilityHelp.ts | 39 +++++++++++++++++-- .../contrib/chat/browser/chat.contribution.ts | 3 +- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts index b1fcadf5d50..e935fda978c 100644 --- a/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts +++ b/src/vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp.ts @@ -12,6 +12,7 @@ import { AccessibleContentProvider, AccessibleViewProviderId, AccessibleViewType import { IAccessibleViewImplentation } from '../../../../../platform/accessibility/browser/accessibleViewRegistry.js'; import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js'; import { IKeybindingService } from '../../../../../platform/keybinding/common/keybinding.js'; +import { ActiveAuxiliaryContext } from '../../../../common/contextkeys.js'; import { AccessibilityVerbositySettingId } from '../../../accessibility/browser/accessibilityConfiguration.js'; import { INLINE_CHAT_ID } from '../../../inlineChat/common/inlineChat.js'; import { ChatAgentLocation } from '../../common/chatAgents.js'; @@ -22,7 +23,7 @@ export class PanelChatAccessibilityHelp implements IAccessibleViewImplentation { readonly priority = 107; readonly name = 'panelChat'; readonly type = AccessibleViewType.Help; - readonly when = ContextKeyExpr.and(ChatContextKeys.location.isEqualTo(ChatAgentLocation.Panel), ChatContextKeys.inQuickChat.negate(), ContextKeyExpr.or(ChatContextKeys.inChatSession, ChatContextKeys.isResponse, ChatContextKeys.isRequest)); + readonly when = ContextKeyExpr.and(ChatContextKeys.location.isEqualTo(ChatAgentLocation.Panel), ChatContextKeys.inQuickChat.negate(), ActiveAuxiliaryContext.isEqualTo('workbench.panel.chat'), ContextKeyExpr.or(ChatContextKeys.inChatSession, ChatContextKeys.isResponse, ChatContextKeys.isRequest)); getProvider(accessor: ServicesAccessor) { const codeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor() || accessor.get(ICodeEditorService).getFocusedCodeEditor(); return getChatAccessibilityHelpProvider(accessor, codeEditor ?? undefined, 'panelChat'); @@ -40,7 +41,18 @@ export class QuickChatAccessibilityHelp implements IAccessibleViewImplentation { } } -export function getAccessibilityHelpText(type: 'panelChat' | 'inlineChat' | 'quickChat', keybindingService: IKeybindingService): string { +export class EditsChatAccessibilityHelp implements IAccessibleViewImplentation { + readonly priority = 119; + readonly name = 'editsView'; + readonly type = AccessibleViewType.Help; + readonly when = ActiveAuxiliaryContext.isEqualTo('workbench.panel.chatEditing'); + getProvider(accessor: ServicesAccessor) { + const codeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor() || accessor.get(ICodeEditorService).getFocusedCodeEditor(); + return getChatAccessibilityHelpProvider(accessor, codeEditor ?? undefined, 'editsView'); + } +} + +export function getAccessibilityHelpText(type: 'panelChat' | 'inlineChat' | 'quickChat' | 'editsView', keybindingService: IKeybindingService): string { const content = []; if (type === 'panelChat' || type === 'quickChat') { if (type === 'quickChat') { @@ -61,6 +73,25 @@ export function getAccessibilityHelpText(type: 'panelChat' | 'inlineChat' | 'qui content.push(localize('workbench.action.chat.newChat', 'To create a new chat session, invoke the New Chat command{0}.', '')); } } + if (type === 'editsView') { + content.push(localize('chatEditing.overview', 'The chat editing view is used to apply edits across files.')); + content.push(localize('chatEditing.format', 'It is comprised of an input box and a file working set (Shift+Tab).')); + content.push(localize('chatEditing.expectation', 'When a request is made, a progress indicator will play while the edits are being applied.')); + content.push(localize('chatEditing.review', 'Once the edits are applied, focus the editor(s) to review, accept, and discard changes.')); + content.push(localize('chatEditing.sections', 'Navigate between edits in the editor with navigate previous{0} and next{1}', '', '')); + content.push(localize('chatEditing.acceptHunk', 'In the editor, Accept{0} and Reject the current Change{1}.', '', '')); + content.push(localize('chatEditing.helpfulCommands', 'When in the edits view, some helpful commands include:')); + content.push(localize('workbench.action.chat.undoEdits', '- Undo Edits{0}.', '')); + content.push(localize('workbench.action.chat.editing.attachFiles', '- Attach Files{0}.', '')); + content.push(localize('chatEditing.removeFileFromWorkingSet', '- Remove File from Working Set{0}.', '')); + content.push(localize('chatEditing.acceptFile', '- Accept{0} and Discard File{1}.', '', '')); + content.push(localize('chatEditing.saveAllFiles', '- Save All Files{0}.', '')); + content.push(localize('chatEditing.acceptAllFiles', '- Accept All Edits{0}.', '')); + content.push(localize('chatEditing.discardAllFiles', '- Discard All Edits{0}.', '')); + content.push(localize('chatEditing.openFileInDiff', '- Open File in Diff{0}.', '')); + content.push(localize('chatEditing.addFileToWorkingSet', '- Add File to Working Set{0}.', '')); + content.push(localize('chatEditing.viewChanges', '- View Changes{0}.', '')); + } else { content.push(localize('inlineChat.overview', "Inline chat occurs within a code editor and takes into account the current selection. It is useful for making changes to the current editor. For example, fixing diagnostics, documenting or refactoring code. Keep in mind that AI generated code may be incorrect.")); content.push(localize('inlineChat.access', "It can be activated via code actions or directly using the command: Inline Chat: Start Inline Chat{0}.", '')); @@ -75,10 +106,10 @@ export function getAccessibilityHelpText(type: 'panelChat' | 'inlineChat' | 'qui return content.join('\n'); } -export function getChatAccessibilityHelpProvider(accessor: ServicesAccessor, editor: ICodeEditor | undefined, type: 'panelChat' | 'inlineChat' | 'quickChat') { +export function getChatAccessibilityHelpProvider(accessor: ServicesAccessor, editor: ICodeEditor | undefined, type: 'panelChat' | 'inlineChat' | 'quickChat' | 'editsView') { const widgetService = accessor.get(IChatWidgetService); const keybindingService = accessor.get(IKeybindingService); - const inputEditor: ICodeEditor | undefined = type === 'panelChat' || type === 'quickChat' ? widgetService.lastFocusedWidget?.inputEditor : editor; + const inputEditor: ICodeEditor | undefined = type === 'panelChat' || type === 'editsView' || type === 'quickChat' ? widgetService.lastFocusedWidget?.inputEditor : editor; if (!inputEditor) { return; diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index 86b780b350c..a43f6b50cac 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -37,7 +37,7 @@ import { ILanguageModelStatsService, LanguageModelStatsService } from '../common import { ILanguageModelToolsService } from '../common/languageModelToolsService.js'; import { LanguageModelToolsExtensionPointHandler } from '../common/tools/languageModelToolsContribution.js'; import { IVoiceChatService, VoiceChatService } from '../common/voiceChatService.js'; -import { PanelChatAccessibilityHelp, QuickChatAccessibilityHelp } from './actions/chatAccessibilityHelp.js'; +import { EditsChatAccessibilityHelp, PanelChatAccessibilityHelp, QuickChatAccessibilityHelp } from './actions/chatAccessibilityHelp.js'; import { ChatCommandCenterRendering, registerChatActions } from './actions/chatActions.js'; import { ACTION_ID_NEW_CHAT, registerNewChatActions } from './actions/chatClearActions.js'; import { registerChatCodeBlockActions, registerChatCodeCompareBlockActions } from './actions/chatCodeblockActions.js'; @@ -207,6 +207,7 @@ class ChatResolverContribution extends Disposable { AccessibleViewRegistry.register(new ChatResponseAccessibleView()); AccessibleViewRegistry.register(new PanelChatAccessibilityHelp()); AccessibleViewRegistry.register(new QuickChatAccessibilityHelp()); +AccessibleViewRegistry.register(new EditsChatAccessibilityHelp()); registerEditorFeature(ChatInputBoxContentProvider);