Example:
String c = `
abc
def
ghi
`.align(-1);
Result:
abc
def
ghi
Pasting error. should have been three leading spaces. That is, align() on
column zero would have left 4 spaces in front of each line. 4 - 1 == 3, hence 3
spaces. Using the columns interpretation, the lines are aligned one column to
the left of the page; c.align().indent(-1) or c.lines(1, 1).indent(-1-19).
Another perspective,
Example:
String x = `
abc
def
ghi
`.align(-4);
Result:
abc
def
ghi
- line 0 would land in column zero by the alignment but can not move any
further.
- line 1 would land in column four by the alignment and then indent(-4) ending
up in column zero
- line 2 would land in column eight by the alignment and then indent(-4) ending
up in column four
> On Jun 8, 2018, at 11:36 AM, Jim Laskey <[email protected]> wrote:
>
> 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 <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>>
>>> On Jun 7, 2018, at 1:48 PM, Brian Goetz <[email protected]
>>> <mailto:[email protected]>> 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. :-)
>>
>