/*
 * Copyright (c) 2002-2018, the original author or authors.
 *
 * This software is distributable under the BSD license. See the terms of the
 * BSD license in the documentation provided with this software.
 *
 * https://opensource.org/licenses/BSD-3-Clause
 */
package jdk.internal.org.jline.utils;

import java.io.Flushable;
import java.io.IOError;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Stack;

Curses helper methods.
Author:Guillaume Nodet
/** * Curses helper methods. * * @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a> */
public final class Curses { private static Object[] sv = new Object[26]; private static Object[] dv = new Object[26]; private static final int IFTE_NONE = 0; private static final int IFTE_IF = 1; private static final int IFTE_THEN = 2; private static final int IFTE_ELSE = 3; private Curses() { }
Print the given terminal capabilities
Params:
  • cap – the capability to output
  • params – optional parameters
Returns:the result string
/** * Print the given terminal capabilities * * @param cap the capability to output * @param params optional parameters * @return the result string */
public static String tputs(String cap, Object... params) { if (cap != null) { StringWriter sw = new StringWriter(); tputs(sw, cap, params); return sw.toString(); } return null; }
Print the given terminal capabilities
Params:
  • out – the output stream
  • str – the capability to output
  • params – optional parameters
/** * Print the given terminal capabilities * * @param out the output stream * @param str the capability to output * @param params optional parameters */
public static void tputs(Appendable out, String str, Object... params) { try { doTputs(out, str, params); } catch (Exception e) { throw new IOError(e); } } private static void doTputs(Appendable out, String str, Object... params) throws IOException { int index = 0; int length = str.length(); int ifte = IFTE_NONE; boolean exec = true; Stack<Object> stack = new Stack<>(); while (index < length) { char ch = str.charAt(index++); switch (ch) { case '\\': ch = str.charAt(index++); if (ch >= '0' && ch <= '7') { int val = ch - '0'; for (int i = 0; i < 2; i++) { ch = str.charAt(index++); if (ch < '0' || ch > '7') { throw new IllegalStateException(); } val = val * 8 + (ch - '0'); } out.append((char) val); } else { switch (ch) { case 'e': case 'E': if (exec) { out.append((char) 27); // escape } break; case 'n': out.append('\n'); break; // case 'l': // rawPrint('\l'); // break; case 'r': if (exec) { out.append('\r'); } break; case 't': if (exec) { out.append('\t'); } break; case 'b': if (exec) { out.append('\b'); } break; case 'f': if (exec) { out.append('\f'); } break; case 's': if (exec) { out.append(' '); } break; case ':': case '^': case '\\': if (exec) { out.append(ch); } break; default: throw new IllegalArgumentException(); } } break; case '^': ch = str.charAt(index++); if (exec) { out.append((char)(ch - '@')); } break; case '%': ch = str.charAt(index++); switch (ch) { case '%': if (exec) { out.append('%'); } break; case 'p': ch = str.charAt(index++); if (exec) { stack.push(params[ch - '1']); } break; case 'P': ch = str.charAt(index++); if (ch >= 'a' && ch <= 'z') { if (exec) { dv[ch - 'a'] = stack.pop(); } } else if (ch >= 'A' && ch <= 'Z') { if (exec) { sv[ch - 'A'] = stack.pop(); } } else { throw new IllegalArgumentException(); } break; case 'g': ch = str.charAt(index++); if (ch >= 'a' && ch <= 'z') { if (exec) { stack.push(dv[ch - 'a']); } } else if (ch >= 'A' && ch <= 'Z') { if (exec) { stack.push(sv[ch - 'A']); } } else { throw new IllegalArgumentException(); } break; case '\'': ch = str.charAt(index++); if (exec) { stack.push((int) ch); } ch = str.charAt(index++); if (ch != '\'') { throw new IllegalArgumentException(); } break; case '{': int start = index; while (str.charAt(index++) != '}') ; if (exec) { int v = Integer.valueOf(str.substring(start, index - 1)); stack.push(v); } break; case 'l': if (exec) { stack.push(stack.pop().toString().length()); } break; case '+': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 + v2); } break; case '-': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 - v2); } break; case '*': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 * v2); } break; case '/': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 / v2); } break; case 'm': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 % v2); } break; case '&': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 & v2); } break; case '|': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 | v2); } break; case '^': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 ^ v2); } break; case '=': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 == v2); } break; case '>': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 > v2); } break; case '<': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 < v2); } break; case 'A': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 != 0 && v2 != 0); } break; case '!': if (exec) { int v1 = toInteger(stack.pop()); stack.push(v1 == 0); } break; case '~': if (exec) { int v1 = toInteger(stack.pop()); stack.push(~v1); } break; case 'O': if (exec) { int v2 = toInteger(stack.pop()); int v1 = toInteger(stack.pop()); stack.push(v1 != 0 || v2 != 0); } break; case '?': if (ifte != IFTE_NONE) { throw new IllegalArgumentException(); } else { ifte = IFTE_IF; } break; case 't': if (ifte != IFTE_IF && ifte != IFTE_ELSE) { throw new IllegalArgumentException(); } else { ifte = IFTE_THEN; } exec = toInteger(stack.pop()) != 0; break; case 'e': if (ifte != IFTE_THEN) { throw new IllegalArgumentException(); } else { ifte = IFTE_ELSE; } exec = !exec; break; case ';': if (ifte == IFTE_NONE || ifte == IFTE_IF) { throw new IllegalArgumentException(); } else { ifte = IFTE_NONE; } exec = true; break; case 'i': if (params.length >= 1) { params[0] = toInteger(params[0]) + 1; } if (params.length >= 2) { params[1] = toInteger(params[1]) + 1; } break; case 'd': out.append(Integer.toString(toInteger(stack.pop()))); break; default: throw new UnsupportedOperationException(); } break; case '$': if (str.charAt(index) == '<') { // We don't honour delays, just skip int nb = 0; while ((ch = str.charAt(++index)) != '>') { if (ch >= '0' && ch <= '9') { nb = nb * 10 + (ch - '0'); } else if (ch == '*') { // ignore } else if (ch == '/') { // ignore } else { // illegal, but ... } } index++; try { if (out instanceof Flushable) { ((Flushable) out).flush(); } Thread.sleep(nb); } catch (InterruptedException e) { } } else { if (exec) { out.append(ch); } } break; default: if (exec) { out.append(ch); } break; } } } private static int toInteger(Object pop) { if (pop instanceof Number) { return ((Number) pop).intValue(); } else if (pop instanceof Boolean) { return (Boolean) pop ? 1 : 0; } else { return Integer.valueOf(pop.toString()); } } }