Repository: Textualize/textual

Issue:
DataTable - When cursor_coordinate updates, we should scroll_cursor_visible
When the cursor moves out of the screen, we should scroll the cursor into visibility.

It seems like there is already code to do this, but because of #2458 the scrolling doesn't work.

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c4acf4a76..56b6aff24 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
+
+- The DataTable cursor is now scrolled into view when the cursor coordinate is changed programmatically https://github.com/Textualize/textual/issues/2459
+
 ## [0.23.0] - 2023-05-03
 
 ### Fixed
diff --git a/src/textual/widgets/_data_table.py b/src/textual/widgets/_data_table.py
index 0681c3993..5991c98db 100644
--- a/src/textual/widgets/_data_table.py
+++ b/src/textual/widgets/_data_table.py
@@ -950,6 +950,7 @@ class DataTable(ScrollView, Generic[CellType], can_focus=True):
             elif self.cursor_type == "column":
                 self.refresh_column(old_coordinate.column)
                 self._highlight_column(new_coordinate.column)
+            self._scroll_cursor_into_view()
 
     def _highlight_coordinate(self, coordinate: Coordinate) -> None:
         """Apply highlighting to the cell at the coordinate, and post event."""


Test patch:
diff --git a/tests/test_data_table.py b/tests/test_data_table.py
index 56b148d56..0bba677cf 100644
--- a/tests/test_data_table.py
+++ b/tests/test_data_table.py
@@ -991,3 +991,28 @@ def test_key_string_lookup():
     assert dictionary[RowKey("foo")] == "bar"
     assert dictionary["hello"] == "world"
     assert dictionary[RowKey("hello")] == "world"
+
+
+async def test_scrolling_cursor_into_view():
+    """Regression test for https://github.com/Textualize/textual/issues/2459"""
+
+    class TableApp(App):
+        CSS = "DataTable { height: 100%; }"
+
+        def compose(self):
+            yield DataTable()
+
+        def on_mount(self) -> None:
+            table = self.query_one(DataTable)
+            table.add_column("n")
+            table.add_rows([(n,) for n in range(300)])
+
+        def key_c(self):
+            self.query_one(DataTable).cursor_coordinate = Coordinate(200, 0)
+
+    app = TableApp()
+
+    async with app.run_test() as pilot:
+        await pilot.press("c")
+        await pilot.pause()
+        assert app.query_one(DataTable).scroll_y > 100