Skip to content

Commit f775d26

Browse files
committed
fix: use language mode to show snippet hints instead of file extension
1 parent 4041aa2 commit f775d26

File tree

3 files changed

+123
-17
lines changed

3 files changed

+123
-17
lines changed

src/extensionsIntegrated/CustomSnippets/src/driver.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,14 @@ define(function (require, exports, module) {
183183
}
184184

185185
const needle = wordInfo.word.toLowerCase();
186-
const fileExtension = Helper.getCurrentFileExtension(editor);
187186

188-
// check if there's at least one exact match - only show snippets if there is
189-
if (!Helper.hasExactMatchingSnippet(needle, fileExtension)) {
187+
// check if there's at least one exact match using language context detection
188+
if (!Helper.hasExactMatchingSnippet(needle, editor)) {
190189
return response;
191190
}
192191

193-
// get all matching snippets (including prefix matches)
194-
const matchingSnippets = Helper.getMatchingSnippets(needle, fileExtension);
192+
// get all matching snippets using language context detection
193+
const matchingSnippets = Helper.getMatchingSnippets(needle, editor);
195194

196195
// if we have matching snippets, prepend them to the hints
197196
if (matchingSnippets.length > 0) {

src/extensionsIntegrated/CustomSnippets/src/helper.js

Lines changed: 115 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,51 @@ define(function (require, exports, module) {
22
const StringMatch = require("utils/StringMatch");
33
const Global = require("./global");
44

5+
6+
/**
7+
* map the language IDs to their file extensions for snippet matching
8+
* this is needed because we expect the user to enter file extensions and not the file type inside the input field
9+
*
10+
* @param {string} languageId - The language ID from Phoenix
11+
* @returns {string} - The equivalent file extension for snippet matching
12+
*/
13+
function mapLanguageToExtension(languageId) {
14+
const languageMap = {
15+
'javascript': '.js',
16+
'css': '.css',
17+
'html': '.html',
18+
'php': '.php',
19+
'python': '.py',
20+
'java': '.java',
21+
'c': '.c',
22+
'cpp': '.cpp',
23+
'csharp': '.cs',
24+
'typescript': '.ts',
25+
'json': '.json',
26+
'xml': '.xml',
27+
'sql': '.sql',
28+
'sass': '.sass',
29+
'scss': '.scss',
30+
'less': '.less',
31+
'stylus': '.styl',
32+
'coffeescript': '.coffee',
33+
'markdown': '.md',
34+
'yaml': '.yml',
35+
'ruby': '.rb',
36+
'go': '.go',
37+
'rust': '.rs',
38+
'swift': '.swift',
39+
'kotlin': '.kt',
40+
'dart': '.dart',
41+
'vue': '.vue',
42+
'jsx': '.jsx',
43+
'tsx': '.tsx'
44+
};
45+
46+
return languageMap[languageId] || languageId;
47+
}
48+
49+
550
/**
651
* This function is responsible to get the snippet data from all the required input fields
752
* it is called when the save button is clicked
@@ -43,6 +88,25 @@ define(function (require, exports, module) {
4388
$saveBtn.prop("disabled", !(hasAbbr && hasTemplate));
4489
}
4590

91+
/**
92+
* this function is responsible to get the current language context,
93+
* from the editor at cursor position
94+
*
95+
* @param {Editor} editor - The editor instance
96+
* @returns {string|null} - The language ID or null if not available
97+
*/
98+
function getCurrentLanguageContext(editor) {
99+
// first try to get the language at cursor pos
100+
// if it for some reason fails, then just go for the file extension
101+
try {
102+
const language = editor.getLanguageForPosition();
103+
const languageId = language ? language.getId() : null;
104+
return languageId;
105+
} catch (e) {
106+
return getCurrentFileExtension(editor);
107+
}
108+
}
109+
46110
/**
47111
* Gets the current file extension from the editor
48112
* @param {Editor} editor - The editor instance
@@ -56,6 +120,44 @@ define(function (require, exports, module) {
56120
return null;
57121
}
58122

123+
/**
124+
* Checks if a snippet is supported in the given language context
125+
* Falls back to file extension matching if language mapping isn't available
126+
*
127+
* @param {Object} snippet - The snippet object
128+
* @param {string|null} languageContext - The current language context
129+
* @param {Editor} editor - The editor instance for fallback
130+
* @returns {boolean} - True if the snippet is supported
131+
*/
132+
function isSnippetSupportedInLanguageContext(snippet, languageContext, editor) {
133+
if (snippet.fileExtension.toLowerCase() === "all") {
134+
return true;
135+
}
136+
137+
if (languageContext) {
138+
const effectiveExtension = mapLanguageToExtension(languageContext);
139+
140+
// if we have a proper mapping (starts with .), use language context matching
141+
if (effectiveExtension.startsWith('.')) {
142+
const supportedExtensions = snippet.fileExtension
143+
.toLowerCase()
144+
.split(",")
145+
.map((ext) => ext.trim());
146+
147+
return supportedExtensions.some((ext) => ext === effectiveExtension);
148+
}
149+
}
150+
151+
// this is just a fallback if language context matching failed
152+
// file extension matching
153+
if (editor) {
154+
const fileExtension = getCurrentFileExtension(editor);
155+
return isSnippetSupportedInFile(snippet, fileExtension);
156+
}
157+
158+
return false;
159+
}
160+
59161
/**
60162
* Checks if a snippet is supported in the given file extension
61163
* @param {Object} snippet - The snippet object
@@ -81,14 +183,16 @@ define(function (require, exports, module) {
81183
/**
82184
* Checks if there's at least one exact match for the query
83185
* @param {string} query - The search query
84-
* @param {string|null} fileExtension - The current file extension
186+
* @param {Editor} editor - The editor instance
85187
* @returns {boolean} - True if there's an exact match
86188
*/
87-
function hasExactMatchingSnippet(query, fileExtension) {
189+
function hasExactMatchingSnippet(query, editor) {
88190
const queryLower = query.toLowerCase();
191+
const languageContext = getCurrentLanguageContext(editor);
192+
89193
return Global.SnippetHintsList.some((snippet) => {
90194
if (snippet.abbreviation.toLowerCase() === queryLower) {
91-
return isSnippetSupportedInFile(snippet, fileExtension);
195+
return isSnippetSupportedInLanguageContext(snippet, languageContext, editor);
92196
}
93197
return false;
94198
});
@@ -97,14 +201,16 @@ define(function (require, exports, module) {
97201
/**
98202
* Gets all snippets that match the query (prefix matches)
99203
* @param {string} query - The search query
100-
* @param {string|null} fileExtension - The current file extension
204+
* @param {Editor} editor - The editor instance
101205
* @returns {Array} - Array of matching snippets
102206
*/
103-
function getMatchingSnippets(query, fileExtension) {
207+
function getMatchingSnippets(query, editor) {
104208
const queryLower = query.toLowerCase();
209+
const languageContext = getCurrentLanguageContext(editor);
210+
105211
return Global.SnippetHintsList.filter((snippet) => {
106212
if (snippet.abbreviation.toLowerCase().startsWith(queryLower)) {
107-
return isSnippetSupportedInFile(snippet, fileExtension);
213+
return isSnippetSupportedInLanguageContext(snippet, languageContext, editor);
108214
}
109215
return false;
110216
});
@@ -364,7 +470,10 @@ define(function (require, exports, module) {
364470
exports.createHintItem = createHintItem;
365471
exports.clearAllInputFields = clearAllInputFields;
366472
exports.getSnippetData = getSnippetData;
473+
exports.getCurrentLanguageContext = getCurrentLanguageContext;
367474
exports.getCurrentFileExtension = getCurrentFileExtension;
475+
exports.mapLanguageToExtension = mapLanguageToExtension;
476+
exports.isSnippetSupportedInLanguageContext = isSnippetSupportedInLanguageContext;
368477
exports.isSnippetSupportedInFile = isSnippetSupportedInFile;
369478
exports.hasExactMatchingSnippet = hasExactMatchingSnippet;
370479
exports.getMatchingSnippets = getMatchingSnippets;

src/extensionsIntegrated/CustomSnippets/src/snippetCodeHints.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,9 @@ define(function (require, exports, module) {
3636
}
3737

3838
const word = wordInfo.word.toLowerCase();
39-
const fileExtension = Helper.getCurrentFileExtension(editor);
4039

41-
// check if there's at least one exact match - this is the same logic as in driver.js
42-
return Helper.hasExactMatchingSnippet(word, fileExtension);
40+
// check if there's at least one exact match using language context detection
41+
return Helper.hasExactMatchingSnippet(word, editor);
4342
};
4443

4544
/**
@@ -65,10 +64,9 @@ define(function (require, exports, module) {
6564
}
6665

6766
const word = wordInfo.word.toLowerCase();
68-
const fileExtension = Helper.getCurrentFileExtension(this.editor);
6967

70-
// find all matching snippets (including prefix matches) - same logic as driver.js
71-
const matchingSnippets = Helper.getMatchingSnippets(word, fileExtension);
68+
// find all matching snippets using language context detection
69+
const matchingSnippets = Helper.getMatchingSnippets(word, this.editor);
7270

7371
if (matchingSnippets.length > 0) {
7472
matchingSnippets.forEach((snippet) => {

0 commit comments

Comments
 (0)