Skip to content

Commit d74dfe8

Browse files
committed
Use a new widget to pick a column
1 parent 897e2a8 commit d74dfe8

2 files changed

Lines changed: 40 additions & 31 deletions

File tree

src/blosc2/b2view/app.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ class HelpScreen(ModalScreen[None]):
265265
[
266266
("left / right", "move cursor; pages at the edges"),
267267
("s / e (home / end)", "first / last column window"),
268-
("c", "go to column index or name..."),
268+
("c", "go to column (searchable name list; CTable, else index)"),
269269
("/", "pick which columns to show (searchable multi-select; CTable)"),
270270
("p", "plot a whole-column overview (needs textual-plotext)"),
271271
("enter", "decode a skipped cell (list/struct/object column)"),
@@ -453,6 +453,7 @@ class ColumnSelectScreen(ModalScreen["int | None"]):
453453
454454
Dismisses with the chosen column's index into *names* (or None on cancel),
455455
a drop-in for :class:`GoToColumnScreen`'s result contract. Used by the
456+
``c`` go-to-column key (CTables, where columns have names) and by the
456457
scatter ``s`` key to pick the Y column from the visible-column universe.
457458
"""
458459

@@ -2707,9 +2708,16 @@ def action_go_to_column(self) -> None:
27072708
page = self.table_page
27082709
if page.get("source_kind") not in _COL_PAGED_KINDS:
27092710
return
2710-
current = page["col_start"] + self.query_one("#data-table", DataTable).cursor_column
2711-
names = self.browser.column_names(self.selected_path) if page["source_kind"] == "ctable" else None
2712-
screen = GoToColumnScreen(ncols=page["ncols"], current=current, names=names)
2711+
if page["source_kind"] == "ctable":
2712+
# Named columns -> pick from a searchable list (type to filter, ↑/↓,
2713+
# Enter); the option ids index into the visible-column universe, which
2714+
# is exactly what _go_to_column expects.
2715+
names = self.browser.column_names(self.selected_path)
2716+
screen: ModalScreen[int | None] = ColumnSelectScreen(names=names, title="Go to column")
2717+
else:
2718+
# N-D arrays have no column names; fall back to a numeric index entry.
2719+
current = page["col_start"] + self.query_one("#data-table", DataTable).cursor_column
2720+
screen = GoToColumnScreen(ncols=page["ncols"], current=current, names=None)
27132721
self.push_screen(screen, self._go_to_column)
27142722

27152723
def action_filter_rows(self) -> None:

tests/b2view/test_basics.py

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
from blosc2.b2view.app import (
5252
B2ViewApp,
5353
ColumnFilterScreen,
54+
ColumnSelectScreen,
5455
FilterScreen,
5556
GoToColumnScreen,
5657
GoToRowScreen,
@@ -301,11 +302,17 @@ async def test_2d_paging(store_path):
301302
await wait_for_table(pilot)
302303
assert app.table_page["col_start"] == 0
303304

304-
# 'c' jumps to a column by index (arrays have no column names)
305+
# 'c' jumps to a column by index (arrays have no column names). The
306+
# modal pre-fills the current index and pre-selects it, so typing a new
307+
# index replaces it (not appends, e.g. "0" + "97" -> "097").
305308
await pilot.press("c")
306309
await pilot.pause()
307310
assert isinstance(app.screen, GoToColumnScreen)
308-
app.screen.query_one("#gotocol-input", Input).value = "97"
311+
gotocol_input = app.screen.query_one("#gotocol-input", Input)
312+
assert gotocol_input.value == "0" # pre-filled with current column
313+
for ch in "97":
314+
await pilot.press(ch)
315+
assert gotocol_input.value == "97" # replaced, not "097"
309316
await pilot.press("enter")
310317
await wait_for_table(pilot)
311318
page = app.table_page
@@ -515,11 +522,14 @@ async def test_ctable_column_paging(store_path):
515522
assert page["start"] + table.cursor_row == 150
516523
_assert_ctable_window_values(page, expected)
517524

518-
# 'c' goes to a column by name; the row position is kept
525+
# 'c' opens a searchable column picker (type to filter, ↑/↓, Enter);
526+
# the row position is kept. Pick v12 by typing its name.
519527
await pilot.press("c")
520528
await pilot.pause()
521-
assert isinstance(app.screen, GoToColumnScreen)
522-
app.screen.query_one("#gotocol-input", Input).value = "v12"
529+
assert isinstance(app.screen, ColumnSelectScreen)
530+
for ch in "v12":
531+
await pilot.press(ch)
532+
await pilot.pause()
523533
await pilot.press("enter")
524534
await wait_for_table(pilot)
525535
page = app.table_page
@@ -529,40 +539,28 @@ async def test_ctable_column_paging(store_path):
529539
assert page["start"] + table.cursor_row == 150
530540
_assert_ctable_window_values(page, expected)
531541

532-
# Typing a name replaces the pre-filled current index (not appends): the
533-
# modal opens with the current column index selected, so the first
534-
# keystroke overwrites it instead of producing e.g. "0v12".
542+
# ↑/↓ drive the highlight: filter to the v1x family, then arrow to v12
535543
await pilot.press("c")
536544
await pilot.pause()
537-
gotocol_input = app.screen.query_one("#gotocol-input", Input)
538-
assert gotocol_input.value == str(app.table_page["col_start"]) # pre-filled
539-
for ch in "v12":
545+
assert isinstance(app.screen, ColumnSelectScreen)
546+
for ch in "v1": # matches v10, v11, ..., v19 in column order
540547
await pilot.press(ch)
541-
assert gotocol_input.value == "v12" # replaced, not "<index>v12"
548+
await pilot.pause()
549+
await pilot.press("down") # v10 -> v11
550+
await pilot.press("down") # v11 -> v12
542551
await pilot.press("enter")
543552
await wait_for_table(pilot)
544553
assert app.table_page["col_start"] == all_names.index("v12")
545554
assert app.table_page["columns"][0] == "v12"
546555

547-
# An ambiguous name prefix keeps the modal open; escape cancels
556+
# escape cancels the picker without moving
548557
await pilot.press("c")
549558
await pilot.pause()
550-
app.screen.query_one("#gotocol-input", Input).value = "v1"
551-
await pilot.press("enter")
552-
await pilot.pause()
553-
assert isinstance(app.screen, GoToColumnScreen)
559+
assert isinstance(app.screen, ColumnSelectScreen)
554560
await pilot.press("escape")
555561
await wait_for_table(pilot)
556562
assert app.table_page["col_start"] == all_names.index("v12")
557563

558-
# ...and a numeric index works as well
559-
await pilot.press("c")
560-
await pilot.pause()
561-
app.screen.query_one("#gotocol-input", Input).value = "0"
562-
await pilot.press("enter")
563-
await wait_for_table(pilot)
564-
assert app.table_page["col_start"] == 0
565-
566564
# Shrinking the terminal re-fits the column window to the new width
567565
wide_columns = list(app.table_page["columns"])
568566
await pilot.resize_terminal(80, 40)
@@ -678,10 +676,13 @@ async def submit_filter(expr: str) -> None:
678676
assert page["columns"][0] == "b"
679677
assert app.browser.get_column_filter("/level0/ctable") == f"{ncols - 1} of {ncols}"
680678

681-
# The goto-column modal resolves names within the visible set.
679+
# The goto-column picker lists names within the visible set.
682680
await pilot.press("c")
683681
await pilot.pause()
684-
app.screen.query_one("#gotocol-input", Input).value = "v15"
682+
assert isinstance(app.screen, ColumnSelectScreen)
683+
for ch in "v15":
684+
await pilot.press(ch)
685+
await pilot.pause()
685686
await pilot.press("enter")
686687
await wait_for_table(pilot)
687688
assert app.table_page["columns"][0] == "v15"

0 commit comments

Comments
 (0)