diff --git a/cheuph/euphoria/__init__.py b/cheuph/euphoria/__init__.py index ec3bba2..5bb2313 100644 --- a/cheuph/euphoria/__init__.py +++ b/cheuph/euphoria/__init__.py @@ -3,6 +3,7 @@ from typing import List from .edit_widgets import * from .euph_config import * from .euph_renderer import * +from .launch_application import * from .room_widget import * from .single_room_application import * from .user_list_widget import * @@ -12,6 +13,7 @@ __all__: List[str] = [] __all__ += edit_widgets.__all__ __all__ += euph_config.__all__ __all__ += euph_renderer.__all__ +__all__ += launch_application.__all__ __all__ += room_widget.__all__ __all__ += single_room_application.__all__ __all__ += user_list_widget.__all__ diff --git a/cheuph/euphoria/launch_application.py b/cheuph/euphoria/launch_application.py new file mode 100644 index 0000000..45ab388 --- /dev/null +++ b/cheuph/euphoria/launch_application.py @@ -0,0 +1,96 @@ +import argparse +import asyncio +import logging +import pathlib +from typing import Any, Callable, Optional + +import urwid +import yaml + +from .euph_config import EuphConfig, EuphLoader + +__all__ = ["DEFAULT_CONFIG_PATHS", "launch"] + +DEFAULT_CONFIG_PATHS = [ + "~/.config/cheuph/cheuph.yaml", + "~/.cheuph/cheuph.yaml", + "~/.cheuph.yaml", +] + +GITHUB_URL = "https://github.com/Garmelon/cheuph" + +def parse_arguments() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="A terminal-based client for euphoria.io", + epilog=f"For more information, see {GITHUB_URL}", + ) + parser.add_argument("-e", "--export-defaults", type=str) + parser.add_argument("-c", "--config-file", type=str) + return parser.parse_args() + +def load_config_yaml(args: argparse.Namespace) -> Optional[str]: + path = None # TODO get from args + if path is None: + paths = DEFAULT_CONFIG_PATHS + else: + paths = [path] + + for raw_path in paths: + path = pathlib.Path(raw_path).expanduser() + try: + with open(path) as f: + return yaml.load(f.read(), Loader=yaml.SafeLoader) + except FileNotFoundError: + print(f"Could not load config from {path}") + + print("Could not find a config file. Using default settings.") + input("Press enter to continue") # TODO use better prompt? + return None + +def load_config(args: Any) -> EuphConfig: + loader = EuphLoader() + defaults = loader.defaults() + config = EuphConfig(defaults) + + config_yaml = load_config_yaml(args) or {} + loader.load_to(config, config_yaml) + + return config + +def export_defaults(path: str) -> None: + path = pathlib.Path(path).expanduser() + print(f"Exporting default config to {path}") + + loader = EuphLoader() + defaults = loader.export(loader.defaults()) + dumped = yaml.dump( + defaults, + Dumper=yaml.SafeDumper, + allow_unicode=True, + ) + + with open(path, "w") as f: + f.write(dumped) + +def launch( + application: Callable[[EuphConfig], urwid.Widget], + ) -> None: + + logging.disable(logging.CRITICAL) + + args = parse_arguments() + + if args.export_defaults is not None: + export_defaults(args.export_defaults) + return + + config = load_config(args) + loop = asyncio.get_event_loop() + + main_loop = urwid.MainLoop( + application(config), + event_loop=urwid.AsyncioEventLoop(loop=loop), + palette=config.palette, + ) + + main_loop.run() diff --git a/cheuph/euphoria/single_room_application.py b/cheuph/euphoria/single_room_application.py index 59c9112..2cb4ae9 100644 --- a/cheuph/euphoria/single_room_application.py +++ b/cheuph/euphoria/single_room_application.py @@ -9,6 +9,7 @@ import yaml from ..attributed_text_widget import ATWidget from ..markup import AT, Attributes from .edit_widgets import EditWidget +from .launch_application import launch from .euph_config import EuphConfig, EuphLoader from .room_widget import RoomWidget @@ -129,31 +130,5 @@ class SingleRoomApplication(urwid.WidgetWrap): return key -def run_single_room_application(config_file: Path) -> None: - logging.disable() - - config_yaml: Any - try: - with open(config_file) as f: - config_yaml = yaml.load(f.read(), Loader=yaml.SafeLoader) - except FileNotFoundError: - config_yaml = {} - - loader = EuphLoader() - defaults = loader.defaults() - config = EuphConfig(defaults) - loader.load_to(config, config_yaml) - - loop = asyncio.get_event_loop() - - main_loop = urwid.MainLoop( - SingleRoomApplication(config), - event_loop=urwid.AsyncioEventLoop(loop=loop), - palette=config.palette, - ) - - main_loop.run() - if __name__ == "__main__": - config_path = Path("~/.cheuph.conf").expanduser() - run_single_room_application(config_path) + launch(SingleRoomApplication)