Skip to content

Commit

Permalink
Use ellipsis to indicate truncation; more padding customization
Browse files Browse the repository at this point in the history
  • Loading branch information
mernst committed Oct 21, 2023
1 parent 9d54fb3 commit b2c0da8
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 23 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
## 1.9.0 (????-??-??)

- Require Java 11
- `StringsPlume`: add `rpad` that pads with an arbitrary character
- `StringsPlume`:
* `rpad` and `lpad` add an ellipsis ("...") if it truncates
* `rpad(double, ...)` does not truncate values before the decimal point
* add `rpad` that pads with an arbitrary character
* add `rpad` that never truncates
* add `lpad` that never truncates
- `CollectionsPlume`:
* add method `duplicates()`
* add an overload for `mapCapacity()`
Expand Down
113 changes: 93 additions & 20 deletions src/main/java/org/plumelib/util/StringsPlume.java
Original file line number Diff line number Diff line change
Expand Up @@ -777,62 +777,126 @@ public static String removeWhitespaceBefore(String arg, String delimiter) {
}

/**
* Returns a string of the specified length, truncated if necessary, and padded with spaces to the
* left if necessary.
* Returns a string of the specified length, truncated if necessary (in which case the last 3
* non-truncated characters are replaced by "..."), and padded with spaces to the left if
* necessary.
*
* @param s string to truncate or pad
* @param length goal length
* @param c the character to use for padding
* @param truncate if false, no truncation is done, only padding
* @return {@code s} truncated or padded to {@code length} characters
*/
@SuppressWarnings({
"allcheckers:purity.not.sideeffectfree.call", // side effect to local state
"lock:method.guarantee.violated" // side effect to local state
})
@SideEffectFree
public static String lpad(String s, @NonNegative int length) {
if (s.length() < length) {
public static String lpad(String s, @NonNegative int length, char c, boolean truncate) {
int sLength = s.length();
if (sLength == length) {
return s;
} else if (sLength < length) {
StringBuilder buf = new StringBuilder();
for (int i = s.length(); i < length; i++) {
buf.append(' ');
for (int i = sLength; i < length; i++) {
buf.append(c);
}
return buf.toString() + s;
buf.append(s);
return buf.toString();
} else {
return s.substring(0, length);
if (truncate && length > 3) {
return s.substring(0, length - 3) + "...";
} else {
return s;
}
}
}

/**
* Returns a string of the specified length, truncated if necessary, and padded with the given
* character to the right if necessary.
* Returns a string of the specified length, truncated if necessary (in which case the last 3
* non-truncated characters are replaced by "..."), and padded with `c` to the left if necessary.
*
* @param s string to truncate or pad
* @param length goal length
* @param c character to use for padding
* @return {@code s} truncated or padded to {@code length} characters
*/
@SideEffectFree
public static String lpad(String s, @NonNegative int length, char c) {
return lpad(s, length, c, true);
}

/**
* Returns a string of the specified length, truncated if necessary (in which case the last 3
* non-truncated characters are replaced by "..."), and padded with spaces to the left if
* necessary.
*
* @param s string to truncate or pad
* @param length goal length
* @return {@code s} truncated or padded to {@code length} characters
*/
@SideEffectFree
public static String lpad(String s, @NonNegative int length) {
return lpad(s, length, ' ', true);
}

/**
* Returns a string of the specified length, truncated if necessary (in which case the last 3
* non-truncated characters are replaced by "..."), and padded with the given character to the
* right if necessary.
*
* @param s string to truncate or pad
* @param length goal length
* @param c character to use for padding
* @param truncate if false, no truncation is done, only padding
* @return {@code s} truncated or padded to {@code length} characters
*/
@SuppressWarnings({
"allcheckers:purity.not.sideeffectfree.call", // side effect to local state
"lock:method.guarantee.violated" // side effect to local state
})
@SideEffectFree
public static String rpad(String s, @NonNegative int length, char c) {
if (s.length() < length) {
public static String rpad(String s, @NonNegative int length, char c, boolean truncate) {
int sLength = s.length();
if (sLength == length) {
return s;
} else if (sLength < length) {
StringBuilder buf = new StringBuilder(s);
for (int i = s.length(); i < length; i++) {
for (int i = sLength; i < length; i++) {
buf.append(c);
}
return buf.toString();
} else {
return s.substring(0, length);
if (truncate && length > 3) {
return s.substring(0, length - 3) + "...";
} else {
return s;
}
}
}

/**
* Returns a string of the specified length, truncated if necessary, and padded with spaces to the
* Returns a string of the specified length, truncated if necessary (in which case the last 3
* non-truncated characters are replaced by "..."), and padded with the given character to the
* right if necessary.
*
* @param s string to truncate or pad
* @param length goal length
* @param c character to use for padding
* @return {@code s} truncated or padded to {@code length} characters
*/
@SideEffectFree
public static String rpad(String s, @NonNegative int length, char c) {
return rpad(s, length, c, true);
}

/**
* Returns a string of the specified length, truncated if necessary (in which case the last 3
* non-truncated characters are replaced by "..."), and padded with spaces to the right if
* necessary.
*
* @param s string to truncate or pad
* @param length goal length
* @return {@code s} truncated or padded to {@code length} characters
*/
@SideEffectFree
Expand All @@ -845,23 +909,32 @@ public static String rpad(String s, @NonNegative int length) {
*
* @param num int whose string representation to truncate or pad
* @param length goal length
* @return a string representation of {@code num} truncated or padded to {@code length} characters
* @return a string representation of {@code num} padded to {@code length} characters
*/
@SideEffectFree
public static String rpad(int num, @NonNegative int length) {
return rpad(String.valueOf(num), length);
return rpad(String.valueOf(num), length, ' ', /* truncate= */ false);
}

/**
* Converts the double to a String, then formats it using {@link #rpad(String,int)}.
* Converts the double to a String, then formats it using {@link #rpad(String,int)}. Does not do
* truncation that is after a decimal point.
*
* @param num double whose string representation to truncate or pad
* @param length goal length
* @return a string representation of {@code num} truncated or padded to {@code length} characters
* @return a string representation of {@code num} padded to {@code length} characters
*/
@SideEffectFree
public static String rpad(double num, @NonNegative int length) {
return rpad(String.valueOf(num), length);
String numString = String.valueOf(num);
int dotIndex = numString.indexOf('.');
if (dotIndex > length) {
return numString.substring(0, dotIndex);
} else if (dotIndex == length) {
return rpad(numString.substring(0, dotIndex), length);
} else {
return rpad(numString, length, ' ');
}
}

///////////////////////////////////////////////////////////////////////////
Expand Down
12 changes: 10 additions & 2 deletions src/test/java/org/plumelib/util/StringsPlumeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,18 @@ public void test_rpad() {
assertEquals(" ", StringsPlume.rpad("", 5));
assertEquals("abcd ", StringsPlume.rpad("abcd", 5));
assertEquals("abcde", StringsPlume.rpad("abcde", 5));
assertEquals("abcde", StringsPlume.rpad("abcdef", 5));
assertEquals("abcde", StringsPlume.rpad("abcde ghij", 5));
assertEquals("ab...", StringsPlume.rpad("abcdef", 5));
assertEquals("ab...", StringsPlume.rpad("abcde ghij", 5));
assertEquals("10 ", StringsPlume.rpad(10, 5));
assertEquals("3.14 ", StringsPlume.rpad(3.14, 5));
assertEquals("3.141592", StringsPlume.rpad(3.141592, 5));
assertEquals("3141592", StringsPlume.rpad(3141592, 5));
assertEquals("12", StringsPlume.rpad(12.34567, 1));
assertEquals("12", StringsPlume.rpad(12.34567, 2));
assertEquals("12 ", StringsPlume.rpad(12.34567, 3));
assertEquals("12.3", StringsPlume.rpad(12.34567, 4));
assertEquals("12.34", StringsPlume.rpad(12.34567, 5));
assertEquals("12.345", StringsPlume.rpad(12.34567, 6));

// public static class NullableStringComparator
// public int compare(Object o1, Object o2)
Expand Down

0 comments on commit b2c0da8

Please sign in to comment.