forked from Shinonome/caelestia-cli
feat: prompt installing optional components
This commit is contained in:
@@ -10,7 +10,7 @@ from caelestia.utils.dots.manifest import ComponentError, Manifest, ManifestErro
|
|||||||
from caelestia.utils.dots.packages import DEFAULT_AUR_HELPER, PackageInstaller
|
from caelestia.utils.dots.packages import DEFAULT_AUR_HELPER, PackageInstaller
|
||||||
from caelestia.utils.dots.source import DotsSource, SourceError
|
from caelestia.utils.dots.source import DotsSource, SourceError
|
||||||
from caelestia.utils.dots.state import DotsState
|
from caelestia.utils.dots.state import DotsState
|
||||||
from caelestia.utils.io import confirm, disable_input, fatal, info, log, pause, warn
|
from caelestia.utils.io import PROMPT_COLOUR, confirm, disable_input, fatal, format_msg, info, log, pause, prompt, warn
|
||||||
from caelestia.utils.paths import (
|
from caelestia.utils.paths import (
|
||||||
config_backup_dir,
|
config_backup_dir,
|
||||||
config_dir,
|
config_dir,
|
||||||
@@ -102,12 +102,14 @@ class Command:
|
|||||||
except SourceError as e:
|
except SourceError as e:
|
||||||
fatal(e)
|
fatal(e)
|
||||||
|
|
||||||
|
enable = _parse_list_arg(self.args.enable_components)
|
||||||
|
disable = _parse_list_arg(self.args.disable_components)
|
||||||
try:
|
try:
|
||||||
manifest = source.manifest_at(tip)
|
manifest = source.manifest_at(tip)
|
||||||
manifest.resolve_components(
|
manifest.resolve_components(enable=enable, disable=disable)
|
||||||
enable=_parse_list_arg(self.args.enable_components),
|
|
||||||
disable=_parse_list_arg(self.args.disable_components),
|
if enable is None and disable is None:
|
||||||
)
|
self.prompt_optional_components(manifest)
|
||||||
except (SourceError, ManifestError, ComponentError) as e:
|
except (SourceError, ManifestError, ComponentError) as e:
|
||||||
fatal(e)
|
fatal(e)
|
||||||
|
|
||||||
@@ -116,6 +118,47 @@ class Command:
|
|||||||
|
|
||||||
return source, tip, manifest
|
return source, tip, manifest
|
||||||
|
|
||||||
|
def prompt_optional_components(self, manifest: Manifest) -> None:
|
||||||
|
comp_arr = manifest.disabled_components
|
||||||
|
if not comp_arr:
|
||||||
|
return
|
||||||
|
|
||||||
|
print(format_msg(PROMPT_COLOUR, "Components to enable?"))
|
||||||
|
for i, comp in enumerate(comp_arr):
|
||||||
|
print(format_msg(PROMPT_COLOUR, f" [{i + 1}] {comp}"))
|
||||||
|
print(format_msg(PROMPT_COLOUR, "[A]ll or (1 2 3, 1-3, ^4)"))
|
||||||
|
ans = prompt("", end="").lower().strip()
|
||||||
|
|
||||||
|
def _valid_v(v: str) -> int:
|
||||||
|
try:
|
||||||
|
i_v = int(v, base=10) - 1 # -1 to translate to 0 index
|
||||||
|
except ValueError:
|
||||||
|
fatal(f'Invalid input. Given value "{v}" must be an integer.')
|
||||||
|
if i_v < 0 or i_v >= len(comp_arr):
|
||||||
|
fatal(f'Invalid input. Given value "{v}" must be between 1 and {len(comp_arr)} inclusive.')
|
||||||
|
return i_v
|
||||||
|
|
||||||
|
if ans in ("a", "all"):
|
||||||
|
manifest.resolve_components(enable=list(manifest.components))
|
||||||
|
elif ans:
|
||||||
|
enabled: list[str] = []
|
||||||
|
toks = ans.split()
|
||||||
|
for tok in toks:
|
||||||
|
fr, sep, to = tok.partition("-")
|
||||||
|
if sep:
|
||||||
|
fr = _valid_v(fr)
|
||||||
|
to = _valid_v(to)
|
||||||
|
if fr > to:
|
||||||
|
fatal(f'Invalid input. Given range "{tok}" must be lo-hi.')
|
||||||
|
enabled += comp_arr[fr : to + 1]
|
||||||
|
elif tok.startswith("^"):
|
||||||
|
t = _valid_v(tok[1:])
|
||||||
|
enabled += comp_arr[:t] + comp_arr[t + 1 :]
|
||||||
|
else:
|
||||||
|
t = _valid_v(tok)
|
||||||
|
enabled.append(comp_arr[t])
|
||||||
|
manifest.resolve_components(enable=list(set(enabled)))
|
||||||
|
|
||||||
def deploy_configs(self, source: DotsSource, manifest: Manifest) -> None:
|
def deploy_configs(self, source: DotsSource, manifest: Manifest) -> None:
|
||||||
log("Installing configs...")
|
log("Installing configs...")
|
||||||
deployer = Deployer()
|
deployer = Deployer()
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ class ManifestComponent:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class _ManifestData:
|
class _ManifestData:
|
||||||
resolved_comps: bool = False
|
|
||||||
enabled_comps: list[str] = field(default_factory=list)
|
enabled_comps: list[str] = field(default_factory=list)
|
||||||
disabled_comps: list[str] = field(default_factory=list)
|
disabled_comps: list[str] = field(default_factory=list)
|
||||||
|
|
||||||
@@ -121,9 +120,6 @@ class Manifest:
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Resolves enabled/disabled components. This MUST be called before calling any other method."""
|
"""Resolves enabled/disabled components. This MUST be called before calling any other method."""
|
||||||
|
|
||||||
if self._data.resolved_comps:
|
|
||||||
return
|
|
||||||
|
|
||||||
enable_set = set(enable or [])
|
enable_set = set(enable or [])
|
||||||
disable_set = set(disable or [])
|
disable_set = set(disable or [])
|
||||||
known = set(self.components)
|
known = set(self.components)
|
||||||
@@ -140,12 +136,13 @@ class Manifest:
|
|||||||
enabled |= enable_set
|
enabled |= enable_set
|
||||||
enabled -= disable_set
|
enabled -= disable_set
|
||||||
|
|
||||||
|
self._data.enabled_comps.clear()
|
||||||
|
self._data.disabled_comps.clear()
|
||||||
for name in self.components:
|
for name in self.components:
|
||||||
if name in enabled:
|
if name in enabled:
|
||||||
self._data.enabled_comps.append(name)
|
self._data.enabled_comps.append(name)
|
||||||
else:
|
else:
|
||||||
self._data.disabled_comps.append(name)
|
self._data.disabled_comps.append(name)
|
||||||
self._data.resolved_comps = True
|
|
||||||
|
|
||||||
def enabled_entries(self) -> list[ManifestEntry]:
|
def enabled_entries(self) -> list[ManifestEntry]:
|
||||||
"""The entries of every enabled component."""
|
"""The entries of every enabled component."""
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
import sys
|
import sys
|
||||||
from typing import Never
|
from typing import Never
|
||||||
|
|
||||||
|
LOG_COLOUR: int = 2
|
||||||
|
INFO_COLOUR: int = 0
|
||||||
|
PROMPT_COLOUR: int = 36
|
||||||
|
WARNING_COLOUR: int = 33
|
||||||
|
ERROR_COLOUR: int = 31
|
||||||
|
|
||||||
_disable_input: bool = False
|
_disable_input: bool = False
|
||||||
|
|
||||||
|
|
||||||
@@ -25,28 +31,28 @@ def log_exception(func):
|
|||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def _format_msg(colour: int, msg: str) -> str:
|
def format_msg(colour: int, msg: str) -> str:
|
||||||
return f"\033[{colour}m:: {msg}\033[0m"
|
return f"\033[{colour}m:: {msg}\033[0m"
|
||||||
|
|
||||||
|
|
||||||
def log(msg: str) -> None:
|
def log(msg: str) -> None:
|
||||||
print(_format_msg(2, msg))
|
print(format_msg(LOG_COLOUR, msg))
|
||||||
|
|
||||||
|
|
||||||
def info(msg: str) -> None:
|
def info(msg: str) -> None:
|
||||||
print(_format_msg(0, msg))
|
print(format_msg(INFO_COLOUR, msg))
|
||||||
|
|
||||||
|
|
||||||
def warn(msg: str) -> None:
|
def warn(msg: str) -> None:
|
||||||
print(_format_msg(33, f"Warning: {msg}"))
|
print(format_msg(WARNING_COLOUR, f"Warning: {msg}"))
|
||||||
|
|
||||||
|
|
||||||
def error(err: str | Exception) -> None:
|
def error(err: str | Exception) -> None:
|
||||||
print(_format_msg(31, f"Error: {err}"), file=sys.stderr)
|
print(format_msg(ERROR_COLOUR, f"Error: {err}"), file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
def fatal(err: str | Exception) -> Never:
|
def fatal(err: str | Exception) -> Never:
|
||||||
print(_format_msg(31, f"Fatal: {err}"), file=sys.stderr)
|
print(format_msg(ERROR_COLOUR, f"Fatal: {err}"), file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
@@ -62,8 +68,8 @@ def _input(prompt: str) -> str:
|
|||||||
raise KeyboardInterrupt()
|
raise KeyboardInterrupt()
|
||||||
|
|
||||||
|
|
||||||
def prompt(msg: str) -> str:
|
def prompt(msg: str, end: str = " ") -> str:
|
||||||
return _input(_format_msg(36, msg) + " ")
|
return _input(format_msg(PROMPT_COLOUR, msg) + end)
|
||||||
|
|
||||||
|
|
||||||
def confirm(msg: str, default: bool = True) -> bool:
|
def confirm(msg: str, default: bool = True) -> bool:
|
||||||
|
|||||||
Reference in New Issue
Block a user