|
1 | 1 | import click
|
2 | 2 | import contextlib
|
3 | 3 | import os
|
| 4 | +import time |
4 | 5 | import sphobjinv as soi
|
5 | 6 | import yaml
|
6 |
| - |
| 7 | +import importlib |
7 | 8 | from pathlib import Path
|
8 |
| - |
| 9 | +from watchdog.observers import Observer |
| 10 | +from functools import partial |
| 11 | +from watchdog.events import FileSystemEventHandler |
9 | 12 | from quartodoc import Builder, convert_inventory
|
10 | 13 |
|
| 14 | +def get_package_path(package_name): |
| 15 | + """ |
| 16 | + Get the path to a package installed in the current environment. |
| 17 | + """ |
| 18 | + try: |
| 19 | + lib = importlib.import_module(package_name) |
| 20 | + return lib.__path__[0] |
| 21 | + except ModuleNotFoundError: |
| 22 | + raise ModuleNotFoundError(f"Package {package_name} not found. Please install it in your environment.") |
| 23 | + |
| 24 | +class FileChangeHandler(FileSystemEventHandler): |
| 25 | + """ |
| 26 | + A handler for file changes. |
| 27 | + """ |
| 28 | + def __init__(self, callback): |
| 29 | + self.callback = callback |
| 30 | + |
| 31 | + @classmethod |
| 32 | + def print_event(cls, event): |
| 33 | + print(f'Rebuilding docs. Detected: {event.event_type} path : {event.src_path}') |
| 34 | + |
| 35 | + def on_modified(self, event): |
| 36 | + self.print_event(event) |
| 37 | + self.callback() |
| 38 | + |
| 39 | + def on_created(self, event): |
| 40 | + self.print_event(event) |
| 41 | + self.callback() |
11 | 42 |
|
12 | 43 | def _enable_logs():
|
13 | 44 | import logging
|
@@ -40,24 +71,44 @@ def cli():
|
40 | 71 | pass
|
41 | 72 |
|
42 | 73 |
|
| 74 | + |
| 75 | + |
| 76 | + |
43 | 77 | @click.command()
|
44 |
| -@click.argument("config", default="_quarto.yml") |
45 |
| -@click.option("--filter", nargs=1, default="*") |
46 |
| -@click.option("--dry-run", is_flag=True, default=False) |
47 |
| -@click.option("--verbose", is_flag=True, default=False) |
48 |
| -def build(config, filter, dry_run, verbose): |
| 78 | +@click.option("--config", default="_quarto.yml", help="Change the path to the configuration file. The default is `./_quarto.yml`") |
| 79 | +@click.option("--filter", nargs=1, default="*", help="Specify the filter to select specific files. The default is '*' which selects all files.") |
| 80 | +@click.option("--dry-run", is_flag=True, default=False, help="If set, prevents new documents from being generated.") |
| 81 | +@click.option("--watch", is_flag=True, default=False, help="If set, the command will keep running and watch for changes in the package directory.") |
| 82 | +@click.option("--verbose", is_flag=True, default=False, help="Enable verbose logging.") |
| 83 | +def build(config, filter, dry_run, watch, verbose): |
| 84 | + """ |
| 85 | + Generate API docs based on the given configuration file (`./_quarto.yml` by default). |
| 86 | + """ |
49 | 87 | if verbose:
|
50 | 88 | _enable_logs()
|
51 | 89 |
|
52 | 90 | builder = Builder.from_quarto_config(config)
|
| 91 | + doc_build = partial(builder.build, filter=filter) |
53 | 92 |
|
54 | 93 | if dry_run:
|
55 |
| - # click.echo(builder.render_index()) |
56 | 94 | pass
|
57 | 95 | else:
|
58 | 96 | with chdir(Path(config).parent):
|
59 |
| - builder.build(filter=filter) |
60 |
| - |
| 97 | + if watch: |
| 98 | + pkg_path = get_package_path(builder.package) |
| 99 | + print(f"Watching {pkg_path} for changes...") |
| 100 | + event_handler = FileChangeHandler(callback=doc_build) |
| 101 | + observer = Observer() |
| 102 | + observer.schedule(event_handler, pkg_path, recursive=True) |
| 103 | + observer.start() |
| 104 | + try: |
| 105 | + while True: |
| 106 | + time.sleep(1) |
| 107 | + except KeyboardInterrupt: |
| 108 | + observer.stop() |
| 109 | + observer.join() |
| 110 | + else: |
| 111 | + doc_build() |
61 | 112 |
|
62 | 113 | @click.command()
|
63 | 114 | @click.argument("config", default="_quarto.yml")
|
|
0 commit comments