From 35ebd08a737f386d929f0dff64635741226d8051 Mon Sep 17 00:00:00 2001 From: Devil1716 Date: Sat, 18 Jul 2026 13:15:29 +0530 Subject: [PATCH] Fix MaskedInput word nav when template starts with separator prev_separator_position used range(..., 0, -1), which never visits index 0. Also treat position 0 as a real separator in cursor/delete word actions (`if position:` treated 0 as missing). Fixes #6641 Co-authored-by: Cursor --- src/textual/widgets/_masked_input.py | 8 ++++---- tests/test_masked_input.py | 13 +++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/textual/widgets/_masked_input.py b/src/textual/widgets/_masked_input.py index a48ef9b60b..d6fbf662c5 100644 --- a/src/textual/widgets/_masked_input.py +++ b/src/textual/widgets/_masked_input.py @@ -344,7 +344,7 @@ def prev_separator_position(self, position: int | None = None) -> int | None: """ if position is None: position = self.input.cursor_position - for index in range(position - 1, 0, -1): + for index in range(position - 1, -1, -1): if _CharFlags.SEPARATOR in self.template[index].flags: return index else: @@ -636,9 +636,9 @@ def action_cursor_left_word(self) -> None: position = self._template.prev_separator_position(self.cursor_position - 1) else: position = self._template.prev_separator_position() - if position: + if position is not None: position += 1 - self.cursor_position = position or 0 + self.cursor_position = position if position is not None else 0 def action_cursor_right_word(self) -> None: """Move the cursor right next to the next separator. If no next @@ -683,7 +683,7 @@ def action_delete_left_word(self) -> None: position = self._template.prev_separator_position(self.cursor_position - 1) else: position = self._template.prev_separator_position() - if position: + if position is not None: position += 1 else: position = 0 diff --git a/tests/test_masked_input.py b/tests/test_masked_input.py index 72b4d9dc09..79987d6bbe 100644 --- a/tests/test_masked_input.py +++ b/tests/test_masked_input.py @@ -221,3 +221,16 @@ async def test_digits_required(): await pilot.press("a", "1") assert input.value == "1" assert not input.is_valid + + +async def test_cursor_left_word_leading_separator(): + """Ctrl+Left must not ignore a separator at index 0.""" + app = InputApp("-NNN-NNN") + async with app.run_test(): + inp = app.query_one(MaskedInput) + inp.value = "-ABC-DEF" + inp.cursor_position = 8 + inp.action_cursor_left_word() + assert inp.cursor_position == 5 + inp.action_cursor_left_word() + assert inp.cursor_position == 1