Refactor keybindings and footer management: streamline keybinding processing and enhance footer item display with key-description pairs for improved clarity and usability.
This commit is contained in:
		
							parent
							
								
									3f0892fb7b
								
							
						
					
					
						commit
						6107b43ac5
					
				
					 3 changed files with 133 additions and 24 deletions
				
			
		| 
						 | 
					@ -147,26 +147,27 @@ class HostsManagerApp(App):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Process keybindings and add to appropriate sections
 | 
					            # Process keybindings and add to appropriate sections
 | 
				
			||||||
            for binding in self.BINDINGS:
 | 
					            for binding in self.BINDINGS:
 | 
				
			||||||
 | 
					                # Skip tuple-style bindings and only process Binding objects
 | 
				
			||||||
 | 
					                if not hasattr(binding, "show"):
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
                # Only show bindings marked with show=True
 | 
					                # Only show bindings marked with show=True
 | 
				
			||||||
                if hasattr(binding, "show") and binding.show:
 | 
					                if binding.show:
 | 
				
			||||||
                    # Get the display key
 | 
					                    # Get the display key
 | 
				
			||||||
                    key_display = getattr(binding, "key_display", None) or binding.key
 | 
					                    key_display = getattr(binding, "key_display", None) or binding.key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    # Get the description
 | 
					                    # Get the description
 | 
				
			||||||
                    description = binding.description or binding.action
 | 
					                    description = binding.description or binding.action
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    # Format the item
 | 
					 | 
				
			||||||
                    item = f"{key_display}: {description}"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    # Determine positioning from id attribute
 | 
					                    # Determine positioning from id attribute
 | 
				
			||||||
                    binding_id = getattr(binding, "id", None)
 | 
					                    binding_id = getattr(binding, "id", None)
 | 
				
			||||||
                    if binding_id and binding_id.startswith("left:"):
 | 
					                    if binding_id and binding_id.startswith("left:"):
 | 
				
			||||||
                        footer.add_left_item(item)
 | 
					                        footer.add_left_item(key_display, description)
 | 
				
			||||||
                    elif binding_id and binding_id.startswith("right:"):
 | 
					                    elif binding_id and binding_id.startswith("right:"):
 | 
				
			||||||
                        footer.add_right_item(item)
 | 
					                        footer.add_right_item(key_display, description)
 | 
				
			||||||
                    else:
 | 
					                    else:
 | 
				
			||||||
                        # Default to right if no specific positioning
 | 
					                        # Default to right if no specific positioning
 | 
				
			||||||
                        footer.add_right_item(item)
 | 
					                        footer.add_right_item(key_display, description)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Status section will be updated by update_status
 | 
					            # Status section will be updated by update_status
 | 
				
			||||||
            self._update_footer_status()
 | 
					            self._update_footer_status()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,42 @@ from textual.app import ComposeResult
 | 
				
			||||||
from textual.containers import Horizontal
 | 
					from textual.containers import Horizontal
 | 
				
			||||||
from textual.widgets import Static
 | 
					from textual.widgets import Static
 | 
				
			||||||
from textual.widget import Widget
 | 
					from textual.widget import Widget
 | 
				
			||||||
 | 
					from rich.text import Text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FooterKey(Widget):
 | 
				
			||||||
 | 
					    """A key/action pair widget for the footer, styled similar to Textual's original FooterKey."""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DEFAULT_CSS = """
 | 
				
			||||||
 | 
					    FooterKey {
 | 
				
			||||||
 | 
					        width: auto;
 | 
				
			||||||
 | 
					        height: 1;
 | 
				
			||||||
 | 
					        content-align: center middle;
 | 
				
			||||||
 | 
					        padding: 0 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .footer-key--key {
 | 
				
			||||||
 | 
					        text-style: bold;
 | 
				
			||||||
 | 
					        color: $text;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .footer-key--description {
 | 
				
			||||||
 | 
					        color: $text-muted;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, key: str, description: str, **kwargs):
 | 
				
			||||||
 | 
					        super().__init__(**kwargs)
 | 
				
			||||||
 | 
					        self.key = key
 | 
				
			||||||
 | 
					        self.description = description
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def render(self) -> Text:
 | 
				
			||||||
 | 
					        """Render the key-description pair with proper styling."""
 | 
				
			||||||
 | 
					        text = Text()
 | 
				
			||||||
 | 
					        text.append(f"{self.key}", style="bold")
 | 
				
			||||||
 | 
					        text.append(" ")
 | 
				
			||||||
 | 
					        text.append(self.description, style="dim")
 | 
				
			||||||
 | 
					        return text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CustomFooter(Widget):
 | 
					class CustomFooter(Widget):
 | 
				
			||||||
| 
						 | 
					@ -39,7 +75,6 @@ class CustomFooter(Widget):
 | 
				
			||||||
    .footer-left {
 | 
					    .footer-left {
 | 
				
			||||||
        width: auto;
 | 
					        width: auto;
 | 
				
			||||||
        text-align: left;
 | 
					        text-align: left;
 | 
				
			||||||
        text-style: dim;
 | 
					 | 
				
			||||||
        height: 1;
 | 
					        height: 1;
 | 
				
			||||||
        content-align: left middle;
 | 
					        content-align: left middle;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -52,7 +87,6 @@ class CustomFooter(Widget):
 | 
				
			||||||
    .footer-right {
 | 
					    .footer-right {
 | 
				
			||||||
        width: auto;
 | 
					        width: auto;
 | 
				
			||||||
        text-align: right;
 | 
					        text-align: right;
 | 
				
			||||||
        text-style: dim;
 | 
					 | 
				
			||||||
        height: 1;
 | 
					        height: 1;
 | 
				
			||||||
        content-align: right middle;
 | 
					        content-align: right middle;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -73,12 +107,25 @@ class CustomFooter(Widget):
 | 
				
			||||||
        height: 1;
 | 
					        height: 1;
 | 
				
			||||||
        content-align: right middle;
 | 
					        content-align: right middle;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /* Enhanced styling for footer key components */
 | 
				
			||||||
 | 
					    .footer-left .footer-key--key,
 | 
				
			||||||
 | 
					    .footer-right .footer-key--key {
 | 
				
			||||||
 | 
					        text-style: bold;
 | 
				
			||||||
 | 
					        color: $text;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    .footer-left .footer-key--description,
 | 
				
			||||||
 | 
					    .footer-right .footer-key--description {
 | 
				
			||||||
 | 
					        color: $text-muted;
 | 
				
			||||||
 | 
					        text-style: dim;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, **kwargs):
 | 
					    def __init__(self, **kwargs):
 | 
				
			||||||
        super().__init__(**kwargs)
 | 
					        super().__init__(**kwargs)
 | 
				
			||||||
        self._left_items = []
 | 
					        self._left_items = []  # List of FooterKey widgets
 | 
				
			||||||
        self._right_items = []
 | 
					        self._right_items = []  # List of FooterKey widgets
 | 
				
			||||||
        self._status_text = ""
 | 
					        self._status_text = ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def compose(self) -> ComposeResult:
 | 
					    def compose(self) -> ComposeResult:
 | 
				
			||||||
| 
						 | 
					@ -90,16 +137,43 @@ class CustomFooter(Widget):
 | 
				
			||||||
            yield Static(" │ ", id="footer-separator", classes="footer-separator")
 | 
					            yield Static(" │ ", id="footer-separator", classes="footer-separator")
 | 
				
			||||||
            yield Static("", id="footer-status", classes="footer-status")
 | 
					            yield Static("", id="footer-status", classes="footer-status")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_left_item(self, item: str) -> None:
 | 
					    def add_left_item(self, key: str, description: str) -> None:
 | 
				
			||||||
        """Add an item to the left section."""
 | 
					        """Add a key-description pair to the left section."""
 | 
				
			||||||
        self._left_items.append(item)
 | 
					        footer_key = FooterKey(key, description)
 | 
				
			||||||
 | 
					        self._left_items.append(footer_key)
 | 
				
			||||||
        self._update_left_section()
 | 
					        self._update_left_section()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_right_item(self, item: str) -> None:
 | 
					    def add_right_item(self, key: str, description: str) -> None:
 | 
				
			||||||
        """Add an item to the right section."""
 | 
					        """Add a key-description pair to the right section."""
 | 
				
			||||||
        self._right_items.append(item)
 | 
					        footer_key = FooterKey(key, description)
 | 
				
			||||||
 | 
					        self._right_items.append(footer_key)
 | 
				
			||||||
        self._update_right_section()
 | 
					        self._update_right_section()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def add_left_item_legacy(self, item: str) -> None:
 | 
				
			||||||
 | 
					        """Add a legacy item (key: description format) to the left section."""
 | 
				
			||||||
 | 
					        if ": " in item:
 | 
				
			||||||
 | 
					            key, description = item.split(": ", 1)
 | 
				
			||||||
 | 
					            self.add_left_item(key, description)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.add_left_item(item, "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def add_right_item_legacy(self, item: str) -> None:
 | 
				
			||||||
 | 
					        """Add a legacy item (key: description format) to the right section."""
 | 
				
			||||||
 | 
					        if ": " in item:
 | 
				
			||||||
 | 
					            key, description = item.split(": ", 1)
 | 
				
			||||||
 | 
					            self.add_right_item(key, description)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.add_right_item(item, "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Backward compatibility - temporarily add the old single parameter methods
 | 
				
			||||||
 | 
					    def add_left_item_old(self, item: str) -> None:
 | 
				
			||||||
 | 
					        """Backward compatibility method."""
 | 
				
			||||||
 | 
					        self.add_left_item_legacy(item)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    def add_right_item_old(self, item: str) -> None:
 | 
				
			||||||
 | 
					        """Backward compatibility method."""
 | 
				
			||||||
 | 
					        self.add_right_item_legacy(item)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def clear_left_items(self) -> None:
 | 
					    def clear_left_items(self) -> None:
 | 
				
			||||||
        """Clear all items from the left section."""
 | 
					        """Clear all items from the left section."""
 | 
				
			||||||
        self._left_items.clear()
 | 
					        self._left_items.clear()
 | 
				
			||||||
| 
						 | 
					@ -119,7 +193,19 @@ class CustomFooter(Widget):
 | 
				
			||||||
        """Update the left section display."""
 | 
					        """Update the left section display."""
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            left_static = self.query_one("#footer-left", Static)
 | 
					            left_static = self.query_one("#footer-left", Static)
 | 
				
			||||||
            left_static.update(" ".join(self._left_items))
 | 
					            if self._left_items:
 | 
				
			||||||
 | 
					                # Combine all FooterKey renderings with spacing
 | 
				
			||||||
 | 
					                combined_text = Text()
 | 
				
			||||||
 | 
					                for i, footer_key in enumerate(self._left_items):
 | 
				
			||||||
 | 
					                    if i > 0:
 | 
				
			||||||
 | 
					                        combined_text.append("  ")  # Add spacing between items
 | 
				
			||||||
 | 
					                    # Render individual key-description pair with styling
 | 
				
			||||||
 | 
					                    combined_text.append(footer_key.key, style="bold")
 | 
				
			||||||
 | 
					                    combined_text.append(" ")
 | 
				
			||||||
 | 
					                    combined_text.append(footer_key.description, style="dim")
 | 
				
			||||||
 | 
					                left_static.update(combined_text)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                left_static.update("")
 | 
				
			||||||
        except Exception:
 | 
					        except Exception:
 | 
				
			||||||
            pass  # Widget not ready yet
 | 
					            pass  # Widget not ready yet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -127,7 +213,19 @@ class CustomFooter(Widget):
 | 
				
			||||||
        """Update the right section display."""
 | 
					        """Update the right section display."""
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            right_static = self.query_one("#footer-right", Static)
 | 
					            right_static = self.query_one("#footer-right", Static)
 | 
				
			||||||
            right_static.update(" ".join(self._right_items))
 | 
					            if self._right_items:
 | 
				
			||||||
 | 
					                # Combine all FooterKey renderings with spacing
 | 
				
			||||||
 | 
					                combined_text = Text()
 | 
				
			||||||
 | 
					                for i, footer_key in enumerate(self._right_items):
 | 
				
			||||||
 | 
					                    if i > 0:
 | 
				
			||||||
 | 
					                        combined_text.append("  ")  # Add spacing between items
 | 
				
			||||||
 | 
					                    # Render individual key-description pair with styling
 | 
				
			||||||
 | 
					                    combined_text.append(footer_key.key, style="bold")
 | 
				
			||||||
 | 
					                    combined_text.append(" ")
 | 
				
			||||||
 | 
					                    combined_text.append(footer_key.description, style="dim")
 | 
				
			||||||
 | 
					                right_static.update(combined_text)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                right_static.update("")
 | 
				
			||||||
        except Exception:
 | 
					        except Exception:
 | 
				
			||||||
            pass  # Widget not ready yet
 | 
					            pass  # Widget not ready yet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,8 +12,20 @@ HOSTS_MANAGER_BINDINGS = [
 | 
				
			||||||
    Binding("a", "add_entry", "Add new entry", show=True, id="left:add_entry"),
 | 
					    Binding("a", "add_entry", "Add new entry", show=True, id="left:add_entry"),
 | 
				
			||||||
    Binding("d", "delete_entry", "Delete entry", show=True, id="left:delete_entry"),
 | 
					    Binding("d", "delete_entry", "Delete entry", show=True, id="left:delete_entry"),
 | 
				
			||||||
    Binding("e", "edit_entry", "Edit entry", show=True, id="left:edit_entry"),
 | 
					    Binding("e", "edit_entry", "Edit entry", show=True, id="left:edit_entry"),
 | 
				
			||||||
    Binding("space", "toggle_entry", "Toggle active/inactive", show=True, id="left:toggle_entry"),
 | 
					    Binding(
 | 
				
			||||||
    Binding("ctrl+e", "toggle_edit_mode", "Toggle edit mode", show=True, id="left:toggle_edit_mode"),
 | 
					        "space",
 | 
				
			||||||
 | 
					        "toggle_entry",
 | 
				
			||||||
 | 
					        "Toggle active/inactive",
 | 
				
			||||||
 | 
					        show=True,
 | 
				
			||||||
 | 
					        id="left:toggle_entry",
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    Binding(
 | 
				
			||||||
 | 
					        "ctrl+e",
 | 
				
			||||||
 | 
					        "toggle_edit_mode",
 | 
				
			||||||
 | 
					        "Toggle edit mode",
 | 
				
			||||||
 | 
					        show=True,
 | 
				
			||||||
 | 
					        id="left:toggle_edit_mode",
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
    Binding("c", "config", "Configuration", show=True, id="right:config"),
 | 
					    Binding("c", "config", "Configuration", show=True, id="right:config"),
 | 
				
			||||||
    Binding(
 | 
					    Binding(
 | 
				
			||||||
        "question_mark",
 | 
					        "question_mark",
 | 
				
			||||||
| 
						 | 
					@ -26,9 +38,7 @@ HOSTS_MANAGER_BINDINGS = [
 | 
				
			||||||
    Binding("q", "quit", "Quit", show=True, id="right:quit"),
 | 
					    Binding("q", "quit", "Quit", show=True, id="right:quit"),
 | 
				
			||||||
    Binding("r", "reload", "Reload hosts file", show=False),
 | 
					    Binding("r", "reload", "Reload hosts file", show=False),
 | 
				
			||||||
    Binding("i", "sort_by_ip", "Sort by IP address", show=False),
 | 
					    Binding("i", "sort_by_ip", "Sort by IP address", show=False),
 | 
				
			||||||
    Binding(
 | 
					    Binding("h", "sort_by_hostname", "Sort by hostname", show=False),
 | 
				
			||||||
        "h", "sort_by_hostname", "Sort by hostname", show=False
 | 
					 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
    Binding("ctrl+s", "save_file", "Save hosts file", show=False),
 | 
					    Binding("ctrl+s", "save_file", "Save hosts file", show=False),
 | 
				
			||||||
    Binding("shift+up", "move_entry_up", "Move entry up", show=False),
 | 
					    Binding("shift+up", "move_entry_up", "Move entry up", show=False),
 | 
				
			||||||
    Binding("shift+down", "move_entry_down", "Move entry down", show=False),
 | 
					    Binding("shift+down", "move_entry_down", "Move entry down", show=False),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue