diff --git a/doc/_extensions/zephyr/kconfig/__init__.py b/doc/_extensions/zephyr/kconfig/__init__.py index 13ebd0b7d01..6bf828a9088 100644 --- a/doc/_extensions/zephyr/kconfig/__init__.py +++ b/doc/_extensions/zephyr/kconfig/__init__.py @@ -233,13 +233,26 @@ class _FindKconfigSearchDirectiveVisitor(nodes.NodeVisitor): return self._found +class KconfigRegexRole(XRefRole): + """Role for creating links to Kconfig regex searches.""" + + def process_link(self, env: BuildEnvironment, refnode: nodes.Element, has_explicit_title: bool, + title: str, target: str) -> tuple[str, str]: + # render as "normal" text when explicit title is provided, literal otherwise + if has_explicit_title: + self.innernodeclass = nodes.inline + else: + self.innernodeclass = nodes.literal + return title, target + + class KconfigDomain(Domain): """Kconfig domain""" name = "kconfig" label = "Kconfig" object_types = {"option": ObjType("option", "option")} - roles = {"option": XRefRole()} + roles = {"option": XRefRole(), "option-regex": KconfigRegexRole()} directives = {"search": KconfigSearch} initial_data: dict[str, Any] = {"options": set()} @@ -259,20 +272,56 @@ class KconfigDomain(Domain): node: pending_xref, contnode: nodes.Element, ) -> nodes.Element | None: - match = [ - (docname, anchor) - for name, _, _, docname, anchor, _ in self.get_objects() - if name == target - ] - - if match: - todocname, anchor = match[0] - - return make_refnode( - builder, fromdocname, todocname, anchor, contnode, anchor - ) + if typ == "option-regex": + # Handle regex search links + search_docname = self._find_search_docname(env) + if search_docname: + # Create a reference to the search page with the regex as a fragment + ref_uri = builder.get_relative_uri(fromdocname, search_docname) + f"#!{target}" + ref_node = nodes.reference('', '', refuri=ref_uri, internal=True) + ref_node.append(contnode) + return ref_node + else: + # Fallback to plain text if no search page is found + return contnode else: - return None + # Handle regular option links + match = [ + (docname, anchor) + for name, _, _, docname, anchor, _ in self.get_objects() + if name == target + ] + + if match: + todocname, anchor = match[0] + + return make_refnode( + builder, fromdocname, todocname, anchor, contnode, anchor + ) + else: + return None + + def _find_search_docname(self, env: BuildEnvironment) -> str | None: + """Find the document containing the kconfig search directive.""" + # Cache the result to avoid repeated searches + if hasattr(env, '_kconfig_search_docname'): + return env._kconfig_search_docname + + for docname in env.all_docs: + try: + doctree = env.get_doctree(docname) + visitor = _FindKconfigSearchDirectiveVisitor(doctree) + doctree.walk(visitor) + if visitor.found_kconfig_search_directive: + env._kconfig_search_docname = docname + return docname + except Exception: + # Skip documents that can't be loaded + continue + + # No search directive found + env._kconfig_search_docname = None + return None def add_option(self, option): """Register a new Kconfig option to the domain.""" diff --git a/doc/contribute/documentation/guidelines.rst b/doc/contribute/documentation/guidelines.rst index c94d6fc0162..d0b44342185 100644 --- a/doc/contribute/documentation/guidelines.rst +++ b/doc/contribute/documentation/guidelines.rst @@ -1083,6 +1083,31 @@ Make sure to use the full name of the Kconfig option, including the ``CONFIG_`` Check out :kconfig:option:`CONFIG_GPIO` for more information. +.. rst:role:: kconfig:option-regex + + This role is used to create links to regex searches for Kconfig options. It generates a link to + the Kconfig search page with the provided regex pattern automatically filled in as the search + query. It is useful for referencing multiple Kconfig options that share a common prefix, or + belong to a common category. For example:: + + Check out :kconfig:option-regex:`CONFIG_SECURE_STORAGE_ITS_(STORE|TRANSFORM)_.*_CUSTOM` for + the various customization possibilities. + + Will render as: + + Check out :kconfig:option-regex:`CONFIG_SECURE_STORAGE_ITS_(STORE|TRANSFORM)_.*_CUSTOM` for + the various customization possibilities. + + It is encouraged to provide a custom link text to make the reference more readable. For example:: + + Check out the :kconfig:option-regex:`ITS Kconfig options ` + for more information. + + Will render as: + + Check out the :kconfig:option-regex:`ITS Kconfig options ` + for more information. + Devicetree bindings ===================