From e19975e1f8069e6500d0b05ed1a0e8ecdf0b7e01 Mon Sep 17 00:00:00 2001 From: James Westman Date: Sat, 19 Oct 2024 18:46:10 -0500 Subject: [PATCH] lsp: Add reference documentation on hover For most constructs and keywords, show the relevant section of the reference documentation on hover. --- blueprintcompiler/ast_utils.py | 6 +- blueprintcompiler/language/adw_breakpoint.py | 4 + .../language/adw_response_dialog.py | 4 + blueprintcompiler/language/binding.py | 8 ++ blueprintcompiler/language/common.py | 1 + blueprintcompiler/language/expression.py | 10 +- blueprintcompiler/language/gobject_signal.py | 10 +- blueprintcompiler/language/gtk_a11y.py | 4 + .../language/gtk_combo_box_text.py | 8 ++ blueprintcompiler/language/gtk_file_filter.py | 23 ++- blueprintcompiler/language/gtk_layout.py | 4 + .../language/gtk_list_item_factory.py | 4 + blueprintcompiler/language/gtk_menu.py | 20 +++ blueprintcompiler/language/gtk_scale.py | 8 ++ blueprintcompiler/language/gtk_size_group.py | 4 + blueprintcompiler/language/gtk_string_list.py | 6 +- blueprintcompiler/language/gtk_styles.py | 4 + .../language/gtkbuilder_child.py | 4 + .../language/gtkbuilder_template.py | 4 + blueprintcompiler/language/imports.py | 8 ++ blueprintcompiler/language/response_id.py | 10 ++ .../language/translation_domain.py | 4 + blueprintcompiler/language/values.py | 13 ++ blueprintcompiler/lsp_utils.py | 26 ++++ docs/collect-sections.py | 136 ++++++++++++++++++ docs/meson.build | 8 ++ docs/reference/extensions.rst | 2 +- meson.build | 4 +- 28 files changed, 326 insertions(+), 21 deletions(-) create mode 100755 docs/collect-sections.py diff --git a/blueprintcompiler/ast_utils.py b/blueprintcompiler/ast_utils.py index c874358..bd5befa 100644 --- a/blueprintcompiler/ast_utils.py +++ b/blueprintcompiler/ast_utils.py @@ -179,14 +179,16 @@ class AstNode: token = self.group.tokens.get(attr.token_name) if token and token.start <= idx < token.end: return getattr(self, name) - else: - return getattr(self, name) for child in self.children: if idx in child.range: if docs := child.get_docs(idx): return docs + for name, attr in self._attrs_by_type(Docs): + if not attr.token_name: + return getattr(self, name) + return None def get_semantic_tokens(self) -> T.Iterator[SemanticToken]: diff --git a/blueprintcompiler/language/adw_breakpoint.py b/blueprintcompiler/language/adw_breakpoint.py index e7716e6..4ad5b24 100644 --- a/blueprintcompiler/language/adw_breakpoint.py +++ b/blueprintcompiler/language/adw_breakpoint.py @@ -207,6 +207,10 @@ class AdwBreakpointSetters(AstNode): def unique(self): self.validate_unique_in_parent("Duplicate setters block") + @docs("setters") + def ref_docs(self): + return get_docs_section("Syntax ExtAdwBreakpoint") + @decompiler("condition", cdata=True) def decompile_condition(ctx: DecompileCtx, gir, cdata): diff --git a/blueprintcompiler/language/adw_response_dialog.py b/blueprintcompiler/language/adw_response_dialog.py index 46172f2..5493d4d 100644 --- a/blueprintcompiler/language/adw_response_dialog.py +++ b/blueprintcompiler/language/adw_response_dialog.py @@ -138,6 +138,10 @@ class ExtAdwResponseDialog(AstNode): def unique_in_parent(self): self.validate_unique_in_parent("Duplicate responses block") + @docs() + def ref_docs(self): + return get_docs_section("Syntax ExtAdwMessageDialog") + @completer( applies_in=[ObjectContent], diff --git a/blueprintcompiler/language/binding.py b/blueprintcompiler/language/binding.py index 3b9af97..07572a9 100644 --- a/blueprintcompiler/language/binding.py +++ b/blueprintcompiler/language/binding.py @@ -58,6 +58,10 @@ class BindingFlag(AstNode): "Only bindings with a single lookup can have flags", ) + @docs() + def ref_docs(self): + return get_docs_section("Syntax Binding") + class Binding(AstNode): grammar = [ @@ -99,6 +103,10 @@ class Binding(AstNode): actions=[CodeAction("use 'bind'", "bind")], ) + @docs("bind") + def ref_docs(self): + return get_docs_section("Syntax Binding") + @dataclass class SimpleBinding: diff --git a/blueprintcompiler/language/common.py b/blueprintcompiler/language/common.py index 29df47d..1cc1b3b 100644 --- a/blueprintcompiler/language/common.py +++ b/blueprintcompiler/language/common.py @@ -55,6 +55,7 @@ from ..lsp_utils import ( SemanticToken, SemanticTokenType, SymbolKind, + get_docs_section, ) from ..parse_tree import * diff --git a/blueprintcompiler/language/expression.py b/blueprintcompiler/language/expression.py index 37e73e8..558392c 100644 --- a/blueprintcompiler/language/expression.py +++ b/blueprintcompiler/language/expression.py @@ -174,7 +174,7 @@ class LookupOp(InfixExpr): class CastExpr(InfixExpr): grammar = [ - "as", + Keyword("as"), AnyOf( ["<", TypeName, Match(">").expected()], [ @@ -220,6 +220,10 @@ class CastExpr(InfixExpr): ], ) + @docs("as") + def ref_docs(self): + return get_docs_section("Syntax CastExpression") + class ClosureArg(AstNode): grammar = Expression @@ -269,6 +273,10 @@ class ClosureExpr(ExprBase): if not self.tokens["extern"]: raise CompileError(f"{self.closure_name} is not a builtin function") + @docs("name") + def ref_docs(self): + return get_docs_section("Syntax ClosureExpression") + expr.children = [ AnyOf(ClosureExpr, LiteralExpr, ["(", Expression, ")"]), diff --git a/blueprintcompiler/language/gobject_signal.py b/blueprintcompiler/language/gobject_signal.py index d2e4526..79f9ae7 100644 --- a/blueprintcompiler/language/gobject_signal.py +++ b/blueprintcompiler/language/gobject_signal.py @@ -40,6 +40,10 @@ class SignalFlag(AstNode): f"Duplicate flag '{self.flag}'", lambda x: x.flag == self.flag ) + @docs() + def ref_docs(self): + return get_docs_section("Syntax Signal") + class Signal(AstNode): grammar = Statement( @@ -50,7 +54,7 @@ class Signal(AstNode): UseIdent("detail_name").expected("a signal detail name"), ] ), - "=>", + Keyword("=>"), Mark("detail_start"), Optional(["$", UseLiteral("extern", True)]), UseIdent("handler").expected("the name of a function to handle the signal"), @@ -184,6 +188,10 @@ class Signal(AstNode): if prop is not None: return prop.doc + @docs("=>") + def ref_docs(self): + return get_docs_section("Syntax Signal") + @decompiler("signal") def decompile_signal( diff --git a/blueprintcompiler/language/gtk_a11y.py b/blueprintcompiler/language/gtk_a11y.py index 8870a74..3657565 100644 --- a/blueprintcompiler/language/gtk_a11y.py +++ b/blueprintcompiler/language/gtk_a11y.py @@ -225,6 +225,10 @@ class ExtAccessibility(AstNode): def unique_in_parent(self): self.validate_unique_in_parent("Duplicate accessibility block") + @docs("accessibility") + def ref_docs(self): + return get_docs_section("Syntax ExtAccessibility") + @completer( applies_in=[ObjectContent], diff --git a/blueprintcompiler/language/gtk_combo_box_text.py b/blueprintcompiler/language/gtk_combo_box_text.py index 3a0d7c7..312750a 100644 --- a/blueprintcompiler/language/gtk_combo_box_text.py +++ b/blueprintcompiler/language/gtk_combo_box_text.py @@ -55,6 +55,10 @@ class Item(AstNode): f"Duplicate item '{self.name}'", lambda x: x.name == self.name ) + @docs("name") + def ref_docs(self): + return get_docs_section("Syntax ExtComboBoxItems") + class ExtComboBoxItems(AstNode): grammar = [ @@ -81,6 +85,10 @@ class ExtComboBoxItems(AstNode): def unique_in_parent(self): self.validate_unique_in_parent("Duplicate items block") + @docs("items") + def ref_docs(self): + return get_docs_section("Syntax ExtComboBoxItems") + @completer( applies_in=[ObjectContent], diff --git a/blueprintcompiler/language/gtk_file_filter.py b/blueprintcompiler/language/gtk_file_filter.py index 482d6e1..e84afc7 100644 --- a/blueprintcompiler/language/gtk_file_filter.py +++ b/blueprintcompiler/language/gtk_file_filter.py @@ -29,25 +29,23 @@ class Filters(AstNode): self.tokens["tag_name"], SymbolKind.Array, self.range, - self.group.tokens[self.tokens["tag_name"]].range, + self.group.tokens["tag_name"].range, ) @validate() def container_is_file_filter(self): validate_parent_type(self, "Gtk", "FileFilter", "file filter properties") - @validate() + @validate("tag_name") def unique_in_parent(self): - # The token argument to validate() needs to be calculated based on - # the instance, hence wrapping it like this. - @validate(self.tokens["tag_name"]) - def wrapped_validator(self): - self.validate_unique_in_parent( - f"Duplicate {self.tokens['tag_name']} block", - check=lambda child: child.tokens["tag_name"] == self.tokens["tag_name"], - ) + self.validate_unique_in_parent( + f"Duplicate {self.tokens['tag_name']} block", + check=lambda child: child.tokens["tag_name"] == self.tokens["tag_name"], + ) - wrapped_validator(self) + @docs("tag_name") + def ref_docs(self): + return get_docs_section("Syntax ExtFileFilter") class FilterString(AstNode): @@ -76,8 +74,7 @@ def create_node(tag_name: str, singular: str): return Group( Filters, [ - Keyword(tag_name), - UseLiteral("tag_name", tag_name), + UseExact("tag_name", tag_name), "[", Delimited( Group( diff --git a/blueprintcompiler/language/gtk_layout.py b/blueprintcompiler/language/gtk_layout.py index 508609d..8d3e37a 100644 --- a/blueprintcompiler/language/gtk_layout.py +++ b/blueprintcompiler/language/gtk_layout.py @@ -83,6 +83,10 @@ class ExtLayout(AstNode): def unique_in_parent(self): self.validate_unique_in_parent("Duplicate layout block") + @docs("layout") + def ref_docs(self): + return get_docs_section("Syntax ExtLayout") + @completer( applies_in=[ObjectContent], diff --git a/blueprintcompiler/language/gtk_list_item_factory.py b/blueprintcompiler/language/gtk_list_item_factory.py index c54547f..3309c08 100644 --- a/blueprintcompiler/language/gtk_list_item_factory.py +++ b/blueprintcompiler/language/gtk_list_item_factory.py @@ -108,3 +108,7 @@ class ExtListItemFactory(AstNode): just hear to satisfy XmlOutput._emit_object_or_template """ return None + + @docs("id") + def ref_docs(self): + return get_docs_section("Syntax ExtListItemFactory") diff --git a/blueprintcompiler/language/gtk_menu.py b/blueprintcompiler/language/gtk_menu.py index a77484a..c7ef5f2 100644 --- a/blueprintcompiler/language/gtk_menu.py +++ b/blueprintcompiler/language/gtk_menu.py @@ -70,6 +70,25 @@ class Menu(AstNode): if self.id in RESERVED_IDS: raise CompileWarning(f"{self.id} may be a confusing object ID") + @docs("menu") + def ref_docs_menu(self): + return get_docs_section("Syntax Menu") + + @docs("section") + def ref_docs_section(self): + return get_docs_section("Syntax Menu") + + @docs("submenu") + def ref_docs_submenu(self): + return get_docs_section("Syntax Menu") + + @docs("item") + def ref_docs_item(self): + if self.tokens["shorthand"]: + return get_docs_section("Syntax MenuItemShorthand") + else: + return get_docs_section("Syntax Menu") + class MenuAttribute(AstNode): tag_name = "attribute" @@ -156,6 +175,7 @@ menu_item_shorthand = Group( [ Keyword("item"), UseLiteral("tag", "item"), + UseLiteral("shorthand", True), "(", Group( MenuAttribute, diff --git a/blueprintcompiler/language/gtk_scale.py b/blueprintcompiler/language/gtk_scale.py index ac4b77c..1fd5ac3 100644 --- a/blueprintcompiler/language/gtk_scale.py +++ b/blueprintcompiler/language/gtk_scale.py @@ -94,6 +94,10 @@ class ExtScaleMark(AstNode): did_you_mean=(self.position, positions.keys()), ) + @docs("mark") + def ref_docs(self): + return get_docs_section("Syntax ExtScaleMarks") + class ExtScaleMarks(AstNode): grammar = [ @@ -123,6 +127,10 @@ class ExtScaleMarks(AstNode): def unique_in_parent(self): self.validate_unique_in_parent("Duplicate 'marks' block") + @docs("marks") + def ref_docs(self): + return get_docs_section("Syntax ExtScaleMarks") + @completer( applies_in=[ObjectContent], diff --git a/blueprintcompiler/language/gtk_size_group.py b/blueprintcompiler/language/gtk_size_group.py index fd23738..54d85e5 100644 --- a/blueprintcompiler/language/gtk_size_group.py +++ b/blueprintcompiler/language/gtk_size_group.py @@ -94,6 +94,10 @@ class ExtSizeGroupWidgets(AstNode): def unique_in_parent(self): self.validate_unique_in_parent("Duplicate widgets block") + @docs("widgets") + def ref_docs(self): + return get_docs_section("Syntax ExtSizeGroupWidgets") + @completer( applies_in=[ObjectContent], diff --git a/blueprintcompiler/language/gtk_string_list.py b/blueprintcompiler/language/gtk_string_list.py index 36a01f6..a146f35 100644 --- a/blueprintcompiler/language/gtk_string_list.py +++ b/blueprintcompiler/language/gtk_string_list.py @@ -57,7 +57,7 @@ class ExtStringListStrings(AstNode): self.group.tokens["strings"].range, ) - @validate("items") + @validate("strings") def container_is_string_list(self): validate_parent_type(self, "Gtk", "StringList", "StringList items") @@ -65,6 +65,10 @@ class ExtStringListStrings(AstNode): def unique_in_parent(self): self.validate_unique_in_parent("Duplicate strings block") + @docs("strings") + def ref_docs(self): + return get_docs_section("Syntax ExtStringListStrings") + @completer( applies_in=[ObjectContent], diff --git a/blueprintcompiler/language/gtk_styles.py b/blueprintcompiler/language/gtk_styles.py index 236dde0..8617522 100644 --- a/blueprintcompiler/language/gtk_styles.py +++ b/blueprintcompiler/language/gtk_styles.py @@ -70,6 +70,10 @@ class ExtStyles(AstNode): def unique_in_parent(self): self.validate_unique_in_parent("Duplicate styles block") + @docs("styles") + def ref_docs(self): + return get_docs_section("Syntax ExtStyles") + @completer( applies_in=[ObjectContent], diff --git a/blueprintcompiler/language/gtkbuilder_child.py b/blueprintcompiler/language/gtkbuilder_child.py index b0563ba..bee551c 100644 --- a/blueprintcompiler/language/gtkbuilder_child.py +++ b/blueprintcompiler/language/gtkbuilder_child.py @@ -53,6 +53,10 @@ class ChildExtension(AstNode): def child(self) -> ExtResponse: return self.children[0] + @docs() + def ref_docs(self): + return get_docs_section("Syntax ChildExtension") + class ChildAnnotation(AstNode): grammar = ["[", AnyOf(ChildInternal, ChildExtension, ChildType), "]"] diff --git a/blueprintcompiler/language/gtkbuilder_template.py b/blueprintcompiler/language/gtkbuilder_template.py index 29f7b37..96383eb 100644 --- a/blueprintcompiler/language/gtkbuilder_template.py +++ b/blueprintcompiler/language/gtkbuilder_template.py @@ -88,6 +88,10 @@ class Template(Object): f"Only one template may be defined per file, but this file contains {len(self.parent.children[Template])}", ) + @docs("id") + def ref_docs(self): + return get_docs_section("Syntax Template") + @decompiler("template") def decompile_template(ctx: DecompileCtx, gir, klass, parent=None): diff --git a/blueprintcompiler/language/imports.py b/blueprintcompiler/language/imports.py index bf5dddd..3060bea 100644 --- a/blueprintcompiler/language/imports.py +++ b/blueprintcompiler/language/imports.py @@ -68,6 +68,10 @@ class GtkDirective(AstNode): # For better error handling, just assume it's 4.0 return gir.get_namespace("Gtk", "4.0") + @docs() + def ref_docs(self): + return get_docs_section("Syntax GtkDecl") + class Import(AstNode): grammar = Statement( @@ -105,3 +109,7 @@ class Import(AstNode): return gir.get_namespace(self.tokens["namespace"], self.tokens["version"]) except CompileError: return None + + @docs() + def ref_docs(self): + return get_docs_section("Syntax Using") diff --git a/blueprintcompiler/language/response_id.py b/blueprintcompiler/language/response_id.py index 8c0c807..939f71f 100644 --- a/blueprintcompiler/language/response_id.py +++ b/blueprintcompiler/language/response_id.py @@ -124,6 +124,16 @@ class ExtResponse(AstNode): object = self.parent_by_type(Child).object return object.id + @docs() + def ref_docs(self): + return get_docs_section("Syntax ExtResponse") + + @docs("response_id") + def response_id_docs(self): + if enum := self.root.gir.get_type("ResponseType", "Gtk"): + if member := enum.members.get(self.response_id, None): + return member.doc + def decompile_response_type(parent_element, child_element): obj_id = None diff --git a/blueprintcompiler/language/translation_domain.py b/blueprintcompiler/language/translation_domain.py index ff20ead..0f60af9 100644 --- a/blueprintcompiler/language/translation_domain.py +++ b/blueprintcompiler/language/translation_domain.py @@ -29,3 +29,7 @@ class TranslationDomain(AstNode): @property def domain(self): return self.tokens["domain"] + + @docs() + def ref_docs(self): + return get_docs_section("Syntax TranslationDomain") diff --git a/blueprintcompiler/language/values.py b/blueprintcompiler/language/values.py index 2678693..63cf4fc 100644 --- a/blueprintcompiler/language/values.py +++ b/blueprintcompiler/language/values.py @@ -20,6 +20,7 @@ import typing as T from blueprintcompiler.gir import ArrayType +from blueprintcompiler.lsp_utils import SemanticToken from .common import * from .contexts import ScopeCtx, ValueTypeCtx @@ -56,6 +57,10 @@ class Translated(AstNode): f"Cannot convert translated string to {expected_type.full_name}" ) + @docs() + def ref_docs(self): + return get_docs_section("Syntax Translated") + class TypeLiteral(AstNode): grammar = [ @@ -101,6 +106,10 @@ class TypeLiteral(AstNode): ], ) + @docs() + def ref_docs(self): + return get_docs_section("Syntax TypeLiteral") + class QuotedLiteral(AstNode): grammar = UseQuoted("value") @@ -258,6 +267,10 @@ class Flags(AstNode): if expected_type is not None and not isinstance(expected_type, gir.Bitfield): raise CompileError(f"{expected_type.full_name} is not a bitfield type") + @docs() + def ref_docs(self): + return get_docs_section("Syntax Flags") + class IdentLiteral(AstNode): grammar = UseIdent("value") diff --git a/blueprintcompiler/lsp_utils.py b/blueprintcompiler/lsp_utils.py index 9362e8c..b938181 100644 --- a/blueprintcompiler/lsp_utils.py +++ b/blueprintcompiler/lsp_utils.py @@ -19,6 +19,8 @@ import enum +import json +import os import typing as T from dataclasses import dataclass, field @@ -200,3 +202,27 @@ class TextEdit: def to_json(self): return {"range": self.range.to_json(), "newText": self.newText} + + +_docs_sections: T.Optional[dict[str, T.Any]] = None + + +def get_docs_section(section_name: str) -> T.Optional[str]: + global _docs_sections + + if _docs_sections is None: + try: + with open( + os.path.join(os.path.dirname(__file__), "reference_docs.json") + ) as f: + _docs_sections = json.load(f) + except FileNotFoundError: + _docs_sections = {} + + if section := _docs_sections.get(section_name): + content = section["content"] + link = section["link"] + content += f"\n\n---\n\n[Online documentation]({link})" + return content + else: + return None diff --git a/docs/collect-sections.py b/docs/collect-sections.py new file mode 100755 index 0000000..c6e01b3 --- /dev/null +++ b/docs/collect-sections.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 + +import json +import os +import re +import sys +from dataclasses import dataclass +from pathlib import Path + +__all__ = ["get_docs_section"] + +DOCS_ROOT = "https://jwestman.pages.gitlab.gnome.org/blueprint-compiler" + + +sections: dict[str, "Section"] = {} + + +@dataclass +class Section: + link: str + lines: str + + def to_json(self): + return { + "content": rst_to_md(self.lines), + "link": self.link, + } + + +def load_reference_docs(): + for filename in Path(os.path.dirname(__file__), "reference").glob("*.rst"): + with open(filename) as f: + section_name = None + lines = [] + + def close_section(): + if section_name: + html_file = re.sub(r"\.rst$", ".html", filename.name) + anchor = re.sub(r"[^a-z0-9]+", "-", section_name.lower()) + link = f"{DOCS_ROOT}/reference/{html_file}#{anchor}" + sections[section_name] = Section(link, lines) + + for line in f: + if m := re.match(r"\.\.\s+_(.*):", line): + close_section() + section_name = m.group(1) + lines = [] + else: + lines.append(line) + + close_section() + + +# This isn't a comprehensive rST to markdown converter, it just needs to handle the +# small subset of rST used in the reference docs. +def rst_to_md(lines: list[str]) -> str: + result = "" + + def rst_to_md_inline(line): + line = re.sub(r"``(.*?)``", r"`\1`", line) + line = re.sub( + r":ref:`(.*?)<(.*?)>`", + lambda m: f"[{m.group(1)}]({sections[m.group(2)].link})", + line, + ) + line = re.sub(r"`([^`]*?) <([^`>]*?)>`_", r"[\1](\2)", line) + return line + + i = 0 + n = len(lines) + heading_levels = {} + + def print_block(lang: str = "", code: bool = True, strip_links: bool = False): + nonlocal result, i + block = "" + while i < n: + line = lines[i].rstrip() + if line.startswith(" "): + line = line[3:] + elif line != "": + break + + if strip_links: + line = re.sub(r":ref:`(.*?)<(.*?)>`", r"\1", line) + + if not code: + line = rst_to_md_inline(line) + + block += line + "\n" + i += 1 + + if code: + result += f"```{lang}\n{block.strip()}\n```\n\n" + else: + result += block + + while i < n: + line = lines[i].rstrip() + i += 1 + if line == ".. rst-class:: grammar-block": + print_block(strip_links=True) + elif line == ".. code-block:: blueprint": + print_block("blueprint") + elif line == ".. note::": + result += "#### Note\n" + print_block(code=False) + elif m := re.match(r"\.\. image:: (.*)", line): + result += f"![{m.group(1)}]({DOCS_ROOT}/_images/{m.group(1)})\n" + elif i < n and re.match(r"^((-+)|(~+)|(\++))$", lines[i]): + level_char = lines[i][0] + if level_char not in heading_levels: + heading_levels[level_char] = max(heading_levels.values(), default=1) + 1 + result += ( + "#" * heading_levels[level_char] + " " + rst_to_md_inline(line) + "\n" + ) + i += 1 + else: + result += rst_to_md_inline(line) + "\n" + + return result + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("Usage: collect_sections.py ") + sys.exit(1) + + outfile = sys.argv[1] + + load_reference_docs() + + # print the sections to a json file + with open(outfile, "w") as f: + json.dump( + {name: section.to_json() for name, section in sections.items()}, f, indent=2 + ) diff --git a/docs/meson.build b/docs/meson.build index 95e545d..d9ad736 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -9,3 +9,11 @@ custom_target('docs', ) endif + +custom_target('reference_docs.json', + output: 'reference_docs.json', + command: [meson.current_source_dir() / 'collect-sections.py', '@OUTPUT@'], + build_always_stale: true, + install: true, + install_dir: py.get_install_dir() / 'blueprintcompiler', +) \ No newline at end of file diff --git a/docs/reference/extensions.rst b/docs/reference/extensions.rst index 93ed0fc..0961d14 100644 --- a/docs/reference/extensions.rst +++ b/docs/reference/extensions.rst @@ -227,7 +227,7 @@ Valid in `Gtk.BuilderListItemFactory `_, `Gtk.ColumnViewRow `_, or `Gtk.ColumnViewCell `_ The template object can be referenced with the ``template`` keyword. +The template type must be `Gtk.ListItem `_, `Gtk.ColumnViewRow `_, or `Gtk.ColumnViewCell `_. The template object can be referenced with the ``template`` keyword. .. code-block:: blueprint diff --git a/meson.build b/meson.build index f676459..63d9489 100644 --- a/meson.build +++ b/meson.build @@ -2,13 +2,13 @@ project('blueprint-compiler', version: '0.14.0', ) -subdir('docs') - prefix = get_option('prefix') datadir = join_paths(prefix, get_option('datadir')) py = import('python').find_installation('python3') +subdir('docs') + configure_file( input: 'blueprint-compiler.pc.in', output: 'blueprint-compiler.pc',