atom / snippets

Atom snippets package
MIT License
206 stars 102 forks source link

snippet not working without spaces between characters #272

Closed axe-z closed 5 years ago

axe-z commented 5 years ago

<!latest, every version:

been ussing Atom for 5 years now, I've waited long enough ;)

ex: .. is my snippet for an arrow FN in js. I type : setTimeout() then want a function in there: setTimeout(..) , hit tab, nothing đź‘Ž

I go back put spaces between: setTimeout( .. ) hit tab:

I finally get setTimeout( () => ) fix the unwanted space: setTimeout(() => )

Got it !!

if Bracket can do this right, there is no way Atom should have issues with this.

jonkri commented 5 years ago

I have a similar issue in HTML mode:

For instance, if I expand a p snippet to expand <p></p>, and then in the middle I type for instance a and try to activate the a snippet and produce a hyperlink, it doesn't work (without the space) either.

savetheclocktower commented 5 years ago

@axe-z, here’s the issue (merely describing, not defending current behavior):

When you hit Tab to expand, the snippets package figures out what the current prefix is based on the cursor position and the characters that precede the cursor.

setTimeout( .. )
              ^

When your cursor is here, the “word prefix” is rather clearly .., since the space after ( clearly marks a “word” boundary.

setTimeout(..)
             ^

When your cursor is here, the “word prefix” is interpreted by Atom to be (.., so a snippet with a prefix of .. is not considered to be a match.

This determination is made by Cursor#getBeginningOfCurrentWordPosition, and the decision about what constitutes a “word” is determined internally to this method depending on what scope(s) the cursor is in.

My snippet for an arrow function is ff, so the fact that I’ve never encountered this problem almost surely has to do with the fact that a clear “word” boundary is implied with (ff (punctuation followed by a letter) that isn’t implied by (.. (three punctuation marks in a row).

For a moment I thought I’d found an elegant fix to this, one that would allow the snippets package to invoke a ..-prefixed snippet when it thinks the last word typed was (... But the fact that it broke a unit test made me realize that the cure would be worse than the disease. It’d mean that if I typed off and pressed Tab, I’d get o()=> {} because off ends with ff.

So I’ll have to meditate on this, and perhaps I’ll throw these corner cases at other editors and see how they’re handled.

@jonkri, haven’t tried your example yet, but since your snippet has an alphanumeric prefix, I think it’s probably not the same underlying cause. I’ll let you know.

savetheclocktower commented 5 years ago

@jonkri, your issue is different. The language-html package explicitly disables certain snippets when the cursor is within a tag. I don’t know why, but this is at least an intentional choice on someone’s part.

So a works outside of a tag because the snippet matches the .text.html scope, but it doesn’t work immediately inside of a tag (pretend ^ represents the cursor)…

<p>^</p>

…because the scope includes meta.tag.block.p.html, and the snippet has been configured to be a no-op when the scope matches .text.html .meta.tag.

However, the snippet does work when there are spaces around the cursor…

<p> ^ </p>

…because the scope no longer includes meta.tag.block.p.html or any other meta.tag scope. I don’t think this is intentional. The fix for this would involve changing the language-html grammar file, but if this were fixed it would prevent you from invoking the a snippet inside of a p tag in all cases, spaces or not, so it doesn’t exactly get you closer to your desired outcome.

In your case, I think you’d be able to work around this by putting this into your snippets.cson:

'.text.html .meta.tag':
  'Anchor':
    'prefix': 'a'
    'body': '<a href="${1:#}">$2</a>$0'

In theory, that ought to take precedence over the config in language-html that nulls out that snippet. If this doesn’t work, you could replace .text.html .meta.tag with .text.html .meta.tag.block, .text.html .meta.tag.inline and that should work because it’s a more specific selector than the one in the language bundle.

axe-z commented 5 years ago

Well it's even worst in jsx code:

AGAIN dot dot .. is my arrow FN snippet when between {.. } I do see in a pop up the snippet, hit tabs or enter , nothing will happen.

capture d ecran 2018-09-20 a 16 00 41

Also when entering lets say:

<h1 onClick={...}>Home

( ... is an other arrow FN snippet , same goes if .. ) And pressing ctrl-space to get the snippet menu, both bracket are now gone :

<h1 onClick=...>Home

snippets in jsx are not working well and for the record I work in a Javascript with JSX environment ( at the bottom right )

thing is creating {.. as a snippet is nowhere near as convenient . This works in other IDE.

if I type: TEST.. the snippets works ! It's not about space. I get TEST() =>

savetheclocktower commented 5 years ago

Now that I understand this better, I’m closing it because it’s a duplicate of #151. This bug is on my radar.

jonkri commented 5 years ago

@savetheclocktower: Thanks a lot! Have a great weekend! :)