Skip to content

Commit

Permalink
refactor: inject chat keybinding hint in postrender (microsoft#200191)
Browse files Browse the repository at this point in the history
  • Loading branch information
joyceerhl committed Dec 6, 2023
1 parent 0156e4e commit b141c5a
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 14 deletions.
15 changes: 2 additions & 13 deletions src/vs/workbench/contrib/chat/browser/chatListRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -816,18 +816,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
const disposables = new DisposableStore();
let codeBlockIndex = 0;

// inject keybinding hints for command links
const value = markdown.value.replace(/\[([^\]]+)\]\(command:([^\)]+)\)/g, (match, label, command) => {
const keybinding = this.keybindingService.lookupKeybinding(command);
const keybindingLabel = keybinding?.getLabel();
if (keybindingLabel) {
// ideally we would use the keybindingLabel renderer but dompurify sanitizes the styling
return `${match} (\`${keybindingLabel}\`)`;
}
return match;
});

markdown = new MarkdownString(value, {
markdown = new MarkdownString(markdown.value, {
isTrusted: {
// Disable all other config options except isTrusted
enabledCommands: typeof markdown.isTrusted === 'object' ? markdown.isTrusted?.enabledCommands : [] ?? []
Expand Down Expand Up @@ -876,7 +865,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
disposables.add(toDisposable(() => this.codeBlocksByResponseId.delete(element.id)));
}

walkTreeAndAnnotateReferenceLinks(result.element);
walkTreeAndAnnotateReferenceLinks(result.element, this.keybindingService);

orderedDisposablesList.reverse().forEach(d => disposables.add(d));
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { basename } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { IRange } from 'vs/editor/common/core/range';
import { Location } from 'vs/editor/common/languages';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IChatProgressRenderableResponseContent, IChatProgressResponseContent } from 'vs/workbench/contrib/chat/common/chatModel';
import { ChatRequestTextPart, IParsedChatRequest } from 'vs/workbench/contrib/chat/common/chatParserTypes';
import { IChatAgentMarkdownContentWithVulnerability, IChatAgentVulnerabilityDetails, IChatContentInlineReference } from 'vs/workbench/contrib/chat/common/chatService';
Expand All @@ -29,7 +30,7 @@ export function convertParsedRequestToMarkdown(parsedRequest: IParsedChatRequest
return result;
}

export function walkTreeAndAnnotateReferenceLinks(element: HTMLElement): void {
export function walkTreeAndAnnotateReferenceLinks(element: HTMLElement, keybindingService: IKeybindingService): void {
element.querySelectorAll('a').forEach(a => {
const href = a.getAttribute('data-href');
if (href) {
Expand All @@ -39,11 +40,26 @@ export function walkTreeAndAnnotateReferenceLinks(element: HTMLElement): void {
a);
} else if (href.startsWith(contentRefUrl)) {
renderFileWidget(href, a);
} else if (href.startsWith('command:')) {
injectKeybindingHint(a, href, keybindingService);
}
}
});
}

function injectKeybindingHint(a: HTMLAnchorElement, href: string, keybindingService: IKeybindingService): void {
const command = href.match(/command:([^\)]+)/)?.[1];
if (command) {
const kb = keybindingService.lookupKeybinding(command);
if (kb) {
const keybinding = kb.getLabel();
if (keybinding) {
a.textContent = `${a.textContent} (${keybinding})`;
}
}
}
}

function renderResourceWidget(name: string): HTMLElement {
const container = dom.$('span.chat-resource-widget');
const alias = dom.$('span', undefined, name);
Expand Down

0 comments on commit b141c5a

Please sign in to comment.