Compare commits

..

23 commits

Author SHA1 Message Date
James Westman
07c9c9df9c Release v0.18.0 2025-07-01 21:12:35 -05:00
James Westman
ee089aa7f9 ci: Configure tarball releases 2025-07-01 21:07:54 -05:00
James Westman
6e010148b2 Remove donate link from README 2025-06-14 15:11:39 -05:00
Matthijs Velsink
5a951696a7 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
2025-06-14 11:44:06 -05:00
James Westman
71dcc02198
Allow inline menus
Newer versions of GTK allow menus to be specified inline in properties.
2025-06-14 10:33:03 -05:00
James Westman
4d42bd68c1
Post-release version bump 2025-06-14 10:19:25 -05:00
James Westman
5c7fb03da7 Fix incorrect error with Adw.AlertDialog responses 2025-05-07 17:08:26 -05:00
James Westman
2e42dc6848
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.
2025-05-03 07:46:34 -05:00
James Westman
a12d3f5c81
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.
2025-04-25 20:13:01 -05:00
James Westman
a83c7e936d
black: Update formatting 2025-04-25 18:32:33 -05:00
James Westman
3816f4fe8d
Add .doap file 2025-04-25 18:29:55 -05:00
James Westman
e9d61cb6f9
Update URLs after move to GNOME namespace on GitLab 2025-04-25 18:29:55 -05:00
James Westman
6a77bfee0a
tests: Fix typing 2025-04-19 13:27:20 -05:00
James Westman
f50b898e4c 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.
2025-04-01 19:27:59 -05:00
Tom Greig
cc09f3d3bb 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.
2025-03-30 10:27:11 +01:00
Tom Greig
f93d5d2acd Handle nested CDATA from nested templates
When putting CDATA into the output, any instances of ']]>' in the text
are replaced with ']]]]><![CDATA[>'.  This allows nested templates, e.g.
from list views inside list views to work properly.
2025-03-28 20:53:03 +00:00
Sertonix
394014429e Sort keys in collect-sections.py
This makes sure that the reference_docs.json file
is build reproducible.

Ref https://reproducible-builds.org/
2025-03-24 22:58:43 +00:00
Chris Mayo
a4e0c3701b docs: Update overview example using format and compile 2025-03-21 01:01:24 +00:00
kotontrion
c1fbcef6d0 Merge branch blueprint-compiler:main into main 2025-03-02 15:26:42 +00:00
James Westman
404ae76787
Update MAINTENANCE.md 2025-01-17 17:25:21 -06:00
kotontrion
e07da3c339 flags: use nick instead of name 2024-12-18 17:46:26 +00:00
kotontrion
2ae41020ab Fix flag return value type 2024-12-18 17:46:26 +00:00
kotontrion
f48b840cfa compile: fix flag values
gtk builder does not support combining interger values with | in flags
properties, so the short names are used instead.
2024-12-18 17:46:26 +00:00
43 changed files with 353 additions and 76 deletions

View file

@ -1,9 +1,21 @@
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/jwestman/blueprint-compiler
image: registry.gitlab.gnome.org/gnome/blueprint-compiler
stage: build
script:
- black --check --diff ./ tests
@ -33,7 +45,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
@ -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:

View file

@ -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

19
NEWS.md
View file

@ -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

View file

@ -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! <https://github.com/sponsors/jameswestman>
## Getting in Touch
Matrix room: [#blueprint-language:matrix.org](https://matrix.to/#/#blueprint-language:matrix.org)

27
blueprint-compiler.doap Normal file
View file

@ -0,0 +1,27 @@
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:gnome="http://api.gnome.org/doap-extensions#"
xmlns="http://usefulinc.com/ns/doap#">
<name xml:lang="en">Blueprint</name>
<shortdesc xml:lang="en">A modern language for creating GTK interfaces</shortdesc>
<description xml:lang="en">Blueprint is a language and associated tooling for building user interfaces for GTK.</description>
<category rdf:resource="http://api.gnome.org/doap-extensions#apps" />
<programming-language>Python</programming-language>
<homepage
rdf:resource="https://gnome.gitlab.gnome.org/blueprint-compiler/" />
<download-page
rdf:resource="https://gitlab.gnome.org/GNOME/blueprint-compiler/-/releases" />
<bug-database
rdf:resource="https://gitlab.gnome.org/GNOME/blueprint-compiler/issues" />
<maintainer>
<foaf:Person>
<foaf:name>James Westman</foaf:name>
<foaf:mbox rdf:resource="mailto:james@jwestman.net" />
<gnome:userid>jwestman</gnome:userid>
</foaf:Person>
</maintainer>
</Project>

View file

@ -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:

View file

@ -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}"""
)

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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})"

View file

@ -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:

View file

@ -225,12 +225,12 @@ 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
elif member := type.members.get(self.name):
return member.value
return member.nick
else:
return None

View file

@ -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)
@ -308,6 +313,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):

View file

@ -73,6 +73,7 @@ class XmlEmitter:
self._needs_newline = False
def put_cdata(self, text: str):
text = text.replace("]]>", "]]]]><![CDATA[>")
self.result += f"<![CDATA[{text}]]>"
self._needs_newline = False

View file

@ -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

View file

@ -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"] = {}
@ -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,
)

View file

@ -16,8 +16,8 @@ a module in your flatpak manifest:
"sources": [
{
"type": "git",
"url": "https://gitlab.gnome.org/jwestman/blueprint-compiler",
"tag": "v0.16.0"
"url": "https://gitlab.gnome.org/GNOME/blueprint-compiler",
"tag": "v0.18.0"
}
]
}

View file

@ -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;
}
}
@ -59,7 +59,7 @@ Features
Links
-----
- `Source code <https://gitlab.gnome.org/jwestman/blueprint-compiler>`_
- `Source code <https://gitlab.gnome.org/GNOME/blueprint-compiler>`_
- `Workbench <https://github.com/sonnyp/Workbench>`_ lets you try, preview and export Blueprint
- `GNOME Builder <https://developer.gnome.org/documentation/introduction/builder.html>`_ provides builtin support
- `Vim syntax highlighting plugin by thetek42 <https://github.com/thetek42/vim-blueprint-syntax>`_

View file

@ -10,20 +10,21 @@ 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() <https://docs.gtk.org/gtk4/vfunc.Buildable.custom_tag_start.html>`_ 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 <https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues>`_.
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 <https://gitlab.gnome.org/GNOME/blueprint-compiler/-/issues>`_.
.. rst-class:: grammar-block
Extension = :ref:`ExtAccessibility<Syntax ExtAccessibility>`
| :ref:`ExtAdwAlertDialog<Syntax ExtAdwAlertDialog>`
| :ref:`ExtAdwMessageDialog<Syntax ExtAdwMessageDialog>`
| :ref:`ExtAdwBreakpoint<Syntax ExtAdwBreakpoint>`
| :ref:`ExtAdwMessageDialog<Syntax ExtAdwMessageDialog>`
| :ref:`ExtComboBoxItems<Syntax ExtComboBoxItems>`
| :ref:`ExtFileFilterMimeTypes<Syntax ExtFileFilter>`
| :ref:`ExtFileFilterPatterns<Syntax ExtFileFilter>`
| :ref:`ExtFileFilterSuffixes<Syntax ExtFileFilter>`
| :ref:`ExtLayout<Syntax ExtLayout>`
| :ref:`ExtListItemFactory<Syntax ExtListItemFactory>`
| :ref:`ExtScaleMarks<Syntax ExtScaleMarks>`
| :ref:`ExtSizeGroupWidgets<Syntax ExtSizeGroupWidgets>`
| :ref:`ExtStringListStrings<Syntax ExtStringListStrings>`
| :ref:`ExtStyles<Syntax 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' '(' <condition::ref:`QUOTED<Syntax QUOTED>`> ')'
ExtAdwBreakpoint = 'setters' '{' ExtAdwBreakpointSetter* '}'
ExtAdwBreakpointSetter = <object::ref:`IDENT<Syntax IDENT>`> '.' <property::ref:`IDENT<Syntax IDENT>`> ':' :ref:`Value <Syntax Value>` ';'
Valid in `Adw.Breakpoint <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Breakpoint.html>`_.
Defines the condition for a breakpoint and the properties that will be set at that breakpoint. See the documentation for `Adw.Breakpoint <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Breakpoint.html>`_.
.. note::
The `Adw.Breakpoint:condition <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/property.Breakpoint.condition.html>`_ property has type `Adw.BreakpointCondition <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/struct.BreakpointCondition.html>`_, 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' '(' <condition::ref:`QUOTED<Syntax QUOTED>`> ')'
ExtAdwBreakpoint = 'setters' '{' ExtAdwBreakpointSetter* '}'
ExtAdwBreakpointSetter = <object::ref:`IDENT<Syntax IDENT>`> '.' <property::ref:`IDENT<Syntax IDENT>`> ':' :ref:`Value <Syntax Value>` ';'
Valid in `Adw.Breakpoint <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Breakpoint.html>`_.
Defines the condition for a breakpoint and the properties that will be set at that breakpoint. See the documentation for `Adw.Breakpoint <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.Breakpoint.html>`_.
.. note::
The `Adw.Breakpoint:condition <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/property.Breakpoint.condition.html>`_ property has type `Adw.BreakpointCondition <https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/struct.BreakpointCondition.html>`_, 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 <https://docs.gtk.org/gtk4/class.Scale.html>`_.
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:

View file

@ -58,7 +58,7 @@ Properties
.. rst-class:: grammar-block
Property = <name::ref:`IDENT<Syntax IDENT>`> ':' ( :ref:`Binding<Syntax Binding>` | :ref:`ExprValue<Syntax ExprValue>` | :ref:`ObjectValue<Syntax ObjectValue>` | :ref:`Value<Syntax Value>` ) ';'
Property = <name::ref:`IDENT<Syntax IDENT>`> ':' ( :ref:`Binding<Syntax Binding>` | :ref:`ExprValue<Syntax ExprValue>` | :ref:`Menu<Syntax Menu>` | :ref:`ObjectValue<Syntax ObjectValue>` | :ref:`Value<Syntax Value>` ) ';'
Properties specify the details of each object, like a label's text, an image's icon name, or the margins on a container.

View file

@ -8,7 +8,7 @@ Setting up Blueprint on a new or existing project
Using the porting tool
~~~~~~~~~~~~~~~~~~~~~~
Clone `blueprint-compiler <https://gitlab.gnome.org/jwestman/blueprint-compiler>`_
Clone `blueprint-compiler <https://gitlab.gnome.org/GNOME/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

View file

@ -1,5 +1,5 @@
project('blueprint-compiler',
version: '0.16.0',
version: '0.18.0',
)
prefix = get_option('prefix')

View file

@ -1 +0,0 @@
4,15,4,Namespace Gtk does not contain a type called menu

View file

@ -1 +0,0 @@
3,1,4,Menu requires an ID

View file

@ -7,7 +7,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
<interface>
<requires lib="gtk" version="4.0"/>
<object class="GApplication">
<property name="flags">1|4</property>
<property name="flags">is-service|handles-open</property>
</object>
<object class="GtkEventControllerScroll">
<property name="flags">1</property>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT!
This file was @generated by blueprint-compiler. Instead, edit the
corresponding .blp file and regenerate this file with blueprint-compiler.
-->
<interface>
<requires lib="gtk" version="4.0"/>
<object class="GtkMenuButton">
<property name="menu-model">
<menu id="primary_menu"></menu>
</property>
</object>
</interface>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<binding name="label">
<lookup type="RecentObject" name="filename">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>

View file

@ -0,0 +1,7 @@
using Gtk 4.0;
template ListItem {
child: Label {
label: bind template.item as <$RecentObject>.filename;
};
}

View file

@ -0,0 +1,11 @@
using Gtk 4.0;
using Adw 1;
Adw.AlertDialog dialog1 {
responses [
ok: "Ok",
cancel: "Cancel",
]
}
Button cancel {}

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT!
This file was @generated by blueprint-compiler. Instead, edit the
corresponding .blp file and regenerate this file with blueprint-compiler.
-->
<interface>
<requires lib="gtk" version="4.0"/>
<object class="AdwAlertDialog" id="dialog1">
<responses>
<response id="ok">Ok</response>
<response id="cancel">Cancel</response>
</responses>
</object>
<object class="GtkButton" id="cancel"></object>
</interface>

View file

@ -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;
};
}
};
};
}
};
}

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT!
This file was @generated by blueprint-compiler. Instead, edit the
corresponding .blp file and regenerate this file with blueprint-compiler.
-->
<interface>
<requires lib="gtk" version="4.0"/>
<object class="GtkListView">
<property name="factory">
<object class="GtkBuilderListItemFactory" id="list_item_factory">
<property name="bytes"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkListView">
<property name="factory">
<object class="GtkBuilderListItemFactory" id="list_item_factory">
<property name="bytes"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<binding name="label">
<lookup name="name" type="MyObject">
<lookup name="item" type="GtkListItem">
<constant>GtkListItem</constant>
</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>]]]]><![CDATA[></property>
</object>
</property>
</object>
</property>
</template>
</interface>]]></property>
</object>
</property>
</object>
</interface>

View file

@ -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;
};
}
};
};
}
};
}

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT!
This file was @generated by blueprint-compiler. Instead, edit the
corresponding .blp file and regenerate this file with blueprint-compiler.
-->
<interface>
<requires lib="gtk" version="4.0"/>
<menu></menu>
</interface>

View file

@ -0,0 +1,7 @@
using Gtk 4.0;
template $MyTemplate {
Button {
clicked => $my_signal_handler(template);
}
}

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
DO NOT EDIT!
This file was @generated by blueprint-compiler. Instead, edit the
corresponding .blp file and regenerate this file with blueprint-compiler.
-->
<interface>
<requires lib="gtk" version="4.0"/>
<template class="MyTemplate">
<child>
<object class="GtkButton">
<signal name="clicked" handler="my_signal_handler" object="MyTemplate"/>
</object>
</child>
</template>
</interface>

View file

@ -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"]
@ -202,6 +198,7 @@ class TestSamples(unittest.TestCase):
"parseable",
"signal",
"signal_not_swapped",
"signal_template_object",
"template",
"template_binding",
"template_binding_extern",
@ -215,7 +212,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 +225,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):

View file

@ -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))