mirror of
https://github.com/NCBM/plyngent.git
synced 2026-07-23 05:55:16 +08:00
core/cli: config open via VISUAL/EDITOR or system default
Prefer $VISUAL then $EDITOR (blocking). Without either, fall back to xdg-open / open / startfile (non-blocking) for config paths only. /edit stays blocking-only so the temp buffer can be re-read.
This commit is contained in:
@@ -15,10 +15,13 @@ from plyngent.cli.editor import (
|
||||
)
|
||||
|
||||
|
||||
def test_get_editor(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_get_editor_prefers_visual(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.delenv("EDITOR", raising=False)
|
||||
monkeypatch.delenv("VISUAL", raising=False)
|
||||
assert get_editor() is None
|
||||
monkeypatch.setenv("EDITOR", " codium --wait ")
|
||||
monkeypatch.setenv("EDITOR", " nano ")
|
||||
assert get_editor() == "nano"
|
||||
monkeypatch.setenv("VISUAL", " codium --wait ")
|
||||
assert get_editor() == "codium --wait"
|
||||
|
||||
|
||||
@@ -49,7 +52,8 @@ def test_open_in_editor_splits_args(tmp_path: Path, monkeypatch: pytest.MonkeyPa
|
||||
return Result()
|
||||
|
||||
monkeypatch.setattr("plyngent.cli.editor.subprocess.run", fake_run)
|
||||
open_in_editor(path, editor="codium --wait")
|
||||
outcome = open_in_editor(path, editor="codium --wait")
|
||||
assert outcome == "waited"
|
||||
assert len(calls) == 1
|
||||
assert calls[0][0] == "codium"
|
||||
assert calls[0][1] == "--wait"
|
||||
@@ -57,10 +61,33 @@ def test_open_in_editor_splits_args(tmp_path: Path, monkeypatch: pytest.MonkeyPa
|
||||
assert path.is_file()
|
||||
|
||||
|
||||
def test_open_in_editor_missing_editor(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_open_in_editor_system_fallback(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
monkeypatch.delenv("EDITOR", raising=False)
|
||||
with pytest.raises(Exception, match="EDITOR"):
|
||||
open_in_editor(tmp_path / "x.toml", editor=None)
|
||||
monkeypatch.delenv("VISUAL", raising=False)
|
||||
path = tmp_path / "x.toml"
|
||||
opened: list[str] = []
|
||||
|
||||
def fake_system(p: Path) -> None:
|
||||
opened.append(str(p))
|
||||
|
||||
monkeypatch.setattr("plyngent.cli.editor._open_with_system_default", fake_system)
|
||||
outcome = open_in_editor(path, editor=None, allow_system_open=True)
|
||||
assert outcome == "system"
|
||||
assert opened == [str(path)]
|
||||
assert path.is_file()
|
||||
|
||||
|
||||
def test_open_in_editor_no_fallback_requires_editor(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
monkeypatch.delenv("EDITOR", raising=False)
|
||||
monkeypatch.delenv("VISUAL", raising=False)
|
||||
with pytest.raises(Exception, match=r"VISUAL|EDITOR"):
|
||||
open_in_editor(tmp_path / "x.toml", editor=None, allow_system_open=False)
|
||||
|
||||
|
||||
def test_edit_text_in_editor(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
@@ -99,9 +126,13 @@ def test_edit_text_empty_cancels(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
assert edit_text_in_editor("") is None
|
||||
|
||||
|
||||
def test_prompt_edit_no_editor(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
def test_edit_text_no_system_fallback(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
from plyngent.cli.editor import edit_text_in_editor
|
||||
|
||||
monkeypatch.delenv("EDITOR", raising=False)
|
||||
assert prompt_edit_config(tmp_path / "p.toml") is False
|
||||
monkeypatch.delenv("VISUAL", raising=False)
|
||||
with pytest.raises(Exception, match=r"VISUAL|EDITOR"):
|
||||
edit_text_in_editor("x")
|
||||
|
||||
|
||||
def test_prompt_edit_declined(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
@@ -111,7 +142,7 @@ def test_prompt_edit_declined(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -
|
||||
return False
|
||||
|
||||
monkeypatch.setattr("click.confirm", _confirm)
|
||||
assert prompt_edit_config(tmp_path / "p.toml", reason="empty") is False
|
||||
assert prompt_edit_config(tmp_path / "p.toml", reason="empty") is None
|
||||
|
||||
|
||||
def test_prompt_edit_accepted(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
@@ -124,15 +155,40 @@ def test_prompt_edit_accepted(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -
|
||||
monkeypatch.setattr("click.confirm", _confirm)
|
||||
opened: list[Path] = []
|
||||
|
||||
def fake_open(p: Path, *, editor: str | None = None) -> None:
|
||||
del editor
|
||||
def fake_open(
|
||||
p: Path,
|
||||
*,
|
||||
editor: str | None = None,
|
||||
ensure_exists: bool = True,
|
||||
allow_system_open: bool = True,
|
||||
) -> str:
|
||||
del editor, ensure_exists, allow_system_open
|
||||
opened.append(p)
|
||||
return "waited"
|
||||
|
||||
monkeypatch.setattr("plyngent.cli.editor.open_in_editor", fake_open)
|
||||
assert prompt_edit_config(path, reason="No providers.") is True
|
||||
assert prompt_edit_config(path, reason="No providers.") == "waited"
|
||||
assert opened == [path]
|
||||
|
||||
|
||||
def test_prompt_edit_without_editor_can_system_open(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
monkeypatch.delenv("EDITOR", raising=False)
|
||||
monkeypatch.delenv("VISUAL", raising=False)
|
||||
|
||||
def _confirm(*_a: object, **_k: object) -> bool:
|
||||
return True
|
||||
|
||||
monkeypatch.setattr("click.confirm", _confirm)
|
||||
monkeypatch.setattr(
|
||||
"plyngent.cli.editor.open_in_editor",
|
||||
lambda *a, **k: "system",
|
||||
)
|
||||
assert prompt_edit_config(tmp_path / "p.toml") == "system"
|
||||
|
||||
|
||||
def test_config_path_command(tmp_path: Path) -> None:
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, ["config", "path", "--config", str(tmp_path / "a.toml")])
|
||||
@@ -159,3 +215,21 @@ def test_config_edit_command(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) ->
|
||||
result = runner.invoke(main, ["config", "edit", "--config", str(path)])
|
||||
assert result.exit_code == 0
|
||||
assert calls and calls[0][-1] == str(path)
|
||||
assert "edited" in result.output
|
||||
|
||||
|
||||
def test_config_edit_system_fallback_message(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
path = tmp_path / "edit.toml"
|
||||
monkeypatch.delenv("EDITOR", raising=False)
|
||||
monkeypatch.delenv("VISUAL", raising=False)
|
||||
monkeypatch.setattr(
|
||||
"plyngent.cli.editor._open_with_system_default",
|
||||
lambda p: None,
|
||||
)
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(main, ["config", "edit", "--config", str(path)])
|
||||
assert result.exit_code == 0
|
||||
assert "system default" in result.output.lower() or "system default" in (result.stderr or "").lower()
|
||||
|
||||
Reference in New Issue
Block a user