2955 *
2956 * @return string with margins removed, indentation adjusted and
2957 * line terminators normalized
2958 *
2959 * @see String#align()
2960 *
2961 * @since 12
2962 */
2963 public String align(int n) {
2964 if (isEmpty()) {
2965 return "";
2966 }
2967 int outdent = lines().filter(not(String::isBlank))
2968 .mapToInt(String::indexOfNonWhitespace)
2969 .min()
2970 .orElse(0);
2971 return indent(n - outdent, true);
2972 }
2973
2974 /**
2975 * This object (which is already a string!) is itself returned.
2976 *
2977 * @return the string itself.
2978 */
2979 public String toString() {
2980 return this;
2981 }
2982
2983 /**
2984 * Returns a stream of {@code int} zero-extending the {@code char} values
2985 * from this sequence. Any char which maps to a <a
2986 * href="{@docRoot}/java.base/java/lang/Character.html#unicode">surrogate code
2987 * point</a> is passed through uninterpreted.
2988 *
2989 * @return an IntStream of char values from this sequence
2990 * @since 9
2991 */
2992 @Override
2993 public IntStream chars() {
2994 return StreamSupport.intStream(
|
2955 *
2956 * @return string with margins removed, indentation adjusted and
2957 * line terminators normalized
2958 *
2959 * @see String#align()
2960 *
2961 * @since 12
2962 */
2963 public String align(int n) {
2964 if (isEmpty()) {
2965 return "";
2966 }
2967 int outdent = lines().filter(not(String::isBlank))
2968 .mapToInt(String::indexOfNonWhitespace)
2969 .min()
2970 .orElse(0);
2971 return indent(n - outdent, true);
2972 }
2973
2974 /**
2975 * Replaces tab (U+0009) characters with enough space
2976 * (U+0020) characters to align to tab stops at
2977 * intervals {@code n}.
2978 *
2979 * @param n number of characters between tab stops
2980 *
2981 * @return this string with tabs replaced with spaces
2982 *
2983 * @throws IllegalArgumentException if n is less that equals to zero.
2984 *
2985 * @since 12
2986 */
2987 public String detab(int n) {
2988 if (n <= 0) {
2989 throw new IllegalArgumentException("n must be greater than zero: " + n);
2990 }
2991 int length = length();
2992 int column = 0;
2993 int spaces = 0;
2994 final StringBuilder sb = new StringBuilder(length * 2);
2995 for (int pos = 0; pos < length; pos++) {
2996 char ch = charAt(pos);
2997 if (ch == ' ') {
2998 spaces++;
2999 } else if (ch == '\t') {
3000 spaces += n - (column + spaces) % n;
3001 } else if (ch == '\n' || ch == '\r') {
3002 sb.append(ch);
3003 column = 0;
3004 spaces = 0;
3005 } else {
3006 if (0 < spaces) {
3007 column += spaces;
3008 while (0 < spaces) {
3009 spaces--;
3010 sb.append(' ');
3011 }
3012 }
3013 sb.append(ch);
3014 column++;
3015 }
3016 }
3017 return sb.toString();
3018 }
3019
3020 /**
3021 * Replaces some space (U+0020) characters with tab
3022 * (U+0009) characters if the spacing aligns to tab
3023 * stops at intervals {@code n}.
3024 *
3025 * @param n number of characters between tab stops
3026 *
3027 * @return this string with some spaces replaced with tabs
3028 *
3029 * @throws IllegalArgumentException if n is less that equals to zero.
3030 *
3031 * @since 12
3032 */
3033 public String entab(int n) {
3034 if (n <= 0) {
3035 throw new IllegalArgumentException("n must be greater than zero: " + n);
3036 }
3037 int length = length();
3038 int column = 0;
3039 int spaces = 0;
3040 final StringBuilder sb = new StringBuilder(length);
3041 for (int i = 0; i < length; i++) {
3042 char ch = charAt(i);
3043 if (ch == ' ') {
3044 spaces++;
3045 } else if (ch == '\t') {
3046 spaces += n - (column + spaces) % n;
3047 } else if (ch == '\n' || ch == '\r') {
3048 sb.append(ch);
3049 column = 0;
3050 spaces = 0;
3051 } else {
3052 if (0 < spaces) {
3053 int nexttab = n - column % n;
3054 column += spaces;
3055 while (nexttab <= spaces) {
3056 spaces -= nexttab;
3057 nexttab = n;
3058 sb.append('\t');
3059 }
3060 while (0 < spaces) {
3061 spaces--;
3062 sb.append(' ');
3063 }
3064 }
3065 sb.append(ch);
3066 column++;
3067 }
3068 }
3069 return sb.toString();
3070 }
3071
3072 /**
3073 * This object (which is already a string!) is itself returned.
3074 *
3075 * @return the string itself.
3076 */
3077 public String toString() {
3078 return this;
3079 }
3080
3081 /**
3082 * Returns a stream of {@code int} zero-extending the {@code char} values
3083 * from this sequence. Any char which maps to a <a
3084 * href="{@docRoot}/java.base/java/lang/Character.html#unicode">surrogate code
3085 * point</a> is passed through uninterpreted.
3086 *
3087 * @return an IntStream of char values from this sequence
3088 * @since 9
3089 */
3090 @Override
3091 public IntStream chars() {
3092 return StreamSupport.intStream(
|