Skip to content

Commit 1e8f7eb

Browse files
committed
Support emoji completions in review comments
1 parent b6091ac commit 1e8f7eb

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

src/common/emoji.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,10 @@ export function emojify(message: string) {
3636
return emojiMap?.[code] || s;
3737
});
3838
}
39+
40+
export function getEmojis(): Record<string, string> {
41+
if (emojiMap === undefined) {
42+
return {};
43+
}
44+
return emojiMap;
45+
}

src/extension.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import { UriHandler } from './uriHandler';
4343
import { CommentDecorationProvider } from './view/commentDecorationProvider';
4444
import { CompareChanges } from './view/compareChangesTreeDataProvider';
4545
import { CreatePullRequestHelper } from './view/createPullRequestHelper';
46+
import { EmojiCompletionProvider } from './view/emojiCompletionProvider';
4647
import { FileTypeDecorationProvider } from './view/fileTypeDecorationProvider';
4748
import { GitHubCommitFileSystemProvider } from './view/githubFileContentProvider';
4849
import { getInMemPRFileSystemProvider } from './view/inMemPRContentProvider';
@@ -181,6 +182,12 @@ async function init(
181182
const reviewsManager = new ReviewsManager(context, reposManager, reviewManagers, prsTreeModel, tree, changesTree, telemetry, credentialStore, git, copilotRemoteAgentManager, notificationsManager);
182183
context.subscriptions.push(reviewsManager);
183184

185+
context.subscriptions.push(vscode.languages.registerCompletionItemProvider(
186+
{ scheme: Schemes.Comment },
187+
new EmojiCompletionProvider(context),
188+
':'
189+
));
190+
184191
git.onDidChangeState(() => {
185192
Logger.appendLine(`Git initialization state changed: state=${git.state}`, ACTIVATION);
186193
reviewsManager.reviewManagers.forEach(reviewManager => reviewManager.updateState(true));
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import * as vscode from 'vscode';
7+
import { ensureEmojis, getEmojis } from '../common/emoji';
8+
import { Schemes } from '../common/uri';
9+
10+
export class EmojiCompletionProvider implements vscode.CompletionItemProvider {
11+
private static readonly ID: string = 'EmojiCompletionProvider';
12+
private _emojiCompletions: vscode.CompletionItem[] = [];
13+
14+
constructor(private context: vscode.ExtensionContext) {
15+
void this.buildEmojiCompletions();
16+
}
17+
18+
private async buildEmojiCompletions(): Promise<void> {
19+
await ensureEmojis(this.context);
20+
const emojis = getEmojis();
21+
22+
for (const [name, emoji] of Object.entries(emojis)) {
23+
const completionItem = new vscode.CompletionItem({ label: emoji, description: `:${name}:` }, vscode.CompletionItemKind.Text);
24+
completionItem.filterText = `:${name}:`;
25+
completionItem.sortText = name;
26+
this._emojiCompletions.push(completionItem);
27+
}
28+
}
29+
30+
provideCompletionItems(
31+
document: vscode.TextDocument,
32+
position: vscode.Position,
33+
_token: vscode.CancellationToken,
34+
_context: vscode.CompletionContext
35+
): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
36+
// Only provide completions for comment documents
37+
if (document.uri.scheme !== Schemes.Comment) {
38+
return [];
39+
}
40+
41+
let wordRange = document.getWordRangeAtPosition(position);
42+
let wordAtPos = wordRange ? document.getText(wordRange) : undefined;
43+
if (!wordRange || wordAtPos?.charAt(0) !== ':') {
44+
const start = wordRange?.start ?? position;
45+
const testWordRange = new vscode.Range(start.translate(undefined, start.character ? -1 : 0), position);
46+
const testWord = document.getText(testWordRange);
47+
if (testWord.charAt(0) === ':') {
48+
wordRange = testWordRange;
49+
wordAtPos = testWord;
50+
}
51+
}
52+
53+
// Only provide completions if we're in an emoji context (don't clutter Ctrl+Space results)
54+
if (!wordRange) {
55+
return [];
56+
}
57+
58+
// Update the range on cached items directly
59+
for (const item of this._emojiCompletions) {
60+
item.range = wordRange;
61+
}
62+
63+
return new vscode.CompletionList(this._emojiCompletions, false);
64+
}
65+
}

0 commit comments

Comments
 (0)