diff --git a/doc/UltiSnips.txt b/doc/UltiSnips.txt index 4afd21d..9a99a38 100644 --- a/doc/UltiSnips.txt +++ b/doc/UltiSnips.txt @@ -201,7 +201,7 @@ will not unmap any mapping that contains the string "somePlugin" or 3.5 Functions *UltiSnips-functions* ------------- -Ultisnips provides two functions for extending core functionality. +UltiSnips provides two functions for extending core functionality. 3.5.1 UltiSnips_AddSnippet *UltiSnips_AddSnippet* @@ -309,6 +309,11 @@ snippet on. The options currently supported are > option is set, UltiSnips will not try to do this expansion, and will leave the tabs alone. This can be useful for snippets dealing with tab delimited formats, etc. + f Do not turn 'formatoptions' off when expanding the snippet. Normally, + UltiSnips will disable the 'c' and the 't' option of 'formatoptions' + because otherwise, Vim might break a line without UltiSnips noticing + and this might mess up the snippet completely. This is useful for + snippets that need paragraphs in their tabstops. < 4.1.1 Character Escaping: *UltiSnips-character-escaping* diff --git a/plugin/UltiSnips/__init__.py b/plugin/UltiSnips/__init__.py index 6532cfd..393bc6d 100644 --- a/plugin/UltiSnips/__init__.py +++ b/plugin/UltiSnips/__init__.py @@ -357,6 +357,10 @@ class Snippet(object): return match + def keep_formatoptions_unchanged(self): + return "f" in self._opts + keep_formatoptions_unchanged = property(keep_formatoptions_unchanged) + def overwrites_previous(self): return "!" in self._opts overwrites_previous = property(overwrites_previous) @@ -587,6 +591,8 @@ class SnippetManager(object): def __init__(self): self._vstate = VimState() self._supertab_keys = None + self._csnippets = [] + self._cached_offending_vim_options = {} self.reset() @@ -594,7 +600,10 @@ class SnippetManager(object): def reset(self, test_error=False): self._test_error = test_error self._snippets = {} - self._csnippets = [] + + while len(self._csnippets): + self._current_snippet_is_done() + self._reinit() @err_to_scratch_buffer @@ -763,8 +772,9 @@ class SnippetManager(object): def entered_insert_mode(self): self._vstate.update() if self._cs and self._vstate.has_moved: + while len(self._csnippets): + self._current_snippet_is_done() self._reinit() - self._csnippets = [] ################################### # Private/Protect Functions Below # @@ -795,12 +805,18 @@ class SnippetManager(object): # Did we leave the snippet with this movement? if self._cs and not (self._vstate.pos in self._cs.abs_span): - self._csnippets.pop() + self._current_snippet_is_done() self._reinit() self._check_if_still_inside_snippet() + def _current_snippet_is_done(self): + self._csnippets.pop() + + if not len(self._csnippets): + self._reset_offending_vim_options() + def _jump(self, backwards = False): jumped = False if self._cs: @@ -812,13 +828,13 @@ class SnippetManager(object): jumped = True if self._ctab.no == 0: self._ctab = None - self._csnippets.pop() + self._current_snippet_is_done() self._vstate.update() else: # This really shouldn't happen, because a snippet should # have been popped when its final tabstop was used. # Cleanup by removing current snippet and recursing. - self._csnippets.pop() + self._current_snippet_is_done() jumped = self._jump(backwards) return jumped @@ -929,6 +945,8 @@ class SnippetManager(object): if snippet.matched: text_before = before[:-len(snippet.matched)] + self._unset_offending_vim_options(snippet) + self._expect_move_wo_change = True if self._cs: # Determine position @@ -981,6 +999,19 @@ class SnippetManager(object): return True + # Handling of offending vim options + def _unset_offending_vim_options(self, snippet): + # Care for textwrapping + if not snippet.keep_formatoptions_unchanged: + self._cached_offending_vim_options["fo"] = ''.join( + c for c in vim.eval("&fo") if c in "ct" + ) + for c in "ct": vim.command("set fo-=%s" % c) + + def _reset_offending_vim_options(self): + # Textwrapping + for c in self._cached_offending_vim_options.pop("fo", []): + vim.command("set fo+=%s" % c) # Input Handling def _chars_entered(self, chars, del_more_lines = 0): diff --git a/test.py b/test.py index 75ce9ea..f8b4b38 100755 --- a/test.py +++ b/test.py @@ -342,13 +342,26 @@ class _FormatoptionsBase(_VimTest): def _options_off(self): self.send(":set tw=0\n") -class FOSimple_ExceptCorrectResult(_FormatoptionsBase): +class FOSimple_WithoutBreak_ExceptCorrectResult(_FormatoptionsBase): snippets = ("test", "${1:longer expand}\n$0") + keys = "test" + EX + "This is a longer text that should not wrap as formatoptions are disabled" + wanted = "This is a longer text that should not wrap as formatoptions are disabled\n" + +class FO_WithoutBreakEnableAfterSnippet_ExceptCorrectResult(_FormatoptionsBase): + snippets = ("test", "${1:longer expand}\n") + keys = "test" + EX + "This is a longer text that should not wrap as formatoptions are disabled" \ + + JF + "This is a longer text that should wrap" + wanted = "This is a longer text that should not wrap as formatoptions are disabled\n" + \ + "This is a longer\ntext that should\nwrap" + + +class FOSimple_WithBreak_ExceptCorrectResult(_FormatoptionsBase): + snippets = ("test", "${1:longer expand}\n$0", "", "f") keys = "test" + EX + "This is a longer text that should wrap" wanted = "This is a longer\ntext that should\nwrap\n" class FOTextBeforeAndAfter_ExceptCorrectResult(_FormatoptionsBase): - snippets = ("test", "Before${1:longer expand}After\nstart$1end") + snippets = ("test", "Before${1:longer expand}After\nstart$1end", "", "f") keys = "test" + EX + "This is a longer text that should wrap" wanted = \ """BeforeThis is a @@ -361,7 +374,7 @@ should wrapend""" class FOTextAfter_ExceptCorrectResult(_FormatoptionsBase): """Testcase for lp:719998""" - snippets = ("test", "${1:longer expand}after\nstart$1end") + snippets = ("test", "${1:longer expand}after\nstart$1end", "", "f") keys = ("test" + EX + "This is a longer snippet that should wrap properly " "and the mirror below should work as well") wanted = \ @@ -378,7 +391,7 @@ should work as wellend""" class FOWrapOnLongWord_ExceptCorrectResult(_FormatoptionsBase): """Testcase for lp:719998""" - snippets = ("test", "${1:longer expand}after\nstart$1end") + snippets = ("test", "${1:longer expand}after\nstart$1end", "", "f") keys = ("test" + EX + "This is a longersnippet that should wrap properly") wanted = \ """This is a