Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR: Find/replace - return match counts on unescaped characters #6526

Merged
merged 2 commits into from
Feb 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion spyder/widgets/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,14 @@ def set_source_text(self, source_text):
"""Set source text of the page. Callback for QWebEngineView."""
self.source_text = source_text

def get_number_matches(self, pattern, source_text='', case=False):
def get_number_matches(self, pattern, source_text='', case=False,
regexp=False):
"""Get the number of matches for the searched text."""
pattern = to_text_string(pattern)
if not pattern:
return 0
if not regexp:
pattern = re.escape(pattern)
if not source_text:
if WEBENGINE:
self.page().toPlainText(self.set_source_text)
Expand Down
6 changes: 4 additions & 2 deletions spyder/widgets/findreplace.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,9 +435,11 @@ def regexp_error_msg(pattern):
else:
self.clear_matches()

number_matches = self.editor.get_number_matches(text, case=case)
number_matches = self.editor.get_number_matches(text, case=case,
regexp=regexp)
if hasattr(self.editor, 'get_match_number'):
match_number = self.editor.get_match_number(text, case=case)
match_number = self.editor.get_match_number(text, case=case,
regexp=regexp)
else:
match_number = 0
self.change_number_matches(current_match=match_number,
Expand Down
11 changes: 7 additions & 4 deletions spyder/widgets/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,11 +523,14 @@ def is_editor(self):
"""Needs to be overloaded in the codeeditor where it will be True"""
return False

def get_number_matches(self, pattern, source_text='', case=False):
def get_number_matches(self, pattern, source_text='', case=False,
regexp=False):
"""Get the number of matches for the searched text."""
pattern = to_text_string(pattern)
if not pattern:
return 0
if not regexp:
pattern = re.escape(pattern)
if not source_text:
source_text = to_text_string(self.toPlainText())
try:
Expand All @@ -536,21 +539,21 @@ def get_number_matches(self, pattern, source_text='', case=False):
else:
regobj = re.compile(pattern, re.IGNORECASE)
except sre_constants.error:
return
return None

number_matches = 0
for match in regobj.finditer(source_text):
number_matches += 1

return number_matches

def get_match_number(self, pattern, case=False):
def get_match_number(self, pattern, case=False, regexp=False):
"""Get number of the match for the searched text."""
position = self.textCursor().position()
source_text = self.get_text(position_from='sof', position_to=position)
match_number = self.get_number_matches(pattern,
source_text=source_text,
case=case)
case=case, regexp=regexp)
return match_number

# --- Numpy matrix/array helper / See 'spyder/widgets/arraybuilder.py'
Expand Down
101 changes: 101 additions & 0 deletions spyder/widgets/tests/test_mixins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# -*- coding: utf-8 -*-
#
# Copyright © Spyder Project Contributors
# Licensed under the terms of the MIT License
#

# Third party imports
from qtpy.QtWidgets import QPlainTextEdit

import pytest

# Local imports
from spyder.widgets import mixins


class BaseWidget(QPlainTextEdit, mixins.BaseEditMixin):
pass

# --- Fixtures
# -----------------------------------------------------------------------------


@pytest.fixture
def mixinsbot(qtbot):
widget = BaseWidget()
qtbot.addWidget(widget)
widget.show()
return qtbot, widget

# --- Tests
# -----------------------------------------------------------------------------


def test_get_number_matches(mixinsbot):
# Test get_number_matches().
qtbot, widget = mixinsbot
get = widget.get_number_matches

code = ('class C():\n'
' def __init__(self):\n'
' pass\n'
' def f(self, a, b):\n'
' pass\n')

# Empty pattern.
assert get('') == 0

# No case, no regexp.
assert get('self', source_text=code) == 2
assert get('c', source_text=code) == 2

# Case, no regexp.
assert get('self', source_text=code, case=True) == 2
assert get('c', source_text=code, case=True) == 1

# No case, regexp.
assert get('e[a-z]?f', source_text=code, regexp=True) == 4
assert get('e[A-Z]?f', source_text=code, regexp=True) == 4

# Case, regexp.
assert get('e[a-z]?f', source_text=code, case=True, regexp=True) == 4
assert get('e[A-Z]?f', source_text=code, case=True, regexp=True) == 2

# Issue 5680.
assert get('(', source_text=code) == 3
assert get('(', source_text=code, case=True) == 3
assert get('(', source_text=code, regexp=True) is None
assert get('(', source_text=code, case=True, regexp=True) is None


def test_get_match_number(mixinsbot):
# Test get_match_number().
qtbot, widget = mixinsbot
get = widget.get_match_number

code = ('class C():\n'
' def __init__(self):\n'
' pass\n'
' def f(self, a, b):\n'
' pass\n')
widget.setPlainText(code)
cursor = widget.textCursor()
cursor.setPosition(widget.get_position('sof'))

# Empty pattern.
assert get('') == 0

# Issue 5680.
widget.find_text('(')
assert get('(') == 1

# First occurrence.
widget.find_text('self')
assert get('self') == 1
assert get('self', case=True) == 1

# Second occurrence.
widget.find_text('pass')
widget.find_text('self')
assert get('self') == 2
assert get('self', case=True) == 2