use full terminal columns for completion test and add native host app as a single script wraper for native host app import
This commit is contained in:
+35
-29
@@ -6,7 +6,6 @@ import click
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import stat
|
||||
import shutil
|
||||
import re
|
||||
from importlib.metadata import PackageNotFoundError, version as package_version
|
||||
@@ -38,6 +37,20 @@ from browser_cli.registry import load_registry
|
||||
|
||||
console = Console()
|
||||
|
||||
# Click's Group.shell_complete hardcodes no limit for get_short_help_str (defaults to 45 chars);
|
||||
# patch to use a wider limit so zsh completion descriptions aren't truncated.
|
||||
def _patched_group_shell_complete(self, ctx, incomplete):
|
||||
from click.shell_completion import CompletionItem
|
||||
results = [
|
||||
CompletionItem(name, help=command.get_short_help_str(limit=shutil.get_terminal_size().columns))
|
||||
for name, command in self.commands.items()
|
||||
if not command.hidden and name.startswith(incomplete)
|
||||
]
|
||||
results.extend(click.Command.shell_complete(self, ctx, incomplete))
|
||||
return results
|
||||
|
||||
click.Group.shell_complete = _patched_group_shell_complete
|
||||
|
||||
NATIVE_HOST_NAME = "com.browsercli.host"
|
||||
EXTENSION_ID = "bfpmkhngkjnfhabmfckgeohlilokodkg"
|
||||
|
||||
@@ -97,15 +110,25 @@ def _ensure_unique_browser_alias(alias: str, target_browser: str | None) -> None
|
||||
raise click.ClickException(f"Browser alias '{alias}' already exists")
|
||||
|
||||
|
||||
def _native_host_wrapper_path() -> Path:
|
||||
base_dir = install_base_dir()
|
||||
def _native_host_exe() -> Path:
|
||||
base = install_base_dir()
|
||||
if is_windows():
|
||||
return base_dir / "libexec" / "native-host.cmd"
|
||||
return base_dir / "libexec" / "native-host"
|
||||
return base / "libexec" / "browser-cli-native-host.cmd"
|
||||
return base / "libexec" / "browser-cli-native-host"
|
||||
|
||||
|
||||
def _native_host_script_path() -> Path:
|
||||
return _native_host_wrapper_path().with_name("native_host.py")
|
||||
def _write_native_host_exe(path: Path) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
if is_windows():
|
||||
path.write_text(
|
||||
f'@echo off\r\n"{sys.executable}" -c "from browser_cli.native_host import main; main()" %*\r\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
else:
|
||||
path.write_text(
|
||||
f'#!{sys.executable}\nfrom browser_cli.native_host import main\nmain()\n'
|
||||
)
|
||||
path.chmod(path.stat().st_mode | 0o111)
|
||||
|
||||
|
||||
def _windows_registry_views():
|
||||
@@ -308,22 +331,8 @@ def cmd_clients_rename(target_browser, alias):
|
||||
def cmd_install(browser):
|
||||
"""Register the native messaging host and print extension load instructions."""
|
||||
|
||||
# Install wrapper outside PATH — the browser uses the absolute path from the
|
||||
# native messaging manifest, so only `browser-cli` needs to be on PATH.
|
||||
wrapper_path = _native_host_wrapper_path()
|
||||
native_host_script_path = _native_host_script_path()
|
||||
wrapper_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(Path(__file__).with_name("native_host.py"), native_host_script_path)
|
||||
if not is_windows():
|
||||
native_host_script_path.chmod(
|
||||
native_host_script_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
|
||||
)
|
||||
wrapper_content = f'#!/bin/sh\nexec "{sys.executable}" "{native_host_script_path}" "$@"\n'
|
||||
wrapper_path.write_text(wrapper_content)
|
||||
wrapper_path.chmod(wrapper_path.stat().st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
|
||||
else:
|
||||
wrapper_content = f'@echo off\r\n"{sys.executable}" "{native_host_script_path}" %*\r\n'
|
||||
wrapper_path.write_text(wrapper_content, encoding="utf-8")
|
||||
host_exe = _native_host_exe()
|
||||
_write_native_host_exe(host_exe)
|
||||
|
||||
# Load extension
|
||||
ext_urls = {
|
||||
@@ -346,14 +355,14 @@ def cmd_install(browser):
|
||||
manifest = {
|
||||
"name": NATIVE_HOST_NAME,
|
||||
"description": "browser-cli native messaging host",
|
||||
"path": str(wrapper_path),
|
||||
"path": str(host_exe),
|
||||
"type": "stdio",
|
||||
"allowed_origins": [f"chrome-extension://{extension_id}/"],
|
||||
}
|
||||
|
||||
installed = []
|
||||
if is_windows():
|
||||
manifest_dir = wrapper_path.parent
|
||||
manifest_dir = host_exe.parent
|
||||
manifest_dir.mkdir(parents=True, exist_ok=True)
|
||||
manifest_path = manifest_dir / f"{NATIVE_HOST_NAME}.json"
|
||||
manifest_path.write_text(json.dumps(manifest, indent=2), encoding="utf-8")
|
||||
@@ -380,10 +389,7 @@ def cmd_install(browser):
|
||||
console.print(f"[green]✓[/green] Registered native host: {p}")
|
||||
else:
|
||||
console.print(f"[green]✓[/green] Wrote native host manifest: {p}")
|
||||
console.print(f"[green]✓[/green] Installed native host script: {native_host_script_path}")
|
||||
console.print(f"[green]✓[/green] Installed native host wrapper: {wrapper_path}")
|
||||
if is_windows():
|
||||
console.print("\n[green]✓[/green] Wrote native host manifest:", manifest_path)
|
||||
console.print(f"[green]✓[/green] Installed native host: {host_exe}")
|
||||
|
||||
console.print(f"\n[bold]Step 2:[/bold] Restart {browser.capitalize()} completely (quit app, then reopen)")
|
||||
console.print("\n[green bold]✓ Installation complete![/green bold]")
|
||||
|
||||
Reference in New Issue
Block a user