diff --git a/blueprintcompiler/errors.py b/blueprintcompiler/errors.py index 8ee80b9..a8ea224 100644 --- a/blueprintcompiler/errors.py +++ b/blueprintcompiler/errors.py @@ -80,14 +80,16 @@ class CompileError(PrintableError): self.hint("Are your dependencies up to date?") def pretty_print(self, filename, code, stream=sys.stdout): - line_num, col_num = utils.idx_to_pos(self.start + 1, code) - line = code.splitlines(True)[line_num] + stream.write(f"""{self.color}{Colors.BOLD}{self.category}: {self.message}{Colors.CLEAR}\n""") - # Display 1-based line numbers - line_num += 1 + if code is not None and self.start is not None: + line_num, col_num = utils.idx_to_pos(self.start + 1, code) + line = code.splitlines(True)[line_num] - stream.write(f"""{self.color}{Colors.BOLD}{self.category}: {self.message}{Colors.CLEAR} -at {filename} line {line_num} column {col_num}: + # Display 1-based line numbers + line_num += 1 + + stream.write(f"""at {filename} line {line_num} column {col_num}: {Colors.FAINT}{line_num :>4} |{Colors.CLEAR}{line.rstrip()}\n {Colors.FAINT}|{" "*(col_num-1)}^{Colors.CLEAR}\n""") for hint in self.hints: @@ -115,6 +117,15 @@ class UnexpectedTokenError(CompileError): super().__init__("Unexpected tokens", start, end) +class GtkTypelibMissingError(CompileError): + def __init__(self, **kwargs): + super().__init__( + "Could not find GTK 4 introspection files. Is gobject-introspection installed?", + fatal=True, + **kwargs + ) + + @dataclass class CodeAction: title: str diff --git a/blueprintcompiler/gir.py b/blueprintcompiler/gir.py index 2b09027..c497590 100644 --- a/blueprintcompiler/gir.py +++ b/blueprintcompiler/gir.py @@ -25,7 +25,7 @@ import gi # type: ignore gi.require_version("GIRepository", "2.0") from gi.repository import GIRepository # type: ignore -from .errors import CompileError, CompilerBugError +from .errors import CompileError, CompilerBugError, GtkTypelibMissingError from . import typelib, xml_reader _namespace_cache = {} @@ -49,10 +49,15 @@ def get_namespace(namespace, version): break if filename not in _namespace_cache: - raise CompileError( - f"Namespace {namespace}-{version} could not be found", - hints=["search path: " + os.pathsep.join(search_paths)], - ) + hints = ["search path: " + os.pathsep.join(search_paths)] + + if namespace == "Gtk": + raise GtkTypelibMissingError(hints=hints) + else: + raise CompileError( + f"Namespace {namespace}-{version} could not be found", + hints=hints, + ) return _namespace_cache[filename] diff --git a/blueprintcompiler/interactive_port.py b/blueprintcompiler/interactive_port.py index ff551df..3f9343c 100644 --- a/blueprintcompiler/interactive_port.py +++ b/blueprintcompiler/interactive_port.py @@ -23,7 +23,7 @@ import difflib import os from . import decompiler, tokenizer, parser -from .errors import MultipleErrors, PrintableError +from .errors import MultipleErrors, PrintableError, GtkTypelibMissingError from .utils import Colors @@ -156,11 +156,15 @@ def step2(): def step3(): print(f"{Colors.BOLD}STEP 3: Convert UI files{Colors.CLEAR}") - files = [ - (file, change_suffix(file), decompile_file(file, change_suffix(file))) - for file in listdir_recursive(".") - if file.endswith(".ui") - ] + try: + files = [ + (file, change_suffix(file), decompile_file(file, change_suffix(file))) + for file in listdir_recursive(".") + if file.endswith(".ui") + ] + except GtkTypelibMissingError as e: + e.pretty_print(None, None) + return ([], []) success = 0 for in_file, out_file, result in files: diff --git a/blueprintcompiler/language/imports.py b/blueprintcompiler/language/imports.py index 4fac192..fd21098 100644 --- a/blueprintcompiler/language/imports.py +++ b/blueprintcompiler/language/imports.py @@ -40,17 +40,7 @@ class GtkDirective(AstNode): err.hint("Expected 'using Gtk 4.0;'") raise err - try: - gir.get_namespace("Gtk", version) - except CompileError as e: - raise CompileError( - "Could not find GTK 4 introspection files. Is gobject-introspection installed?", - fatal=True, - # preserve the hints from the original error, because it contains - # useful debugging information - hints=e.hints, - ) - + gir.get_namespace("Gtk", version) @property def gir_namespace(self):