public static void handle(TtyConnection conn) { conn.setEventHandler((event, key) -> { switch (event) { case INTR: conn.write("You did a Ctrl-C\n"); break; case SUSP: conn.write("You did a Ctrl-Z\n"); break; case EOF: conn.write("You did a Ctrl-D: closing\n"); conn.close(); break; } }); conn.setSizeHandler(size -> { conn.write("You resized your terminal to " + size + "\n"); }); conn.setTerminalTypeHandler(term -> { conn.write("Your terminal is " + term + "\n"); }); conn.setStdinHandler(keys -> { for (int key : keys) { conn.write("You typed " + key + "\n"); } }); }
private void install() { prevReadHandler = conn.getStdinHandler(); prevSizeHandler = conn.getSizeHandler(); prevEventHandler = conn.getEventHandler(); conn.setStdinHandler(data -> { synchronized (Readline.this) { decoder.append(data); } deliver(); }); size = conn.size(); conn.setSizeHandler(dim -> { if (size != null) { // Not supported for now // interaction.resize(size.width(), dim.width()); } size = dim; }); conn.setEventHandler(null); } }
/** * Write a string to the client. * * @param s the string to write */ default TtyConnection write(String s) { int[] codePoints = Helper.toCodePoints(s); stdoutHandler().accept(codePoints); return this; }
@Override public void execute(TtyConnection conn, List<String> args) throws Exception { conn.write("Current window size " + conn.size() + ", try resize it\n"); // Refresh the screen with the new size conn.setSizeHandler(size -> { conn.write("Window resized " + size + "\n"); }); try { // Wait until interrupted new CountDownLatch(1).await(); } finally { conn.setSizeHandler(null); } } },
private void onStdOut(TtyConnection conn, int[] buffer) { conn.execute(() -> { conn.stdoutHandler().accept(buffer); }); if (processStdoutListener != null) { processStdoutListener.accept(buffer); } } }
/** * End the current interaction with a callback. * * @param s the */ private boolean end(String s) { synchronized (Readline.this) { if (interaction == null) { return false; } interaction = null; conn.setStdinHandler(prevReadHandler); conn.setSizeHandler(prevSizeHandler); conn.setEventHandler(prevEventHandler); } requestHandler.accept(s); return true; }
public void handle() { if (conn.size() != null) { broadcast(); } else { conn.setSizeHandler(size -> broadcast()); } }
@Test public void testServerDisconnect() throws Exception { CountDownLatch closedLatch = new CountDownLatch(1); server(conn -> { conn.setStdinHandler(bytes -> { conn.close(); }); conn.setCloseHandler(v -> { closedLatch.countDown(); }); }); assertConnect(); assertWrite("whatever"); assertTrue(closedLatch.await(10, TimeUnit.SECONDS)); }
@Override public void accept(TtyConnection conn) { conn.setEventHandler((event, key) -> { if (event == TtyEvent.INTR) { interrupted = true; } }); if (conn.size() != null) { run(conn); } else { conn.setSizeHandler(size -> run(conn)); } }
@Override public Tty write(String data) { conn.write(data); return this; }
@Override public void accept(final TtyConnection conn) { assertTrue(conn.lastAccessedTime() >= connTime); final long openTime = System.currentTimeMillis(); conn.setStdinHandler(new Consumer<int[]>() { @Override public void accept(int[] cp) { long delta = conn.lastAccessedTime() - openTime; switch (count.getAndIncrement()) { case 0: assertTrue(delta >= 0); latch.countDown(); break; case 1: assertTrue(delta >= 10); testComplete(); break; } } }); } });
@Override public void accept(TtyConnection conn) { conn.setCloseHandler(new Consumer<Void>() { @Override public void accept(Void v) { new Thread() { @Override public void run() { for (int i = 0;i < 100;i++) { if (checkDisconnected()) { testComplete(); return; } try { Thread.sleep(10); } catch (InterruptedException e) { fail(e); } } } }.start(); } }); conn.close(); } });
@Test public void testRead() throws Exception { final ArrayBlockingQueue<int[]> queue = new ArrayBlockingQueue<>(1); server(conn -> conn.setStdinHandler(data -> { queue.add(data); conn.stdoutHandler().accept(new int[]{'h', 'e', 'l', 'l', 'o'}); })); assertConnect(); assertWriteln(""); int[] data = queue.poll(10, TimeUnit.SECONDS); assertTrue(Arrays.equals(new int[]{'\r'}, data)); assertEquals("hello", assertReadString(5)); }
/** * Write a block of text below the current edition line, a {@code CRLF} sequence is inserted before the * block of text.<p/> * * @param text the text to insert inline */ public void suggest(int[] text) { if (!done.compareAndSet(false, true)) { throw new IllegalStateException(); } interaction.conn.write("\n"); interaction.conn.stdoutHandler().accept(text); interaction.redraw(); interaction.resume(); }
@Test public void testExitCode() throws Exception { server(conn -> { conn.setStdinHandler(bytes -> { conn.close(25); }); }); assertConnect(); assertWrite("whatever"); long timeout = System.currentTimeMillis() + 5000; while (!channel.isClosed()) { assertTrue(System.currentTimeMillis() < timeout); Thread.sleep(10); } assertEquals(25, channel.getExitStatus()); }
@Override public void execute(TtyConnection conn, List<String> args) throws Exception { // Subscribe to key events and print them conn.setStdinHandler(keys -> { for (int key : keys) { conn.write(key + " pressed\n"); } }); try { // Wait until interrupted new CountDownLatch(1).await(); } finally { conn.setStdinHandler(null); } } },
private void onNewLine(TtyConnection conn, Readline readline, String line) { if (processStdinListener != null) { processStdinListener.accept(line); } if (line == null) { conn.close(); return; } PtyMaster task = new PtyMaster(line, buffer -> onStdOut(conn, buffer), empty -> doneHandler(conn, readline)); conn.setEventHandler((event,cp) -> { if (event == TtyEvent.INTR) { task.interruptProcess(); } }); if (processListener != null) { processListener.accept(task); } task.start(); }
private void doneHandler(TtyConnection conn, Readline readline) { conn.setEventHandler(null); conn.execute(() -> read(conn, readline)); }