scheme: add --json flag to list-presets, --accent flag, drop :accent from preset spec
- list-presets --json outputs structured JSON with variants, modes, accents, and default_accent for accent-aware schemes - --accent flag replaces :accent shorthand in preset string - Validate --accent against variant's available accents - resolve_preset returns tuple[str, str] (scheme + variant only) - Update tests for new signature
This commit is contained in:
@@ -21,18 +21,36 @@ app = typer.Typer()
|
|||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
def list_presets():
|
def list_presets(
|
||||||
|
json_format: bool = typer.Option(False, "--json", help="Output in JSON format"),
|
||||||
|
):
|
||||||
schemes = list_schemes()
|
schemes = list_schemes()
|
||||||
for sid, meta in sorted(schemes.items()):
|
if json_format:
|
||||||
var_list = []
|
out = {}
|
||||||
for v in meta.variants:
|
for sid, meta in sorted(schemes.items()):
|
||||||
parts = [f"{v.id} ({', '.join(sorted(v.modes))})"]
|
variants = {}
|
||||||
if v.accents:
|
for v in meta.variants:
|
||||||
parts.append(f"accents: {', '.join(v.accents)}")
|
entry = {"modes": sorted(v.modes)}
|
||||||
var_list.append(" | ".join(parts))
|
if v.accents:
|
||||||
print(f"{meta.name} ({sid})")
|
entry["accents"] = sorted(v.accents)
|
||||||
print(f" Variants: {', '.join(var_list)}")
|
entry["default_accent"] = sorted(v.accents)[0]
|
||||||
print()
|
variants[v.id] = entry
|
||||||
|
out[meta.name] = {
|
||||||
|
"id": sid,
|
||||||
|
"variants": variants,
|
||||||
|
}
|
||||||
|
print(json.dumps({"presets": out}, indent=2))
|
||||||
|
else:
|
||||||
|
for sid, meta in sorted(schemes.items()):
|
||||||
|
var_list = []
|
||||||
|
for v in meta.variants:
|
||||||
|
parts = [f"{v.id} ({', '.join(sorted(v.modes))})"]
|
||||||
|
if v.accents:
|
||||||
|
parts.append(f"accents: {', '.join(v.accents)}")
|
||||||
|
var_list.append(" | ".join(parts))
|
||||||
|
print(f"{meta.name} ({sid})")
|
||||||
|
print(f" Variants: {', '.join(var_list)}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
@@ -41,10 +59,9 @@ def generate(
|
|||||||
scheme: Optional[str] = typer.Option(
|
scheme: Optional[str] = typer.Option(
|
||||||
None, help="Color scheme algorithm to use for image mode. Ignored in preset mode."
|
None, help="Color scheme algorithm to use for image mode. Ignored in preset mode."
|
||||||
),
|
),
|
||||||
preset: Optional[str] = typer.Option(
|
preset: Optional[str] = typer.Option(None, help="Name of a premade scheme in this format: <scheme>:<variant>"),
|
||||||
None, help="Name of a premade scheme in this format: <scheme>:<variant>[:<accent>]"
|
|
||||||
),
|
|
||||||
mode: Optional[str] = typer.Option(None, help="Mode of the preset scheme (dark or light)."),
|
mode: Optional[str] = typer.Option(None, help="Mode of the preset scheme (dark or light)."),
|
||||||
|
accent: Optional[str] = typer.Option(None, help="Accent for schemes that support it (e.g. mauve)."),
|
||||||
):
|
):
|
||||||
|
|
||||||
HOME = str(os.getenv("HOME"))
|
HOME = str(os.getenv("HOME"))
|
||||||
@@ -473,8 +490,17 @@ def generate(
|
|||||||
scheme_class = get_scheme_class(scheme)
|
scheme_class = get_scheme_class(scheme)
|
||||||
|
|
||||||
if preset:
|
if preset:
|
||||||
p_scheme, p_variant, p_accent = resolve_preset(preset)
|
p_scheme, p_variant = resolve_preset(preset)
|
||||||
palette_obj = get_palette(p_scheme, p_variant, mode or config_mode, accent=p_accent)
|
schemes = list_schemes()
|
||||||
|
if accent and p_scheme in schemes:
|
||||||
|
meta = schemes[p_scheme]
|
||||||
|
var_accents = next((v.accents for v in meta.variants if v.id == p_variant), ())
|
||||||
|
if accent not in var_accents:
|
||||||
|
available = ", ".join(var_accents) if var_accents else "none"
|
||||||
|
raise typer.BadParameter(
|
||||||
|
f"Accent '{accent}' not available for '{p_scheme}:{p_variant}'. Available accents: {available}"
|
||||||
|
)
|
||||||
|
palette_obj = get_palette(p_scheme, p_variant, mode or config_mode, accent=accent)
|
||||||
colors = palette_obj.colors
|
colors = palette_obj.colors
|
||||||
effective_mode = palette_obj.mode
|
effective_mode = palette_obj.mode
|
||||||
name = palette_obj.scheme
|
name = palette_obj.scheme
|
||||||
|
|||||||
@@ -132,12 +132,10 @@ def list_schemes() -> dict[str, SchemeMeta]:
|
|||||||
return dict(SCHEMES)
|
return dict(SCHEMES)
|
||||||
|
|
||||||
|
|
||||||
def resolve_preset(spec: str) -> tuple[str, str, str | None]:
|
def resolve_preset(spec: str) -> tuple[str, str]:
|
||||||
parts = spec.split(":")
|
parts = spec.split(":")
|
||||||
if len(parts) == 3:
|
|
||||||
return parts[0], parts[1], parts[2]
|
|
||||||
if len(parts) == 2:
|
if len(parts) == 2:
|
||||||
return parts[0], parts[1], None
|
return parts[0], parts[1]
|
||||||
if len(parts) == 1:
|
if len(parts) == 1:
|
||||||
return parts[0], "default", None
|
return parts[0], "default"
|
||||||
raise ValueError(f"Invalid preset spec '{spec}'. Use <scheme>:<variant>[:<accent>]")
|
raise ValueError(f"Invalid preset spec '{spec}'. Use <scheme>:<variant>")
|
||||||
|
|||||||
@@ -154,13 +154,14 @@ class TestListSchemes:
|
|||||||
|
|
||||||
class TestResolvePreset:
|
class TestResolvePreset:
|
||||||
def test_two_parts(self):
|
def test_two_parts(self):
|
||||||
assert sp.resolve_preset("gruvbox:medium") == ("gruvbox", "medium", None)
|
assert sp.resolve_preset("gruvbox:medium") == ("gruvbox", "medium")
|
||||||
|
|
||||||
def test_three_parts(self):
|
def test_three_parts(self):
|
||||||
assert sp.resolve_preset("catppuccin:mocha:mauve") == ("catppuccin", "mocha", "mauve")
|
with pytest.raises(ValueError, match="Invalid preset spec"):
|
||||||
|
sp.resolve_preset("catppuccin:mocha:mauve")
|
||||||
|
|
||||||
def test_one_part(self):
|
def test_one_part(self):
|
||||||
assert sp.resolve_preset("default") == ("default", "default", None)
|
assert sp.resolve_preset("default") == ("default", "default")
|
||||||
|
|
||||||
def test_edge_spaces(self):
|
def test_edge_spaces(self):
|
||||||
assert sp.resolve_preset(" catppuccin : mocha : mauve ") == (" catppuccin ", " mocha ", " mauve ")
|
assert sp.resolve_preset(" catppuccin : mocha ") == (" catppuccin ", " mocha ")
|
||||||
|
|||||||
Reference in New Issue
Block a user