Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8200435

String::align, String::indent

    Details

    • Type: CSR
    • Status: Closed
    • Priority: P3
    • Resolution: Approved
    • Fix Version/s: 12
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Compatibility Risk:
      minimal
    • Interface Kind:
      Java API
    • Scope:
      SE

      Description

      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, 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) {

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                jlaskey Jim Laskey
                Reporter:
                jlaskey Jim Laskey
                Reviewed By:
                John Rose, Roger Riggs, Sundararajan Athijegannathan, Xueming Shen
              • Votes:
                0 Vote for this issue
                Watchers:
                5 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: