Coverage for src/prosemark/cli/materialize.py: 100%

37 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-09-24 18:08 +0000

1"""CLI command for materializing placeholders.""" 

2 

3from pathlib import Path 

4 

5import click 

6 

7from prosemark.adapters.binder_repo_fs import BinderRepoFs 

8from prosemark.adapters.clock_system import ClockSystem 

9from prosemark.adapters.editor_launcher_system import EditorLauncherSystem 

10from prosemark.adapters.id_generator_uuid7 import IdGeneratorUuid7 

11from prosemark.adapters.logger_stdout import LoggerStdout 

12from prosemark.adapters.node_repo_fs import NodeRepoFs 

13from prosemark.app.use_cases import MaterializeNode 

14from prosemark.exceptions import AlreadyMaterializedError, FileSystemError, PlaceholderNotFoundError 

15 

16 

17@click.command() 

18@click.argument('title') 

19@click.option('--parent', '_parent', help='Parent node ID to search within') 

20@click.option('--path', '-p', type=click.Path(path_type=Path), help='Project directory') 

21def materialize_command(title: str, _parent: str | None, path: Path | None) -> None: 

22 """Convert a placeholder to an actual node.""" 

23 try: 

24 project_root = path or Path.cwd() 

25 

26 # Wire up dependencies 

27 binder_repo = BinderRepoFs(project_root) 

28 clock = ClockSystem() 

29 editor = EditorLauncherSystem() 

30 node_repo = NodeRepoFs(project_root, editor, clock) 

31 id_generator = IdGeneratorUuid7() 

32 logger = LoggerStdout() 

33 

34 # Execute use case 

35 interactor = MaterializeNode( 

36 binder_repo=binder_repo, 

37 node_repo=node_repo, 

38 id_generator=id_generator, 

39 logger=logger, 

40 ) 

41 

42 node_id = interactor.execute(display_title=title, synopsis=None) 

43 

44 # Success output 

45 click.echo(f'Materialized "{title}" ({node_id})') 

46 click.echo(f'Created files: {node_id}.md, {node_id}.notes.md') 

47 click.echo('Updated binder structure') 

48 

49 except PlaceholderNotFoundError: 

50 click.echo('Error: Placeholder not found', err=True) 

51 raise SystemExit(1) from None 

52 except AlreadyMaterializedError: 

53 click.echo(f"Error: '{title}' is already materialized", err=True) 

54 raise SystemExit(1) from None 

55 except FileSystemError: 

56 click.echo('Error: File creation failed', err=True) 

57 raise SystemExit(2) from None