|
CSR :
|
|
|
Relates :
|
|
|
Relates :
|
Summary
-------
This feature introduces three new String instance methods used to manage
incidental indentation introduced by code aligning a Raw String Literal
in source. These methods may also be used to manage incidental
indentation from strings derived from external sources (ex., character
files.)
Problem
-------
With the introduction of
[JEP 326: Raw String Literals](http://openjdk.java.net/jeps/326),
many developers will make regular use of multi-line strings.
Unfortunately, Raw String Literals are inherently undiscerning of
formatting conventions used in code surrounding the literal. This may
lead to the introduction of leading white space (indentation) not
intended to be included in the content of the string.
In the following example the HTML Raw String Literal is indented
to align with assignment expression. To do so, extra white space is
added to each line (incidental white space denoted with periods).
```
Ex 1.
String html = `
..................<html>
.................. <body>
.................. <p>Hello World</p>
.................. </body>
..................</html>
..................`;
```
However, when the string is used or displayed, that extra white space
may be undesired.
Solution
--------
There are a few incidental indentation removal solutions currently available.
```
Ex 2.
// Remove a fixed number of spaces from each line.
int indent = 18;
String trimmed = html.lines()
.map(s -> s.substring(indent))
.collect(joining("\n", "", "\n"));
Ex 3.
// Remove all leading (and trailing) spaces from each line.
String trimmed = html.lines()
.map(String::strip)
.collect(joining("\n", "", "\n"));
```
However, in many cases the developer would like to keep some spacing to
maintain relative indentation without having to count out how many
spaces to be removed. This proposal provides two solutions;
`String::align()` and `String::indent(int n)`.
`String::align()` after removing all leading and trailing blank lines,
left justifies each line without loss of relative indentation. Thus,
stripping away all incidental indentation and line spacing.
```
Ex 4.
// The manual and aligned are equivalant strings
String manual =
`<html>
<body>
<p>Hello World</p>
</body>
</html>
`;
String aligned = `
.....................<html>
..................... <body>
..................... <p>Hello World</p>
..................... </body>
.....................</html>
.....................`.align();
```
`String::indent(int n)` can be used to control the amount of white space
added or removed from each line; a positive n adds n spaces (U+0020) and
negative n removes n white spaces.
```
Ex 5.
// The manual and stripped are equivalant strings
String manual =
` <html>
<body>
<p>Hello World</p>
</body>
</html>
`;
String aligned = `
.....................<html>
..................... <body>
..................... <p>Hello World</p>
..................... </body>
.....................</html>
.....................`.align().indent(4);
```
In the cases where align() is not what the developer wants, we expect the
preponderance of cases to be align().ident(n). Therefore, an additional
variation of `align` will be provided: `String::align(int n)` where `n`
is the indentation applied to the string after _alignment_.
```
Ex 6.
// The manual and stripped are equivalant strings
String manual =
` <html>
<body>
<p>Hello World</p>
</body>
</html>
`;
String aligned = `
.....................<html>
..................... <body>
..................... <p>Hello World</p>
..................... </body>
.....................</html>
.....................`.align(4);
```
Specification
-------------
```
/**
* Adjusts the indentation of each line of this string based on the value of
* {@code n}, and normalizes line termination characters.
* <p>
* This string is conceptually separated into lines using
* {@link String#lines()}. Each line is then adjusted as described below
* and then suffixed with a line feed {@code "\n"} (U+000A). The resulting
* lines are then concatenated and returned.
* <p>
* If {@code n > 0} then {@code n} spaces (U+0020) are inserted at the
* beginning of each line. {@link String#isBlank() Blank lines} are
* unaffected.
* <p>
* If {@code n < 0} then up to {@code n}
* {@link Character#isWhitespace(int) white space characters} are removed
* from the beginning of each line. If a given line does not contain
* sufficient white space then all leading
* {@link Character#isWhitespace(int) white space characters} are removed.
* Each white space character is treated as a single character. In
* particular, the tab character {@code "\t"} (U+0009) is considered a
* single character; it is not expanded.
* <p>
* If {@code n == 0} then the line remains unchanged. However, line
* terminators are still normalized.
* <p>
*
* @param n number of leading
* {@link Character#isWhitespace(int) white space characters}
* to add or remove
*
* @return string with indentation adjusted and line endings normalized
*
* @see String#lines()
* @see String#isBlank()
* @see Character#isWhitespace(int)
*
* @since 12
*/
public String indent(int n) {
/**
* Removes vertical and horizontal white space from around the
* essential body of this string's lines, while preserving relative
* indentation.
* <p>
* This string is first conceptually separated into lines as if by
* {@link String#lines()}.
* <p>
* Then, the <i>minimum indentation</i> (min) is determined as follows. For
* each non-blank line (as defined by {@link String#isBlank()}), the
* leading {@link Character#isWhitespace(int) white space} characters are
* counted. The <i>min</i> value is the smallest of these counts.
* <p>
* For each non-blank line, <i>min</i> leading white space characters are
* removed. Each white space character is treated as a single character. In
* particular, the tab character {@code "\t"} (U+0009) is considered a
* single character; it is not expanded.
* <p>
* Leading and trailing blank lines, if any, are removed. Trailing spaces are
* preserved.
* <p>
* Each line is suffixed with a line feed character {@code "\n"} (U+000A).
* <p>
* Finally, the lines are concatenated into a single string and returned.
*
* @apiNote
* This method's primary purpose is to shift a block of lines as far as
* possible to the left, while preserving relative indentation. Lines
* that were indented the least will thus have no leading white space.
*
* Example:
* <blockquote><pre>
* `
* This is the first line
* This is the second line
* `.align();
*
* returns
* This is the first line
* This is the second line
* </pre></blockquote>
*
* @return string with margins removed and line terminators normalized
*
* @see String#lines()
* @see String#isBlank()
* @see String#indent(int)
* @see Character#isWhitespace(int)
*
* @since 12
*/
public String align() {
/**
* Removes vertical and horizontal white space from around the
* essential body of this string's lines, while preserving relative
* indentation with optional indentation adjustment.
* <p>
* Invoking this method is equivalent to:
* <blockquote>
* {@code this.align().indent(n)}
* </blockquote>
*
* @apiNote
* Examples:
* <blockquote><pre>
* `
* This is the first line
* This is the second line
* `.align(0);
*
* returns
* This is the first line
* This is the second line
*
*
* `
* This is the first line
* This is the second line
* `.align(4);
* returns
* This is the first line
* This is the second line
* </pre></blockquote>
*
* @param n number of leading white space characters
* to add or remove
*
* @return string with margins removed, indentation adjusted and
* line terminators normalized
*
* @see String#align()
*
* @since 12
*/
public String align(int n) {
```
|