io.termd.core.util.Helper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of termd-core Show documentation
Show all versions of termd-core Show documentation
An open source terminal daemon library providing terminal handling in Java,
back ported to Alibaba by core engine team to support running on JDK 6+.
The newest version!
/*
* Copyright 2015 Julien Viet
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.termd.core.util;
import io.termd.core.function.Consumer;
import io.termd.core.function.IntConsumer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;
/**
* Various utils.
*
* @author Julien Viet
*/
public class Helper {
public static void uncheckedThrow(Throwable throwable) {
Helper.throwIt(throwable);
}
private static void throwIt(Throwable throwable) throws T {
throw (T)throwable;
}
/**
* Do absolutely nothing. This can be useful for code coverage analysis.
*/
public static void noop() {}
/**
* Convert the string to an array of code points.
*
* @param s the string to convert
* @return the code points
*/
public static int[] toCodePoints(String s) {
List codePoints = new ArrayList();
for (int offset = 0; offset < s.length();) {
int cp = s.codePointAt(offset);
codePoints.add(cp);
offset += Character.charCount(cp);
}
return convert(codePoints);
}
/**
* Code point to string conversion.
*
* @param codePoints the code points
* @return the corresponding string
*/
public static String fromCodePoints(int[] codePoints) {
return new String(codePoints, 0, codePoints.length);
}
public static void appendCodePoints(int[] codePoints, final StringBuilder sb) {
consumeTo(codePoints, new IntConsumer() {
@Override
public void accept(int cp) {
sb.appendCodePoint(cp);
}
});
}
public static void consumeTo(int[] i, IntConsumer consumer) {
for (int codePoint : i) {
consumer.accept(codePoint);
}
}
public static List loadServices(ClassLoader loader, Class serviceClass) {
ArrayList services = new ArrayList();
Iterator i = ServiceLoader.load(serviceClass, loader).iterator();
while (i.hasNext()) {
try {
S service = i.next();
services.add(service);
} catch (Exception ignore) {
// Log me
}
}
return services;
}
public static List list(int... list) {
ArrayList result = new ArrayList(list.length);
for (int i : list) {
result.add(i);
}
return result;
}
public static List split(String s, char c) {
List ret = new ArrayList();
int prev = 0;
while (true) {
int pos = s.indexOf('\n', prev);
if (pos == -1) {
break;
}
ret.add(s.substring(prev, pos));
prev = pos + 1;
}
ret.add(s.substring(prev));
return ret;
}
/**
* Escape a string to be printable in a terminal: any non printable char is replaced by its
* octal escape and the {@code \} char is replaced by the @{code \\} sequence.
*
* @param s the string to escape
* @return the escaped string
*/
public static String escape(String s) {
StringBuilder sb = new StringBuilder();
for (int i = 0;i < s.length();i++) {
char c = s.charAt(i);
if (c == 0) {
sb.append("\\0");
} else if (c < 32) {
sb.append("\\");
String octal = Integer.toOctalString(c);
for (int j = octal.length();j < 3;j++) {
sb.append('0');
}
sb.append(octal);
} else if (c == '\\') {
sb.append("\\\\");
} else {
sb.append(c);
}
}
return sb.toString();
}
public static int[] findLongestCommonPrefix(List entries) {
if (entries.isEmpty()) {
return new int[0];
}
int minLen = min(entries);
int len = 0;
out:
while (len < minLen) {
for (int j = 1;j < entries.size();j++) {
if (entries.get(j)[len] != entries.get(j - 1)[len]) {
break out;
}
}
len++;
}
return Arrays.copyOf(entries.get(0), len);
}
public static int[] computeBlock(Vector size, List completions) {
if (completions.size() == 0) {
return new int[0];
}
int max = max(completions);
int row = size.x() / (max + 1);
int count = 0;
StringBuilder sb = new StringBuilder();
for (int[] completion : completions) {
Helper.appendCodePoints(completion, sb);
for (int i = completion.length;i < max;i++) {
sb.append(' ');
}
count++;
if (count < row) {
sb.append(' ');
} else {
sb.append('\n');
count = 0;
}
}
sb.append("\n");
return Helper.toCodePoints(sb.toString());
}
/**
* Compute the position of the char at the specified {@literal offset} of the {@literal codePoints} given a
* {@literal width} and a relative {@literal origin} position.
*
* @param origin the relative position to start from
* @param width the screen width
* @return the height
*/
public static Vector computePosition(int[] codePoints, Vector origin, int offset, int width) {
if (offset < 0) {
throw new IndexOutOfBoundsException("Offset cannot be negative");
}
if (offset > codePoints.length) {
throw new IndexOutOfBoundsException("Offset cannot bebe greater than the length");
}
int col = origin.x();
int row = origin.y();
for (int i = 0;i < offset;i++) {
int cp = codePoints[i];
int w = Wcwidth.of(cp);
if (w == -1) {
if (cp == '\r') {
col = 0;
} else if (cp == '\n') {
col = 0;
row++;
}
} else {
if (col + w > width) {
if (w > width) {
throw new UnsupportedOperationException("Handle this case gracefully");
}
col = 0;
row++;
}
col += w;
if (col >= width) {
col -= width;
row++;
}
}
}
return new Vector(col, row);
}
public static Consumer startedHandler(final CompletableFuture> fut) {
return new Consumer() {
@Override
public void accept(Throwable err) {
if (err == null) {
fut.complete(null);
} else {
fut.completeExceptionally(err);
}
}
};
}
public static Consumer stoppedHandler(final CompletableFuture> fut) {
return new Consumer() {
@Override
public void accept(Throwable err) {
fut.complete(null);
}
};
}
public static int[] convert(List ints) {
int[] result = new int[ints.size()];
for (int index = 0; index < ints.size(); index++) {
result[index] = ints.get(index);
}
return result;
}
private static int min(List entries) {
int minLen = entries.get(0).length;
for (int i = 1; i < entries.size(); i++) {
int len = entries.get(i).length;
if (minLen > len) {
minLen = len;
}
}
return minLen;
}
private static int max(List entries) {
int maxLen = entries.get(0).length;
for (int i = 1; i < entries.size(); i++) {
int len = entries.get(i).length;
if (maxLen < len) {
maxLen = len;
}
}
return maxLen;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy