Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion sqlit/core/state_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,10 @@ def allows(
help_key=help_key or key,
help_description=help,
)
if key and label:
# A label means the author wants this in the footer. The display
# key can be omitted here and resolved at render time via the
# global keymap (see ActionSpec.get_display_binding).
if label:
if right:
self._right_bindings.append(action_name)
else:
Expand Down
7 changes: 6 additions & 1 deletion sqlit/domains/explorer/state/tree_focused.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ def _setup_actions(self) -> None:
self.allows("tree_cursor_down") # vim j
self.allows("tree_cursor_up") # vim k
self.allows("tree_filter", help="Filter items")
self.allows("enter_tree_visual_mode", label="Visual", help="Enter visual selection mode")
self.allows(
"enter_tree_visual_mode",
lambda app: app.tree_node_kind is not None,
label="Visual",
help="Enter visual selection mode",
)

def is_active(self, app: InputContext) -> bool:
return app.focus == "explorer" and not app.tree_filter_active
36 changes: 36 additions & 0 deletions tests/ui/keybindings/test_state_machine.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,39 @@ def test_collapse_all_only_in_tree_mode(self):
value_view_tree_mode=False,
)
assert sm.check_action(ctx, "collapse_all_json_nodes") is False


class TestEmptyExplorerFooter:
"""Empty-state footer must guide a first-time user toward `n` for New."""

def test_new_connection_in_footer_when_explorer_focused_empty(self):
sm = UIStateMachine()
ctx = make_context(focus="explorer", tree_node_kind=None)
left, _right = sm.get_display_bindings(ctx)
actions = [b.action for b in left]
assert "new_connection" in actions, (
"First-time users with no connections must see `n` for New "
"in the footer when the explorer is focused."
)

def test_refresh_tree_in_footer_when_explorer_focused_empty(self):
sm = UIStateMachine()
ctx = make_context(focus="explorer", tree_node_kind=None)
left, _right = sm.get_display_bindings(ctx)
actions = [b.action for b in left]
assert "refresh_tree" in actions

def test_visual_mode_hidden_from_footer_when_tree_empty(self):
"""Visual selection mode only makes sense when there's something to select."""
sm = UIStateMachine()
ctx = make_context(focus="explorer", tree_node_kind=None)
left, _right = sm.get_display_bindings(ctx)
actions = [b.action for b in left]
assert "enter_tree_visual_mode" not in actions

def test_visual_mode_shown_in_footer_when_node_highlighted(self):
sm = UIStateMachine()
ctx = make_context(focus="explorer", tree_node_kind="connection")
left, _right = sm.get_display_bindings(ctx)
actions = [b.action for b in left]
assert "enter_tree_visual_mode" in actions
Loading