mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-07-14 02:19:10 -04:00
Compare commits
No commits in common. "main" and "v0.16.0" have entirely different histories.
49 changed files with 98 additions and 395 deletions
|
@ -1,12 +1,9 @@
|
||||||
include:
|
stages:
|
||||||
- project: "GNOME/citemplates"
|
- build
|
||||||
file: "templates/default-rules.yml"
|
- pages
|
||||||
- component: "gitlab.gnome.org/GNOME/citemplates/release-service@master"
|
|
||||||
inputs:
|
|
||||||
dist-job-name: "build"
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
image: registry.gitlab.gnome.org/gnome/blueprint-compiler
|
image: registry.gitlab.gnome.org/jwestman/blueprint-compiler
|
||||||
stage: build
|
stage: build
|
||||||
script:
|
script:
|
||||||
- black --check --diff ./ tests
|
- black --check --diff ./ tests
|
||||||
|
@ -22,24 +19,21 @@ build:
|
||||||
- ninja -C _build docs/en
|
- ninja -C _build docs/en
|
||||||
- git clone https://gitlab.gnome.org/jwestman/blueprint-regression-tests.git
|
- git clone https://gitlab.gnome.org/jwestman/blueprint-regression-tests.git
|
||||||
- cd blueprint-regression-tests
|
- cd blueprint-regression-tests
|
||||||
- git checkout 57e988aa0f7c1e16fc806a6751df5abffe4bf8a5
|
- git checkout 5f9e155c1333e84e6f683cdb26b02a5925fd8db3
|
||||||
- ./test.sh
|
- ./test.sh
|
||||||
- cd ..
|
- cd ..
|
||||||
- meson dist -C _build --include-subprojects --no-tests
|
|
||||||
- cp -r "_build/meson-dist/" "${CI_PROJECT_DIR}/public-dist/"
|
|
||||||
coverage: '/TOTAL.*\s([.\d]+)%/'
|
coverage: '/TOTAL.*\s([.\d]+)%/'
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- _build
|
- _build
|
||||||
- htmlcov
|
- htmlcov
|
||||||
- public-dist
|
|
||||||
reports:
|
reports:
|
||||||
coverage_report:
|
coverage_report:
|
||||||
coverage_format: cobertura
|
coverage_format: cobertura
|
||||||
path: coverage.xml
|
path: coverage.xml
|
||||||
|
|
||||||
fuzz:
|
fuzz:
|
||||||
image: registry.gitlab.gnome.org/gnome/blueprint-compiler
|
image: registry.gitlab.gnome.org/jwestman/blueprint-compiler
|
||||||
stage: build
|
stage: build
|
||||||
script:
|
script:
|
||||||
- meson _build
|
- meson _build
|
||||||
|
@ -52,7 +46,7 @@ fuzz:
|
||||||
- crashes
|
- crashes
|
||||||
|
|
||||||
pages:
|
pages:
|
||||||
stage: deploy
|
stage: pages
|
||||||
dependencies:
|
dependencies:
|
||||||
- build
|
- build
|
||||||
script:
|
script:
|
||||||
|
|
|
@ -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.
|
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.
|
4. Create a "Post-release version bump" commit.
|
||||||
5. Go to the Releases page in GitLab and create a new release from the tag.
|
5. Go to the Releases page in GitLab and create a new release from the tag.
|
||||||
6. Announce the release through relevant channels (Mastodon, TWIG, etc.)
|
6. Announce the release through relevant channels (Twitter, TWIG, etc.)
|
||||||
|
|
||||||
## Related projects
|
## Related projects
|
||||||
|
|
||||||
|
|
19
NEWS.md
19
NEWS.md
|
@ -1,22 +1,3 @@
|
||||||
# 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
|
# v0.16.0
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
|
@ -82,6 +82,10 @@ Visual Studio Code
|
||||||
|
|
||||||
- [Blueprint Language Plugin by bodil](https://github.com/bodil/vscode-blueprint)
|
- [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
|
## Getting in Touch
|
||||||
|
|
||||||
Matrix room: [#blueprint-language:matrix.org](https://matrix.to/#/#blueprint-language:matrix.org)
|
Matrix room: [#blueprint-language:matrix.org](https://matrix.to/#/#blueprint-language:matrix.org)
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
<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>
|
|
|
@ -255,11 +255,7 @@ def decompile_element(
|
||||||
|
|
||||||
ctx._node_stack.append(xml)
|
ctx._node_stack.append(xml)
|
||||||
ctx.start_block()
|
ctx.start_block()
|
||||||
|
|
||||||
try:
|
|
||||||
gir = decompiler(*args, **kwargs)
|
gir = decompiler(*args, **kwargs)
|
||||||
except TypeError as e:
|
|
||||||
raise UnsupportedError(tag=xml.tag)
|
|
||||||
|
|
||||||
if not decompiler._skip_children:
|
if not decompiler._skip_children:
|
||||||
for child in xml.children:
|
for child in xml.children:
|
||||||
|
@ -270,6 +266,8 @@ def decompile_element(
|
||||||
|
|
||||||
except UnsupportedError as e:
|
except UnsupportedError as e:
|
||||||
raise e
|
raise e
|
||||||
|
except TypeError as e:
|
||||||
|
raise UnsupportedError(tag=xml.tag)
|
||||||
|
|
||||||
|
|
||||||
def decompile(data: str) -> str:
|
def decompile(data: str) -> str:
|
||||||
|
|
|
@ -219,7 +219,7 @@ def report_bug(): # pragma: no cover
|
||||||
f"""{Colors.BOLD}{Colors.RED}***** COMPILER BUG *****
|
f"""{Colors.BOLD}{Colors.RED}***** COMPILER BUG *****
|
||||||
The blueprint-compiler program has crashed. Please report the above stacktrace,
|
The blueprint-compiler program has crashed. Please report the above stacktrace,
|
||||||
along with the input file(s) if possible, on GitLab:
|
along with the input file(s) if possible, on GitLab:
|
||||||
{Colors.BOLD}{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/GNOME/blueprint-compiler/-/issues/new?issue
|
{Colors.BOLD}{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues/new?issue
|
||||||
{Colors.CLEAR}"""
|
{Colors.CLEAR}"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ def decompile_file(in_file, out_file) -> T.Union[str, CouldNotPort]:
|
||||||
print(
|
print(
|
||||||
f"""{Colors.FAINT}Either the original XML file had an error, or there is a bug in the
|
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:
|
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/GNOME/blueprint-compiler/-/issues/new?issue{Colors.CLEAR}\n"""
|
{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues/new?issue{Colors.CLEAR}\n"""
|
||||||
)
|
)
|
||||||
|
|
||||||
return CouldNotPort("does not compile")
|
return CouldNotPort("does not compile")
|
||||||
|
@ -136,7 +136,7 @@ def step1():
|
||||||
wrap.write(
|
wrap.write(
|
||||||
f"""[wrap-git]
|
f"""[wrap-git]
|
||||||
directory = blueprint-compiler
|
directory = blueprint-compiler
|
||||||
url = https://gitlab.gnome.org/GNOME/blueprint-compiler.git
|
url = https://gitlab.gnome.org/jwestman/blueprint-compiler.git
|
||||||
revision = {VERSION}
|
revision = {VERSION}
|
||||||
depth = 1
|
depth = 1
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,8 @@ class AdwBreakpointSetter(AstNode):
|
||||||
return self.tokens["property"]
|
return self.tokens["property"]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> T.Optional[Value]:
|
def value(self) -> Value:
|
||||||
return self.children[Value][0] if len(self.children[Value]) > 0 else None
|
return self.children[Value][0]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def gir_class(self) -> T.Optional[GirType]:
|
def gir_class(self) -> T.Optional[GirType]:
|
||||||
|
@ -106,10 +106,7 @@ class AdwBreakpointSetter(AstNode):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def document_symbol(self) -> T.Optional[DocumentSymbol]:
|
def document_symbol(self) -> DocumentSymbol:
|
||||||
if self.value is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return DocumentSymbol(
|
return DocumentSymbol(
|
||||||
f"{self.object_id}.{self.property_name}",
|
f"{self.object_id}.{self.property_name}",
|
||||||
SymbolKind.Property,
|
SymbolKind.Property,
|
||||||
|
|
|
@ -60,21 +60,19 @@ class ScopeCtx:
|
||||||
|
|
||||||
passed = {}
|
passed = {}
|
||||||
for obj in self._iter_recursive(self.node):
|
for obj in self._iter_recursive(self.node):
|
||||||
from .gtk_menu import Menu
|
if obj.tokens["id"] is None:
|
||||||
|
|
||||||
if not (isinstance(obj, Object) or isinstance(obj, Menu)) or obj.id is None:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if obj.id in passed:
|
if obj.tokens["id"] in passed:
|
||||||
token = obj.group.tokens["id"]
|
token = obj.group.tokens["id"]
|
||||||
if not isinstance(obj, Template) and not isinstance(
|
if not isinstance(obj, Template) and not isinstance(
|
||||||
obj, ExtListItemFactory
|
obj, ExtListItemFactory
|
||||||
):
|
):
|
||||||
raise CompileError(
|
raise CompileError(
|
||||||
f"Duplicate object ID '{obj.id}'",
|
f"Duplicate object ID '{obj.tokens['id']}'",
|
||||||
token.range,
|
token.range,
|
||||||
)
|
)
|
||||||
passed[obj.id] = obj
|
passed[obj.tokens["id"]] = obj
|
||||||
|
|
||||||
def _iter_recursive(self, node: AstNode):
|
def _iter_recursive(self, node: AstNode):
|
||||||
yield node
|
yield node
|
||||||
|
|
|
@ -302,18 +302,12 @@ expr.children = [
|
||||||
|
|
||||||
@decompiler("lookup", skip_children=True, cdata=True)
|
@decompiler("lookup", skip_children=True, cdata=True)
|
||||||
def decompile_lookup(
|
def decompile_lookup(
|
||||||
ctx: DecompileCtx,
|
ctx: DecompileCtx, gir: gir.GirContext, cdata: str, name: str, type: str
|
||||||
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":
|
if ctx.parent_node is not None and ctx.parent_node.tag == "property":
|
||||||
ctx.print("expr ")
|
ctx.print("expr ")
|
||||||
|
|
||||||
if type is None:
|
if t := ctx.type_by_cname(type):
|
||||||
type = ""
|
|
||||||
elif t := ctx.type_by_cname(type):
|
|
||||||
type = decompile.full_name(t)
|
type = decompile.full_name(t)
|
||||||
else:
|
else:
|
||||||
type = "$" + type
|
type = "$" + type
|
||||||
|
@ -333,7 +327,7 @@ def decompile_lookup(
|
||||||
if constant == ctx.template_class:
|
if constant == ctx.template_class:
|
||||||
ctx.print("template." + name)
|
ctx.print("template." + name)
|
||||||
elif constant == "":
|
elif constant == "":
|
||||||
ctx.print(f"item as <{type}>.{name}")
|
ctx.print("item as <" + type + ">." + name)
|
||||||
else:
|
else:
|
||||||
ctx.print(constant + "." + name)
|
ctx.print(constant + "." + name)
|
||||||
return
|
return
|
||||||
|
|
|
@ -71,15 +71,12 @@ class Object(AstNode):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def signature(self) -> str:
|
def signature(self) -> str:
|
||||||
if t := self.class_name.gir_type:
|
|
||||||
result = t.full_name
|
|
||||||
else:
|
|
||||||
result = self.class_name.as_string
|
|
||||||
|
|
||||||
if self.id:
|
if self.id:
|
||||||
result += " " + self.id
|
return f"{self.class_name.gir_type.full_name} {self.id}"
|
||||||
|
elif t := self.class_name.gir_type:
|
||||||
return result
|
return f"{t.full_name}"
|
||||||
|
else:
|
||||||
|
return f"{self.class_name.as_string}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def document_symbol(self) -> T.Optional[DocumentSymbol]:
|
def document_symbol(self) -> T.Optional[DocumentSymbol]:
|
||||||
|
|
|
@ -21,15 +21,12 @@
|
||||||
from .binding import Binding
|
from .binding import Binding
|
||||||
from .common import *
|
from .common import *
|
||||||
from .contexts import ValueTypeCtx
|
from .contexts import ValueTypeCtx
|
||||||
from .gtk_menu import menu
|
|
||||||
from .values import ArrayValue, ExprValue, ObjectValue, Value
|
from .values import ArrayValue, ExprValue, ObjectValue, Value
|
||||||
|
|
||||||
|
|
||||||
class Property(AstNode):
|
class Property(AstNode):
|
||||||
grammar = Statement(
|
grammar = Statement(
|
||||||
UseIdent("name"),
|
UseIdent("name"), ":", AnyOf(Binding, ExprValue, ObjectValue, Value, ArrayValue)
|
||||||
":",
|
|
||||||
AnyOf(Binding, ExprValue, menu, ObjectValue, Value, ArrayValue),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -225,14 +225,8 @@ class Signal(AstNode):
|
||||||
|
|
||||||
|
|
||||||
@decompiler("signal")
|
@decompiler("signal")
|
||||||
def decompile_signal(
|
def decompile_signal(ctx, gir, name, handler, swapped=None, after="false", object=None):
|
||||||
ctx: DecompileCtx, gir, name, handler, swapped=None, after="false", object=None
|
|
||||||
):
|
|
||||||
object_name = object or ""
|
object_name = object or ""
|
||||||
|
|
||||||
if object_name == ctx.template_class:
|
|
||||||
object_name = "template"
|
|
||||||
|
|
||||||
name = name.replace("_", "-")
|
name = name.replace("_", "-")
|
||||||
line = f"{name} => ${handler}({object_name})"
|
line = f"{name} => ${handler}({object_name})"
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ def get_property_types(gir):
|
||||||
"autocomplete": gir.get_type("AccessibleAutocomplete", "Gtk"),
|
"autocomplete": gir.get_type("AccessibleAutocomplete", "Gtk"),
|
||||||
"description": StringType(),
|
"description": StringType(),
|
||||||
"has-popup": BoolType(),
|
"has-popup": BoolType(),
|
||||||
"help-text": StringType(),
|
|
||||||
"key-shortcuts": StringType(),
|
"key-shortcuts": StringType(),
|
||||||
"label": StringType(),
|
"label": StringType(),
|
||||||
"level": IntType(),
|
"level": IntType(),
|
||||||
|
@ -87,7 +86,6 @@ def get_state_types(gir):
|
||||||
"invalid": gir.get_type("AccessibleInvalidState", "Gtk"),
|
"invalid": gir.get_type("AccessibleInvalidState", "Gtk"),
|
||||||
"pressed": gir.get_type("AccessibleTristate", "Gtk"),
|
"pressed": gir.get_type("AccessibleTristate", "Gtk"),
|
||||||
"selected": BoolType(),
|
"selected": BoolType(),
|
||||||
"visited": BoolType(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,11 @@ class Menu(AstNode):
|
||||||
def items(self) -> T.List[T.Union["Menu", "MenuAttribute"]]:
|
def items(self) -> T.List[T.Union["Menu", "MenuAttribute"]]:
|
||||||
return self.children
|
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")
|
@validate("id")
|
||||||
def object_id_not_reserved(self):
|
def object_id_not_reserved(self):
|
||||||
if self.id in RESERVED_IDS:
|
if self.id in RESERVED_IDS:
|
||||||
|
|
|
@ -225,12 +225,12 @@ class Flag(AstNode):
|
||||||
return self.tokens["value"]
|
return self.tokens["value"]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def value(self) -> T.Optional[str]:
|
def value(self) -> T.Optional[int]:
|
||||||
type = self.context[ValueTypeCtx].value_type
|
type = self.context[ValueTypeCtx].value_type
|
||||||
if not isinstance(type, Enumeration):
|
if not isinstance(type, Enumeration):
|
||||||
return None
|
return None
|
||||||
elif member := type.members.get(self.name):
|
elif member := type.members.get(self.name):
|
||||||
return member.nick
|
return member.value
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -338,14 +338,7 @@ class IdentLiteral(AstNode):
|
||||||
raise CompileError(
|
raise CompileError(
|
||||||
'"item" can only be used in an expression literal'
|
'"item" can only be used in an expression literal'
|
||||||
)
|
)
|
||||||
elif self.ident in ["true", "false"]:
|
elif self.ident not in ["true", "false"]:
|
||||||
if expected_type is not None and not isinstance(
|
|
||||||
expected_type, gir.BoolType
|
|
||||||
):
|
|
||||||
raise CompileError(
|
|
||||||
f"Cannot assign boolean to {expected_type.full_name}"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
raise CompileError(
|
raise CompileError(
|
||||||
f"Could not find object with ID {self.ident}",
|
f"Could not find object with ID {self.ident}",
|
||||||
did_you_mean=(
|
did_you_mean=(
|
||||||
|
|
|
@ -170,18 +170,6 @@ class BlueprintApp:
|
||||||
add_typelib_search_path(typelib_path)
|
add_typelib_search_path(typelib_path)
|
||||||
|
|
||||||
for file in opts.inputs:
|
for file in opts.inputs:
|
||||||
path = os.path.join(
|
|
||||||
opts.output_dir,
|
|
||||||
os.path.relpath(os.path.splitext(file.name)[0] + ".ui", opts.input_dir),
|
|
||||||
)
|
|
||||||
|
|
||||||
if os.path.isfile(path):
|
|
||||||
in_time = os.path.getmtime(file.name)
|
|
||||||
out_time = os.path.getmtime(path)
|
|
||||||
|
|
||||||
if out_time >= in_time:
|
|
||||||
continue
|
|
||||||
|
|
||||||
data = file.read()
|
data = file.read()
|
||||||
file_abs = os.path.abspath(file.name)
|
file_abs = os.path.abspath(file.name)
|
||||||
input_dir_abs = os.path.abspath(opts.input_dir)
|
input_dir_abs = os.path.abspath(opts.input_dir)
|
||||||
|
@ -198,6 +186,12 @@ class BlueprintApp:
|
||||||
for warning in warnings:
|
for warning in warnings:
|
||||||
warning.pretty_print(file.name, data, stream=sys.stderr)
|
warning.pretty_print(file.name, data, stream=sys.stderr)
|
||||||
|
|
||||||
|
path = os.path.join(
|
||||||
|
opts.output_dir,
|
||||||
|
os.path.relpath(
|
||||||
|
os.path.splitext(file.name)[0] + ".ui", opts.input_dir
|
||||||
|
),
|
||||||
|
)
|
||||||
os.makedirs(os.path.dirname(path), exist_ok=True)
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||||
with open(path, "w") as file:
|
with open(path, "w") as file:
|
||||||
file.write(xml)
|
file.write(xml)
|
||||||
|
|
|
@ -139,11 +139,6 @@ class XmlOutput(OutputFormat):
|
||||||
self._emit_expression(value.expression, xml)
|
self._emit_expression(value.expression, xml)
|
||||||
xml.end_tag()
|
xml.end_tag()
|
||||||
|
|
||||||
elif isinstance(value, Menu):
|
|
||||||
xml.start_tag("property", **props)
|
|
||||||
self._emit_menu(value, xml)
|
|
||||||
xml.end_tag()
|
|
||||||
|
|
||||||
elif isinstance(value, ObjectValue):
|
elif isinstance(value, ObjectValue):
|
||||||
xml.start_tag("property", **props)
|
xml.start_tag("property", **props)
|
||||||
self._emit_object(value.object, xml)
|
self._emit_object(value.object, xml)
|
||||||
|
@ -313,9 +308,6 @@ class XmlOutput(OutputFormat):
|
||||||
|
|
||||||
elif isinstance(extension, AdwBreakpointSetters):
|
elif isinstance(extension, AdwBreakpointSetters):
|
||||||
for setter in extension.setters:
|
for setter in extension.setters:
|
||||||
if setter.value is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
attrs = {}
|
attrs = {}
|
||||||
|
|
||||||
if isinstance(setter.value.child, Translated):
|
if isinstance(setter.value.child, Translated):
|
||||||
|
|
|
@ -73,7 +73,6 @@ class XmlEmitter:
|
||||||
self._needs_newline = False
|
self._needs_newline = False
|
||||||
|
|
||||||
def put_cdata(self, text: str):
|
def put_cdata(self, text: str):
|
||||||
text = text.replace("]]>", "]]]]><![CDATA[>")
|
|
||||||
self.result += f"<![CDATA[{text}]]>"
|
self.result += f"<![CDATA[{text}]]>"
|
||||||
self._needs_newline = False
|
self._needs_newline = False
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
# 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
|
import typing as T
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
|
@ -9,7 +9,7 @@ from pathlib import Path
|
||||||
|
|
||||||
__all__ = ["get_docs_section"]
|
__all__ = ["get_docs_section"]
|
||||||
|
|
||||||
DOCS_ROOT = "https://gnome.pages.gitlab.gnome.org/blueprint-compiler"
|
DOCS_ROOT = "https://jwestman.pages.gitlab.gnome.org/blueprint-compiler"
|
||||||
|
|
||||||
|
|
||||||
sections: dict[str, "Section"] = {}
|
sections: dict[str, "Section"] = {}
|
||||||
|
@ -132,8 +132,5 @@ if __name__ == "__main__":
|
||||||
# print the sections to a json file
|
# print the sections to a json file
|
||||||
with open(outfile, "w") as f:
|
with open(outfile, "w") as f:
|
||||||
json.dump(
|
json.dump(
|
||||||
{name: section.to_json() for name, section in sections.items()},
|
{name: section.to_json() for name, section in sections.items()}, f, indent=2
|
||||||
f,
|
|
||||||
indent=2,
|
|
||||||
sort_keys=True,
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,8 +16,8 @@ a module in your flatpak manifest:
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://gitlab.gnome.org/GNOME/blueprint-compiler",
|
"url": "https://gitlab.gnome.org/jwestman/blueprint-compiler",
|
||||||
"tag": "v0.18.0"
|
"tag": "v0.16.0"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ Blueprint is a markup language and compiler for GTK 4 user interfaces.
|
||||||
|
|
||||||
using Gtk 4.0;
|
using Gtk 4.0;
|
||||||
|
|
||||||
template $MyAppWindow: ApplicationWindow {
|
template MyAppWindow : ApplicationWindow {
|
||||||
default-width: 600;
|
default-width: 600;
|
||||||
default-height: 300;
|
default-height: 300;
|
||||||
title: _("Hello, Blueprint!");
|
title: _("Hello, Blueprint!");
|
||||||
|
@ -35,7 +35,7 @@ Blueprint is a markup language and compiler for GTK 4 user interfaces.
|
||||||
HeaderBar {}
|
HeaderBar {}
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
label: bind template.main_text;
|
label: bind MyAppWindow.main_text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ Features
|
||||||
Links
|
Links
|
||||||
-----
|
-----
|
||||||
|
|
||||||
- `Source code <https://gitlab.gnome.org/GNOME/blueprint-compiler>`_
|
- `Source code <https://gitlab.gnome.org/jwestman/blueprint-compiler>`_
|
||||||
- `Workbench <https://github.com/sonnyp/Workbench>`_ lets you try, preview and export Blueprint
|
- `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
|
- `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>`_
|
- `Vim syntax highlighting plugin by thetek42 <https://github.com/thetek42/vim-blueprint-syntax>`_
|
||||||
|
|
|
@ -10,21 +10,20 @@ 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.
|
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/GNOME/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/jwestman/blueprint-compiler/-/issues>`_.
|
||||||
|
|
||||||
.. rst-class:: grammar-block
|
.. rst-class:: grammar-block
|
||||||
|
|
||||||
Extension = :ref:`ExtAccessibility<Syntax ExtAccessibility>`
|
Extension = :ref:`ExtAccessibility<Syntax ExtAccessibility>`
|
||||||
| :ref:`ExtAdwAlertDialog<Syntax ExtAdwAlertDialog>`
|
| :ref:`ExtAdwAlertDialog<Syntax ExtAdwAlertDialog>`
|
||||||
| :ref:`ExtAdwBreakpoint<Syntax ExtAdwBreakpoint>`
|
|
||||||
| :ref:`ExtAdwMessageDialog<Syntax ExtAdwMessageDialog>`
|
| :ref:`ExtAdwMessageDialog<Syntax ExtAdwMessageDialog>`
|
||||||
|
| :ref:`ExtAdwBreakpoint<Syntax ExtAdwBreakpoint>`
|
||||||
| :ref:`ExtComboBoxItems<Syntax ExtComboBoxItems>`
|
| :ref:`ExtComboBoxItems<Syntax ExtComboBoxItems>`
|
||||||
| :ref:`ExtFileFilterMimeTypes<Syntax ExtFileFilter>`
|
| :ref:`ExtFileFilterMimeTypes<Syntax ExtFileFilter>`
|
||||||
| :ref:`ExtFileFilterPatterns<Syntax ExtFileFilter>`
|
| :ref:`ExtFileFilterPatterns<Syntax ExtFileFilter>`
|
||||||
| :ref:`ExtFileFilterSuffixes<Syntax ExtFileFilter>`
|
| :ref:`ExtFileFilterSuffixes<Syntax ExtFileFilter>`
|
||||||
| :ref:`ExtLayout<Syntax ExtLayout>`
|
| :ref:`ExtLayout<Syntax ExtLayout>`
|
||||||
| :ref:`ExtListItemFactory<Syntax ExtListItemFactory>`
|
| :ref:`ExtListItemFactory<Syntax ExtListItemFactory>`
|
||||||
| :ref:`ExtScaleMarks<Syntax ExtScaleMarks>`
|
|
||||||
| :ref:`ExtSizeGroupWidgets<Syntax ExtSizeGroupWidgets>`
|
| :ref:`ExtSizeGroupWidgets<Syntax ExtSizeGroupWidgets>`
|
||||||
| :ref:`ExtStringListStrings<Syntax ExtStringListStrings>`
|
| :ref:`ExtStringListStrings<Syntax ExtStringListStrings>`
|
||||||
| :ref:`ExtStyles<Syntax ExtStyles>`
|
| :ref:`ExtStyles<Syntax ExtStyles>`
|
||||||
|
@ -48,6 +47,25 @@ 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.
|
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:
|
.. _Syntax ExtAdwAlertDialog:
|
||||||
|
|
||||||
|
@ -78,26 +96,6 @@ 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:
|
.. _Syntax ExtAdwMessageDialog:
|
||||||
|
|
||||||
Adw.MessageDialog Responses
|
Adw.MessageDialog Responses
|
||||||
|
@ -264,16 +262,6 @@ 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.
|
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:
|
.. _Syntax ExtSizeGroupWidgets:
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ Properties
|
||||||
|
|
||||||
.. rst-class:: grammar-block
|
.. rst-class:: grammar-block
|
||||||
|
|
||||||
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>` ) ';'
|
Property = <name::ref:`IDENT<Syntax IDENT>`> ':' ( :ref:`Binding<Syntax Binding>` | :ref:`ExprValue<Syntax ExprValue>` | :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.
|
Properties specify the details of each object, like a label's text, an image's icon name, or the margins on a container.
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ Setting up Blueprint on a new or existing project
|
||||||
Using the porting tool
|
Using the porting tool
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Clone `blueprint-compiler <https://gitlab.gnome.org/GNOME/blueprint-compiler>`_
|
Clone `blueprint-compiler <https://gitlab.gnome.org/jwestman/blueprint-compiler>`_
|
||||||
from source. You can install it using ``meson _build`` and ``ninja -C _build install``,
|
from source. You can install it using ``meson _build`` and ``ninja -C _build install``,
|
||||||
or you can leave it uninstalled.
|
or you can leave it uninstalled.
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ blueprint-compiler works as a meson subproject.
|
||||||
|
|
||||||
[wrap-git]
|
[wrap-git]
|
||||||
directory = blueprint-compiler
|
directory = blueprint-compiler
|
||||||
url = https://gitlab.gnome.org/GNOME/blueprint-compiler.git
|
url = https://gitlab.gnome.org/jwestman/blueprint-compiler.git
|
||||||
revision = main
|
revision = main
|
||||||
depth = 1
|
depth = 1
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
project('blueprint-compiler',
|
project('blueprint-compiler',
|
||||||
version: '0.18.0',
|
version: '0.16.0',
|
||||||
)
|
)
|
||||||
|
|
||||||
prefix = get_option('prefix')
|
prefix = get_option('prefix')
|
||||||
|
|
|
@ -7,28 +7,25 @@ from blueprintcompiler.outputs.xml import XmlOutput
|
||||||
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
|
||||||
|
|
||||||
from blueprintcompiler import gir, parser, tokenizer
|
from blueprintcompiler import decompiler, gir, parser, tokenizer, utils
|
||||||
from blueprintcompiler.completions import complete
|
from blueprintcompiler.completions import complete
|
||||||
from blueprintcompiler.errors import (
|
from blueprintcompiler.errors import (
|
||||||
|
CompileError,
|
||||||
CompilerBugError,
|
CompilerBugError,
|
||||||
|
MultipleErrors,
|
||||||
PrintableError,
|
PrintableError,
|
||||||
)
|
)
|
||||||
from blueprintcompiler.lsp import LanguageServer
|
from blueprintcompiler.tokenizer import Token, TokenType, tokenize
|
||||||
|
|
||||||
fuzz_level = int(os.getenv("FUZZ_LEVEL") or "0")
|
|
||||||
|
|
||||||
|
|
||||||
@PythonFuzz
|
@PythonFuzz
|
||||||
def fuzz(buf: bytes):
|
def fuzz(buf):
|
||||||
try:
|
try:
|
||||||
blueprint = buf.decode("ascii")
|
blueprint = buf.decode("ascii")
|
||||||
|
|
||||||
tokens = tokenizer.tokenize(blueprint)
|
tokens = tokenizer.tokenize(blueprint)
|
||||||
ast, errors, warnings = parser.parse(tokens)
|
ast, errors, warnings = parser.parse(tokens)
|
||||||
|
|
||||||
if fuzz_level >= 1:
|
|
||||||
assert_ast_doesnt_crash(blueprint, tokens, ast)
|
|
||||||
|
|
||||||
xml = XmlOutput()
|
xml = XmlOutput()
|
||||||
if errors is None and ast is not None:
|
if errors is None and ast is not None:
|
||||||
xml.emit(ast)
|
xml.emit(ast)
|
||||||
|
@ -40,17 +37,6 @@ def fuzz(buf: bytes):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def assert_ast_doesnt_crash(text, tokens, ast):
|
|
||||||
lsp = LanguageServer()
|
|
||||||
for i in range(len(text) + 1):
|
|
||||||
ast.get_docs(i)
|
|
||||||
for i in range(len(text) + 1):
|
|
||||||
list(complete(lsp, ast, tokens, i))
|
|
||||||
for i in range(len(text) + 1):
|
|
||||||
ast.get_reference(i)
|
|
||||||
ast.get_document_symbols()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Make sure Gtk 4.0 is accessible, otherwise every test will fail on that
|
# Make sure Gtk 4.0 is accessible, otherwise every test will fail on that
|
||||||
# and nothing interesting will be tested
|
# and nothing interesting will be tested
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
using Gtk 4.0;
|
|
||||||
|
|
||||||
Button {
|
|
||||||
child: false;
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
4,10,5,Cannot assign boolean to Gtk.Widget
|
|
1
tests/sample_errors/inline_menu.err
Normal file
1
tests/sample_errors/inline_menu.err
Normal file
|
@ -0,0 +1 @@
|
||||||
|
4,15,4,Namespace Gtk does not contain a type called menu
|
1
tests/sample_errors/menu_no_id.err
Normal file
1
tests/sample_errors/menu_no_id.err
Normal file
|
@ -0,0 +1 @@
|
||||||
|
3,1,4,Menu requires an ID
|
|
@ -7,7 +7,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||||
<interface>
|
<interface>
|
||||||
<requires lib="gtk" version="4.0"/>
|
<requires lib="gtk" version="4.0"/>
|
||||||
<object class="GApplication">
|
<object class="GApplication">
|
||||||
<property name="flags">is-service|handles-open</property>
|
<property name="flags">1|4</property>
|
||||||
</object>
|
</object>
|
||||||
<object class="GtkEventControllerScroll">
|
<object class="GtkEventControllerScroll">
|
||||||
<property name="flags">1</property>
|
<property name="flags">1</property>
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,15 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,7 +0,0 @@
|
||||||
using Gtk 4.0;
|
|
||||||
|
|
||||||
template ListItem {
|
|
||||||
child: Label {
|
|
||||||
label: bind template.item as <$RecentObject>.filename;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
using Gtk 4.0;
|
|
||||||
using Adw 1;
|
|
||||||
|
|
||||||
Adw.AlertDialog dialog1 {
|
|
||||||
responses [
|
|
||||||
ok: "Ok",
|
|
||||||
cancel: "Cancel",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
Button cancel {}
|
|
|
@ -1,16 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,17 +0,0 @@
|
||||||
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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,18 +0,0 @@
|
||||||
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;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
<?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>
|
|
|
@ -1,7 +0,0 @@
|
||||||
using Gtk 4.0;
|
|
||||||
|
|
||||||
template $MyTemplate {
|
|
||||||
Button {
|
|
||||||
clicked => $my_signal_handler(template);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
<?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>
|
|
|
@ -181,7 +181,11 @@ class TestSamples(unittest.TestCase):
|
||||||
|
|
||||||
def test_samples(self):
|
def test_samples(self):
|
||||||
# list the samples directory
|
# list the samples directory
|
||||||
samples = [f.stem for f in Path(__file__).parent.glob("samples/*.blp")]
|
samples = [
|
||||||
|
f.stem
|
||||||
|
for f in Path(__file__).parent.glob("samples/*.blp")
|
||||||
|
if not f.stem.endswith("_dec")
|
||||||
|
]
|
||||||
samples.sort()
|
samples.sort()
|
||||||
for sample in samples:
|
for sample in samples:
|
||||||
REQUIRE_ADW_1_4 = ["adw_breakpoint"]
|
REQUIRE_ADW_1_4 = ["adw_breakpoint"]
|
||||||
|
@ -198,7 +202,6 @@ class TestSamples(unittest.TestCase):
|
||||||
"parseable",
|
"parseable",
|
||||||
"signal",
|
"signal",
|
||||||
"signal_not_swapped",
|
"signal_not_swapped",
|
||||||
"signal_template_object",
|
|
||||||
"template",
|
"template",
|
||||||
"template_binding",
|
"template_binding",
|
||||||
"template_binding_extern",
|
"template_binding_extern",
|
||||||
|
@ -212,7 +215,7 @@ class TestSamples(unittest.TestCase):
|
||||||
]
|
]
|
||||||
|
|
||||||
# Decompiler-only tests
|
# Decompiler-only tests
|
||||||
SKIP_COMPILE = ["issue_177", "issue_187", "translator_comments"]
|
SKIP_COMPILE = ["issue_177", "translator_comments"]
|
||||||
|
|
||||||
SKIP_DECOMPILE = [
|
SKIP_DECOMPILE = [
|
||||||
# Comments are not preserved in either direction
|
# Comments are not preserved in either direction
|
||||||
|
@ -225,7 +228,7 @@ class TestSamples(unittest.TestCase):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
with self.subTest(sample):
|
with self.subTest(sample):
|
||||||
if sample not in SKIP_COMPILE and not sample.endswith("_dec"):
|
if sample not in SKIP_COMPILE:
|
||||||
self.assert_sample(sample, skip_run=sample in SKIP_RUN)
|
self.assert_sample(sample, skip_run=sample in SKIP_RUN)
|
||||||
|
|
||||||
with self.subTest("decompile/" + sample):
|
with self.subTest("decompile/" + sample):
|
||||||
|
|
|
@ -25,7 +25,7 @@ from blueprintcompiler.tokenizer import Token, TokenType, tokenize
|
||||||
|
|
||||||
|
|
||||||
class TestTokenizer(unittest.TestCase):
|
class TestTokenizer(unittest.TestCase):
|
||||||
def assert_tokenize(self, string: str, expect: list[Token]):
|
def assert_tokenize(self, string: str, expect: [Token]):
|
||||||
try:
|
try:
|
||||||
tokens = tokenize(string)
|
tokens = tokenize(string)
|
||||||
self.assertEqual(len(tokens), len(expect))
|
self.assertEqual(len(tokens), len(expect))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue