(inline and at the bottom)

> On Apr 16, 2019, at 8:03 PM, Liam Miller-Cushon <cus...@google.com> wrote:
> 
> On Wed, Apr 10, 2019 at 8:25 AM Jim Laskey <james.las...@oracle.com 
> <mailto:james.las...@oracle.com>> wrote:
> Don’t peek yet.  Stop and comment first.
> 
> Here's a variation on the narrative you provided. This is more thinking aloud 
> than a proposal I'm advocating for, but I think it's a potentially 
> interesting point in the design space.
> 
> Idea: multi-line strings should be formatted like other expressions, rather 
> than a block-like construct (this differs from the 'fat delimiter pattern' in 
> the original message), i.e.:
> 
> String a = """
>         ...
>         """; // +8 expression continuation indent
> 
> Policy: both delimiters must be on a separate line from the contents of the 
> string. This means we can't have 'multi-line' strings that do not span 
> multiple lines of source code.

Stephen also suggests this.  While not unreasonable, it's more of a convention 
than a rule.  We need a strong argument for why to not allow content on the 
same lines.

> 
> Since the closing delimiter's indentation is independent of the position of 
> the opening delimiter, and cannot be on the same line as the string contents, 
> this opens the door to basing the relative indentation off the closing 
> delimiter. (It also avoids needing information from the scanner to manage 
> indentation.)

This has been mentioned before and is "how Swift does it". I tend to favour 
this approach and what String::align did until CSR discussions.

> 
> > What control knobs do we have, that we could assign meaning to, that would 
> > let the user choose either way?
> 
> The position of the closing delimiter.
> 
> > Do we allow content on the same lines as the delimiters?
> 
> No
> 
> > How do we interpret auto-alignment on single-line strings? Strip?
> 
> Single-line strings cannot use `"""`, since we require the delimiters to be 
> on their own line.
> 
> > Should we always add a final newline?
> > Should we strip blanks lines?  Only on the first and last?  All leading and 
> > trailing?
> > Should we right strip lines?
> 
> Maybe (read on for some discussion of trailing newlines). For the most part 
> the other choices don't affect the following examples.
> 
> Examples:
> 
> String a = """
>            +--------+
>            |  text  |
>            +--------+
>            """; // first characters in first column?
> 
> Actual:
> 
> +--------+\n
> |  text  |\n
> +--------+
> 
> String b = """
>                +--------+
>                |  text  |
>                +--------+
>            """; // first characters in first column or indented four spaces?
> 
> Actual: +4 indentation relative to closing delimiter:
> 
>     +--------+\n
>     |  text  |\n
>     +--------+
> 
> String c = """
>                +--------+
>                |  text  |
>                +--------+
> """; // first characters in first column or indented several?
> 
> Actual: indented several, relative to closing delimiter:
> 
>                +--------+\n
>                |  text  |\n
>                +--------+
> 
> String d = """
>     +--------+
>     |  text  |
>     +--------+
> """; // first characters in first column or indented four?
> 
> Actual: +4 indentation relative to closing delimiter:
> 
>     +--------+\n
>     |  text  |\n
>     +--------+
> 
> String e =
> """
> +--------+
> |  text  |
> +--------+
> """; // heredoc?
> 
> Actual:
> 
> +--------+\n
> |  text  |\n
> +--------+
> 
> String f = """
> 
> 
>                +--------+
>                |  text  |
>                +--------+
> 
> 
>            """; // one or all leading or trailing blank lines stripped?
> 
> Actual:
> 
>            \n
>            \n
>            +--------+\n
>            |  text  |\n
>            +--------+\n
>            \n
> 
> 
> Examples g, h, and i are disallowed, since delimiters must be on their own 
> line.
> 
> For j, since delimiters must be on their own line, we'd need something like:
> 
> String j = """
>            public static void
>            """
>            + " " + name 
>            + """
>            (String... args) {
>                System.out.println(String.join(args));
>            }
>            """;
> 
> Using a multi-line string for "public static void" is unnecessary, but I kept 
> that to illustrate what concatenation looks like with multi-line strings. 
> This example suggests we'd usually prefer `String.format` to concatenating 
> multi-line strings under this approach.
> 
> Conclusions:
> 
> Requiring delimiters to be on their own line rules out some potentially 
> surprising edge-cases, and allows indentation management to work without 
> special knowledge from the scanner. It also provides a convenient opt-out 
> mechanism if leading indentation is desired.
> 
> One disadvantage is the handling of the trailing newline. Requiring the 
> closing delimiter to be on its own line means there's always a trailing 
> newline in source. If we want to allow expressing multi-line strings that 
> don't have a trailing newline we could automatically trim one trailing 
> newline character, but then it would be necessary to leave an extra blank 
> line after multi-line strings in cases where a trailing newline is actually 
> desired. Example:
> 
> String message = """
>         hello
>         world
> 
>         """;
> 
> Actual:
> 
> hello\n
> world\n
> 


Not sure that having or not having a new line at the end really matters much.  
Both String::split('\n') and String::lines() are agnostic whether the last \n 
is present.  Of course, it's easier to add than to remove, so not having it 
might be preferable.

But, that is all conditional on the "both delimiters must be on a separate line 
from the contents of the string" rule.  As stated, this is more of a convention 
than a syntax rule. 

Let's go back to having close delimiter influencing indentation and the 
original close delimiter influencing presence of trailing \n.  Can we have 
both?  Do they conflict?  If so, how do we counteract the default action?

So the default alignment would play out as this;

String s = """
                line 1
                line 2
           """;

Actual: 
    line 1\n
    line 2\n


Let's look at the two contrary examples.

// We want to indent 4 but no \n at end
String noNewline = """
                       line 1
                       line 2
                   """;

Actual fail: 
    line 1\n
    line 2\n


In this case, we get the indentation we want, but get a final \n we don't want.

A workaround here is

String noNewline = """
                       line 1
                       line 2""". indent(4);

Actual: 
    line 1\n
    line 2


Next case.

// We want no \n at the end but we want to indent 4
String wrongIndent = """
                         line 1
                         line 2""";

Actual fails: 
line 1\n
line 2

In this case, we drop the \n we want to drop, but get the wrong indentation.

Interestingly, the workaround here is the same

String wrongIndent = """
                         line 1
                         line 2""". indent(4);

Actual: 
    line 1\n
    line 2

So we can have both close delimiter influences, with workarounds for the 
contrary cases.




Reply via email to