Skip to content

Commit

Permalink
Merge pull request #22728 from athompson673/patch-1
Browse files Browse the repository at this point in the history
PR: Select full floating point numbers by double-clicking them
  • Loading branch information
ccordoba12 authored Nov 1, 2024
2 parents c61b936 + eeccb57 commit 3db4320
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 1 deletion.
32 changes: 32 additions & 0 deletions spyder/plugins/ipythonconsole/tests/test_ipythonconsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from packaging.version import parse
import pytest
from qtpy.QtCore import Qt
from qtpy.QtGui import QTextCursor
from qtpy.QtWebEngineWidgets import WEBENGINE
from spyder_kernels import __version__ as spyder_kernels_version
from spyder_kernels.utils.pythonenv import is_conda_env
Expand Down Expand Up @@ -2417,5 +2418,36 @@ def test_restore_tmpdir(ipyconsole, qtbot, tmp_path):
assert shell.get_value('tmpdir') == system_tmpdir


def test_floats_selected_on_double_click(ipyconsole, qtbot):
"""
Check that doing a double click on floats selects the entire number.
This is a regression test for issue spyder-ide/spyder#22207
"""
# Wait until the window is fully up
shell = ipyconsole.get_current_shellwidget()
qtbot.waitUntil(
lambda: shell._prompt_html is not None, timeout=SHELL_TIMEOUT
)

# Write a floating point number
control = shell._control
float_number = "10.999e5"
qtbot.keyClicks(control, float_number)

# Move the cursor to the left a bit
for __ in range(3):
control.moveCursor(QTextCursor.Left, mode=QTextCursor.MoveAnchor)

# Perform a double click and check the entire number was selected
qtbot.mouseDClick(control.viewport(), Qt.LeftButton)
assert control.get_selected_text() == float_number

# Move cursor at the beginning and check the number is also selected
qtbot.keyClick(control, Qt.Key_Home)
qtbot.mouseDClick(control.viewport(), Qt.LeftButton)
assert control.get_selected_text() == float_number


if __name__ == "__main__":
pytest.main()
42 changes: 41 additions & 1 deletion spyder/widgets/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,23 @@
"""

# Standard library imports
from io import StringIO
import os
import os.path as osp
import re
import sre_constants
import sys
import textwrap
from token import NUMBER
from tokenize import generate_tokens, TokenError

# Third party imports
from packaging.version import parse
from qtpy import QT_VERSION
from qtpy.QtCore import QPoint, QRegularExpression, Qt, QUrl
from qtpy.QtGui import (
QDesktopServices, QFontMetrics, QTextCursor, QTextDocument)
from qtpy.QtWidgets import QApplication
from qtpy.QtWidgets import QApplication, QPlainTextEdit, QTextEdit
from spyder_kernels.utils.dochelpers import (getargspecfromtext, getobj,
getsignaturefromtext)

Expand Down Expand Up @@ -1499,6 +1502,43 @@ def _enter_array(self, inline):
self.sig_text_was_inserted.emit()
cursor.endEditBlock()

# ---- Qt methods
def mouseDoubleClickEvent(self, event):
"""Select NUMBER tokens to select numeric literals on double click."""
cursor = self.cursorForPosition(event.pos())
block = cursor.block()
text = block.text()
pos = block.position()
pos_in_block = cursor.positionInBlock()

# Strip quotes to prevent tokenizer from trying to emit STRING tokens
# because we want to interpret numbers inside strings. This solves
# an EOF error trying to double click a line with opening or closing
# triple quotes as well.
text = text.replace('"', ' ').replace("'", ' ')
readline = StringIO(text).read

try:
for t_type, _, start, end, _ in generate_tokens(readline):
if t_type == NUMBER and start[1] <= pos_in_block <= end[1]:
cursor.setPosition(pos + start[1])
cursor.setPosition(
pos + end[1], QTextCursor.MoveMode.KeepAnchor
)
self.setTextCursor(cursor)
return
elif start[1] > pos_in_block:
break
except TokenError:
# Ignore 'EOF in multi-line statement' from tokenize._tokenize
# IndentationError should be impossible from tokenizing one line
pass

if isinstance(self, QPlainTextEdit):
QPlainTextEdit.mouseDoubleClickEvent(self, event)
elif isinstance(self, QTextEdit):
QTextEdit.mouseDoubleClickEvent(self, event)


class TracebackLinksMixin(object):
"""Mixin to make file names in tracebacks and anchors clickable."""
Expand Down

0 comments on commit 3db4320

Please sign in to comment.