fd5447cbb9
Testing / remote-protocol-compat (0.9.3) (push) Successful in 42s
Testing / remote-protocol-compat (0.9.5) (push) Successful in 44s
Package Extension / package-extension (push) Successful in 43s
Build & Publish Package / publish (push) Successful in 43s
Testing / test (push) Successful in 45s
Restructure the Python API and internals around composable namespaces and a standalone transport/endpoint layer. Bump to 0.12.0. Python API: - Replace flat methods (b.tabs_list(), b.group_list()) with namespaces: b.nav, b.tabs, b.groups, b.windows, b.dom, b.extract, b.page, b.storage, b.cookies, b.session, b.perf, b.extension. - Shrink browser_cli/__init__.py to a thin composition root; move all behaviour into browser_cli/sdk/ (one module per namespace + factories, base, routing). Internals: - Add browser_cli/transport.py and remote_transport.py to isolate IPC from command logic; client.py now delegates instead of owning transport. - Add browser_cli/endpoints.py for endpoint resolution and browser_cli/errors.py for shared error types. - Extract markdown rendering into browser_cli/markdown.py (out of extract). - Add USER_AGENT to version_manager. Tooling & tests: - Add justfile with common dev tasks. - Update CLI commands and demo to the namespaced API. - Rework tests for the new layout; add test_transport.py and test_refactor_boundaries.py to lock in module boundaries. BREAKING CHANGE: flat API methods are removed in favour of namespaces (e.g. b.tabs_list() -> b.tabs.list(), b.group_list() -> b.groups.list()).
81 lines
3.8 KiB
Python
81 lines
3.8 KiB
Python
import click
|
|
from browser_cli.commands import client_from_ctx, handle_errors
|
|
from rich.console import Console
|
|
|
|
console = Console()
|
|
|
|
ENGINES = {
|
|
"google": "https://www.google.com/search?q={query}",
|
|
"brave": "https://search.brave.com/search?q={query}",
|
|
"duckduckgo": "https://duckduckgo.com/?q={query}",
|
|
"ddg": "https://duckduckgo.com/?q={query}",
|
|
"youtube": "https://www.youtube.com/results?search_query={query}",
|
|
"yt": "https://www.youtube.com/results?search_query={query}",
|
|
"spotify": "https://open.spotify.com/search/{query}",
|
|
"amazon": "https://www.amazon.com/s?k={query}",
|
|
"ecosia": "https://www.ecosia.org/search?q={query}",
|
|
"furaffinity": "https://www.furaffinity.net/search/?q={query}",
|
|
"fa": "https://www.furaffinity.net/search/?q={query}",
|
|
"bing": "https://www.bing.com/search?q={query}",
|
|
"github": "https://github.com/search?q={query}",
|
|
"wikipedia": "https://en.wikipedia.org/wiki/Special:Search?search={query}",
|
|
"wiki": "https://en.wikipedia.org/wiki/Special:Search?search={query}",
|
|
"reddit": "https://www.reddit.com/search/?q={query}",
|
|
"stackoverflow": "https://stackoverflow.com/search?q={query}",
|
|
"so": "https://stackoverflow.com/search?q={query}",
|
|
}
|
|
|
|
_DISPLAY_NAMES = {
|
|
"google": "Google", "brave": "Brave Search", "duckduckgo": "DuckDuckGo",
|
|
"ddg": "DuckDuckGo", "youtube": "YouTube", "yt": "YouTube",
|
|
"spotify": "Spotify", "amazon": "Amazon", "ecosia": "Ecosia",
|
|
"furaffinity": "FurAffinity", "fa": "FurAffinity", "bing": "Bing",
|
|
"github": "GitHub", "wikipedia": "Wikipedia", "wiki": "Wikipedia",
|
|
"reddit": "Reddit", "stackoverflow": "Stack Overflow", "so": "Stack Overflow",
|
|
}
|
|
|
|
_SUBCOMMANDS = [
|
|
("google", "Search with Google."),
|
|
("brave", "Search with Brave Search."),
|
|
("duckduckgo", "Search with DuckDuckGo."),
|
|
("ddg", "Search with DuckDuckGo (alias for duckduckgo)."),
|
|
("youtube", "Search YouTube videos."),
|
|
("yt", "Search YouTube (alias for youtube)."),
|
|
("spotify", "Search Spotify."),
|
|
("amazon", "Search Amazon."),
|
|
("ecosia", "Search with Ecosia."),
|
|
("furaffinity", "Search FurAffinity."),
|
|
("fa", "Search FurAffinity (alias for furaffinity)."),
|
|
("bing", "Search with Bing."),
|
|
("github", "Search GitHub."),
|
|
("wikipedia", "Search Wikipedia."),
|
|
("wiki", "Search Wikipedia (alias for wikipedia)."),
|
|
("reddit", "Search Reddit."),
|
|
("stackoverflow", "Search Stack Overflow."),
|
|
("so", "Search Stack Overflow (alias for stackoverflow)."),
|
|
]
|
|
|
|
|
|
@click.group("search")
|
|
def search_group():
|
|
"""Search the web — open a query in a search engine."""
|
|
|
|
def _build_command(engine_key: str, help_text: str) -> click.Command:
|
|
@click.command(engine_key, help=help_text)
|
|
@click.argument("query", nargs=-1, required=True)
|
|
@click.option("--bg", is_flag=True, help="Open in background (no focus)")
|
|
@click.option("--window", "window", default=None, help="Open in named window")
|
|
@click.option("--group", "group", default=None, help="Open in tab group (name or ID)")
|
|
@handle_errors
|
|
def _cmd(query, bg, window, group):
|
|
terms = " ".join(query)
|
|
client_from_ctx().nav.search(engine_key, terms, background=bg, window=window, group=group)
|
|
suffix = f" in group '{group}'" if group else (f" in window '{window}'" if window else "")
|
|
display = _DISPLAY_NAMES.get(engine_key, engine_key.capitalize())
|
|
console.print(f"[green]Searching[/green] [cyan]{display}[/cyan]: {terms}{suffix}")
|
|
|
|
return _cmd
|
|
|
|
for _name, _help in _SUBCOMMANDS:
|
|
search_group.add_command(_build_command(_name, _help))
|