Skip to content

Commit 58004f1

Browse files
committed
fix: effective handling of closing braces in emmet abbr
1 parent d4d7bda commit 58004f1

File tree

1 file changed

+65
-26
lines changed
  • src/extensionsIntegrated/Emmet

1 file changed

+65
-26
lines changed

src/extensionsIntegrated/Emmet/main.js

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
define(function (require, exports, module) {
22
const AppInit = require("utils/AppInit");
3-
const EditorManager = require("editor/EditorManager");
3+
// const EditorManager = require("editor/EditorManager");
44
const PreferencesManager = require("preferences/PreferencesManager");
55
const Strings = require("strings");
66
const CodeHintManager = require("editor/CodeHintManager");
@@ -294,8 +294,8 @@ define(function (require, exports, module) {
294294

295295

296296
/**
297-
* Responsible to create the configuration based on the file type.
298-
* Config is an object with two properties, type & snytax.
297+
* Responsible to create the configuration based on the file type
298+
* Config is an object with two properties, type & snytax
299299
* This is required by the Emmet API to distinguish between HTML & Stylesheets
300300
*
301301
* @param {Editor} editor - The editor instance
@@ -316,53 +316,92 @@ define(function (require, exports, module) {
316316
}
317317

318318
/**
319-
* Responsible to get the current word before cursor
319+
* Determines whether a given character is allowed as part of an Emmet abbreviation
320320
*
321-
* @param {Editor} editor - The editor instance
322-
* @returns {Object} an object in the format :
323-
* {
324-
* word: "", // the word before the cursor
325-
* start: {line: Number, ch: Number},
326-
* end: {line: Number, ch: Number}
327-
* }
321+
* @param {String} char - The character to test
322+
* @param {Boolean} insideBraces - Flag indicating if we are inside braces (e.g. {} or [])
323+
* @returns True if the character is valid for an abbreviation
328324
*/
329-
function getWordBeforeCursor(editor) {
330-
const pos = editor.getCursorPos();
331-
const line = editor.document.getLine(pos.line);
332-
let start = pos.ch;
325+
function isEmmetChar(char, insideBraces) {
326+
// Valid abbreviation characters: letters, digits, and some punctuation
327+
// Adjust this regex or the list as needed for your implementation
328+
const validPattern = /[a-zA-Z0-9:+*<>()/!$\-@#}{]/;
329+
const specialChars = new Set(['.', '#', '[', ']', '"', '=', ':', ',', '-']);
330+
return validPattern.test(char) || specialChars.has(char) || (insideBraces && char === ' ');
331+
}
332+
333+
334+
/**
335+
* Scans backwards from the given cursor position on a line to locate the start of the Emmet abbreviation
336+
*
337+
* @param {String} line - The full text of the current line
338+
* @param {Number} cursorCh - The cursor's character (column) position on that line
339+
* @returns The index (column) where the abbreviation starts
340+
*/
341+
function findAbbreviationStart(line, cursorCh) {
342+
let start = cursorCh;
333343
let insideBraces = false;
334-
// special chars that may be in emmet abbr
335-
const specialChars = new Set(['.', '#', '[', ']', '"', '=', '//', ':', '-', ',']);
336344

337-
// If the cursor is right before '}', move it inside
338-
if (line.charAt(start) === '}') {
345+
// If the cursor is right before a closing brace, adjust it to be "inside" the braces
346+
if (line.charAt(start) === '}' || line.charAt(start) === ']') {
339347
start--;
340348
insideBraces = true;
341349
}
342350

343-
// Look backwards
351+
// Walk backwards from the cursor to find the boundary of the abbreviation
344352
while (start > 0) {
345353
const char = line.charAt(start - 1);
346354

355+
// Update our "inside braces" state based on the character
347356
if (char === '}' || char === ']') {
348357
insideBraces = true;
349358
} else if (char === '{' || char === '[') {
350359
insideBraces = false;
351360
}
352361

353-
if (/[a-zA-Z0-9:+*<>()/!$\-@#}{]/.test(char) ||
354-
specialChars.has(char) ||
355-
(insideBraces && char === ' ')) {
362+
// If the character is valid as part of an Emmet abbreviation, continue scanning backwards
363+
if (isEmmetChar(char, insideBraces)) {
356364
start--;
357365
} else {
358366
break;
359367
}
360368
}
369+
return start;
370+
}
371+
372+
373+
/**
374+
* Retrieves the Emmet abbreviation (i.e. the word before the cursor) from the current editor state
375+
*
376+
* @param {Editor} editor - The editor instance
377+
* @returns An object with the abbreviation and its start/end positions
378+
*
379+
* Format:
380+
* {
381+
* word: string, // the extracted abbreviation
382+
* start: { line: number, ch: number },
383+
* end: { line: number, ch: number }
384+
* }
385+
*/
386+
function getWordBeforeCursor(editor) {
387+
const pos = editor.getCursorPos();
388+
const lineText = editor.document.getLine(pos.line);
389+
390+
// to determine where the abbreviation starts on the line
391+
const abbreviationStart = findAbbreviationStart(lineText, pos.ch);
392+
393+
// Optionally, adjust the end position if the cursor is immediately before a closing brace.
394+
let abbreviationEnd = pos.ch;
395+
if (lineText.charAt(abbreviationEnd) === '}' || lineText.charAt(abbreviationEnd) === ']') {
396+
abbreviationEnd++;
397+
}
398+
399+
const word = lineText.substring(abbreviationStart, abbreviationEnd);
361400

362401
return {
363-
word: line.substring(start, pos.ch),
364-
start: { line: pos.line, ch: start },
365-
end: pos
402+
word: word,
403+
start: { line: pos.line, ch: abbreviationStart },
404+
end: { line: pos.line, ch: abbreviationEnd }
366405
};
367406
}
368407

0 commit comments

Comments
 (0)