We’re going to try align.

Example:

    String a = `
                   abc
                   def
                   ghi
               `.align();

Result:
    abc
    def
    ghi

Example:

    String b = `
                   abc
                   def
                   ghi
               `.align(4);
Result:
        abc
        def
        ghi

Example:

    String c = `
                   abc
                   def
                   ghi
               `.align(-1);
Result:
abc
def
ghi

Implementation:

/**
 * When applied to a string, left justifies
 * lines without loss of relative indentation. This is
 * accomplished by removing an equal number of
 * {@link Character#isWhitespace(int) white space} characters
 * from each line so that at least one line has a non-white
 * space character in the left-most position.
 * The result is realigned by indenting {@code n}
 * {@link Character#isWhitespace(int) white space}
 * characters.
 * First and last blank lines introduced to allow
 * bracketing  delimiters to appear on separate source lines
 * are also removed.
 * <p>
 * @apinote All
 *          {@link Character#isWhitespace(int) white space characters},
 *          including tab, are treated as a single space.
 * <p>
 * @apiNote The all line terminators in the result will be
 *          replaced with line feed {@code "\n"} ({@code U+000A}).
 *
 * @param n  number of leading white space characters
 *           to adjust
 *
 * @return string left justified
 *
 * @see Character#isWhitespace(int)
 * @see String#indent(int)
 * @see String#lines()
 * @see String#lines(LinesOptions... options)
 *
 * @since 11
 */
public String align(int n) {
    if (isEmpty()) {
        return "";
    }
    int min = lines().skip(1)
                     .filter(not(String::isEmpty))
                     .mapToInt(String::indexOfNonWhitespace)
                     .min()
                     .orElse(0);
    return indent(n - min, true);
}

/**
 * When applied to a string, left justifies
 * lines without loss of relative indentation. This is
 * accomplished by removing an equal number of
 * {@link Character#isWhitespace(int) white space} characters
 * from each line so that at least one line has a non-white
 * space character in the left-most position.
 * First and last blank lines introduced to allow
 * bracketing  delimiters to appear on separate source lines
 * are also removed.
 * <p>
 * @apinote All
 *          {@link Character#isWhitespace(int) white space characters},
 *          including tab, are treated as a single space.
 * <p>
 * @apiNote The all line terminators in the result will be
 *          replaced with line feed {@code "\n"} ({@code U+000A}).
 *
 * @return string left justified
 *
 * @see Character#isWhitespace(int)
 * @see String#indent(int)
 * @see String#lines()
 * @see String#lines(LinesOptions... options)
 *
 * @since 11
 */
public String align() {
    return align(0);
}

With lines, we’re going to drop the LinesOptions silliness and just go with 
maxLeading and maxTrailing.

Example:

    int d = `
                abc
                def
                ghi
            `.lines().count();

Result:
5

Example:

    int e = `
                abc
                def
                ghi
            `.lines(1, 1).count();

Result:
3

Example:

    int f = `



                abc
                def
                ghi



            `.lines(Integer.Max_VALUE,Integer.Max_VALUE).count();

Result:
3

Implementation:

/**
 * Returns a stream of substrings extracted from this string
 * partitioned by line terminators.
 * <p>
 * Line terminators recognized are line feed
 * {@code "\n"} ({@code U+000A}),
 * carriage return
 * {@code "\r"} ({@code U+000D})
 * and a carriage return followed immediately by a line feed
 * {@code "\r\n"} ({@code U+000D U+000A}).
 * <p>
 * The stream returned by this method contains each line of
 * this string that is terminated by a line terminator except that
 * the last line can either be terminated by a line terminator or the
 * end of the string.
 * The lines in the stream are in the order in which
 * they occur in this string and do not include the line terminators
 * partitioning the lines.
 * <p>
 * The {@code maxLeading} and {@code maxTrailing} arguments can be
 * used to remove incidental blank lines from the beginning and
 * end of a multi-line sequence. A value of {@code 1} will remove
 * at most one blank line. A value of {@link Integer.MAX_VALUE}
 * will all leading or trailing blank lines.
 *
 * @implNote This method provides better performance than
 *           split("\R") by supplying elements lazily and
 *           by faster search of new line terminators.
 *
 * @param  maxLeading   the maximum number of leading blank lines
 *                      to remove
 *
 * @param  maxTrailing  the maximum number of trailing blank lines
 *                      to remove
 *
 * @return  the stream of strings extracted from this string
 *          partitioned by line terminators
 *
 * @throws  IllegalArgumentException if {@code maxLeading} or
 *          {@code maxTrailing} is negative.
 *
 * @since 11
 */
public Stream<String> lines(int maxLeading, int maxTrailing) {
    if (maxLeading < 0) {
        throw new IllegalArgumentException("maxLeading is negative: " + 
maxLeading);
    }
    if (maxTrailing < 0) {
        throw new IllegalArgumentException("maxTrailing is negative: " + 
maxTrailing);
    }
    Stream<String> stream = isLatin1() ? StringLatin1.lines(value, maxLeading, 
maxTrailing)
                                       : StringUTF16.lines(value, maxLeading, 
maxTrailing);
    return stream;
}

/**
 * Returns a stream of substrings extracted from this string
 * partitioned by line terminators.
 * <p>
 * Line terminators recognized are line feed
 * {@code "\n"} ({@code U+000A}),
 * carriage return
 * {@code "\r"} ({@code U+000D})
 * and a carriage return followed immediately by a line feed
 * {@code "\r\n"} ({@code U+000D U+000A}).
 * <p>
 * The stream returned by this method contains each line of
 * this string that is terminated by a line terminator except that
 * the last line can either be terminated by a line terminator or the
 * end of the string.
 * The lines in the stream are in the order in which
 * they occur in this string and do not include the line terminators
 * partitioning the lines.
 *
 * @implNote This method provides better performance than
 *           split("\R") by supplying elements lazily and
 *           by faster search of new line terminators.
 *
 * @return  the stream of strings extracted from this string
 *          partitioned by line terminators
 *
 * @since 11
 */
public Stream<String> lines() {
    return lines(0, 0);
}

> On Jun 7, 2018, at 2:49 PM, Guy Steele <guy.ste...@oracle.com> wrote:
> 
> 
>> On Jun 7, 2018, at 1:48 PM, Brian Goetz <brian.go...@oracle.com 
>> <mailto:brian.go...@oracle.com>> wrote:
>> 
>>> 
>>> Part of the goal was to shorten the name to reduce the annoyance quotient. 
>>> “reindent” speaks to me more than “leftMargin” (starts searching 
>>> thesaurus.) The combo makes sense too. Then you start thinking in terms of 
>>> indent is just reindent without the magic.
>> 
>> reindent() is OK by me; its a little longer but it says what it means, and 
>> still less fussy than trimMargin() or autoMagicReindent().  
>> 
>> undent() is shorter, but sounds more like what happens at an auto-body 
>> repair shop :)
> 
> Or redent(), which happens a week later.  :-)
> 

Reply via email to