diff --git a/CHANGELOG.md b/CHANGELOG.md index 67652d343d..bff260ef49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## Unreleased + +### Changed + +- shift+backspace is now an alias for backspace in Input and TextArea https://github.com/Textualize/textual/pull/6611 + ## [8.2.8] - 2026-06-30 ### Fixed diff --git a/src/textual/widgets/_input.py b/src/textual/widgets/_input.py index bcf2c2994d..38091b9cb5 100644 --- a/src/textual/widgets/_input.py +++ b/src/textual/widgets/_input.py @@ -111,7 +111,12 @@ class Input(ScrollView): "Move cursor right a word and select", show=False, ), - Binding("backspace", "delete_left", "Delete character left", show=False), + Binding( + "backspace,shift+backspace", + "delete_left", + "Delete character left", + show=False, + ), Binding("ctrl+shift+a", "select_all", "Select all", show=False), Binding("home,ctrl+a", "home", "Go to start", show=False), Binding("end,ctrl+e", "end", "Go to end", show=False), @@ -149,7 +154,7 @@ class Input(ScrollView): | ctrl+shift+left | Move cursor left a word and select. | | shift+right | Move cursor right and select. | | ctrl+right | Move the cursor one word to the right. | - | backspace | Delete the character to the left of the cursor. | + | backspace,shift+backspace | Delete the character to the left of the cursor. | | ctrl+backspace,alt+backspace | Delete right to start of word. | | ctrl+shift+right | Move cursor right a word and select. | | ctrl+shift+a | Select all text in the input. | diff --git a/src/textual/widgets/_text_area.py b/src/textual/widgets/_text_area.py index 1ca74675e5..cdffe0be16 100644 --- a/src/textual/widgets/_text_area.py +++ b/src/textual/widgets/_text_area.py @@ -348,7 +348,7 @@ class TextArea(ScrollView): ), # Deletion Binding( - "backspace", + "backspace,shift+backspace", "delete_left", "Delete character left", show=False, diff --git a/tests/input/test_input_key_modification_actions.py b/tests/input/test_input_key_modification_actions.py index 187fe5e8b1..3df4e62c78 100644 --- a/tests/input/test_input_key_modification_actions.py +++ b/tests/input/test_input_key_modification_actions.py @@ -179,3 +179,19 @@ async def test_delete_right_all_from_end() -> None: input.action_delete_right_all() assert input.cursor_position == len(input.value) assert input.value == TEST_INPUTS[input.id] + + +async def test_shift_backspace_deletes_left() -> None: + """shift+backspace should behave the same as backspace.""" + + class SingleInputApp(App[None]): + def compose(self) -> ComposeResult: + yield Input() + + async with SingleInputApp().run_test() as pilot: + input = pilot.app.query_one(Input) + await pilot.click(input) + await pilot.press(*"Hello") + await pilot.press("shift+backspace") + assert input.value == "Hell" + assert input.cursor_position == 4 diff --git a/tests/text_area/test_edit_via_bindings.py b/tests/text_area/test_edit_via_bindings.py index c3712773fb..1572f535d4 100644 --- a/tests/text_area/test_edit_via_bindings.py +++ b/tests/text_area/test_edit_via_bindings.py @@ -113,6 +113,17 @@ async def test_delete_left_end(): assert text_area.selection == Selection.cursor((0, 12)) +async def test_delete_left_shift_backspace_alias(): + app = TextAreaApp() + async with app.run_test() as pilot: + text_area = app.query_one(TextArea) + text_area.load_text("Hello, world!") + text_area.move_cursor((0, 6)) + await pilot.press("shift+backspace") + assert text_area.text == "Hello world!" + assert text_area.selection == Selection.cursor((0, 5)) + + @pytest.mark.parametrize( "key,selection", [ @@ -132,14 +143,11 @@ async def test_deletion_with_non_empty_selection(key, selection): text_area.selection = selection await pilot.press(key) assert text_area.selection == Selection.cursor((1, 2)) - assert ( - text_area.text - == """\ + assert text_area.text == """\ ABCDE FGT UVWXY Z""" - ) async def test_delete_right():