-
Notifications
You must be signed in to change notification settings - Fork 27.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for Emmet's wrap with abbreviation inserting extra spaces #43345
Conversation
if (expandOptions['text'][0].indexOf('\n') === -1) { | ||
expandOptions['text'][0] = '\n\t' + expandOptions['text'][0] + '\n'; | ||
} | ||
expandedText = helper.expandAbbreviation(input.abbreviation, expandOptions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why expand again? Why not just add the \n\t
and t
around $TM_SELECTED_TEXT
in the expanded text?
@@ -436,14 +443,20 @@ function expandAbbr(input: ExpandAbbreviationInput): string | undefined { | |||
let expandedText = helper.expandAbbreviation(input.abbreviation, expandOptions); | |||
|
|||
if (input.textToWrap) { | |||
// Fetch innermost element in the expanded abbreviation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldnt we do the search for block elements only if textToWrap was a single line?
if (input.textToWrap.length === 1 && input.rangeToReplace.isSingleLine)
// Fetch innermost element in the expanded abbreviation | ||
let wrappingEnd = expandedText.substring(expandedText.indexOf('$TM_SELECTED_TEXT')); | ||
let tagName = wrappingEnd.substring(wrappingEnd.indexOf('/') + 1, wrappingEnd.indexOf('>')); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do you think about using regular expressions here instead?
Instead of expanding the abbreviation to figure out if the wrapping element is inline or not, we can parse the abbreviation to get a tree and use it to figure out the same. And then, the same tree can be used by the expand module |
let parsedAbbr = helper.parseAbbreviation(input.abbreviation, expandOptions); | ||
if (input.rangeToReplace.isSingleLine) { | ||
|
||
// Fetch innermost element in the expanded abbreviation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"parsed" not "expanded"
tagName = lastNode.name; | ||
} | ||
|
||
// If wrapping with a block element, insert newline and expand again |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These comments need to be updated as we are not expanding "again" anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right
|
||
// If wrapping with a block element, insert newline and expand again | ||
// We need to expand again because emmet module can't know if the text being wrapped is multiline. | ||
if (inlineElements.indexOf(tagName) === -1 && input.textToWrap.length === 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can move the input.textToWrap.length === 1
check up to line 449
|
||
// Fetch innermost element in the expanded abbreviation | ||
let lastNode = parsedAbbr; | ||
let tagName = parsedAbbr.name || ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can move this after finding the innermost node i.e after the while loop. This way we can avoid setting the tagName multiple times inside the loop
if (input.rangeToReplace.isSingleLine) { | ||
|
||
// Fetch innermost element in the expanded abbreviation | ||
let lastNode = parsedAbbr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets rename this to innerMostNode
. It will then match with your comment and is also more intuitive than lastNode
// Fetch innermost element in the expanded abbreviation | ||
let lastNode = parsedAbbr; | ||
let tagName = parsedAbbr.name || ''; | ||
while (lastNode.children && lastNode.children.length > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if parsedAbbr
was null or undefined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'll throw an error when trying to obtain its property 'name', and we'll catch that. Do you think we should treat it differently?
@@ -197,6 +197,30 @@ suite('Tests for Wrap with Abbreviations', () => { | |||
}); | |||
}); | |||
|
|||
test('Wrap with multiline abbreviation doesnt add extra spaces', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add the bug id here in the test name
…microsoft#43345)" This reverts commit 7420a04.
* Revert "Fix for Emmet's wrap with abbreviation inserting extra spaces (#43345)" This reverts commit 7420a04. * Adding ability for emmet to wrap with abbreviation in real time. Currently it's only working for single cursor. * Fixes to wrap in real time: - Removed flickering when typing abbreviation - Removed tabstops - Fixed bug when wrapping multiline text * Fixes to a few issues. - Added checks for not reverting previews more times than needed, that was causing extra text to be deleted. - Fixed issue when wrapping nodes with multiple level of indentation. - Removed all the undo commands. Now all the logic of going back to the original state is handled by revertPreview. * Ammend for previous revert * Reapplying reverted commit, fixing the bug for this branch's version Refactoring some of the code, now a single object contains the current and original ranges, as well as the original content to wrap * Adding multicursor support * Renaming, refactoring and other stuff * More refactorings * More renaming and refactoring * Replacing placeholders when previewing, simplifying the extracting of preceeding whitespace, added a check for validity of expandedtext on each selection. * More refactoring * Adding a comment. * Readding test removed by mistake. * Refactoring * Carefully reverting changes in yarn.lock * carefully but right
There needs to be a setting for VSCode which will allow to completely disable automatic indentation based on identifying what type of element the wrapping tag is. For example, current implementation for wrapping a selected piece of text with any block level element like
which might be technically correct but it's ugly and completely unnecessary in terms of wasting lines and space. I basically need VSCode to stop overthinking everything and just wrap code with a tag of my selection without automatically indenting it. |
@brezanac, That might work well for your case, but doesn't really help when wrapping multi-line text or better yet, multi line html If you do have a solution that works for both cases, please do send a PR. We would appreciate it. |
Fix for #29898
Now, when wrapping text with a multiline abbreviation such as
ul>li>a
, no extra spaces are added.Added a unit test to keep track of this issue.