Feature request: Limiting snippets to word boundaries

Bug #417893 reported by Michael Henry
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
UltiSnips
Fix Released
Wishlist
Unassigned

Bug Description

This is a new ticket split off from #407105 ("Feature request: Support for inword snippets expansion"). It contains a request for a new feature to limit snippet triggers to word boundaries. A patch is included to demonstrate the concept. I'm very new to Bazaar, so hopefully I've correctly published the branch here:
https://code.launchpad.net/~drmikehenry/ultisnips/word-boundary
It's revision 184 of the above branch. I've pasted the diff in this ticket as well in case the branch didn't publish correctly.

The basic idea is very similar to the newly added Inword trigger expansion feature. It provides a less restrictive trigger boundary than the standard whitespace-delimited trigger, but more restrictive than the Inword feature that matches somewhat too freely for some applications.

Thanks for considering this patch as input for a future UltiSnips feature.

Michael Henry

Patch follows:

=== modified file 'doc/UltiSnips.txt'
--- doc/UltiSnips.txt 2009-08-16 18:55:08 +0000
+++ doc/UltiSnips.txt 2009-08-23 22:44:19 +0000
@@ -180,9 +180,15 @@
        of the cursor). Default is to expand snippets at every position, even
        mitten in the line. Most of my snippets have this option set, it keeps
        UltiSnips out of the way.
- i Inword expansion - normally, triggers need whitespace before them to be
+ i Inword expansion - Normally, triggers need whitespace before them to be
        expanded. With this option, triggers are also expanded in the middle of
        a word.
+ w Word boundary - Normally, triggers need whitespace before them to be
+ expanded. With this option, the trigger will be expanded at a "word"
+ boundary as well, where word characters are letters, digits, and the
+ underscore character ('_'). This enables expansion of a trigger that
+ adjoins punctuation (for example) without expanding suffixes of larger
+ words.

 4.2 Plaintext snippets *UltiSnips-plaintext-snippets*
 ----------------------

=== modified file 'plugin/UltiSnips/__init__.py'
--- plugin/UltiSnips/__init__.py 2009-08-16 18:55:08 +0000
+++ plugin/UltiSnips/__init__.py 2009-08-23 22:44:19 +0000
@@ -96,14 +96,42 @@
         return "Snippet(%s,%s,%s)" % (self._t,self._d,self._opts)

     def matches(self, trigger):
- if "i" not in self._opts:
- return trigger == self._t
- return trigger.endswith(self._t)
+ # If user supplies both "w" and "i", it should perhaps be an
+ # error, but if permitted it seems that "w" should take precedence
+ # (since matching at word boundary and within a word == matching at word
+ # boundary).
+ if "w" in self._opts:
+ trigger_len = len(self._t)
+ trigger_prefix = trigger[:-trigger_len]
+ trigger_suffix = trigger[-trigger_len:]
+ match = (trigger_suffix == self._t)
+ if match and trigger_prefix:
+ # Require a word boundary between prefix and suffix.
+ boundaryChars = trigger_prefix[-1:] + trigger_suffix[:1]
+ match = re.match(r'.\b.', boundaryChars)
+ elif "i" in self._opts:
+ match = trigger.endswith(self._t)
+ else:
+ match = (trigger == self._t)
+ return match

     def could_match(self, trigger):
- # it i hard to define when a inword snippet could match
- # therefore we do not specially look for it
- return self._t.startswith(trigger)
+ if "w" in self._opts:
+ # Trim non-empty prefix up to word boundary, if present.
+ trigger_suffix = re.sub(r'^.+\b(.+)$', r'\1', trigger)
+ match = self._t.startswith(trigger_suffix)
+
+ # TODO: list_snippets() function cannot handle partial-trigger
+ # matches yet, so for now fail if we trimmed the prefix.
+ if trigger_suffix != trigger:
+ match = False
+ elif "i" in self._opts:
+ # TODO: It is hard to define when a inword snippet could match,
+ # therefore we check only for full-word trigger.
+ match = self._t.startswith(trigger)
+ else:
+ match = self._t.startswith(trigger)
+ return match

     def overwrites_previous(self):
         return "!" in self._opts

=== modified file 'test.py'
--- test.py 2009-08-17 15:33:28 +0000
+++ test.py 2009-08-23 22:44:19 +0000
@@ -1099,6 +1099,28 @@
     keys = "ätest" + EX
     wanted = "äExpand me!"

+class _SnippetOptions_ExpandWordSnippets(_VimTest):
+ snippets = (("test", "Expand me!", "", "w"), )
+class SnippetOptions_ExpandWordSnippets_NormalExpand(
+ _SnippetOptions_ExpandWordSnippets):
+ keys = "test" + EX
+ wanted = "Expand me!"
+class SnippetOptions_ExpandWordSnippets_NoExpand(
+ _SnippetOptions_ExpandWordSnippets):
+ keys = "atest" + EX
+ wanted = "atest"
+class SnippetOptions_ExpandWordSnippets_ExpandSuffix(
+ _SnippetOptions_ExpandWordSnippets):
+ keys = "a-test" + EX
+ wanted = "a-Expand me!"
+class SnippetOptions_ExpandWordSnippets_ExpandSuffix2(
+ _SnippetOptions_ExpandWordSnippets):
+ keys = "a(test" + EX
+ wanted = "a(Expand me!"
+class SnippetOptions_ExpandWordSnippets_ExpandSuffix3(
+ _SnippetOptions_ExpandWordSnippets):
+ keys = "[[test" + EX
+ wanted = "[[Expand me!"

 ######################

Related branches

Revision history for this message
Michael Henry (drmikehenry) wrote :

I should have put the patch as an attachment, as the indentation is not preserved in the comment body. Here's another try.

Michael Henry

Revision history for this message
SirVer (sirver) wrote :

Henry,

If I would get money for UltiSnips, I'd hire you right away. Your patches are excellent, even containing documentation and test updates.
Thanks for the work!

I applied your patch as is; though I feel the 'correct' way to do word boundaries is to parse and use the 'iskeyword' vim option. This is more trouble than it's worth currently though, since I see no use case that can't be handled with 'i' and 'w' currently. Nevertheless; if you feel bored and/or need a challenge, feel free to tackle this.

Greetings,
Holger

SirVer (sirver)
Changed in ultisnips:
importance: Undecided → Wishlist
status: New → Fix Released
Revision history for this message
Michael Henry (drmikehenry) wrote : Re: [Bug 417893] Re: Feature request: Limiting snippets to word boundaries

On 08/30/2009 02:27 PM, SirVer wrote:
> Henry,
>
> If I would get money for UltiSnips, I'd hire you right away. Your
patches are excellent, even containing documentation and test updates.

Thanks :-)

> I applied your patch as is;

Did it make it into the trunk? I did a "bzr update" and the
patch didn't seem to be there. I'm not very familiar with
Bazaar. I did notice that my other two branches were marked as
"Merged" and are part of the trunk now. My "word-boundary"
branch is still listed with status "Development", though, which
makes me think it didn't get merged quite yet.

Thanks,
Michael Henry

Revision history for this message
SirVer (sirver) wrote :

Fixed. I forgot to push my local changes to launchpad. Please verify that all is alright.

Revision history for this message
Michael Henry (drmikehenry) wrote :

Thanks - that fixed it.

Michael Henry

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.