mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Fixing insert value on tab key press, tests for get_tab_widths
This commit is contained in:
@@ -7,6 +7,7 @@ from rich.cells import chop_cells
|
||||
|
||||
from ._cells import cell_len
|
||||
from ._loop import loop_last
|
||||
from .expand_tabs import get_tab_widths
|
||||
|
||||
re_chunk = re.compile(r"\s*\S+\s*")
|
||||
|
||||
@@ -21,13 +22,11 @@ def chunks(text: str) -> Iterable[tuple[int, int, str]]:
|
||||
Returns:
|
||||
Yields tuples containing the start, end and content for each chunk.
|
||||
"""
|
||||
position = 0
|
||||
chunk_match = re_chunk.match(text, position)
|
||||
while chunk_match is not None:
|
||||
end = 0
|
||||
while (chunk_match := re_chunk.match(text, end)) is not None:
|
||||
start, end = chunk_match.span()
|
||||
chunk = chunk_match.group(0)
|
||||
yield start, end, chunk
|
||||
chunk_match = re_chunk.match(text, end)
|
||||
|
||||
|
||||
def divide_line(
|
||||
@@ -59,28 +58,33 @@ def divide_line(
|
||||
# 14, then we go through the tab_widths tuples until we’ve seen 14 codepoints, and note the total widths of tabs
|
||||
# encountered.
|
||||
|
||||
# these wrap offsets all assume every tab has width 1.
|
||||
# now, for each offset
|
||||
# build mapping of tab positions to tab widths. then, for each chunk, check if a
|
||||
# get all of the tab
|
||||
|
||||
# foo\tbar\t\baz
|
||||
|
||||
tab_widths = get_tab_widths(text, tab_size)
|
||||
cumulative_widths = []
|
||||
cumulative_width = 0
|
||||
for tab_section, tab_width in tab_widths:
|
||||
cumulative_widths.extend([cumulative_width] * len(tab_section))
|
||||
cumulative_width += tab_width
|
||||
|
||||
for start, _end, chunk in chunks(text):
|
||||
# todo, 1st, terrible name, 2nd can we get the "word width" here to account for tab widths?
|
||||
for start, end, chunk in chunks(text):
|
||||
# todo, 1st, terrible name, 2nd can we get the "word width" here to account
|
||||
# for tab widths?
|
||||
chunk_width = _cell_len(chunk)
|
||||
# Count the tabs
|
||||
# Determine the total widths of the tabs in this chunk
|
||||
# Account for the tabs such that we convert every tab
|
||||
# character from width 1 to the new width by adding tab_width
|
||||
# MINUS one for each tab.
|
||||
# So old width + total tab width - num tabs in chunk
|
||||
num_tabs = chunk.count(tab)
|
||||
|
||||
print(start, end, chunk, len(chunk))
|
||||
tab_width_before_start = cumulative_widths[start]
|
||||
tab_width_before_end = cumulative_widths[end]
|
||||
chunk_tab_width = tab_width_before_end - tab_width_before_start
|
||||
chunk_width += chunk_tab_width
|
||||
remaining_space = width - cell_offset
|
||||
chunk_fits = remaining_space >= chunk_width
|
||||
|
||||
if chunk_fits:
|
||||
# Simplest case - the word fits within the remaining width for this line.
|
||||
cell_offset += width_contribution
|
||||
cell_offset += chunk_width
|
||||
else:
|
||||
# Not enough space remaining for this word on the current line.
|
||||
if chunk_width > width:
|
||||
|
||||
@@ -77,10 +77,7 @@ class WrappedDocument:
|
||||
current_offset = 0
|
||||
|
||||
for line_index, line in enumerate(self.document.lines):
|
||||
line = expand_tabs_inline(line, tab_width)
|
||||
wrap_offsets = (
|
||||
divide_line(line, width, keep_whitespace=True) if width else []
|
||||
)
|
||||
wrap_offsets = divide_line(line, width, tab_size=tab_width) if width else []
|
||||
append_wrap_offset(wrap_offsets)
|
||||
line_index_to_offsets.append([])
|
||||
for section_y_offset in range(len(wrap_offsets) + 1):
|
||||
@@ -173,10 +170,7 @@ class WrappedDocument:
|
||||
# Add the new offsets between the top and new bottom (the new post-edit offsets)
|
||||
current_y_offset = top_y_offset
|
||||
for line_index, line in enumerate(new_lines, top_line_index):
|
||||
line = expand_tabs_inline(line, tab_width)
|
||||
wrap_offsets = (
|
||||
divide_line(line, width, keep_whitespace=True) if width else []
|
||||
)
|
||||
wrap_offsets = divide_line(line, width, tab_size=tab_width) if width else []
|
||||
append_wrap_offsets(wrap_offsets)
|
||||
|
||||
# Collect up the new y offsets for this document line
|
||||
|
||||
@@ -1056,7 +1056,10 @@ TextArea {
|
||||
"enter": "\n",
|
||||
}
|
||||
if self.tab_behaviour == "indent":
|
||||
insert_values["tab"] = " " * self._find_columns_to_next_tab_stop()
|
||||
if self.indent_type == "tabs":
|
||||
insert_values["tab"] = "\t"
|
||||
else:
|
||||
insert_values["tab"] = " " * self._find_columns_to_next_tab_stop()
|
||||
|
||||
self._restart_blink()
|
||||
if event.is_printable or key in insert_values:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import pytest
|
||||
|
||||
from textual.expand_tabs import expand_tabs_inline
|
||||
from textual.expand_tabs import expand_tabs_inline, get_tab_widths
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -23,3 +23,10 @@ from textual.expand_tabs import expand_tabs_inline
|
||||
)
|
||||
def test_expand_tabs_inline(line, expanded_line):
|
||||
assert expand_tabs_inline(line) == expanded_line
|
||||
|
||||
|
||||
def test_get_tab_widths():
|
||||
assert get_tab_widths("\tbar") == [("", 4), ("bar", 0)]
|
||||
assert get_tab_widths("\tbar\t") == [("", 4), ("bar", 1)]
|
||||
assert get_tab_widths("\tfoo\t\t") == [("", 4), ("foo", 1), ("", 4)]
|
||||
assert get_tab_widths("\t木foo\t木\t\t") == [("", 4), ("木foo", 3), ("木", 2), ("", 4)]
|
||||
|
||||
Reference in New Issue
Block a user