Commit 44a79cc5 authored by Tal Einat's avatar Tal Einat Committed by GitHub

bpo-35208: Fix IDLE Squeezer line counting (GH-10449)

parent e7eed78f
......@@ -3,6 +3,8 @@ Released on 2019-10-20?
======================================
bpo-35208: Squeezer now counts wrapped lines before newlines.
bpo-35555: Gray out Code Context menu entry when it's not applicable.
bpo-22703: Improve the Code Context and Zoom Height menu labels.
......
from collections import namedtuple
from textwrap import dedent
from tkinter import Text, Tk
import unittest
from unittest.mock import Mock, NonCallableMagicMock, patch, sentinel, ANY
......@@ -77,6 +78,28 @@ class CountLinesTest(unittest.TestCase):
self.check(expected=3, text='\t' * 6, linewidth=11, tabwidth=4)
self.check(expected=2, text='\t' * 6, linewidth=13, tabwidth=4)
def test_empty_lines(self):
self.check(expected=1, text='\n', linewidth=80, tabwidth=8)
self.check(expected=2, text='\n\n', linewidth=80, tabwidth=8)
self.check(expected=10, text='\n' * 10, linewidth=80, tabwidth=8)
def test_long_line(self):
self.check(expected=3, text='a' * 200, linewidth=80, tabwidth=8)
self.check(expected=3, text='a' * 200 + '\n', linewidth=80, tabwidth=8)
def test_several_lines_different_lengths(self):
text = dedent("""\
13 characters
43 is the number of characters on this line
7 chars
13 characters""")
self.check(expected=5, text=text, linewidth=80, tabwidth=8)
self.check(expected=5, text=text + '\n', linewidth=80, tabwidth=8)
self.check(expected=6, text=text, linewidth=40, tabwidth=8)
self.check(expected=7, text=text, linewidth=20, tabwidth=8)
self.check(expected=11, text=text, linewidth=10, tabwidth=8)
class SqueezerTest(unittest.TestCase):
"""Tests for the Squeezer class."""
......
......@@ -46,6 +46,14 @@ def count_lines_with_wrapping(s, linewidth=80, tabwidth=8):
# deal with tab or newline
if s[pos] == '\n':
# Avoid the `current_column == 0` edge-case, and while we're at it,
# don't bother adding 0.
if current_column > linewidth:
# If the current column was exactly linewidth, divmod would give
# (1,0), even though a new line hadn't yet been started. The same
# is true if length is any exact multiple of linewidth. Therefore,
# subtract 1 before dividing a non-empty line.
linecount += (current_column - 1) // linewidth
linecount += 1
current_column = 0
else:
......@@ -60,17 +68,6 @@ def count_lines_with_wrapping(s, linewidth=80, tabwidth=8):
pos += 1 # after the tab or newline
# avoid divmod(-1, linewidth)
if current_column > 0:
# If the length was exactly linewidth, divmod would give (1,0),
# even though a new line hadn't yet been started. The same is true
# if length is any exact multiple of linewidth. Therefore, subtract
# 1 before doing divmod, and later add 1 to the column to
# compensate.
lines, column = divmod(current_column - 1, linewidth)
linecount += lines
current_column = column + 1
# process remaining chars (no more tabs or newlines)
current_column += len(s) - pos
# avoid divmod(-1, linewidth)
......@@ -106,7 +103,8 @@ class ExpandingButton(tk.Button):
# before the iomark
self.base_text = editwin.per.bottom
button_text = "Squeezed text (%d lines)." % self.numoflines
line_plurality = "lines" if numoflines != 1 else "line"
button_text = f"Squeezed text ({numoflines} {line_plurality})."
tk.Button.__init__(self, text, text=button_text,
background="#FFFFC0", activebackground="#FFFFE0")
......
Squeezer now properly counts wrapped lines before newlines.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment