-
Notifications
You must be signed in to change notification settings - Fork 264
Tolerate Escaped Right Braces And Empty Groups #388
Conversation
# 1. Pull the snippets out, replacing with placeholder | ||
# 2. Highlight relevant characters | ||
# 3. Place snippet HTML back at the placeholders | ||
getHighlightedHTML: (text, snippet, replacementPrefix) => |
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 the fat arrow?
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.
Fixed in 4fda987.
The markers are there so the snippets dont get highlighted in the char highlight process. There are tests for this, but you've edited them so they no longer test what they're supposed to. See https://github.com/atom-community/autocomplete-plus/issues/301 and atom-community@37f2151 |
@@ -336,7 +335,7 @@ describe 'Autocomplete Manager', -> | |||
charMatch = editorView.querySelector('.autocomplete-plus li span.word .character-match') | |||
expect(word.textContent).toBe 'ab(c)c' | |||
expect(charMatch.textContent).toBe 'c' | |||
expect(charMatch.parentNode).toHaveClass 'word' | |||
expect(charMatch.parentNode.parentNode).toHaveClass 'word' |
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.
This makes the test invalid. The entire point of this test is this line. In this new code, the first c
, the snippet, will be highlighted, when the second c
is the one that should be highlighted.
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.
@benogle I think the tests you have are invalid. It should be valid to have a character match for something within the snippet body. It's just not valid to match any of the HTML wrapping a snippet (i.e. <span class="snippet-completion">
or </span>
) or the snippet definition (i.e. ${0:
or }
).
With my new logic, I'm able to stably determine the snippet definition text and exclude it from character matches, prior to insertion of snippet HTML. Consequently, the tests need to change. I think the intent of #301 is to ensure that:
- Snippet HTML does not make its way into the suggestion list
- Snippet HTML is not highlighted
- Snippet definition text does not make its way into the suggestion list
- Snippet definition text does not cause incorrect highlighting of character matches
This is now achieved with my latest changes, that I am about to push.
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.
If you are going to change the spec, check that the parent node is the snippet span class, not this parent.parent indirect check.
I'm fine with the non-regex parser, but i think we need to come up with a way to separate the html generation of the snippets with that of the char highlights. My thinking:
|
text += char | ||
continue | ||
|
||
return text |
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.
just text
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.
Fixed in 4fda987.
0a8fe6b
to
e0385de
Compare
@benogle 👀 |
Looking... |
return text unless text?.length and text.indexOf('$') isnt -1 # No snippets | ||
text.replace(@emptySnippetGroupRegex, '') # Remove all occurrences of $0 or ${0} or ${0:} | ||
|
||
removeAllSnippets: (text) -> |
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.
Looks like nothing calls this method?
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.
Yes, need to remove that. Ignore that function.
Overall, it uses a lot of arrays, and this function will be run a lot. Like several times for each list display. I feel like the
e.g. snippet = 'text(${1:ab}, ${2:cd})'
# Run findSnippets(snippet)
snippets = [{
start: 5
end: 11
textStart: 9
textEnd: 10
text: 'ab'
}, {
start: 14
end: 20
textStart: 18
textEnd: 19
text: 'ab'
}]
# Use snippets to assemble this
replacementText = 'text(ab, cd)'
# Mung snippets to have indices into `replacementText`
snippets = [{
start: 5
end: 11
textStart: 9
textEnd: 10
replacementStart: 5
replacementEnd: 6
text: 'ab'
}, {
start: 14
end: 20
textStart: 18
textEnd: 19
replacementStart: 9
replacementEnd: 10
text: 'cd'
}]
# Run findCharacterMatches(replacementText)
characterMatches = [0, 2, 5]
displayHTML = ''
for replacementChar, index in replacementText
# update displayHTML using your indices.
return displayHTML |
Got any idea why the symbol-provider-specs are failing? |
It's a flaky test. It almost always fails on the |
Also, you could do away with the indexOf checks with 2 objects: one for snippet starts/ends, and one for char matches. So maybe |
I'm not sure switching the snippet info over to 'start' / 'end' saves anything; is it just to avoid indexOf checks? The storage of the information will be larger. |
It saves allll the skipChar arrays. |
Wait, you're referring to the last comment. Yes, it's saving the Also, I'm not optimizing for absolute storage as this stuff is temp. I want to optimize for minimal garbage and cycles. |
And to be clear, I meant creating an object with the |
- ... then perform one pass over the text to add HTML / remove snippet definitions
ee736ab
to
8904e0b
Compare
@benogle 👀 on the latest changes please. |
Ok looking / tinkering |
Those tests seem to fail pretty reliably for stable reasons. Could it be they need modifying? |
Yes, they should be fixed to reliably pass. I've left feedback in the form of a PR: https://github.com/atom-community/autocomplete-plus/pull/396 |
atom/snippets#123 allows snippets to contain escaped right braces (
\\}
). This might be useful - for example - to displayinterface{}
within a snippet's body (as is common forgo
suggestions). This PR allows them to be displayed correctly in the suggestion list. Additionally, it resolves #375, by removing empty snippet groups from the text displayed in the suggestion list.E.g.:
hello$0
>hello
hello${0}
>hello
hello${0:}
>hello
${0:hello}
><span class="snippet-completion">hello</span>
${0:hello{\\}}
><span class="snippet-completion">hello{}</span>
When reviewing the code, you may find the lack of regex ugly, or overly complex. However, without the presence of lookbehind in javascript regexes, an alternative approach is required to differentiate an escaped right brace from an unescaped right brace.
Additionally, a small epilogue:
This also does away with snippet markers; they seem unnecessary. Implicitly, the moment a person who is typing reaches the first snippet, their replacement prefix will no longer match - the snippetMarker (
|
) will not match the text in almost all scenarios.