Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve readabillity of multiline string blocks #5794

Open
Tracked by #40488
MikeSchulze opened this issue Nov 16, 2022 · 7 comments
Open
Tracked by #40488

Improve readabillity of multiline string blocks #5794

MikeSchulze opened this issue Nov 16, 2022 · 7 comments

Comments

@MikeSchulze
Copy link

Describe the project you are working on

GdUnit3/4 a unit test framework

Describe the problem or limitation you are having in your project

I have an internal test coverage for generated assert error messages.
These error messages can be quite complex, to test them I use multiline strings as references but the formatting is very bad.

func test_dic_is_equal_fail() -> void:
	assert_dict({1:1, "key_b": "value_b"}, GdUnitAssert.EXPECT_FAIL)\
		.is_equal({"key_a": "value_a", 1:1})\
		.has_failure_message("""Expecting:
 '{
1: 1,
"key_a": "value_a"
}'
 but was
 '{
1: 1,
"key_ab": "value_ab"
}'""")

The text block should strip the incidental white spaces to allow better code readabillity.

func test_dic_is_equal_fail() -> void:
	assert_dict({1:1, "key_b": "value_b"}, GdUnitAssert.EXPECT_FAIL)\
		.is_equal({"key_a": "value_a", 1:1})\
		.has_failure_message("""
			Expecting:
			 '{
			1: 1,
			"key_a": "value_a"
			}'
			 but was
			 '{
			1: 1,
			"key_ab": "value_ab"
			}'""")

For better visualisation (using dots to visualize spaces:)

String html = """
..............<html>...
..............    <body>
..............        <p>Hello, world</p>....
..............    </body>.
..............</html>...
..............""";

Should be parsed as (using | to visualize margins:)

|<html>|
|    <body>|
|        <p>Hello, world</p>|
|    </body>|
|</html>|

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Text blocks should follow the same rules as described here https://docs.oracle.com/en/java/javase/15/text-blocks/index.html

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

This improvement allows you to write better formatted code

func test_dic_is_equal_fail() -> void:
	assert_dict({1:1, "key_b": "value_b"}, GdUnitAssert.EXPECT_FAIL)\
		.is_equal({"key_a": "value_a", 1:1})\
		.has_failure_message("""
			Expecting:
			 '{
			1: 1,
			"key_a": "value_a"
			}'
			 but was
			 '{
			1: 1,
			"key_ab": "value_ab"
			}'""")

If this enhancement will not be used often, can it be worked around with a few lines of script?

no workaround exists, would be a core fature

Is there a reason why this should be core and not an add-on in the asset library?

it is not possible because is part of the core GdScript parser

@dalexeev
Copy link
Member

dalexeev commented Nov 16, 2022

Now you can use .dedent() to remove the indentation (in this example, decrease by 2 tabs / 8 spaces):

func _run() -> void:
    print("""
        <html>
            <body>
                <p>Hello, world</p>
            </body>
        </html>
    """.dedent())

We could add a special literal, for example d-strings (dedent), like f-strings and r-strings:

func _run() -> void:
    print(d"""
        <html>
            <body>
                <p>Hello, world</p>
            </body>
        </html>
    """)

But there is a question: how should the initial and final line breaks be handled?

@MikeSchulze
Copy link
Author

MikeSchulze commented Nov 16, 2022

hi .dedent() is not helping me because my string has no inital line break

Try this:

func _run() -> void:
     print("""<html>
                  <body>
                     <p>Hello, world</p>
                 </body>
             </html>
     """.dedent())

The linked document descripes in detail how it should work.
This is the standard for text blocks.

my current workaround is to use .dedent().trim_prefix("\n")

@Calinou
Copy link
Member

Calinou commented Nov 16, 2022

"""some_string""".dedent().trim_prefix("\n").trim_suffix("\n") should handle both leading and trailing newline. It's not pretty to write, but it's the kind of function you could move to an helper function when you need it often.

@MikeSchulze
Copy link
Author

"""some_string""".dedent().trim_prefix("\n").trim_suffix("\n") should handle both leading and trailing newline. It's not pretty to write, but it's the kind of function you could move to an helper function when you need it often.

Yes sure, but is would be nice to have this as standard :)
It will be help to limit the code noise

@MewPurPur
Copy link

I also have doubts about how useful it would be. I would never format my strings like this personally, and I'd assume the same for most people.

@MikeSchulze
Copy link
Author

I also have doubts about how useful it would be. I would never format my strings like this personally, and I'd assume the same for most people.

sorry you like more to write this

func foo() -> void:
	var message = """
This is a message.
With multi lines.
"""
	prints(message)

instead of a good formatted code like this?

func foo() -> void:
	var message = """
		This is a message.
		With multi lines.
		"""
	prints(message)

@MewPurPur
Copy link

MewPurPur commented Nov 18, 2022

True that it's better-formatted, but again I'd just dedent() it and possibly use strip_edges(). Otherwise the user must abide by some arbitrary code style, so the characters inside the string don't get silently cut out. For a constant string, there isn't even a performance reduction.

The idea of changing the standard is almost out of the question now, as it would be a compat-breaking change. It'd be a method, and I can't think of any way to make a useful method for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants