Skip to content

Commit

Permalink
Fix #636 cs"<div class="x">
Browse files Browse the repository at this point in the history
  • Loading branch information
gerardroche committed Oct 18, 2019
1 parent add5f0a commit 362300f
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 19 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,9 @@ All notable changes are documented in this file using the [Keep a CHANGELOG](htt

## 1.17.6 - Unreleased

* Fixed [#636](https://github.com/NeoVintageous/NeoVintageous/issues/636): `cs"<div class="x">` should strip class from closing tag
* Fixed [#636](https://github.com/NeoVintageous/NeoVintageous/issues/636): `ys{motion}<div class="x">` should strip class from closing tag
* Fixed [#636](https://github.com/NeoVintageous/NeoVintageous/issues/636): `ys{motion}tdiv>` alias "t" (`<`) does not work
* Fixed [#635](https://github.com/NeoVintageous/NeoVintageous/issues/635): Visual block mode resets to visual when switching view
* Fixed [#633](https://github.com/NeoVintageous/NeoVintageous/issues/633): `ds|`doesn't work

Expand Down
30 changes: 11 additions & 19 deletions nv/plugin_surround.py
Expand Up @@ -233,6 +233,11 @@ def _get_punctuation_marks(target):
# which append an additional space to the inside. Like with the targets above,
# b, B, r, and a are aliases for ), }, ], and >.
def _get_punctuation_mark_replacements(target):
if target[0] in ('t', '<') and len(target) >= 3:
# Attributes are stripped in the closing tag. The first character if
# "t", which is an alias for "<", is replaced too.
return ('<' + target[1:], '</' + target[1:].strip()[:-1].strip().split(' ', 1)[0] + '>')

target = _resolve_punctuation_aliases(target)
append_addition_space = True if target in '({[' else False
begin, end = _get_punctuation_marks(target)
Expand Down Expand Up @@ -288,16 +293,6 @@ def _f(view, s):
open_, close_ = _get_punctuation_marks(old)
new_open, new_close = _get_punctuation_mark_replacements(new)

# Replacements > 1 are always tags, and the first character could be
# "t", which is an alias for "<".
if len(replacement) > 1:
new_open = '<' + new_open[1:]

# Replacements > 1 are always tags, and the first character could be
# "t", which is an alias for "<".
if len(replacement) > 1:
new_close = '</' + new_close[1:]

if open_ == 't':
open_, close_ = ('<[^>\\/]+>', '<\\/[^>]+>')
next_ = view.find(close_, s.b)
Expand Down Expand Up @@ -446,17 +441,14 @@ def _f(view, s):

def _do_ys(view, edit, mode=None, motion=None, replacement='"', count=1):
def surround(view, edit, s, replacement):
open_, close_ = _get_punctuation_mark_replacements(replacement)
# Takes <q class="foo"> and produces: <q class="foo">text</q>
if open_.startswith('<'):
name = open_[1:].strip()[:-1].strip()
name = name.split(' ', 1)[0]
view.insert(edit, s.b, "</{0}>".format(name))
view.insert(edit, s.a, replacement)
replacement_open, replacement_close = _get_punctuation_mark_replacements(replacement)
if replacement_open.startswith('<'):
view.insert(edit, s.b, replacement_close)
view.insert(edit, s.a, replacement_open)
return

view.insert(edit, s.end(), close_)
view.insert(edit, s.begin(), open_)
view.insert(edit, s.end(), replacement_close)
view.insert(edit, s.begin(), replacement_open)

def f(view, s):
if mode == INTERNAL_NORMAL:
Expand Down
2 changes: 2 additions & 0 deletions tests/functional/test__plugin_surround_cs.py
Expand Up @@ -118,3 +118,5 @@ def test_tags(self):
self.eq("'a|b'", "cs'tq>", '|<q>ab</q>')
self.eq("'a|b'", "cs'<div>", '|<div>ab</div>')
self.eq("'a|b'", "cs'tdiv>", '|<div>ab</div>')
self.eq('"fi|zz"', 'cs"ti x="y">', '|<i x="y">fizz</i>')
self.eq('"fi|zz"', 'cs"<i x="y">', '|<i x="y">fizz</i>')
4 changes: 4 additions & 0 deletions tests/functional/test__plugin_surround_ys.py
Expand Up @@ -58,3 +58,7 @@ def test_multiple_cursors(self):

def test_issue_305_multiple_selection_leaves_cursors_in_the_wrong_place(self):
self.eq("eats fi|sh\neats fi|sh\neats fi|sh", "ysiw'", "eats |'fish'\neats |'fish'\neats |'fish'")

def test_tags(self):
self.eq('"fi|zz"', 'ysiw<i x="y">', '"|<i x="y">fizz</i>"')
self.eq('"fi|zz"', 'ysiwti x="y">', '"|<i x="y">fizz</i>"')
4 changes: 4 additions & 0 deletions tests/unittest.py
Expand Up @@ -1372,12 +1372,14 @@ def assertRunCommand(cmd, args=None, count=1):
'cs")': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '"', 'replacement': ')'}}, # noqa: E241,E501
'cs"2': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '"', 'replacement': '2'}}, # noqa: E241,E501
'cs"<': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '"', 'replacement': '<'}}, # noqa: E241,E501
'cs"<i x="y">': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': "\"", 'replacement': 'ti x="y">'}}, # noqa: E241,E501
'cs"<x>': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '"', 'replacement': '<x>'}}, # noqa: E241,E501
'cs">': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '"', 'replacement': '>'}}, # noqa: E241,E501
'cs"[': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '"', 'replacement': '['}}, # noqa: E241,E501
'cs"\'': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '"', 'replacement': "'"}}, # noqa: E241,E501
'cs"]': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '"', 'replacement': ']'}}, # noqa: E241,E501
'cs"`': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '"', 'replacement': '`'}}, # noqa: E241,E501
'cs"ti x="y">': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': "\"", 'replacement': 'ti x="y">'}}, # noqa: E241,E501
'cs"{': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '"', 'replacement': '{'}}, # noqa: E241,E501
'cs"}': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '"', 'replacement': '}'}}, # noqa: E241,E501
'cs("': {'command': '_nv_surround', 'args': {'action': 'cs', 'target': '(', 'replacement': '"'}}, # noqa: E241,E501
Expand Down Expand Up @@ -1708,13 +1710,15 @@ def assertRunCommand(cmd, args=None, count=1):
'ysiw)': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': ')', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiw2': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': '2', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiw<foo>': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': '<foo>', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiw<i x="y">': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': '<i x="y">', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiwB': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': 'B', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiw[': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': '[', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiw\'': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': '\'', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiw]': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': ']', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiwafoo>': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': '<foo>', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiwb': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': 'b', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiwr': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': 'r', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiwti x="y">': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': 'ti x="y">', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiw{': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': '{', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'ysiw}': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': '}', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'w', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
'yss)': {'command': '_nv_surround', 'args': {'action': 'ys', 'replacement': ')', 'motion': {'motion': '_vi_select_text_object', 'motion_args': {'text_object': 'l', 'mode': INTERNAL_NORMAL, 'count': 1, 'inclusive': False}}}}, # noqa: E241,E501
Expand Down

0 comments on commit 362300f

Please sign in to comment.