diff --git a/src/DecoratorProvider.ts b/src/DecoratorProvider.ts index 4bd5c3a..e96ca44 100644 --- a/src/DecoratorProvider.ts +++ b/src/DecoratorProvider.ts @@ -65,14 +65,15 @@ export default class DecoratorProvider extends vscode.Disposable { const d: vscode.DecorationOptions[] = []; while ((match = regEx.exec(text))) { const name = match[1]; - const emoji = this.emojiProvider.lookup(name); - if (!emoji) { + const emojis = this.emojiProvider.lookup(name); + if (!emojis.length) { continue; } const startPos = activeEditor.document.positionAt(match.index + 1); const endPos = activeEditor.document.positionAt(match.index + match[0].length - 1); - d.push({ + + const emojiDecorations = emojis.map(emoji => ({ range: new vscode.Range(startPos, endPos), hoverMessage: this.hoverMessage(emoji), renderOptions: { @@ -82,7 +83,9 @@ export default class DecoratorProvider extends vscode.Disposable { color: 'rgba(255, 255, 255, 0.55)', }, }, - }); + })); + + d.push(...emojiDecorations); } activeEditor.setDecorations(this.decorationType, d); } diff --git a/src/EmojiCompletionProvider.ts b/src/EmojiCompletionProvider.ts index 013e893..27983e3 100644 --- a/src/EmojiCompletionProvider.ts +++ b/src/EmojiCompletionProvider.ts @@ -54,8 +54,15 @@ export default class EmojiCompletionProvider implements vscode.CompletionItemPro const kind = vscode.CompletionItemKind.Text; return this.emojiProvider.emojis.map((x) => { - const item = new vscode.CompletionItem(`:${x.name}: ${x.emoji}`, kind); - item.filterText = `:${x.name}:`; + const item = new vscode.CompletionItem({ + label: `:${x.name}: ${x.emoji}`, + // If the search term doesn't match + // the actual emoji name, show the + // search term, as well + description: x.name === x.lookupKey ? + undefined : x.lookupKey + }, kind); + item.filterText = `:${x.lookupKey}:`; item.documentation = new vscode.MarkdownString(`# ${x.emoji}`); item.insertText = x.emoji; item.range = replacementSpan; @@ -73,8 +80,15 @@ export default class EmojiCompletionProvider implements vscode.CompletionItemPro const kind = vscode.CompletionItemKind.Text; return this.emojiProvider.emojis.map((x) => { - const item = new vscode.CompletionItem(`::${x.name} ${x.emoji}`, kind); - item.filterText = `::${x.name}`; + const item = new vscode.CompletionItem({ + label: `::${x.name} ${x.emoji}`, + // If the search term doesn't match + // the actual emoji name, show the + // search term, as well + description: x.name === x.lookupKey ? + undefined : x.lookupKey + }, kind); + item.filterText = `::${x.lookupKey}`; item.documentation = new vscode.MarkdownString(`# ${x.emoji}`); item.insertText = `:${x.name}:`; item.range = replacementSpan; diff --git a/src/emoji.ts b/src/emoji.ts index e804d6b..dac754d 100644 --- a/src/emoji.ts +++ b/src/emoji.ts @@ -3,31 +3,49 @@ import { gemoji } from 'gemoji'; export interface Emoji { readonly name: string; readonly emoji: string; + readonly lookupKey: string; } export class EmojiProvider { - private _emojiMap?: Map; + private _emojiMap?: Map; private _emojis?: ReadonlyArray; public get emojis(): ReadonlyArray { if (!this._emojis) { - this._emojis = Array.from(this.emojiMap.values()); + // Grab all Emoji[] values for each alias + // then flatten into an array + this._emojis = Array.from(this.emojiMap.values()) + .reduce((arr, emojis) => [...arr, ...emojis], []); } return this._emojis; } - public lookup(name: string): Emoji | undefined { - return this.emojiMap.get(name.toLowerCase()); + /** + * Find a list of matching emojis + * Lookup by name, tag, or description + */ + public lookup(key: string): Emoji[] { + return this.emojiMap.get(key.toLowerCase()) || []; } - private get emojiMap(): Map { + private get emojiMap(): Map { if (!this._emojiMap) { - this._emojiMap = new Map(); + this._emojiMap = new Map(); for (const g of gemoji) { - for (const name of g.names) { - if (!this._emojiMap.has(name)) { - this._emojiMap.set(name, { name, emoji: g.emoji }); - } + // We can lookup emojis by name, tag, or description + const lookupKeys = [ + ...g.names, + ...g.tags, + g.description + ]; + + for (const key of lookupKeys) { + // Each lookup key may have multiple matching emojis + const otherEmojis = this._emojiMap.get(key) || []; + this._emojiMap.set(key, [ + ...otherEmojis, + { name: g.names[0], emoji: g.emoji, lookupKey: key } + ]); } } }