From 278f624cd8594b7f15d1db713baa5c7b5a65b80b Mon Sep 17 00:00:00 2001 From: Shengyu Zhang Date: Wed, 9 Oct 2024 20:24:54 +0800 Subject: [PATCH] feat: Record document dependent files (#32) --- src/sphinxnotes/snippet/__init__.py | 14 +++++++++- src/sphinxnotes/snippet/cli.py | 42 +++++++++++++++++++++++------ src/sphinxnotes/snippet/picker.py | 2 +- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/sphinxnotes/snippet/__init__.py b/src/sphinxnotes/snippet/__init__.py index 042d354..0a6c945 100644 --- a/src/sphinxnotes/snippet/__init__.py +++ b/src/sphinxnotes/snippet/__init__.py @@ -9,6 +9,7 @@ from __future__ import annotations from typing import List, Tuple, Optional, TYPE_CHECKING import itertools +from os import path from docutils import nodes @@ -29,7 +30,7 @@ class Snippet(object): # :rst:role:`doc`. docname: str - #: Source file path of snippet + #: Absolute path of the source file. file: str #: Line number range of snippet, in the source file which is left closed @@ -136,10 +137,21 @@ def __init__(self, node: nodes.section) -> None: class Document(Section): + #: A set of absolute paths of dependent files for document. + #: Obtained from :attr:`BuildEnvironment.dependencies`. + deps: set[str] + def __init__(self, node: nodes.document) -> None: assert isinstance(node, nodes.document) super().__init__(node.next_node(nodes.section)) + # Record document's dependent files + self.deps = set() + env: BuildEnvironment = node.settings.env + for dep in env.dependencies[self.docname]: + # Relative to documentation root -> Absolute path of file system. + self.deps.add(path.join(env.srcdir, dep)) + ################ # Nodes helper # diff --git a/src/sphinxnotes/snippet/cli.py b/src/sphinxnotes/snippet/cli.py index ee9f741..9e3d81f 100644 --- a/src/sphinxnotes/snippet/cli.py +++ b/src/sphinxnotes/snippet/cli.py @@ -18,7 +18,7 @@ from xdg.BaseDirectory import xdg_config_home from sphinx.util.matching import patmatch -from . import __version__ +from . import __version__, Document from .config import Config from .cache import Cache, IndexID, Index from .table import tablify, COLUMNS @@ -114,6 +114,9 @@ def main(argv: List[str] = sys.argv[1:]): getparser.add_argument( '--file', '-f', action='store_true', help='get source file path of snippet' ) + getparser.add_argument( + '--deps', action='store_true', help='get dependent files of document' + ) getparser.add_argument( '--line-start', action='store_true', @@ -234,17 +237,36 @@ def _on_command_list(args: argparse.Namespace): def _on_command_get(args: argparse.Namespace): + # Wrapper for warning when nothing is printed + printed = False + + def p(*args, **opts): + nonlocal printed + printed = True + print(*args, **opts) + for index_id in args.index_id: item = args.cache.get_by_index_id(index_id) if not item: - print('no such index ID', file=sys.stderr) + p('no such index ID', file=sys.stderr) sys.exit(1) if args.text: - print('\n'.join(item.snippet.rst)) + p('\n'.join(item.snippet.rst)) if args.docname: - print(item.snippet.docname) + p(item.snippet.docname) if args.file: - print(item.snippet.file) + p(item.snippet.file) + if args.deps: + if not isinstance(item.snippet, Document): + print( + f'{type(item.snippet)} ({index_id}) is not a document', + file=sys.stderr, + ) + sys.exit(1) + if len(item.snippet.deps) == 0: + p('') # prevent print nothing warning + for dep in item.snippet.deps: + p(dep) if args.url: # HACK: get doc id in better way doc_id, _ = args.cache.index_id_to_doc_id.get(index_id) @@ -258,11 +280,15 @@ def _on_command_get(args: argparse.Namespace): url = posixpath.join(base_url, doc_id[1] + '.html') if item.snippet.refid: url += '#' + item.snippet.refid - print(url) + p(url) if args.line_start: - print(item.snippet.lineno[0]) + p(item.snippet.lineno[0]) if args.line_end: - print(item.snippet.lineno[1]) + p(item.snippet.lineno[1]) + + if not printed: + print('please specify at least one argument', file=sys.stderr) + sys.exit(1) def _on_command_integration(args: argparse.Namespace): diff --git a/src/sphinxnotes/snippet/picker.py b/src/sphinxnotes/snippet/picker.py index 9b2ac2a..d7e7383 100644 --- a/src/sphinxnotes/snippet/picker.py +++ b/src/sphinxnotes/snippet/picker.py @@ -40,7 +40,7 @@ def pick( logger.debug('Skipped document with nosearch metadata') return [] - snippets = [] + snippets: list[tuple[Snippet, nodes.section]] = [] # Pick document toplevel_section = doctree.next_node(nodes.section)