starlark icon indicating copy to clipboard operation
starlark copied to clipboard

Add a string function that dedents multi-line strings

Open fmeum opened this issue 11 months ago • 2 comments

The usability of multi-line string literals could be greatly improved if there was a way to have leading and trailing newlines stripped and common indent removed, similar to how Java textblocks work. Python doesn't do this, but offers functions such as inspect.cleandoc and textwrap.dedent that perform such postprocessing. It would be very convenient for Starlark strings to provide such a function as a member function.

Before:

def f():
    return """\
foo
bar
baz"""

After:

def f():
    return """
        foo
        bar
        baz
        """.dedented()

Implementations could detect obvious calls to detended() and optimize them so that there is a single dedented string instance.

fmeum avatar Jan 17 '25 12:01 fmeum

cleandoc() seems like nice behavior. I remember dedent() being not too useful, because it didn't handle strings with text on the same line as the opening triple quote. (Java textblocks eliminated that ambiguity by requiring the first line of text to start on the line after the quotes.)

In Bazel we have a lot of doc=... annotations. I don't think it'd be a nice experience to expect users to call .dedented() every time. Hence, the doc tool (stardoc) should be responsible for trimming that spacing. Or you can make the argument that the interpreter itself should do it. But hopefully not the user.

I imagine it can still be helpful in user logic, say for embedding raw content to be written to a file (e.g. in a Bazel rule's write() action).

Side note: If I had my way, there might be a new string literal syntax for this in Python, like

    # ('d' for "dedent")
    content = d"""first line
              second line
              """

But I wouldn't want to break syntactic compatibility with Python over this.

brandjon avatar Mar 12 '25 18:03 brandjon

I imagine it can still be helpful in user logic, say for embedding raw content to be written to a file (e.g. in a Bazel rule's write() action).

This, together with repo rules, is my primary use case. Would you be okay with an explicit method call in that case?

fmeum avatar Mar 12 '25 21:03 fmeum