@@ -440,10 +440,37 @@ func format_code(script: GDScript, force_reorder := false) -> String:
440440 push_error ("GDScript Formatter Error: Can't format an unsaved script." )
441441 return ""
442442
443- var output : Array = []
444- var error_output : Array = []
445- var formatter_arguments := PackedStringArray (["--stdout" ])
443+ # This is a bit of a hack to avoid two issues:
444+ #
445+ # 1. Running GDScript formatter on stdin/stdout through Godot with
446+ # OS.execute() has encoding issues with UTF-8 characters and we don't have
447+ # control over the output encoding (it might be assuming ASCII characters)
448+ #
449+ # 2. If we modify a file in place using the external formatter from Godot,
450+ # it will bring up a pop-up that warns users that the file has been changed
451+ # outside Godot.
452+ #
453+ # To work around that, I save a copy of the script as a temporary file,
454+ # format the file, and read it specifically as a UTF-8 string.
455+ var source_file := FileAccess .open (ProjectSettings .globalize_path (script_path ), FileAccess .READ )
456+ if not source_file :
457+ push_error ("GDScript Formatter Error: Cannot read source file: " + script_path )
458+ return ""
459+
460+ # FileAccess.get_as_text() reads the file as UTF-8. We use it here and after
461+ # formatting the temporary file.
462+ var source_content := source_file .get_as_text ()
463+ source_file .close ()
446464
465+ var path_temporary_file := OS .get_temp_dir ().path_join ("gdscript_formatter_%d .gd" % Time .get_ticks_msec ())
466+ var temporary_file := FileAccess .open (path_temporary_file , FileAccess .WRITE )
467+ if temporary_file == null :
468+ push_error ("GDScript Formatter Error: Cannot create temporary file: " + path_temporary_file )
469+ return ""
470+ temporary_file .store_string (source_content )
471+ temporary_file .close ()
472+
473+ var formatter_arguments := PackedStringArray ()
447474 if get_editor_setting (SETTING_USE_SPACES ):
448475 formatter_arguments .push_back ("--use-spaces" )
449476 formatter_arguments .push_back ("--indent-size=%d " % get_editor_setting (SETTING_INDENT_SIZE ))
@@ -456,28 +483,35 @@ func format_code(script: GDScript, force_reorder := false) -> String:
456483 if get_editor_setting (SETTING_SAFE_MODE ):
457484 formatter_arguments .push_back ("--safe" )
458485
459- formatter_arguments .push_back (ProjectSettings . globalize_path ( script_path ) )
486+ formatter_arguments .push_back (path_temporary_file )
460487
488+ var output : Array = []
461489 var exit_code := OS .execute (
462490 get_editor_setting (SETTING_FORMATTER_PATH ),
463491 formatter_arguments ,
464492 output ,
465493 )
494+
495+ var formatted_content := ""
466496 if exit_code == OK :
467- if output .is_empty ():
468- push_error ("Format GDScript returned no output for: " + script_path )
469- return ""
470- return output .front ()
497+ var result_file := FileAccess .open (path_temporary_file , FileAccess .READ )
498+ if result_file :
499+ formatted_content = result_file .get_as_text ()
500+ result_file .close ()
501+ else :
502+ push_error ("Format GDScript: Cannot read formatted output from temp file" )
471503 else :
472504 push_error ("Format GDScript failed: " + script_path )
473505 push_error (
474- "\t Exit code: " + str (exit_code ) + " Stdout : " +
475- (output . front () .strip_edges () if output .size () > 0 else "No output" ),
506+ "\t Exit code: " + str (exit_code ) + " Output : " +
507+ (output [ 0 ] .strip_edges () if output .size () > 0 else "No output" ),
476508 )
477- if error_output .size () > 0 :
478- push_error ("\t Stderr: " + error_output .front ().strip_edges ())
479509 push_error ('\t If your script does not have any syntax errors, this might be a formatter bug.' )
480- return ""
510+
511+ if FileAccess .file_exists (path_temporary_file ):
512+ DirAccess .remove_absolute (path_temporary_file )
513+
514+ return formatted_content
481515
482516
483517## Lints a GDScript file using the GDScript Formatter's linter,
0 commit comments