Skip to content
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

Merged
merged 8 commits into from
Feb 15, 2018

Conversation

gushuro
Copy link
Contributor

@gushuro gushuro commented Feb 9, 2018

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.

if (expandOptions['text'][0].indexOf('\n') === -1) {
expandOptions['text'][0] = '\n\t' + expandOptions['text'][0] + '\n';
}
expandedText = helper.expandAbbreviation(input.abbreviation, expandOptions);
Copy link
Contributor

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
Copy link
Contributor

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('>'));

Copy link
Contributor

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?

@ramya-rao-a
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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

Copy link
Contributor Author

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) {
Copy link
Contributor

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 || '';
Copy link
Contributor

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;
Copy link
Contributor

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) {
Copy link
Contributor

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?

Copy link
Contributor Author

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', () => {
Copy link
Contributor

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

@ramya-rao-a ramya-rao-a merged commit 7420a04 into microsoft:master Feb 15, 2018
@gushuro gushuro deleted the extraspaces branch February 28, 2018 18:34
gushuro pushed a commit to gushuro/vscode that referenced this pull request Mar 5, 2018
ramya-rao-a pushed a commit that referenced this pull request Mar 7, 2018
* 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
@brezanac
Copy link

brezanac commented May 4, 2018

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 p or div will produce the following result

<p>    
    Selected text
</p>

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.

@ramya-rao-a
Copy link
Contributor

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.

@github-actions github-actions bot locked and limited conversation to collaborators Mar 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants