15

Can anyone suggest a method for writing a mutli-line String to a system console and having that text block be indented? I'm looking for something relatively lightweight because it's only being used for displaying help for a command line program.

BillMan
  • 9,434
  • 9
  • 32
  • 52
  • 1
    Do you have a string that contains linebreaks, or do you want auto-wrapping, or do you just have multiple lines and want to align them in some tabular format? In short: please give an example of input and desired output. – Cephalopod Apr 08 '13 at 21:14
  • 1
    @Arian. I would like auto-wrapping. Something similar to how man pages are formatted. I was hoping for something lightweight, but maybe some sort of template language is the only way. – BillMan Apr 09 '13 at 11:51
  • What about splitting the string at spaces and inserting a line break whenever a word exceeds line width? – Cephalopod Apr 09 '13 at 18:51
  • I was hoping that there was something already out there to do this for me. I did a little research and it seems like something as simple as getting the console width isn't supported in a cross platform way. I'm not sure why this doesn't get more attention, but I think it should. I don't see the command line going away anytime soon. – BillMan Apr 09 '13 at 19:07
  • These answers may be useful: http://stackoverflow.com/questions/19425508/format-text-output-for-console-in-java – joelittlejohn Oct 27 '16 at 15:08

2 Answers2

45

NOTE: The approach described below does not meet the updated requirements described by @BillMan in the question's comments. This will not automatically wrap lines that are longer than the console line length - only use this approach if wrapping isn't an issue.


As a simple option, you could use String.replaceAll() as follows:
String output = <your string here>
String indented = output.replaceAll("(?m)^", "\t");

If you're unfamiliar with Java regular expressions, it works as follows:

  • (?m) enables multiline mode. This means each line in output is considered individually, instead of treating output as a single line (which is the default).
  • ^ is a regex matching the start of each line.
  • \t causes each match of the preceding regex (i.e. the start of each line) to be replaced by a tab character.

As an example, the following code:

String output = "foo\nbar\nbaz\n"
String indented = output.replaceAll("(?m)^", "\t");
System.out.println(indented);

Produces this output:

	foo
	bar
	baz
Community
  • 1
  • 1
Mac
  • 14,615
  • 9
  • 62
  • 80
  • I don't think this is what the OP is looking for, as lines that are too long are wrapped by the console and not indented. I think what's needed here is a method that a) wraps to N char limit (e.g. 80 chars) but splits on words and b) indents each line, even the ones that have been wrapped. – joelittlejohn Oct 27 '16 at 15:06
  • 4
    @joelittlejohn: you are right - the updated requirements (added as comments *after* I last looked at this question) are not met by the approach I describe. It may still be useful advice for others with similar requirements, though. I've added a disclaimer to that effect at the top. Thanks for bringing that to my attention. – Mac Oct 28 '16 at 00:47
  • 1
    This was exactly what I needed! ... Except I'm in Java 1.3 land and `replaceAll()` doesn't exist there. – Andrew Keeton Feb 19 '19 at 14:41
  • 1
    @AndrewKeeton: yep, looking at the version history, [regexes were added in 1.4](https://en.wikipedia.org/wiki/Java_version_history#J2SE_1.4). That was **17 years ago** though, are you really stuck with such an ancient Java version? – Mac Feb 19 '19 at 23:12
  • @Mac: Embedded device. It's OK, I didn't need this for anything important. My main point was acknowledging the "It may still be useful advice for others..." comment. – Andrew Keeton Feb 20 '19 at 00:42
6

With JDK/12 early access builds, one can now make use of the indent API of the String class which is currently available under the preview feature and can be used as :

String indentedBody =
`<html>
   <body>
       <p>Hello World - Indented.</p>
   </body>
</html>`.indent(4);

and the output of the above code would be

    <html>
       <body>
           <p>Hello World - Indented.</p>
       </body>
    </html>

The current documented specification of the API further is as follows:

/**
 * 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)
Naman
  • 27,789
  • 26
  • 218
  • 353
  • 2
    You can read the answer from me on how to [enable preview features and test out with maven](https://stackoverflow.com/a/52232682/1746118) for exploring this via Maven. – Naman Sep 21 '18 at 09:37