Thank you.
> On Jun 8, 2018, at 12:43 PM, Guy Steele <guy.ste...@oracle.com> wrote: > > I think “align” is an excellent choice of method name. > > In the doc, "The result is realigned” => "The result is then realigned” ? > > And the simplification to just `.lines(m, n)` is welcome. If you really want > to eliminate blank lines in the middle, just say `.lines(m, > n).filter(not(String::isEmpty))`. > > —Guy > >> On Jun 8, 2018, at 10:36 AM, Jim Laskey <james.las...@oracle.com >> <mailto:james.las...@oracle.com>> 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 <guy.ste...@oracle.com >>> <mailto: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. :-) >>> >> >