package picocli; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; public class Size { public static void main(String[] args) throws Exception { String device = args.length > 0 ? args[0] : "/dev/tty"; tput_cols(device); stty_size(device); ascii_signals(device); } ///bin/stty -echo; /bin/stty -icanon; /bin/stty min 1; java WinSize; /bin/stty echo; /bin/stty icanon; private static void ascii_signals(final String device) { final StringBuilder sb = new StringBuilder(); Thread t = new Thread(new Runnable() { public void run() { exec("sh", "-c", "stty -echo < " + device); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { exec("sh", "-c", "stty echo < " + device); } }); exec("sh", "-c", "stty -icanon < " + device); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { exec("sh", "-c", "stty icanon < " + device); } }); String[] signals = new String[] { "\u001b[s", // save cursor position "\u001b[5000;5000H", // move to col 5000 row 5000 "\u001b[6n", // request cursor position "\u001b[u", // restore cursor position }; for (String s : signals) { System.out.print(s); } System.out.flush(); try { System.in.read(); int read = -1; byte[] buff = new byte[1]; while ((read = System.in.read(buff, 0, 1)) != -1) { sb.append((char) buff[0]); //System.err.printf("Read %s chars, buf size=%s%n", read, sb.length()); if ('R' == buff[0]) { break; } } } catch (Exception ignored) { // nothing to do... } } }); t.start(); String size = sb.toString(); if (sb.length() == 0) { System.err.println("ascii sequence gave no result"); } else { int rows = Integer.parseInt(size.substring(size.indexOf("\u001b[") + 2, size.indexOf(';'))); int cols = Integer.parseInt(size.substring(size.indexOf(';') + 1, size.indexOf('R'))); System.err.printf("ascii commands found: rows = %s, cols = %s%n", rows, cols); } } private static void tput_cols(final String device) { final AtomicInteger size = new AtomicInteger(-1); Thread t = new Thread(new Runnable() { public void run() { String line = exec("sh", "-c", "tput cols 2> " + device); size.set(Integer.valueOf(line.trim())); } }); t.start(); long timeout = System.currentTimeMillis() + 2000; do { if (size.intValue() >= 0) { break; } try {Thread.sleep(25);} catch (InterruptedException ignored) {} } while (System.currentTimeMillis() < timeout); System.out.println("Value of env var COLUMNS: " + System.getenv("COLUMNS")); if (size.intValue() < 0) { System.out.println("`tput cols` timed out"); } else { System.out.println("`tput cols` found size: " + size); } } private static void stty_size(final String device) { final AtomicBoolean done = new AtomicBoolean(); final String[] line = new String[1]; final Thread t = new Thread(new Runnable() { public void run() { // line[0] = exec("/bin/stty", "-a", "-F", "/dev/tty"); // line[0] = exec("sh", "-c", "stty -a -F " + device + " 2> " + device); line[0] = exec("sh", "-c", "stty -a -F " + device + " 2> " + device); done.set(true); } }); t.start(); long timeout = System.currentTimeMillis() + 2000; do { if (!done.get()) { break; } try {Thread.sleep(25);} catch (InterruptedException ignored) {} } while (System.currentTimeMillis() < timeout); if (line[0] == null) { System.out.printf("`stty -a -F %s` timed out%n", device); } else { System.out.printf("`stty -a -F %s` found: %s%n", device, line[0]); } } private static String exec(String... cmd) { try { return tryExec(cmd); } catch (Exception e) { e.printStackTrace(); throw new InternalError(e.toString()); } } private static String tryExec(String[] cmd) throws IOException, InterruptedException { ProcessBuilder pb = new ProcessBuilder(cmd); Process process = pb.start(); ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); InputStream stdout = process.getInputStream(); process.waitFor(); int readByte = stdout.read(); while (readByte >= 0) { stdoutBuffer.write(readByte); readByte = stdout.read(); } process.destroy(); return stdoutBuffer.toString(); // ByteArrayInputStream stdoutBufferInputStream = new ByteArrayInputStream(stdoutBuffer.toByteArray()); // BufferedReader reader = new BufferedReader(new InputStreamReader(stdoutBufferInputStream)); // StringBuilder builder = new StringBuilder(); // String line; // while((line = reader.readLine()) != null) { // builder.append(line); // } // reader.close(); // return builder.toString(); } }