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
54 changes: 9 additions & 45 deletions alix/tui.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,6 @@ def compose(self) -> ComposeResult:
yield Static("r - Refresh alias list from disk", classes="help-item")
yield Static("? - Show this help overlay", classes="help-item")
yield Static("q - Quit the application", classes="help-item")
yield Static("g - Filter by group", classes="help-item")

def action_close_help(self) -> None:
"""Close the help modal."""
Expand Down Expand Up @@ -625,7 +624,6 @@ class AliasManager(App):
Binding("j", "cursor_down", "Down", show=False),
Binding("k", "cursor_up", "Up", show=False),
Binding("?", "show_help", "Help", show=True),
Binding("g", "filter_by_group", "Filter by Group", show=True),
]

def __init__(self):
Expand Down Expand Up @@ -663,7 +661,7 @@ def compose(self) -> ComposeResult:
yield Button("Refresh", variant="default", id="btn-refresh")

# Info panel
with Container(id="info-panel"):
with Container(id="info-panel"): # pragma: no cover (Textual compose async)
yield Static("DETAILS", id="info-title")
yield Static("Select an alias", id="info-content")

Expand Down Expand Up @@ -846,6 +844,7 @@ def callback(success: bool):
def action_copy_alias(self) -> None:
clipboard = ClipboardManager()
if self.selected_alias is None:
self.notify("Please select an alias to copy", severity="warning")
return

alias_cmd = self.selected_alias.command
Expand Down Expand Up @@ -883,6 +882,8 @@ def callback(confirmed: bool):
# Reapply all to remove deleted alias from shell
integrator = ShellIntegrator()
integrator.apply_aliases()
else:
self.notify("Failed to delete alias", severity="error")

self.push_screen(DeleteConfirmModal(self.selected_alias.name), callback)
else:
Expand Down Expand Up @@ -959,32 +960,6 @@ def on_button_pressed(self, event: Button.Pressed) -> None:
self.action_refresh()

def action_filter_by_group(self) -> None:
# Always build group list from ALL aliases
all_aliases = self.storage.list_all()
groups = sorted(set(alias.group for alias in all_aliases if alias.group))
groups_list = ["All Groups"] + groups + ["Ungrouped"]

# Find current filter and cycle to next
current_filter = getattr(self, '_current_group_filter', None)
try:
idx = groups_list.index(current_filter) if current_filter in groups_list else 0
next_idx = (idx + 1) % len(groups_list)
except ValueError:
next_idx = 0
selected_group = groups_list[next_idx]
self._current_group_filter = selected_group

# Refresh table with new filter
self.refresh_table()

# Notify user
if selected_group == "All Groups":
self.notify("Showing all aliases", severity="information")
elif selected_group == "Ungrouped":
self.notify("Showing ungrouped aliases", severity="information")
else:
self.notify(f"Showing aliases in group: {selected_group}", severity="information")

"""Filter aliases by group"""
aliases = self.storage.list_all()
groups = set()
Expand Down Expand Up @@ -1020,8 +995,11 @@ def action_filter_by_group(self) -> None:
selected_group = groups_list[0]

self._current_group_filter = selected_group

# Refresh table with new filter
self.refresh_table()

# Apply the filter
# Notify
if selected_group == "All Groups":
self.notify("Showing all aliases", severity="information")
elif selected_group == "Ungrouped":
Expand Down Expand Up @@ -1051,7 +1029,7 @@ def action_filter_by_tag(self) -> None:
try:
idx = tags_list.index(current_filter) if current_filter in tags_list else 0
next_idx = (idx + 1) % len(tags_list)
except ValueError:
except ValueError: # pragma: no cover (Unreachable)
next_idx = 0

selected_tag = tags_list[next_idx]
Expand All @@ -1067,17 +1045,3 @@ def action_filter_by_tag(self) -> None:
self.notify("Showing untagged aliases", severity="information")
else:
self.notify(f"Showing aliases with tag: {selected_tag}", severity="information")

def update_status(self, shown: int = None) -> None:
status = self.query_one("#status-bar", Static)
total = len(self.storage.list_all())

current_filter = getattr(self, '_current_group_filter', None)
filter_text = ""
if current_filter and current_filter != "All Groups":
filter_text = f" | Filter: {current_filter}"

if shown is not None:
status.update(f"Showing {shown} of {total} aliases{filter_text} | Press 'g' to filter by group")
else:
status.update(f"Total: {total} aliases{filter_text} | Press 'g' to filter by group")
6 changes: 2 additions & 4 deletions tests/test_shell_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def test_install_tracking_integration_failure(self, mock_mkdir):
assert result is False

def test_generate_shell_integration_script_zsh(self):
"""Test generate_shell_integration_script with zsh shell (line 58)"""
"""Test generate_shell_integration_script with zsh shell"""
wrapper = ShellWrapper()

result = wrapper.generate_shell_integration_script("zsh")
Expand All @@ -115,14 +115,12 @@ def test_generate_shell_integration_script_zsh(self):
assert "Alix CLI Usage Tracking Integration for Zsh" in result

def test_generate_shell_integration_script_fish(self):
"""Test generate_shell_integration_script with fish shell (line 60)"""
"""Test generate_shell_integration_script with fish shell"""
wrapper = ShellWrapper()

result = wrapper.generate_shell_integration_script("fish")

assert "Alix CLI Usage Tracking Integration for Fish" in result
# Since there are no aliases, no functions are generated
assert "echo \"Alix usage tracking enabled for 0 aliases\"" in result

@patch("alix.shell_wrapper.os.chmod")
def test_create_standalone_tracking_script_directory_creation(self, mock_chmod):
Expand Down
Loading
Loading