refactor(tui): flatten _multiselect_loop key handling
The interactive multiselect loop nested key dispatch up to six indent levels deep — the worst offender being the space-bar toggle (while > if focus > elif key > if filtered > if/else membership) and the long order-mode elif chain inside the focus branch. Extract two behaviour-identical helpers: - `_toggle_membership(items, item)` collapses the add/remove if/else, pulling the space branch back to four levels. - `_handle_order_key(key, selected, order_cursor)` moves the entire order-focus dispatch out of the loop, returning the new cursor. No control-flow or key-binding changes; the loop's early returns and focus toggling are untouched. (git_gate.py's deep-looking lines named in the issue are multiline call-argument continuations already under four levels of control nesting, so no change was warranted there.) Closes #288 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NkwFXLFff9PYPy4wgVBJp9
This commit is contained in:
+40
-32
@@ -301,6 +301,44 @@ def _run_multiselect(
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _toggle_membership(items: list[str], item: str) -> None:
|
||||||
|
"""Add `item` if absent, remove it if present (in place)."""
|
||||||
|
if item in items:
|
||||||
|
items.remove(item)
|
||||||
|
else:
|
||||||
|
items.append(item)
|
||||||
|
|
||||||
|
|
||||||
|
def _handle_order_key(key: int, selected: list[str], order_cursor: int) -> int:
|
||||||
|
"""Apply a keypress in 'order' focus: navigate, reorder, or remove the
|
||||||
|
item at `order_cursor`. Mutates `selected` in place and returns the new
|
||||||
|
order cursor."""
|
||||||
|
if key in (curses.KEY_UP, ord("k")):
|
||||||
|
if order_cursor > 0:
|
||||||
|
order_cursor -= 1
|
||||||
|
elif key in (curses.KEY_DOWN, ord("j")):
|
||||||
|
if order_cursor < len(selected) - 1:
|
||||||
|
order_cursor += 1
|
||||||
|
elif key == ord("K"):
|
||||||
|
# Move selected item up (earlier in order).
|
||||||
|
if order_cursor > 0:
|
||||||
|
i = order_cursor
|
||||||
|
selected[i - 1], selected[i] = selected[i], selected[i - 1]
|
||||||
|
order_cursor -= 1
|
||||||
|
elif key == ord("J"):
|
||||||
|
# Move selected item down (later in order).
|
||||||
|
if order_cursor < len(selected) - 1:
|
||||||
|
i = order_cursor
|
||||||
|
selected[i], selected[i + 1] = selected[i + 1], selected[i]
|
||||||
|
order_cursor += 1
|
||||||
|
elif key in (curses.KEY_ENTER, _KEY_ENTER_ALT, ord("\r"), _KEY_SPACE):
|
||||||
|
# Remove item from selection while in order mode.
|
||||||
|
del selected[order_cursor]
|
||||||
|
if order_cursor >= len(selected) and order_cursor > 0:
|
||||||
|
order_cursor -= 1
|
||||||
|
return order_cursor
|
||||||
|
|
||||||
|
|
||||||
def _multiselect_loop(
|
def _multiselect_loop(
|
||||||
screen: Any, items: list[str], *, title: str, initial: list[str]
|
screen: Any, items: list[str], *, title: str, initial: list[str]
|
||||||
) -> Optional[list[str]]:
|
) -> Optional[list[str]]:
|
||||||
@@ -362,11 +400,7 @@ def _multiselect_loop(
|
|||||||
|
|
||||||
elif key == _KEY_SPACE:
|
elif key == _KEY_SPACE:
|
||||||
if filtered:
|
if filtered:
|
||||||
item = filtered[cursor]
|
_toggle_membership(selected, filtered[cursor])
|
||||||
if item in selected:
|
|
||||||
selected.remove(item)
|
|
||||||
else:
|
|
||||||
selected.append(item)
|
|
||||||
|
|
||||||
elif key in (curses.KEY_UP, ord("k")):
|
elif key in (curses.KEY_UP, ord("k")):
|
||||||
if cursor > 0:
|
if cursor > 0:
|
||||||
@@ -387,33 +421,7 @@ def _multiselect_loop(
|
|||||||
cursor = 0
|
cursor = 0
|
||||||
|
|
||||||
else: # focus == "order"
|
else: # focus == "order"
|
||||||
if key in (curses.KEY_UP, ord("k")):
|
order_cursor = _handle_order_key(key, selected, order_cursor)
|
||||||
if order_cursor > 0:
|
|
||||||
order_cursor -= 1
|
|
||||||
|
|
||||||
elif key in (curses.KEY_DOWN, ord("j")):
|
|
||||||
if order_cursor < len(selected) - 1:
|
|
||||||
order_cursor += 1
|
|
||||||
|
|
||||||
elif key == ord("K"):
|
|
||||||
# Move selected item up (earlier in order).
|
|
||||||
if order_cursor > 0:
|
|
||||||
i = order_cursor
|
|
||||||
selected[i - 1], selected[i] = selected[i], selected[i - 1]
|
|
||||||
order_cursor -= 1
|
|
||||||
|
|
||||||
elif key == ord("J"):
|
|
||||||
# Move selected item down (later in order).
|
|
||||||
if order_cursor < len(selected) - 1:
|
|
||||||
i = order_cursor
|
|
||||||
selected[i], selected[i + 1] = selected[i + 1], selected[i]
|
|
||||||
order_cursor += 1
|
|
||||||
|
|
||||||
elif key in (curses.KEY_ENTER, _KEY_ENTER_ALT, ord("\r"), _KEY_SPACE):
|
|
||||||
# Remove item from selection while in order mode.
|
|
||||||
del selected[order_cursor]
|
|
||||||
if order_cursor >= len(selected) and order_cursor > 0:
|
|
||||||
order_cursor -= 1
|
|
||||||
|
|
||||||
|
|
||||||
def _render_multiselect(
|
def _render_multiselect(
|
||||||
|
|||||||
Reference in New Issue
Block a user