"""Navigation namespace: ``b.nav.*``.""" from __future__ import annotations from browser_cli.models import Tab from browser_cli.sdk.base import Namespace, sdk_command def _open_args(self, url, *, background=False, focus=False, window=None, group=None): return {"url": url, "background": background or not focus, "focus": focus, "window": window, "group": group} def _tab_args(self, tab_id=None): return {"tabId": tab_id} class NavigationNS(Namespace): """Open URLs, navigate history, and focus tabs.""" @sdk_command("navigate.open", _open_args) def open( self, url: str, *, background: bool = False, focus: bool = False, window: str | None = None, group: str | None = None, ) -> None: """Open *url* in a new tab without stealing OS focus by default.""" def open_wait( self, url: str, *, timeout: float = 30.0, background: bool = False, focus: bool = False, window: str | None = None, group: str | None = None, ) -> Tab: """Open *url* in a new tab and block until fully loaded. Returns the Tab.""" return self.require_tab( self.command("navigate.open_wait", { "url": url, "timeout": int(timeout * 1000), "background": background or not focus, "focus": focus, "window": window, "group": group, }), "navigate.open_wait returned unexpected data", ) @sdk_command("navigate.reload", _tab_args) def reload(self, tab_id: int | None = None) -> None: """Reload the active tab or a specific tab.""" @sdk_command("navigate.hard_reload", _tab_args) def hard_reload(self, tab_id: int | None = None) -> None: """Hard-reload the active tab or a specific tab.""" @sdk_command("navigate.back", _tab_args) def back(self, tab_id: int | None = None) -> None: """Navigate back in the active tab or a specific tab.""" @sdk_command("navigate.forward", _tab_args) def forward(self, tab_id: int | None = None) -> None: """Navigate forward in the active tab or a specific tab.""" @sdk_command("navigate.focus", lambda self, pattern: {"pattern": pattern}) def focus(self, pattern: str) -> dict | None: """Focus the first tab whose URL matches *pattern*. Returns the matched tab info, if any.""" @sdk_command("navigate.to", lambda self, tab_id, url: {"tabId": tab_id, "url": url}) def to(self, tab_id: int, url: str) -> None: """Navigate a specific tab to *url* in place.""" def search( self, engine: str, query: str, *, background: bool = False, focus: bool = False, window: str | None = None, group: str | None = None, ) -> None: """Open a search query in the given engine (e.g. 'google', 'youtube', 'ddg').""" from urllib.parse import quote_plus from browser_cli.commands.search import ENGINES template = ENGINES.get(engine) if template is None: raise ValueError(f"Unknown search engine '{engine}'. Available: {', '.join(ENGINES)}") url = template.format(query=quote_plus(query)) self.command("navigate.open", {"url": url, "background": background or not focus, "focus": focus, "window": window, "group": group})