Merged my fix for bug 427298

This commit is contained in:
Holger Rapp 2010-08-20 10:30:33 +02:00
commit 00656a2bb7
5 changed files with 199 additions and 39 deletions

View File

@ -1,5 +1,7 @@
version 1.2:
- many bugs were fixed
- smode mappings for printable characters are now removed before expanding a
snippet. This is configurable. *UltiSnips-warning-smappings*
- all shipped snippets are now fully compatible with UltiSnips
- added support for global snippets which enhance python interpolation even
more *UltiSnips-globals*

View File

@ -8,9 +8,10 @@ UltiSnips *snippet* *snippets* *UltiSnips*
2.2 Deinstallation |UltiSnips-deinstallation|
2.3 Updating |UltiSnips-updating|
3. Settings |UltiSnips-settings|
3.1 Warning About Select Mode Mappings |UltiSnips-warning-smappings|
4. Syntax |UltiSnips-syntax|
4.1 Adding Snippets |UltiSnips-adding-snippets|
4.2 Plaintext snippets |UltiSnips-plaintext-snippets|
4.2 Plaintext Snippets |UltiSnips-plaintext-snippets|
4.3 Interpolation |UltiSnips-integration|
4.3.1 Shellcode |UltiSnips-shellcode|
4.3.2 VimScript |UltiSnips-vimscript|
@ -25,8 +26,8 @@ UltiSnips *snippet* *snippets* *UltiSnips*
5. Helping out |UltiSnips-helping|
6. Contact |UltiSnips-contact|
7. Contributors |UltiSnips-contributors|
8.1 Patches & Coding |UltiSnips-contricoding|
8.2 Snippets |UltiSnips-contrisnippets|
7.1 Patches & Coding |UltiSnips-contricoding|
7.2 Snippets |UltiSnips-contrisnippets|
For Vim version 7.0 or later.
This plugin only works if 'compatible' is not set.
@ -125,6 +126,31 @@ you vimrc: >
let g:UltiSnipsJumpForwardTrigger="<tab>"
let g:UltiSnipsJumpBackwardTrigger="<s-tab>"
3.1 Warning About Select Mode Mappings *UltiSnips-warning-smappings*
--------------------------------------
The help for vim's *mapmode-s* states: >
NOTE: Mapping a printable character in Select mode may confuse the user.
It's better to explicitly use :xmap and :smap for printable characters. Or
use :sunmap after defining the mapping.
But most vim plugins (even the ones shipped with vim) do not adhere to this.
As UltiSnips uses select mode to mark tabstops in snippets for overwriting
these wrong mappings get in the way. UltiSnips therefore defaults to
*:sunmap* all mappings for printable characters in select mode. It will not
touch any other mappings, especially not normal, insert or visual mode
mappings.
If this behaviour is not desired, you can disable it via >
let g:UltiSnipsRemoveSelectModeMappings = 0
If you want to keep certain mappings, you can modify the list of ignores for
this feature. For example >
let g:UltiSnipsMappingsToIgnore = [ "somePlugin", "otherPlugin" ]
will not unmap any mapping that contains the string "somePlugin" or
"otherPlugin" in its complete definition as listed by *:smap* .
=============================================================================
4. SYNTAX *UltiSnips-syntax*
@ -204,7 +230,7 @@ snippet on. The options currently supported are >
match is also passed to any python code blocks in your snippet
definition as the local variable "match".
4.2 Plaintext snippets *UltiSnips-plaintext-snippets*
4.2 Plaintext Snippets *UltiSnips-plaintext-snippets*
----------------------
Lets start with a simple example. Add this to your all snippets file: >

View File

@ -37,6 +37,16 @@ if !exists("g:UltiSnipsJumpBackwardTrigger")
let g:UltiSnipsJumpBackwardTrigger = "<c-k>"
endif
" Should UltiSnips unmap select mode mappings automagically?
if !exists("g:UltiSnipsRemoveSelectModeMappings")
let g:UltiSnipsRemoveSelectModeMappings = 1
end
" If UltiSnips should remove Mappings, which should be ignored
if !exists("g:UltiSnipsMappingsToIgnore")
let g:UltiSnipsMappingsToIgnore = []
endif
" }}}
"" FUNCTIONS {{{

View File

@ -405,7 +405,6 @@ class LangMapTranslator(object):
return s.translate(self._maps[langmap])
class VimState(object):
def __init__(self):
self._abs_pos = None
@ -454,6 +453,8 @@ class VimState(object):
self._cline = vim.current.buffer[line]
def select_span(self, r):
self._unmap_select_mode_mapping()
delta = r.end - r.start
lineno, col = r.start.line, r.start.col
@ -534,6 +535,60 @@ class VimState(object):
return self._lline
last_line = property(last_line)
###########################
# Private functions below #
###########################
def _unmap_select_mode_mapping(self):
"""This function unmaps select mode mappings if so wished by the user.
Removes select mode mappings that can actually be typed by the user
(ie, ignores things like <Plug>).
"""
if int(vim.eval("g:UltiSnipsRemoveSelectModeMappings")):
ignores = vim.eval("g:UltiSnipsMappingsToIgnore") + ['UltiSnips']
for option in ("<buffer>", ""):
# Put all smaps into a var, and then read the var
vim.command(r"redir => _tmp_smaps | silent smap %s " % option +
"| redir END")
# Check if any mappings where found
all_maps = filter(len, vim.eval(r"_tmp_smaps").splitlines())
if (len(all_maps) == 1 and
all_maps[0][0] not in " sv"):
# "No maps found". String could be localized. Hopefully
# it doesn't start with any of these letters in any
# language
continue
# Only keep mappings that should not be ignored
maps = [m for m in all_maps if
not any(i in m for i in ignores) and len(m.strip())]
for m in maps:
# Some mappings have their modes listed
trig = m.split()
if m[0] == " ":
trig = trig[0]
else:
trig = trig[1]
# The bar separates commands
if trig[-1] == "|":
trig = trig[:-1] + "<Bar>"
# Special ones
if trig[0] == "<":
add = False
# Only allow these
for valid in ["Tab", "NL", "CR", "C-Tab", "BS"]:
if trig == "<%s>" % valid:
add = True
if not add:
continue
# Actually unmap it
vim.command("sunmap %s %s" % (option,trig))
class SnippetManager(object):
def __init__(self):
self._vstate = VimState()

67
test.py
View File

@ -1933,6 +1933,73 @@ xj
k
"""
#######################
# Test for bug 427298 #
#######################
class _SelectModeMappings(_VimTest):
snippets = ("test", "${1:World}")
keys = "test" + EX + "Hello"
wanted = "Hello"
maps = ("", "")
buffer_maps = ("", "")
do_unmapping = True
ignores = []
def _options_on(self):
self.send(":let g:UltiSnipsRemoveSelectModeMappings=%i\n" %
int(self.do_unmapping))
self.send(":let g:UltiSnipsMappingsToIgnore=%s\n" %
repr(self.ignores))
if not isinstance(self.maps[0], tuple):
self.maps = (self.maps,)
if not isinstance(self.buffer_maps[0], tuple):
self.buffer_maps = (self.buffer_maps,)
for key, m in self.maps:
if not len(key): continue
self.send(":smap %s %s\n" % (key,m))
for key, m in self.buffer_maps:
if not len(key): continue
self.send(":smap <buffer> %s %s\n" % (key,m))
def _options_off(self):
for key, m in self.maps:
if not len(key): continue
self.send(":sunmap %s\n" % key)
for key, m in self.buffer_maps:
if not len(key): continue
self.send(":sunmap <buffer> %s\n" % key)
self.send(":let g:UltiSnipsRemoveSelectModeMappings=1\n")
self.send(":let g:UltiSnipsMappingsToIgnore= []\n")
class SelectModeMappings_RemoveBeforeSelecting_ECR(_SelectModeMappings):
maps = ("H", "x")
wanted = "Hello"
class SelectModeMappings_DisableRemoveBeforeSelecting_ECR(_SelectModeMappings):
do_unmapping = False
maps = ("H", "x")
wanted = "xello"
class SelectModeMappings_IgnoreMappings_ECR(_SelectModeMappings):
ignores = ["e"]
maps = ("H", "x"), ("e", "l")
wanted = "Hello"
class SelectModeMappings_IgnoreMappings1_ECR(_SelectModeMappings):
ignores = ["H"]
maps = ("H", "x"), ("e", "l")
wanted = "xello"
class SelectModeMappings_IgnoreMappings2_ECR(_SelectModeMappings):
ignores = ["e", "H"]
maps = ("e", "l"), ("H", "x")
wanted = "xello"
class SelectModeMappings_BufferLocalMappings_ECR(_SelectModeMappings):
buffer_maps = ("H", "blah")
wanted = "Hello"
###########################################################################
# END OF TEST #