fix(external_editor): cache auto-detect result, avoid hitting registry on every UI frame

This commit is contained in:
2026-05-07 21:00:41 -04:00
parent 93f6bcbd67
commit ca4719687a
6 changed files with 117 additions and 15 deletions
+80 -1
View File
@@ -46,6 +46,75 @@ class ExternalEditorLauncher:
return None
_cached_vscode_config: Optional[TextEditorConfig] = None
def auto_detect_vscode() -> Optional[TextEditorConfig]:
global _cached_vscode_config
if _cached_vscode_config is not None:
return _cached_vscode_config
vscode_path = _find_vscode_in_registry() or _find_vscode_common_paths()
if vscode_path:
_cached_vscode_config = TextEditorConfig(
name="vscode",
path=vscode_path,
diff_args=["--new-window", "--diff"]
)
return _cached_vscode_config
def get_default_launcher() -> ExternalEditorLauncher:
import subprocess
paths = []
reg_keys = [
r"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
r"HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
r"HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
]
for key in reg_keys:
try:
result = subprocess.run(
["powershell", "-Command", f"Get-ItemProperty -Path '{key}' -ErrorAction SilentlyContinue | Where-Object {{ $_.DisplayName -like '*Visual Studio Code*' }} | Select-Object -ExpandProperty InstallLocation"],
capture_output=True, text=True, timeout=5
)
for line in result.stdout.strip().split('\n'):
line = line.strip()
if line and line != "":
exe_path = line.strip() + "\\Code.exe"
if subprocess.run(["test", "-f", exe_path], check=False).returncode == 0:
paths.append(exe_path)
except Exception:
pass
if paths:
return paths[0]
return None
def _find_vscode_common_paths() -> Optional[str]:
import os
candidates = [
r"C:\apps\Microsoft VS Code\Code.exe",
r"C:\Program Files\Microsoft VS Code\Code.exe",
r"C:\Program Files (x86)\Microsoft VS Code\Code.exe",
os.path.expanduser(r"~\AppData\Local\Programs\Microsoft VS Code\Code.exe"),
]
for path in candidates:
if os.path.exists(path):
return path
return None
def auto_detect_vscode() -> Optional[TextEditorConfig]:
vscode_path = _find_vscode_in_registry() or _find_vscode_common_paths()
if vscode_path:
return TextEditorConfig(
name="vscode",
path=vscode_path,
diff_args=["--new-window", "--diff"]
)
return None
def get_default_launcher() -> ExternalEditorLauncher:
from src import models
config = models.load_config()
@@ -55,7 +124,17 @@ def get_default_launcher() -> ExternalEditorLauncher:
"editors": editors_config,
"default_editor": default_editor,
})
return ExternalEditorLauncher(ext_config)
launcher = ExternalEditorLauncher(ext_config)
detected = auto_detect_vscode()
if detected:
if not launcher.config.editors:
launcher.config.editors["vscode"] = detected
launcher.config.default_editor = "vscode"
else:
vscode = launcher.config.editors.get("vscode")
if vscode and "--new-window" not in vscode.diff_args:
vscode.diff_args = ["--new-window", "--diff"]
return launcher
def resolve_project_editor_override(project_path: Optional[str]) -> Optional[str]: