diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a7487fe28..e7dd34ab05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ 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 + +### Added + +- Added `immediate` parameter to scroll methods https://github.com/Textualize/textual/pull/5164 +- Added `textual._loop.loop_from_index` https://github.com/Textualize/textual/pull/5164 + ## [0.84.0] - 2024-10-22 ### Fixed diff --git a/src/textual/_loop.py b/src/textual/_loop.py index 0f50f864b3..7711a99d57 100644 --- a/src/textual/_loop.py +++ b/src/textual/_loop.py @@ -46,7 +46,7 @@ def loop_first_last(values: Iterable[T]) -> Iterable[tuple[bool, bool, T]]: def loop_from_index( - values: Sequence[T], index: int, direction: Literal[+1, -1] = +1 + values: Sequence[T], index: int, direction: Literal[+1, -1] = +1, wrap: bool = True ) -> Iterable[tuple[int, T]]: """Iterate over values in a sequence from a given starting index, wrapping the index if it would go out of bounds. @@ -55,32 +55,19 @@ def loop_from_index( values: A sequence of values. index: Starting index. direction: Direction to move index (+1 for forward, -1 for backward). + bool: Should the index wrap when out of bounds? Yields: A tuple of index and value from the sequence. """ count = len(values) - for _ in range(count): - index = (index + direction) % count - yield (index, values[index]) - - -def loop_from_index_no_wrap( - values: Sequence[T], index: int, direction: Literal[+1, -1] = +1 -) -> Iterable[tuple[int, T]]: - """Iterate over values in a sequence from a given starting index, without wrapping the index. - - Args: - values: A sequence of values. - index: Starting index. - direction: Direction to move index (+1 for forward, -1 for backward). - - Yields: - A tuple of index and value from the sequence. - """ - count = len(values) - maxima = (-1, count) - for _ in range(count): - if (index := index + direction) in maxima: - break - yield (index, values[index]) + if wrap: + maxima = (-1, count) + for _ in range(count): + if (index := index + direction) in maxima: + break + yield (index, values[index]) + else: + for _ in range(count): + index = (index + direction) % count + yield (index, values[index]) diff --git a/src/textual/widgets/_list_view.py b/src/textual/widgets/_list_view.py index e8e47f8172..4ec1ff711b 100644 --- a/src/textual/widgets/_list_view.py +++ b/src/textual/widgets/_list_view.py @@ -4,7 +4,7 @@ from typing_extensions import TypeGuard -from textual._loop import loop_from_index_no_wrap +from textual._loop import loop_from_index from textual.await_remove import AwaitRemove from textual.binding import Binding, BindingType from textual.containers import VerticalScroll @@ -280,7 +280,7 @@ def action_cursor_down(self) -> None: self.index = 0 else: index = self.index - for index, item in loop_from_index_no_wrap(self._nodes, self.index): + for index, item in loop_from_index(self._nodes, self.index, wrap=False): if not item.disabled: self.index = index break @@ -291,8 +291,8 @@ def action_cursor_up(self) -> None: if self._nodes: self.index = len(self._nodes) - 1 else: - for index, item in loop_from_index_no_wrap( - self._nodes, self.index, direction=-1 + for index, item in loop_from_index( + self._nodes, self.index, direction=-1, wrap=False ): if not item.disabled: self.index = index