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 <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. :-) >> >