diff --git a/bec_widgets/utils/bec_plugin_manager/create/widget.py b/bec_widgets/utils/bec_plugin_manager/create/widget.py index cfb5f8f7..8af4bb02 100644 --- a/bec_widgets/utils/bec_plugin_manager/create/widget.py +++ b/bec_widgets/utils/bec_plugin_manager/create/widget.py @@ -32,24 +32,27 @@ def _editor_cb(ctx: typer.Context, value: bool): return value +_bold_blue = "\033[34m\033[1m" +_off = "\033[0m" +_USE_UI_MSG = "Generate a .ui file for use in bec-designer." +_OPEN_DESIGNER_MSG = f"""This app can watch for changes and recompile them to a python file imported to the widget whenever it is saved. +To open this editor independently, you can use {_bold_blue}bec-plugin-manager edit-ui [widget_name]{_off}. +Open the created widget .ui file in bec-designer now?""" + + @_app.command() def widget( name: Annotated[str, typer.Argument(help="Enter a name for your widget in snake_case")], - use_ui: Annotated[ - bool, typer.Option(prompt=True, help="Generate a .ui file for use in bec-designer.") - ] = True, + use_ui: Annotated[bool, typer.Option(prompt=_USE_UI_MSG, help=_USE_UI_MSG)] = True, open_editor: Annotated[ - bool, - typer.Option( - prompt=True, help="Open the created widget in bec-designer.", callback=_editor_cb - ), + bool, typer.Option(prompt=_OPEN_DESIGNER_MSG, help=_OPEN_DESIGNER_MSG, callback=_editor_cb) ] = True, ): """Create a new widget plugin with the given name. If [bold white]use_ui[/bold white] is set, a bec-designer .ui file will also be created. If \ [bold white]open_editor[/bold white] is additionally set, the .ui file will be opened in \ -bec-designer and the compiled python version will be updated when changes are made.""" +bec-designer and the compiled python version will be updated when changes are made and saved.""" if (formatted_name := name.lower().replace("-", "_")) != name: logger.warning(f"Adjusting widget name from {name} to {formatted_name}") if not formatted_name.isidentifier(): diff --git a/bec_widgets/utils/bec_plugin_manager/edit_ui.py b/bec_widgets/utils/bec_plugin_manager/edit_ui.py index 384fb1ee..54f444b0 100644 --- a/bec_widgets/utils/bec_plugin_manager/edit_ui.py +++ b/bec_widgets/utils/bec_plugin_manager/edit_ui.py @@ -55,10 +55,42 @@ class RecompileHandler(FileSystemEventHandler): ["pyside6-uic", "--absolute-imports", self.in_file, "-o", self.out_file] ) logger.success(f"compilation exited with code {code}") - if code == 0: - logger.success("updating imports...") - self._update_imports() - logger.success("done!") + if code != 0: + return + self._add_comment_to_file() + logger.success("updating imports...") + self._update_imports() + logger.success("formatting...") + code = subprocess.call( + ["black", "--line-length=100", "--skip-magic-trailing-comma", self.out_file] + ) + if code != 0: + logger.error(f"Error while running black on {self.out_file}, code: {code}") + return + code = subprocess.call( + [ + "isort", + "--line-length=100", + "--profile=black", + "--multi-line=3", + "--trailing-comma", + self.out_file, + ] + ) + if code != 0: + logger.error(f"Error while running isort on {self.out_file}, code: {code}") + return + logger.success("done!") + + def _add_comment_to_file(self): + with open(self.out_file, "r+") as f: + initial = f.read() + f.seek(0) + f.write(f"# Generated from {self.in_file} by bec-plugin-manager - do not edit! \n") + f.write( + "# Use 'bec-plugin-manager edit-ui [widget_name]' to make changes, and this file will be updated accordingly. \n\n" + ) + f.write(initial) def _update_imports(self): with open(self.out_file, "r+") as f: @@ -83,11 +115,15 @@ class RecompileHandler(FileSystemEventHandler): def open_and_watch_ui_editor(widget_name: str): - logger.info(f"Opening the editor for {widget_name}... ") + logger.info(f"Opening the editor for {widget_name}, and watching") repo = Path(plugin_repo_path()) widget_dir = repo / repo.name / "bec_widgets" / "widgets" / widget_name ui_file = widget_dir / f"{widget_name}.ui" ui_outfile = widget_dir / f"{widget_name}_ui.py" + + logger.info( + f"Opening the editor for {widget_name}, and watching {ui_file} for changes. Whenever you save the file, it will be recompiled to {ui_outfile}" + ) recompile_handler = RecompileHandler(ui_file, ui_outfile) observer = Observer() observer.schedule(recompile_handler, str(ui_file.parent))