From f48b840cfa478d6bfeb6e16f24fd5b650c70e4f2 Mon Sep 17 00:00:00 2001 From: kotontrion Date: Wed, 20 Nov 2024 10:41:56 +0100 Subject: [PATCH 01/22] compile: fix flag values gtk builder does not support combining interger values with | in flags properties, so the short names are used instead. --- blueprintcompiler/language/values.py | 2 +- tests/samples/flags.ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/blueprintcompiler/language/values.py b/blueprintcompiler/language/values.py index 63cf4fc..e060b65 100644 --- a/blueprintcompiler/language/values.py +++ b/blueprintcompiler/language/values.py @@ -216,7 +216,7 @@ class Flag(AstNode): if not isinstance(type, Enumeration): return None elif member := type.members.get(self.name): - return member.value + return member.name else: return None diff --git a/tests/samples/flags.ui b/tests/samples/flags.ui index 2f0a26e..d13c424 100644 --- a/tests/samples/flags.ui +++ b/tests/samples/flags.ui @@ -7,7 +7,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler. - 1|4 + is_service|handles_open 1 From 2ae41020abfb04649e9791f57c84fc708d428283 Mon Sep 17 00:00:00 2001 From: kotontrion Date: Thu, 21 Nov 2024 09:28:40 +0100 Subject: [PATCH 02/22] Fix flag return value type --- blueprintcompiler/language/values.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blueprintcompiler/language/values.py b/blueprintcompiler/language/values.py index e060b65..4cd600d 100644 --- a/blueprintcompiler/language/values.py +++ b/blueprintcompiler/language/values.py @@ -211,7 +211,7 @@ class Flag(AstNode): return self.tokens["value"] @property - def value(self) -> T.Optional[int]: + def value(self) -> T.Optional[str]: type = self.context[ValueTypeCtx].value_type if not isinstance(type, Enumeration): return None From e07da3c33946e7ab4afed9c564a9e7ae0b3fbbb8 Mon Sep 17 00:00:00 2001 From: kotontrion Date: Tue, 26 Nov 2024 10:52:37 +0100 Subject: [PATCH 03/22] flags: use nick instead of name --- blueprintcompiler/language/values.py | 2 +- tests/samples/flags.ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/blueprintcompiler/language/values.py b/blueprintcompiler/language/values.py index 4cd600d..96787ee 100644 --- a/blueprintcompiler/language/values.py +++ b/blueprintcompiler/language/values.py @@ -216,7 +216,7 @@ class Flag(AstNode): if not isinstance(type, Enumeration): return None elif member := type.members.get(self.name): - return member.name + return member.nick else: return None diff --git a/tests/samples/flags.ui b/tests/samples/flags.ui index d13c424..44eb2c4 100644 --- a/tests/samples/flags.ui +++ b/tests/samples/flags.ui @@ -7,7 +7,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler. - is_service|handles_open + is-service|handles-open 1 From 404ae767870b6da6005f2f4aaa878deed82829e5 Mon Sep 17 00:00:00 2001 From: James Westman Date: Fri, 17 Jan 2025 17:25:21 -0600 Subject: [PATCH 04/22] Update MAINTENANCE.md --- MAINTENANCE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTENANCE.md b/MAINTENANCE.md index 220c117..3ab4fa2 100644 --- a/MAINTENANCE.md +++ b/MAINTENANCE.md @@ -8,7 +8,7 @@ in the NEWS file. 3. Make a new commit with just these two changes. Use `Release v{version}` as the commit message. Tag the commit as `v{version}` and push the tag. 4. Create a "Post-release version bump" commit. 5. Go to the Releases page in GitLab and create a new release from the tag. -6. Announce the release through relevant channels (Twitter, TWIG, etc.) +6. Announce the release through relevant channels (Mastodon, TWIG, etc.) ## Related projects From a4e0c3701b1510191f72cc606c2fa20d97800444 Mon Sep 17 00:00:00 2001 From: Chris Mayo Date: Thu, 30 Jan 2025 19:23:40 +0000 Subject: [PATCH 05/22] docs: Update overview example using format and compile --- docs/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 34b942c..a71b968 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -26,7 +26,7 @@ Blueprint is a markup language and compiler for GTK 4 user interfaces. using Gtk 4.0; - template MyAppWindow : ApplicationWindow { + template $MyAppWindow: ApplicationWindow { default-width: 600; default-height: 300; title: _("Hello, Blueprint!"); @@ -35,7 +35,7 @@ Blueprint is a markup language and compiler for GTK 4 user interfaces. HeaderBar {} Label { - label: bind MyAppWindow.main_text; + label: bind template.main_text; } } From 394014429e819347d107eb5fa9fd2871bdb3d0ac Mon Sep 17 00:00:00 2001 From: Sertonix Date: Thu, 20 Mar 2025 10:52:57 +0000 Subject: [PATCH 06/22] Sort keys in collect-sections.py This makes sure that the reference_docs.json file is build reproducible. Ref https://reproducible-builds.org/ --- docs/collect-sections.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/collect-sections.py b/docs/collect-sections.py index e6227e7..07bc5f6 100755 --- a/docs/collect-sections.py +++ b/docs/collect-sections.py @@ -132,5 +132,8 @@ if __name__ == "__main__": # 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 + {name: section.to_json() for name, section in sections.items()}, + f, + indent=2, + sort_keys=True, ) From f93d5d2acd53365f70e48a0002e91e94be37f733 Mon Sep 17 00:00:00 2001 From: Tom Greig Date: Fri, 28 Mar 2025 20:26:19 +0000 Subject: [PATCH 07/22] Handle nested CDATA from nested templates When putting CDATA into the output, any instances of ']]>' in the text are replaced with ']]]]>'. This allows nested templates, e.g. from list views inside list views to work properly. --- blueprintcompiler/outputs/xml/xml_emitter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/blueprintcompiler/outputs/xml/xml_emitter.py b/blueprintcompiler/outputs/xml/xml_emitter.py index ea91e03..d34eff4 100644 --- a/blueprintcompiler/outputs/xml/xml_emitter.py +++ b/blueprintcompiler/outputs/xml/xml_emitter.py @@ -73,6 +73,7 @@ class XmlEmitter: self._needs_newline = False def put_cdata(self, text: str): + text = text.replace("]]>", "]]]]>") self.result += f"" self._needs_newline = False From cc09f3d3bb8e6f273072c1b4727929bf7b0bad83 Mon Sep 17 00:00:00 2001 From: Tom Greig Date: Sun, 30 Mar 2025 10:27:11 +0100 Subject: [PATCH 08/22] Add tests for nested templates Basically just a copy of the list_factory test, but with an extra copy of the list factory inside it. --- tests/samples/list_factory_nested.blp | 17 +++++++++ tests/samples/list_factory_nested.ui | 44 +++++++++++++++++++++++ tests/samples/list_factory_nested_dec.blp | 18 ++++++++++ 3 files changed, 79 insertions(+) create mode 100644 tests/samples/list_factory_nested.blp create mode 100644 tests/samples/list_factory_nested.ui create mode 100644 tests/samples/list_factory_nested_dec.blp diff --git a/tests/samples/list_factory_nested.blp b/tests/samples/list_factory_nested.blp new file mode 100644 index 0000000..86a59b3 --- /dev/null +++ b/tests/samples/list_factory_nested.blp @@ -0,0 +1,17 @@ +using Gtk 4.0; + +Gtk.ListView { + factory: Gtk.BuilderListItemFactory list_item_factory { + template ListItem { + child: Gtk.ListView { + factory: Gtk.BuilderListItemFactory list_item_factory { + template ListItem { + child: Gtk.Label { + label: bind template.item as <$MyObject>.name; + }; + } + }; + }; + } + }; +} diff --git a/tests/samples/list_factory_nested.ui b/tests/samples/list_factory_nested.ui new file mode 100644 index 0000000..44cdb2b --- /dev/null +++ b/tests/samples/list_factory_nested.ui @@ -0,0 +1,44 @@ + + + + + + + + + + +]]> + + + + diff --git a/tests/samples/list_factory_nested_dec.blp b/tests/samples/list_factory_nested_dec.blp new file mode 100644 index 0000000..755491c --- /dev/null +++ b/tests/samples/list_factory_nested_dec.blp @@ -0,0 +1,18 @@ +using Gtk 4.0; + +ListView { + factory: BuilderListItemFactory list_item_factory { + template ListItem { + child: ListView { + factory: BuilderListItemFactory list_item_factory { + template ListItem { + child: Label { + label: bind template.item as <$MyObject>.name; + }; + } + }; + }; + } + }; +} + From f50b898e4ce74d84cfa92ce44e90f9aaca2ec133 Mon Sep 17 00:00:00 2001 From: James Westman Date: Tue, 1 Apr 2025 19:27:59 -0500 Subject: [PATCH 09/22] adw_breakpoint: Fix crash in language server Fix a crash that happened when an AdwBreakpointSetter rule was incomplete, such as when you're still typing it. Fixes #189. --- blueprintcompiler/language/adw_breakpoint.py | 9 ++++++--- blueprintcompiler/outputs/xml/__init__.py | 3 +++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/blueprintcompiler/language/adw_breakpoint.py b/blueprintcompiler/language/adw_breakpoint.py index 4ad5b24..3d2c10d 100644 --- a/blueprintcompiler/language/adw_breakpoint.py +++ b/blueprintcompiler/language/adw_breakpoint.py @@ -81,8 +81,8 @@ class AdwBreakpointSetter(AstNode): return self.tokens["property"] @property - def value(self) -> Value: - return self.children[Value][0] + def value(self) -> T.Optional[Value]: + return self.children[Value][0] if len(self.children[Value]) > 0 else None @property def gir_class(self) -> T.Optional[GirType]: @@ -106,7 +106,10 @@ class AdwBreakpointSetter(AstNode): return None @property - def document_symbol(self) -> DocumentSymbol: + def document_symbol(self) -> T.Optional[DocumentSymbol]: + if self.value is None: + return None + return DocumentSymbol( f"{self.object_id}.{self.property_name}", SymbolKind.Property, diff --git a/blueprintcompiler/outputs/xml/__init__.py b/blueprintcompiler/outputs/xml/__init__.py index 5c03761..15850f7 100644 --- a/blueprintcompiler/outputs/xml/__init__.py +++ b/blueprintcompiler/outputs/xml/__init__.py @@ -308,6 +308,9 @@ class XmlOutput(OutputFormat): elif isinstance(extension, AdwBreakpointSetters): for setter in extension.setters: + if setter.value is None: + continue + attrs = {} if isinstance(setter.value.child, Translated): From 6a77bfee0a5b2a03390c4ed7f945902a070ef697 Mon Sep 17 00:00:00 2001 From: James Westman Date: Sat, 19 Apr 2025 13:27:20 -0500 Subject: [PATCH 10/22] tests: Fix typing --- tests/test_tokenizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tokenizer.py b/tests/test_tokenizer.py index 2bca595..ad5f828 100644 --- a/tests/test_tokenizer.py +++ b/tests/test_tokenizer.py @@ -25,7 +25,7 @@ from blueprintcompiler.tokenizer import Token, TokenType, tokenize class TestTokenizer(unittest.TestCase): - def assert_tokenize(self, string: str, expect: [Token]): + def assert_tokenize(self, string: str, expect: list[Token]): try: tokens = tokenize(string) self.assertEqual(len(tokens), len(expect)) From e9d61cb6f915d6688dc46cb9142eb6acae7110f7 Mon Sep 17 00:00:00 2001 From: James Westman Date: Fri, 25 Apr 2025 18:15:15 -0500 Subject: [PATCH 11/22] Update URLs after move to GNOME namespace on GitLab --- .gitlab-ci.yml | 4 ++-- blueprintcompiler/errors.py | 2 +- blueprintcompiler/interactive_port.py | 4 ++-- docs/collect-sections.py | 2 +- docs/flatpak.rst | 2 +- docs/index.rst | 2 +- docs/reference/extensions.rst | 2 +- docs/setup.rst | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1ec071e..6d373cc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,7 @@ stages: - pages build: - image: registry.gitlab.gnome.org/jwestman/blueprint-compiler + image: registry.gitlab.gnome.org/gnome/blueprint-compiler stage: build script: - black --check --diff ./ tests @@ -33,7 +33,7 @@ build: path: coverage.xml fuzz: - image: registry.gitlab.gnome.org/jwestman/blueprint-compiler + image: registry.gitlab.gnome.org/gnome/blueprint-compiler stage: build script: - meson _build diff --git a/blueprintcompiler/errors.py b/blueprintcompiler/errors.py index 1e7297c..df1c2e1 100644 --- a/blueprintcompiler/errors.py +++ b/blueprintcompiler/errors.py @@ -219,7 +219,7 @@ def report_bug(): # pragma: no cover f"""{Colors.BOLD}{Colors.RED}***** COMPILER BUG ***** The blueprint-compiler program has crashed. Please report the above stacktrace, along with the input file(s) if possible, on GitLab: -{Colors.BOLD}{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues/new?issue +{Colors.BOLD}{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/GNOME/blueprint-compiler/-/issues/new?issue {Colors.CLEAR}""" ) diff --git a/blueprintcompiler/interactive_port.py b/blueprintcompiler/interactive_port.py index 0c37885..12dd485 100644 --- a/blueprintcompiler/interactive_port.py +++ b/blueprintcompiler/interactive_port.py @@ -71,7 +71,7 @@ def decompile_file(in_file, out_file) -> T.Union[str, CouldNotPort]: print( f"""{Colors.FAINT}Either the original XML file had an error, or there is a bug in the porting tool. If you think it's a bug (which is likely), please file an issue on GitLab: -{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues/new?issue{Colors.CLEAR}\n""" +{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/GNOME/blueprint-compiler/-/issues/new?issue{Colors.CLEAR}\n""" ) return CouldNotPort("does not compile") @@ -136,7 +136,7 @@ def step1(): wrap.write( f"""[wrap-git] directory = blueprint-compiler -url = https://gitlab.gnome.org/jwestman/blueprint-compiler.git +url = https://gitlab.gnome.org/GNOME/blueprint-compiler.git revision = {VERSION} depth = 1 diff --git a/docs/collect-sections.py b/docs/collect-sections.py index 07bc5f6..a2dd004 100755 --- a/docs/collect-sections.py +++ b/docs/collect-sections.py @@ -9,7 +9,7 @@ from pathlib import Path __all__ = ["get_docs_section"] -DOCS_ROOT = "https://jwestman.pages.gitlab.gnome.org/blueprint-compiler" +DOCS_ROOT = "https://gnome.pages.gitlab.gnome.org/blueprint-compiler" sections: dict[str, "Section"] = {} diff --git a/docs/flatpak.rst b/docs/flatpak.rst index 86112cf..8081c8d 100644 --- a/docs/flatpak.rst +++ b/docs/flatpak.rst @@ -16,7 +16,7 @@ a module in your flatpak manifest: "sources": [ { "type": "git", - "url": "https://gitlab.gnome.org/jwestman/blueprint-compiler", + "url": "https://gitlab.gnome.org/GNOME/blueprint-compiler", "tag": "v0.16.0" } ] diff --git a/docs/index.rst b/docs/index.rst index a71b968..6cd130f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -59,7 +59,7 @@ Features Links ----- -- `Source code `_ +- `Source code `_ - `Workbench `_ lets you try, preview and export Blueprint - `GNOME Builder `_ provides builtin support - `Vim syntax highlighting plugin by thetek42 `_ diff --git a/docs/reference/extensions.rst b/docs/reference/extensions.rst index 0961d14..2fd5dbb 100644 --- a/docs/reference/extensions.rst +++ b/docs/reference/extensions.rst @@ -10,7 +10,7 @@ Properties are the main way to set values on objects, but they are limited by th Extensions are a feature of ``Gtk.Buildable``--see `Gtk.Buildable.custom_tag_start() `_ for internal details. - Because they aren't part of the type system, they aren't present in typelib files like properties and signals are. Therefore, if a library adds a new extension, syntax for it must be added to Blueprint manually. If there's a commonly used extension that isn't supported by Blueprint, please `file an issue `_. + Because they aren't part of the type system, they aren't present in typelib files like properties and signals are. Therefore, if a library adds a new extension, syntax for it must be added to Blueprint manually. If there's a commonly used extension that isn't supported by Blueprint, please `file an issue `_. .. rst-class:: grammar-block diff --git a/docs/setup.rst b/docs/setup.rst index 839f8f6..914c753 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -8,7 +8,7 @@ Setting up Blueprint on a new or existing project Using the porting tool ~~~~~~~~~~~~~~~~~~~~~~ -Clone `blueprint-compiler `_ +Clone `blueprint-compiler `_ from source. You can install it using ``meson _build`` and ``ninja -C _build install``, or you can leave it uninstalled. @@ -29,7 +29,7 @@ blueprint-compiler works as a meson subproject. [wrap-git] directory = blueprint-compiler - url = https://gitlab.gnome.org/jwestman/blueprint-compiler.git + url = https://gitlab.gnome.org/GNOME/blueprint-compiler.git revision = main depth = 1 From 3816f4fe8da291704d54a9dd945ba253b9233ca1 Mon Sep 17 00:00:00 2001 From: James Westman Date: Fri, 25 Apr 2025 18:26:45 -0500 Subject: [PATCH 12/22] Add .doap file --- blueprint-compiler.doap | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 blueprint-compiler.doap diff --git a/blueprint-compiler.doap b/blueprint-compiler.doap new file mode 100644 index 0000000..f3e4000 --- /dev/null +++ b/blueprint-compiler.doap @@ -0,0 +1,27 @@ + + + Blueprint + A modern language for creating GTK interfaces + Blueprint is a language and associated tooling for building user interfaces for GTK. + + Python + + + + + + + + James Westman + + jwestman + + + From a83c7e936dafa19afd9753138fd66b7e3aaee008 Mon Sep 17 00:00:00 2001 From: James Westman Date: Fri, 25 Apr 2025 18:32:33 -0500 Subject: [PATCH 13/22] black: Update formatting --- blueprintcompiler/parse_tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blueprintcompiler/parse_tree.py b/blueprintcompiler/parse_tree.py index ae062fb..e590539 100644 --- a/blueprintcompiler/parse_tree.py +++ b/blueprintcompiler/parse_tree.py @@ -17,7 +17,7 @@ # # SPDX-License-Identifier: LGPL-3.0-or-later -""" Utilities for parsing an AST from a token stream. """ +"""Utilities for parsing an AST from a token stream.""" import typing as T from enum import Enum From a12d3f5c81ee231f8bdb87cb06cf8afe5e35f4ad Mon Sep 17 00:00:00 2001 From: James Westman Date: Fri, 25 Apr 2025 20:13:01 -0500 Subject: [PATCH 14/22] decompile: Fix bug in lookup tags A lookup tag with no type attribute would crash the decompiler, even if that was valid. This wasn't caught by the tests since blueprint never generates such XML. Also fixed a bug in the tests that caused decompiler-only tests not to run. --- blueprintcompiler/decompiler.py | 8 +++++--- blueprintcompiler/language/expression.py | 12 +++++++++--- tests/samples/issue_187.ui | 15 +++++++++++++++ tests/samples/issue_187_dec.blp | 7 +++++++ tests/test_samples.py | 10 +++------- 5 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 tests/samples/issue_187.ui create mode 100644 tests/samples/issue_187_dec.blp diff --git a/blueprintcompiler/decompiler.py b/blueprintcompiler/decompiler.py index de6c06f..850b6d8 100644 --- a/blueprintcompiler/decompiler.py +++ b/blueprintcompiler/decompiler.py @@ -255,7 +255,11 @@ def decompile_element( ctx._node_stack.append(xml) ctx.start_block() - gir = decompiler(*args, **kwargs) + + try: + gir = decompiler(*args, **kwargs) + except TypeError as e: + raise UnsupportedError(tag=xml.tag) if not decompiler._skip_children: for child in xml.children: @@ -266,8 +270,6 @@ def decompile_element( except UnsupportedError as e: raise e - except TypeError as e: - raise UnsupportedError(tag=xml.tag) def decompile(data: str) -> str: diff --git a/blueprintcompiler/language/expression.py b/blueprintcompiler/language/expression.py index e0b4246..de6fbf1 100644 --- a/blueprintcompiler/language/expression.py +++ b/blueprintcompiler/language/expression.py @@ -302,12 +302,18 @@ expr.children = [ @decompiler("lookup", skip_children=True, cdata=True) def decompile_lookup( - ctx: DecompileCtx, gir: gir.GirContext, cdata: str, name: str, type: str + ctx: DecompileCtx, + gir: gir.GirContext, + cdata: str, + name: str, + type: T.Optional[str] = None, ): if ctx.parent_node is not None and ctx.parent_node.tag == "property": ctx.print("expr ") - if t := ctx.type_by_cname(type): + if type is None: + type = "" + elif t := ctx.type_by_cname(type): type = decompile.full_name(t) else: type = "$" + type @@ -327,7 +333,7 @@ def decompile_lookup( if constant == ctx.template_class: ctx.print("template." + name) elif constant == "": - ctx.print("item as <" + type + ">." + name) + ctx.print(f"item as <{type}>.{name}") else: ctx.print(constant + "." + name) return diff --git a/tests/samples/issue_187.ui b/tests/samples/issue_187.ui new file mode 100644 index 0000000..941a00f --- /dev/null +++ b/tests/samples/issue_187.ui @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/tests/samples/issue_187_dec.blp b/tests/samples/issue_187_dec.blp new file mode 100644 index 0000000..30b997c --- /dev/null +++ b/tests/samples/issue_187_dec.blp @@ -0,0 +1,7 @@ +using Gtk 4.0; + +template ListItem { + child: Label { + label: bind template.item as <$RecentObject>.filename; + }; +} diff --git a/tests/test_samples.py b/tests/test_samples.py index 1f56eb6..f96d0eb 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -181,11 +181,7 @@ class TestSamples(unittest.TestCase): def test_samples(self): # list the samples directory - samples = [ - f.stem - for f in Path(__file__).parent.glob("samples/*.blp") - if not f.stem.endswith("_dec") - ] + samples = [f.stem for f in Path(__file__).parent.glob("samples/*.blp")] samples.sort() for sample in samples: REQUIRE_ADW_1_4 = ["adw_breakpoint"] @@ -215,7 +211,7 @@ class TestSamples(unittest.TestCase): ] # Decompiler-only tests - SKIP_COMPILE = ["issue_177", "translator_comments"] + SKIP_COMPILE = ["issue_177", "issue_187", "translator_comments"] SKIP_DECOMPILE = [ # Comments are not preserved in either direction @@ -228,7 +224,7 @@ class TestSamples(unittest.TestCase): continue with self.subTest(sample): - if sample not in SKIP_COMPILE: + if sample not in SKIP_COMPILE and not sample.endswith("_dec"): self.assert_sample(sample, skip_run=sample in SKIP_RUN) with self.subTest("decompile/" + sample): From 2e42dc68486c62eb250215a756958b2e0000a6ff Mon Sep 17 00:00:00 2001 From: James Westman Date: Sat, 3 May 2025 07:46:34 -0500 Subject: [PATCH 15/22] decompiler: Fix bug in signals with template object If a signal handler had the template as its object, the decompiler would output the class name instead of the 'template' keyword. --- blueprintcompiler/language/gobject_signal.py | 8 +++++++- tests/samples/signal_template_object.blp | 7 +++++++ tests/samples/signal_template_object.ui | 16 ++++++++++++++++ tests/test_samples.py | 1 + 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/samples/signal_template_object.blp create mode 100644 tests/samples/signal_template_object.ui diff --git a/blueprintcompiler/language/gobject_signal.py b/blueprintcompiler/language/gobject_signal.py index 9c27b97..3b4235f 100644 --- a/blueprintcompiler/language/gobject_signal.py +++ b/blueprintcompiler/language/gobject_signal.py @@ -225,8 +225,14 @@ class Signal(AstNode): @decompiler("signal") -def decompile_signal(ctx, gir, name, handler, swapped=None, after="false", object=None): +def decompile_signal( + ctx: DecompileCtx, gir, name, handler, swapped=None, after="false", object=None +): object_name = object or "" + + if object_name == ctx.template_class: + object_name = "template" + name = name.replace("_", "-") line = f"{name} => ${handler}({object_name})" diff --git a/tests/samples/signal_template_object.blp b/tests/samples/signal_template_object.blp new file mode 100644 index 0000000..16dd5a0 --- /dev/null +++ b/tests/samples/signal_template_object.blp @@ -0,0 +1,7 @@ +using Gtk 4.0; + +template $MyTemplate { + Button { + clicked => $my_signal_handler(template); + } +} diff --git a/tests/samples/signal_template_object.ui b/tests/samples/signal_template_object.ui new file mode 100644 index 0000000..c9a680a --- /dev/null +++ b/tests/samples/signal_template_object.ui @@ -0,0 +1,16 @@ + + + + + + diff --git a/tests/test_samples.py b/tests/test_samples.py index f96d0eb..0807d65 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -198,6 +198,7 @@ class TestSamples(unittest.TestCase): "parseable", "signal", "signal_not_swapped", + "signal_template_object", "template", "template_binding", "template_binding_extern", From 5c7fb03da79abd9dc691675f4b83a33fe770f091 Mon Sep 17 00:00:00 2001 From: James Westman Date: Wed, 7 May 2025 17:08:26 -0500 Subject: [PATCH 16/22] Fix incorrect error with Adw.AlertDialog responses --- blueprintcompiler/language/contexts.py | 10 ++++++---- tests/samples/issue_195.blp | 11 +++++++++++ tests/samples/issue_195.ui | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 tests/samples/issue_195.blp create mode 100644 tests/samples/issue_195.ui diff --git a/blueprintcompiler/language/contexts.py b/blueprintcompiler/language/contexts.py index 6e26048..9376211 100644 --- a/blueprintcompiler/language/contexts.py +++ b/blueprintcompiler/language/contexts.py @@ -60,19 +60,21 @@ class ScopeCtx: passed = {} for obj in self._iter_recursive(self.node): - if obj.tokens["id"] is None: + from .gtk_menu import Menu + + if not (isinstance(obj, Object) or isinstance(obj, Menu)) or obj.id is None: continue - if obj.tokens["id"] in passed: + if obj.id in passed: token = obj.group.tokens["id"] if not isinstance(obj, Template) and not isinstance( obj, ExtListItemFactory ): raise CompileError( - f"Duplicate object ID '{obj.tokens['id']}'", + f"Duplicate object ID '{obj.id}'", token.range, ) - passed[obj.tokens["id"]] = obj + passed[obj.id] = obj def _iter_recursive(self, node: AstNode): yield node diff --git a/tests/samples/issue_195.blp b/tests/samples/issue_195.blp new file mode 100644 index 0000000..50b5b95 --- /dev/null +++ b/tests/samples/issue_195.blp @@ -0,0 +1,11 @@ +using Gtk 4.0; +using Adw 1; + +Adw.AlertDialog dialog1 { + responses [ + ok: "Ok", + cancel: "Cancel", + ] +} + +Button cancel {} diff --git a/tests/samples/issue_195.ui b/tests/samples/issue_195.ui new file mode 100644 index 0000000..b57a379 --- /dev/null +++ b/tests/samples/issue_195.ui @@ -0,0 +1,16 @@ + + + + + + + Ok + Cancel + + + + \ No newline at end of file From 4d42bd68c1ad4366d2f2ed6f3c8f887932fd7fc1 Mon Sep 17 00:00:00 2001 From: James Westman Date: Sat, 14 Jun 2025 10:19:25 -0500 Subject: [PATCH 17/22] Post-release version bump --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index f298d15..635fac5 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('blueprint-compiler', - version: '0.16.0', + version: '0.17.0', ) prefix = get_option('prefix') From 71dcc02198f6e61e00d0bd9890bfd236e2bc0ae9 Mon Sep 17 00:00:00 2001 From: James Westman Date: Sat, 14 Jun 2025 10:27:45 -0500 Subject: [PATCH 18/22] Allow inline menus Newer versions of GTK allow menus to be specified inline in properties. --- blueprintcompiler/language/gobject_property.py | 5 ++++- blueprintcompiler/language/gtk_menu.py | 5 ----- blueprintcompiler/outputs/xml/__init__.py | 5 +++++ docs/reference/objects.rst | 2 +- tests/sample_errors/inline_menu.err | 1 - tests/sample_errors/menu_no_id.err | 1 - tests/{sample_errors => samples}/inline_menu.blp | 0 tests/samples/inline_menu.ui | 14 ++++++++++++++ tests/{sample_errors => samples}/menu_no_id.blp | 0 tests/samples/menu_no_id.ui | 10 ++++++++++ 10 files changed, 34 insertions(+), 9 deletions(-) delete mode 100644 tests/sample_errors/inline_menu.err delete mode 100644 tests/sample_errors/menu_no_id.err rename tests/{sample_errors => samples}/inline_menu.blp (100%) create mode 100644 tests/samples/inline_menu.ui rename tests/{sample_errors => samples}/menu_no_id.blp (100%) create mode 100644 tests/samples/menu_no_id.ui diff --git a/blueprintcompiler/language/gobject_property.py b/blueprintcompiler/language/gobject_property.py index 50a7512..c782d2e 100644 --- a/blueprintcompiler/language/gobject_property.py +++ b/blueprintcompiler/language/gobject_property.py @@ -21,12 +21,15 @@ from .binding import Binding from .common import * from .contexts import ValueTypeCtx +from .gtk_menu import menu from .values import ArrayValue, ExprValue, ObjectValue, Value class Property(AstNode): grammar = Statement( - UseIdent("name"), ":", AnyOf(Binding, ExprValue, ObjectValue, Value, ArrayValue) + UseIdent("name"), + ":", + AnyOf(Binding, ExprValue, menu, ObjectValue, Value, ArrayValue), ) @property diff --git a/blueprintcompiler/language/gtk_menu.py b/blueprintcompiler/language/gtk_menu.py index c7ef5f2..bc38f37 100644 --- a/blueprintcompiler/language/gtk_menu.py +++ b/blueprintcompiler/language/gtk_menu.py @@ -60,11 +60,6 @@ class Menu(AstNode): def items(self) -> T.List[T.Union["Menu", "MenuAttribute"]]: return self.children - @validate("menu") - def has_id(self): - if self.tokens["tag"] == "menu" and self.tokens["id"] is None: - raise CompileError("Menu requires an ID") - @validate("id") def object_id_not_reserved(self): if self.id in RESERVED_IDS: diff --git a/blueprintcompiler/outputs/xml/__init__.py b/blueprintcompiler/outputs/xml/__init__.py index 15850f7..32291ee 100644 --- a/blueprintcompiler/outputs/xml/__init__.py +++ b/blueprintcompiler/outputs/xml/__init__.py @@ -139,6 +139,11 @@ class XmlOutput(OutputFormat): self._emit_expression(value.expression, xml) xml.end_tag() + elif isinstance(value, Menu): + xml.start_tag("property", **props) + self._emit_menu(value, xml) + xml.end_tag() + elif isinstance(value, ObjectValue): xml.start_tag("property", **props) self._emit_object(value.object, xml) diff --git a/docs/reference/objects.rst b/docs/reference/objects.rst index 6f76da6..d759abe 100644 --- a/docs/reference/objects.rst +++ b/docs/reference/objects.rst @@ -58,7 +58,7 @@ Properties .. rst-class:: grammar-block - Property = `> ':' ( :ref:`Binding` | :ref:`ExprValue` | :ref:`ObjectValue` | :ref:`Value` ) ';' + Property = `> ':' ( :ref:`Binding` | :ref:`ExprValue` | :ref:`Menu` | :ref:`ObjectValue` | :ref:`Value` ) ';' Properties specify the details of each object, like a label's text, an image's icon name, or the margins on a container. diff --git a/tests/sample_errors/inline_menu.err b/tests/sample_errors/inline_menu.err deleted file mode 100644 index 3115750..0000000 --- a/tests/sample_errors/inline_menu.err +++ /dev/null @@ -1 +0,0 @@ -4,15,4,Namespace Gtk does not contain a type called menu \ No newline at end of file diff --git a/tests/sample_errors/menu_no_id.err b/tests/sample_errors/menu_no_id.err deleted file mode 100644 index e97f033..0000000 --- a/tests/sample_errors/menu_no_id.err +++ /dev/null @@ -1 +0,0 @@ -3,1,4,Menu requires an ID \ No newline at end of file diff --git a/tests/sample_errors/inline_menu.blp b/tests/samples/inline_menu.blp similarity index 100% rename from tests/sample_errors/inline_menu.blp rename to tests/samples/inline_menu.blp diff --git a/tests/samples/inline_menu.ui b/tests/samples/inline_menu.ui new file mode 100644 index 0000000..2910b14 --- /dev/null +++ b/tests/samples/inline_menu.ui @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/tests/sample_errors/menu_no_id.blp b/tests/samples/menu_no_id.blp similarity index 100% rename from tests/sample_errors/menu_no_id.blp rename to tests/samples/menu_no_id.blp diff --git a/tests/samples/menu_no_id.ui b/tests/samples/menu_no_id.ui new file mode 100644 index 0000000..934f6da --- /dev/null +++ b/tests/samples/menu_no_id.ui @@ -0,0 +1,10 @@ + + + + + + From 5a951696a73493c0ddb0430829acc9132c919ca6 Mon Sep 17 00:00:00 2001 From: Matthijs Velsink Date: Fri, 13 Jun 2025 01:51:05 +0200 Subject: [PATCH 19/22] docs: Small improvements for extensions - Add Gtk.Scale mark example - Add ExtScaleMarks to the index - Keep the index alphabetically sorted - Use the same order in the text --- docs/reference/extensions.rst | 52 +++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/docs/reference/extensions.rst b/docs/reference/extensions.rst index 2fd5dbb..3a9ad36 100644 --- a/docs/reference/extensions.rst +++ b/docs/reference/extensions.rst @@ -16,14 +16,15 @@ Properties are the main way to set values on objects, but they are limited by th Extension = :ref:`ExtAccessibility` | :ref:`ExtAdwAlertDialog` - | :ref:`ExtAdwMessageDialog` | :ref:`ExtAdwBreakpoint` + | :ref:`ExtAdwMessageDialog` | :ref:`ExtComboBoxItems` | :ref:`ExtFileFilterMimeTypes` | :ref:`ExtFileFilterPatterns` | :ref:`ExtFileFilterSuffixes` | :ref:`ExtLayout` | :ref:`ExtListItemFactory` + | :ref:`ExtScaleMarks` | :ref:`ExtSizeGroupWidgets` | :ref:`ExtStringListStrings` | :ref:`ExtStyles` @@ -47,25 +48,6 @@ The ``accessibility`` block defines values relevant to accessibility software. T Relations which allow for a list of values, for example `labelled-by`, must be given as a single relation with a list of values instead of duplicating the relation like done in Gtk.Builder. -.. _Syntax ExtAdwBreakpoint: - -Adw.Breakpoint --------------- - -.. rst-class:: grammar-block - - ExtAdwBreakpointCondition = 'condition' '(' `> ')' - ExtAdwBreakpoint = 'setters' '{' ExtAdwBreakpointSetter* '}' - ExtAdwBreakpointSetter = `> '.' `> ':' :ref:`Value ` ';' - -Valid in `Adw.Breakpoint `_. - -Defines the condition for a breakpoint and the properties that will be set at that breakpoint. See the documentation for `Adw.Breakpoint `_. - -.. note:: - - The `Adw.Breakpoint:condition `_ property has type `Adw.BreakpointCondition `_, which GtkBuilder doesn't know how to parse from a string. Therefore, the ``condition`` syntax is used instead. - .. _Syntax ExtAdwAlertDialog: @@ -96,6 +78,26 @@ The ``responses`` block defines the buttons that will be added to the dialog. Th } +.. _Syntax ExtAdwBreakpoint: + +Adw.Breakpoint +-------------- + +.. rst-class:: grammar-block + + ExtAdwBreakpointCondition = 'condition' '(' `> ')' + ExtAdwBreakpoint = 'setters' '{' ExtAdwBreakpointSetter* '}' + ExtAdwBreakpointSetter = `> '.' `> ':' :ref:`Value ` ';' + +Valid in `Adw.Breakpoint `_. + +Defines the condition for a breakpoint and the properties that will be set at that breakpoint. See the documentation for `Adw.Breakpoint `_. + +.. note:: + + The `Adw.Breakpoint:condition `_ property has type `Adw.BreakpointCondition `_, which GtkBuilder doesn't know how to parse from a string. Therefore, the ``condition`` syntax is used instead. + + .. _Syntax ExtAdwMessageDialog: Adw.MessageDialog Responses @@ -262,6 +264,16 @@ Valid in `Gtk.Scale `_. The ``marks`` block defines the marks on a scale. A single ``mark`` has up to three arguments: a value, an optional position, and an optional label. The position can be ``left``, ``right``, ``top``, or ``bottom``. The label may be translated. +.. code-block:: blueprint + + Scale { + marks [ + mark (-1, bottom), + mark (0, top, _("Origin")), + mark (2), + ] + } + .. _Syntax ExtSizeGroupWidgets: From 6e010148b2b340876a8d1ac456819d4232c0ef93 Mon Sep 17 00:00:00 2001 From: James Westman Date: Sat, 14 Jun 2025 15:11:39 -0500 Subject: [PATCH 20/22] Remove donate link from README --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 503d7a3..f01ecf9 100644 --- a/README.md +++ b/README.md @@ -82,10 +82,6 @@ Visual Studio Code - [Blueprint Language Plugin by bodil](https://github.com/bodil/vscode-blueprint) -## Donate - -You can support my work on GitHub Sponsors! - ## Getting in Touch Matrix room: [#blueprint-language:matrix.org](https://matrix.to/#/#blueprint-language:matrix.org) From ee089aa7f9d8164553967a58a56c860d903f7abf Mon Sep 17 00:00:00 2001 From: James Westman Date: Sat, 14 Jun 2025 11:30:25 -0500 Subject: [PATCH 21/22] ci: Configure tarball releases --- .gitlab-ci.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6d373cc..83122d0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,19 @@ +include: + - component: "gitlab.gnome.org/GNOME/citemplates/release-service@master" + inputs: + job-stage: "release" + dist-job-name: "build-release-tarball" + tarball-artifact-path: "${TARBALL_ARTIFACT_PATH}" + stages: - build +- release - pages +variables: + MESON_BUILD_DIR: "_build" + TARBALL_ARTIFACT_PATH: "${MESON_BUILD_DIR}/meson-dist/${CI_PROJECT_NAME}-${CI_COMMIT_TAG}.tar.xz" + build: image: registry.gitlab.gnome.org/gnome/blueprint-compiler stage: build @@ -45,6 +57,18 @@ fuzz: - corpus - crashes +build-release-tarball: + stage: build + image: registry.gitlab.gnome.org/gnome/blueprint-compiler + script: + - meson setup "${MESON_BUILD_DIR}" + - xvfb-run meson dist -C "${MESON_BUILD_DIR}" --include-subprojects + artifacts: + name: "${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: "always" + paths: + - "${TARBALL_ARTIFACT_PATH}" + pages: stage: pages dependencies: From 07c9c9df9cd1b6b4454ecba21ee58211e9144a4b Mon Sep 17 00:00:00 2001 From: James Westman Date: Tue, 1 Jul 2025 21:06:21 -0500 Subject: [PATCH 22/22] Release v0.18.0 --- NEWS.md | 19 +++++++++++++++++++ docs/flatpak.rst | 2 +- meson.build | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index a12dab0..715aab4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,22 @@ +# v0.18.0 + +## Added +- GtkBuilder now allows menus to be specified inline as a property value. Blueprint now supports this as well. + +## Fixed +- Made reference_docs.json build reproducible (Sertonix) +- Correctly emit XML for nested templates (Tom Greig) +- Fix crash in language server while typing an AdwBreakpointSetter rule +- Update URLs after move to GNOME namespace on GitLab +- Fix crash when decompiling a lookup tag with no type attribute +- Fix incorrect result when decompiling a signal that has the template as its object +- Fix an incorrect "Duplicate object ID" error when an Adw.AlertDialog response had the same ID as an object + +## Documentation +- Updated syntax in the example on the Overview page (Chris Mayo) +- Added examples of Gtk.Scale marks (Matthijs Velsink) +- Corrected errors in the index on the Extensions page (Matthijs Velsink) + # v0.16.0 ## Added diff --git a/docs/flatpak.rst b/docs/flatpak.rst index 8081c8d..b2f42a4 100644 --- a/docs/flatpak.rst +++ b/docs/flatpak.rst @@ -17,7 +17,7 @@ a module in your flatpak manifest: { "type": "git", "url": "https://gitlab.gnome.org/GNOME/blueprint-compiler", - "tag": "v0.16.0" + "tag": "v0.18.0" } ] } diff --git a/meson.build b/meson.build index 635fac5..405ed10 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('blueprint-compiler', - version: '0.17.0', + version: '0.18.0', ) prefix = get_option('prefix')