Skip to content

Commit

Permalink
Implement pause/resume on terminals, #140
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Jan 8, 2018
1 parent ac77a8a commit fc908f3
Show file tree
Hide file tree
Showing 12 changed files with 310 additions and 77 deletions.
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2002-2016, the original author or authors.
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.
Expand Down Expand Up @@ -78,7 +78,7 @@
<maven.compiler.target>1.8</maven.compiler.target>

<jna.version>4.2.2</jna.version>
<jansi.version>1.16</jansi.version>
<jansi.version>1.17-SNAPSHOT</jansi.version>
<juniversalchardet.version>1.0.3</juniversalchardet.version>
<sshd.version>1.4.0</sshd.version>
<easymock.version>3.3.1</easymock.version>
Expand Down
23 changes: 14 additions & 9 deletions reader/src/main/java/org/jline/reader/LineReaderBuilder.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
* 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.
Expand All @@ -12,6 +12,7 @@
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import org.jline.reader.impl.LineReaderImpl;
import org.jline.reader.impl.history.DefaultHistory;
Expand All @@ -26,7 +27,8 @@ public static LineReaderBuilder builder() {

Terminal terminal;
String appName;
Map<String, Object> variables;
Map<String, Object> variables = new HashMap<>();
Map<LineReader.Option, Boolean> options = new HashMap<>();
History history;
Completer completer;
History memoryHistory;
Expand All @@ -49,21 +51,21 @@ public LineReaderBuilder appName(String appName) {

public LineReaderBuilder variables(Map<String, Object> variables) {
Map<String, Object> old = this.variables;
this.variables = variables;
if (old != null) {
this.variables.putAll(old);
}
this.variables = Objects.requireNonNull(variables);
this.variables.putAll(old);
return this;
}

public LineReaderBuilder variable(String name, Object value) {
if (variables == null) {
variables = new HashMap<>();
}
this.variables.put(name, value);
return this;
}

public LineReaderBuilder option(LineReader.Option option, boolean value) {
this.options.put(option, value);
return this;
}

public LineReaderBuilder history(History history) {
this.history = history;
return this;
Expand Down Expand Up @@ -119,6 +121,9 @@ public LineReader build() {
if (expander != null) {
reader.setExpander(expander);
}
for (Map.Entry<LineReader.Option, Boolean> e : options.entrySet()) {
reader.option(e.getKey(), e.getValue());
}
return reader;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2017, the original author or authors.
* 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.
Expand Down Expand Up @@ -39,7 +39,7 @@ public JansiWinSysTerminal(String name, Charset encoding, int codepage, boolean
name, encoding, codepage, nativeSignals, signalHandler);

// Start input pump thread
pump.start();
resume();
}

@Override
Expand All @@ -65,7 +65,7 @@ public Size getSize() {
}

protected boolean processConsoleInput() throws IOException {
INPUT_RECORD[] events = WindowsSupport.readConsoleInput(1);
INPUT_RECORD[] events = WindowsSupport.readConsoleInput(1, 100);
if (events == null) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
* 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.
Expand Down Expand Up @@ -35,7 +35,7 @@ public JnaWinSysTerminal(String name, Charset encoding, int codepage, boolean na
strings.put(InfoCmp.Capability.key_mouse, "\\E[M");

// Start input pump thread
pump.start();
resume();
}

@Override
Expand All @@ -62,7 +62,7 @@ public Size getSize() {
}

protected boolean processConsoleInput() throws IOException {
Kernel32.INPUT_RECORD event = readConsoleInput();
Kernel32.INPUT_RECORD event = readConsoleInput(100);
if (event == null) {
return false;
}
Expand Down Expand Up @@ -126,7 +126,10 @@ private void processMouseEvent(Kernel32.MOUSE_EVENT_RECORD mouseEvent) throws IO
private final Kernel32.INPUT_RECORD[] inputEvents = new Kernel32.INPUT_RECORD[1];
private final IntByReference eventsRead = new IntByReference();

private Kernel32.INPUT_RECORD readConsoleInput() throws IOException {
private Kernel32.INPUT_RECORD readConsoleInput(int dwMilliseconds) throws IOException {
if (Kernel32.INSTANCE.WaitForSingleObject(consoleIn, dwMilliseconds) != 0) {
return null;
}
Kernel32.INSTANCE.ReadConsoleInput(consoleIn, inputEvents, 1, eventsRead);
if (eventsRead.getValue() == 1) {
return inputEvents[0];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
* 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.
Expand Down Expand Up @@ -64,6 +64,12 @@ interface Kernel32 extends StdCallLibrary {
int MOUSE_WHEELED = 0x0004;
int MOUSE_HWHEELED = 0x0008;

// DWORD WINAPI WaitForSingleObject(
// _In_ HANDLE hHandle,
// _In_ DWORD dwMilliseconds
// );
int WaitForSingleObject(Pointer in_hHandle, int in_dwMilliseconds);

// HANDLE WINAPI GetStdHandle(
// __in DWORD nStdHandle
// );
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
* 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.
Expand Down Expand Up @@ -205,24 +205,4 @@ public MouseEvent readMouseEvent(IntSupplier reader) {
return lastMouseEvent = MouseSupport.readMouse(reader, lastMouseEvent);
}

@Override
public boolean canPauseResume() {
return false;
}

@Override
public void pause() {
throw new UnsupportedOperationException();
}

@Override
public void resume() {
throw new UnsupportedOperationException();
}

@Override
public boolean paused() {
return false;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
* 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.
Expand Down Expand Up @@ -33,6 +33,7 @@
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
* The AbstractWindowsTerminal is used as the base class for windows terminal.
Expand Down Expand Up @@ -68,9 +69,11 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
protected final Map<Signal, Object> nativeHandlers = new HashMap<>();
protected final ShutdownHooks.Task closer;
protected final Attributes attributes = new Attributes();
protected final Thread pump;
protected final int originalConsoleMode;

protected Thread pump;
protected final AtomicBoolean paused = new AtomicBoolean(true);

protected MouseTracking tracking = MouseTracking.Off;
private volatile boolean closing;

Expand Down Expand Up @@ -99,11 +102,6 @@ public AbstractWindowsTerminal(Writer writer, String name, Charset encoding, int
}
}
}
pump = new Thread(this::pump, "WindowsStreamPump");
pump.setDaemon(true);
// This is called by the JNA/Jansi terminal implementation to avoid
// race conditions if they do initialization in their constructor
//pump.start();
closer = this::close;
ShutdownHooks.add(closer);
}
Expand Down Expand Up @@ -400,9 +398,33 @@ private String translate(String str, Object... params) {
return null;
}

@Override
public boolean canPauseResume() {
return true;
}

@Override
public void pause() {
paused.set(true);
}

@Override
public void resume() {
if (paused.compareAndSet(true, false)) {
pump = new Thread(this::pump, "WindowsStreamPump");
pump.setDaemon(true);
pump.start();
}
}

@Override
public boolean paused() {
return paused.get();
}

protected void pump() {
try {
while (!closing) {
while (!closing && !paused.get()) {
if (processConsoleInput()) {
slaveInputPipe.flush();
}
Expand Down
23 changes: 20 additions & 3 deletions terminal/src/main/java/org/jline/terminal/impl/DumbTerminal.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2017, the original author or authors.
* 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.
Expand All @@ -8,10 +8,8 @@
*/
package org.jline.terminal.impl;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
Expand Down Expand Up @@ -130,4 +128,23 @@ public void setSize(Size sz) {

public void close() throws IOException {
}

@Override
public boolean canPauseResume() {
return false;
}

@Override
public void pause() {
}

@Override
public void resume() {
}

@Override
public boolean paused() {
return false;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2016, the original author or authors.
* 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.
Expand Down Expand Up @@ -31,8 +31,9 @@
public class ExternalTerminal extends LineDisciplineTerminal {

protected final AtomicBoolean closed = new AtomicBoolean();
protected final Thread pumpThread;
protected final InputStream masterInput;
protected final AtomicBoolean paused = new AtomicBoolean(true);
protected Thread pumpThread;

public ExternalTerminal(String name, String type,
InputStream masterInput,
Expand All @@ -48,25 +49,51 @@ public ExternalTerminal(String name, String type,
SignalHandler signalHandler) throws IOException {
super(name, type, masterOutput, encoding, signalHandler);
this.masterInput = masterInput;
this.pumpThread = new Thread(this::pump, toString() + " input pump thread");
this.pumpThread.start();
resume();
}

public void close() throws IOException {
if (closed.compareAndSet(false, true)) {
pumpThread.interrupt();
pause();
super.close();
}
}

@Override
public boolean canPauseResume() {
return true;
}

@Override
public void pause() {
if (paused.compareAndSet(false, true)) {
this.pumpThread.interrupt();
}
}

@Override
public void resume() {
if (paused.compareAndSet(true, false)) {
this.pumpThread = new Thread(this::pump, toString() + " input pump thread");
this.pumpThread.start();
}
}

@Override
public boolean paused() {
return paused.get();
}

public void pump() {
try {
while (true) {
int c = masterInput.read();
if (c < 0 || closed.get()) {
if (c >= 0) {
processInputByte((char) c);
}
if (c < 0 || closed.get() || paused.get()) {
break;
}
processInputByte((char) c);
}
} catch (IOException e) {
// Ignore
Expand Down

0 comments on commit fc908f3

Please sign in to comment.