1414
1515import tkinter # Ensure tkinter is available for GUI extensions
1616
17+ def _print_error (msg : str ) -> None :
18+ """Print an error message to stderr prefixed with U+0007 (BEL)."""
19+ print ("\u0007 " + str (msg ), file = sys .stderr )
20+
1721
1822def _print_internal_error (* , exc : BaseException , interpreter : Optional [Interpreter ] = None , verbose : bool = False , traceback_json : bool = False ) -> int :
1923 """Last-resort error handler.
@@ -37,15 +41,15 @@ def _print_internal_error(*, exc: BaseException, interpreter: Optional[Interpret
3741 if interpreter .logger .entries :
3842 error .step_index = interpreter .logger .entries [- 1 ].step_index
3943 formatter = TracebackFormatter (interpreter )
40- print (formatter .format_text (error , verbose = verbose ), file = sys . stderr )
44+ _print_error (formatter .format_text (error , verbose = verbose ))
4145 if traceback_json :
42- print (formatter .to_json (error ), file = sys . stderr )
46+ _print_error (formatter .to_json (error ))
4347 return 1
4448 except Exception :
4549 # If formatting itself fails, fall back to a simple one-liner.
4650 pass
4751
48- print (message , file = sys . stderr )
52+ _print_error (message )
4953 return 1
5054
5155
@@ -112,7 +116,7 @@ def _output_sink(text: str) -> None:
112116 try :
113117 return runner (ctx )
114118 except ASMExtensionError as exc :
115- print (f"ExtensionError: { exc } " , file = sys . stderr )
119+ _print_error (f"ExtensionError: { exc } " )
116120 return 1
117121 except BaseException as exc :
118122 return _print_internal_error (exc = exc , interpreter = None , verbose = verbose )
@@ -127,7 +131,7 @@ def _output_sink(text: str) -> None:
127131 output_sink = _output_sink ,
128132 )
129133 except ASMExtensionError as exc :
130- print (f"ExtensionError: { exc } " , file = sys . stderr )
134+ _print_error (f"ExtensionError: { exc } " )
131135 return 1
132136 except BaseException as exc :
133137 return _print_internal_error (exc = exc , interpreter = None , verbose = verbose )
@@ -174,7 +178,7 @@ def _output_sink(text: str) -> None:
174178 if interpreter .logger .entries :
175179 error .step_index = interpreter .logger .entries [- 1 ].step_index
176180 formatter = TracebackFormatter (interpreter )
177- print (formatter .format_text (error , verbose = interpreter .verbose ), file = sys . stderr )
181+ _print_error (formatter .format_text (error , verbose = interpreter .verbose ))
178182 interpreter .call_stack = [global_frame ]
179183 except ASMParseError :
180184 # If a single-line parse fails, treat it as start of multi-line input
@@ -192,12 +196,12 @@ def _output_sink(text: str) -> None:
192196 except ExitSignal as sig :
193197 return sig .code
194198 except ASMParseError as error :
195- print (f"ParseError: { error } " , file = sys . stderr )
199+ _print_error (f"ParseError: { error } " )
196200 except ASMRuntimeError as error :
197201 if interpreter .logger .entries :
198202 error .step_index = interpreter .logger .entries [- 1 ].step_index
199203 formatter = TracebackFormatter (interpreter )
200- print (formatter .format_text (error , verbose = interpreter .verbose ), file = sys . stderr )
204+ _print_error (formatter .format_text (error , verbose = interpreter .verbose ))
201205 # reset call stack to single top-level frame to keep REPL usable
202206 interpreter .call_stack = [global_frame ]
203207 except BaseException as exc :
@@ -263,21 +267,21 @@ def run_cli(argv: Optional[List[str]] = None) -> int:
263267 try :
264268 services = load_runtime_services (ext_paths ) if ext_paths else load_runtime_services ([])
265269 except ASMExtensionError as exc :
266- print (f"ExtensionError: { exc } " , file = sys . stderr )
270+ _print_error (f"ExtensionError: { exc } " )
267271 return 1
268272 except BaseException as exc :
269273 return _print_internal_error (exc = exc , interpreter = None , verbose = bool (getattr (args , "verbose" , False )))
270274
271275 program : Optional [str ] = None
272276 if remaining :
273277 if len (remaining ) > 1 :
274- print ("Too many non-extension inputs; expected a single program argument" , file = sys . stderr )
278+ _print_error ("Too many non-extension inputs; expected a single program argument" )
275279 return 1
276280 program = remaining [0 ]
277281
278282 if program is None :
279283 if args .source_mode and not ext_paths :
280- print ("-source requires a program string" , file = sys . stderr )
284+ _print_error ("-source requires a program string" )
281285 return 1
282286 # If only extensions are present, run REPL with the loaded extensions.
283287 return run_repl (verbose = args .verbose , services = services )
@@ -291,30 +295,30 @@ def run_cli(argv: Optional[List[str]] = None) -> int:
291295 with open (filename , "r" , encoding = "utf-8" ) as handle :
292296 source_text = handle .read ()
293297 except OSError as exc :
294- print (f"Failed to read { filename } : { exc } " , file = sys . stderr )
298+ _print_error (f"Failed to read { filename } : { exc } " )
295299 return 1
296300
297301 interpreter : Optional [Interpreter ] = None
298302 try :
299303 interpreter = Interpreter (source = source_text , filename = filename , verbose = args .verbose , services = services )
300304 except ASMExtensionError as exc :
301- print (f"ExtensionError: { exc } " , file = sys . stderr )
305+ _print_error (f"ExtensionError: { exc } " )
302306 return 1
303307 except BaseException as exc :
304308 return _print_internal_error (exc = exc , interpreter = None , verbose = args .verbose , traceback_json = args .traceback_json )
305309
306310 try :
307311 interpreter .run ()
308312 except ASMParseError as error :
309- print (f"ParseError: { error } " , file = sys . stderr )
313+ _print_error (f"ParseError: { error } " )
310314 return 1
311315 except ExitSignal as sig :
312316 return sig .code
313317 except ASMRuntimeError as error :
314318 formatter = TracebackFormatter (interpreter )
315- print (formatter .format_text (error , verbose = args .verbose ), file = sys . stderr )
319+ _print_error (formatter .format_text (error , verbose = args .verbose ))
316320 if args .traceback_json :
317- print (formatter .to_json (error ), file = sys . stderr )
321+ _print_error (formatter .to_json (error ))
318322 return 1
319323 except BaseException as exc :
320324 return _print_internal_error (exc = exc , interpreter = interpreter , verbose = args .verbose , traceback_json = args .traceback_json )
0 commit comments