Skip to content

Commit

Permalink
Support advanced escape sequences on Windows 10, fixes #279
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Jun 7, 2018
1 parent 44bafc2 commit d2cc0e3
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 53 deletions.
24 changes: 14 additions & 10 deletions builtins/src/main/java/org/jline/builtins/Nano.java
Original file line number Diff line number Diff line change
Expand Up @@ -973,25 +973,27 @@ public void run() throws IOException {
newAttr.setControlChar(ControlChar.VTIME, 0);
newAttr.setControlChar(ControlChar.VINTR, 0);
terminal.setAttributes(newAttr);
SignalHandler prevHandler = terminal.handle(Signal.WINCH, this::handle);
terminal.puts(Capability.enter_ca_mode);
terminal.puts(Capability.keypad_xmit);
size.copy(terminal.getSize());
display.clear();
display.reset();
display.resize(size.getRows(), size.getColumns());
if (mouseSupport) {
terminal.trackMouse(Terminal.MouseTracking.Normal);
}

this.shortcuts = standardShortcuts();

SignalHandler prevHandler = null;
try {
buffer.open();
if (buffer.file != null) {
setMessage("Read " + buffer.lines.size() + " lines");
}

size.copy(terminal.getSize());
display.clear();
display.reset();
display.resize(size.getRows(), size.getColumns());
prevHandler = terminal.handle(Signal.WINCH, this::handle);

display();

while (true) {
Expand Down Expand Up @@ -1923,11 +1925,13 @@ protected List<AttributedString> computeFooter() {
}

protected void handle(Signal signal) {
size.copy(terminal.getSize());
buffer.computeAllOffsets();
buffer.moveToChar(buffer.offsetInLine + buffer.column);
resetDisplay();
display();
if (buffer != null) {
size.copy(terminal.getSize());
buffer.computeAllOffsets();
buffer.moveToChar(buffer.offsetInLine + buffer.column);
resetDisplay();
display();
}
}

protected void bindKeys() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough
@Override
public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused) throws IOException {
if (JANSI_MAJOR_VERSION > 1 || JANSI_MAJOR_VERSION == 1 && JANSI_MINOR_VERSION >= 12) {
JansiWinSysTerminal terminal = new JansiWinSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused);
JansiWinSysTerminal terminal = JansiWinSysTerminal.createTerminal(name, type, encoding, codepage, nativeSignals, signalHandler, paused);
if (JANSI_MAJOR_VERSION == 1 && JANSI_MINOR_VERSION < 16) {
terminal.disableScrolling();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.io.BufferedWriter;
import java.io.IOError;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.function.IntConsumer;

Expand All @@ -21,38 +22,50 @@
import org.fusesource.jansi.internal.WindowsSupport;
import org.jline.terminal.Cursor;
import org.jline.terminal.Size;
import org.jline.terminal.Terminal;
import org.jline.terminal.impl.AbstractWindowsTerminal;
import org.jline.utils.InfoCmp;

import static org.fusesource.jansi.internal.Kernel32.GetConsoleScreenBufferInfo;
import static org.fusesource.jansi.internal.Kernel32.GetStdHandle;
import static org.fusesource.jansi.internal.Kernel32.STD_OUTPUT_HANDLE;
import org.jline.utils.OSUtils;

public class JansiWinSysTerminal extends AbstractWindowsTerminal {

public JansiWinSysTerminal(String name, boolean nativeSignals) throws IOException {
this(name, TYPE_WINDOWS, false, null, 0, nativeSignals, SignalHandler.SIG_DFL);
}

public JansiWinSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler) throws IOException {
this(name, TYPE_WINDOWS, false, null, 0, nativeSignals, signalHandler, false);
}

public JansiWinSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler, boolean paused) throws IOException {
super(ansiPassThrough
? new JansiWinConsoleWriter()
: new WindowsAnsiWriter(new BufferedWriter(new JansiWinConsoleWriter())),
name,
type,
encoding,
codepage,
nativeSignals,
signalHandler);

public static JansiWinSysTerminal createTerminal(String name, String type, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused) throws IOException {
Writer writer;
long console = GetStdHandle(STD_OUTPUT_HANDLE);
int[] mode = new int[1];
if (Kernel32.GetConsoleMode(console, mode) == 0) {
throw new IOException("Failed to get console mode: " + WindowsSupport.getLastErrorMessage());
}
if (Kernel32.SetConsoleMode(console, mode[0] | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0) {
if (type == null) {
type = TYPE_WINDOWS_VTP;
}
writer = new JansiWinConsoleWriter();
} else if (OSUtils.IS_CONEMU) {
if (type == null) {
type = TYPE_WINDOWS_256_COLOR;
}
writer = new JansiWinConsoleWriter();
} else {
if (type == null) {
type = TYPE_WINDOWS;
}
writer = new WindowsAnsiWriter(new BufferedWriter(new JansiWinConsoleWriter()));
}
JansiWinSysTerminal terminal = new JansiWinSysTerminal(writer, name, type, encoding, codepage, nativeSignals, signalHandler);
// Start input pump thread
if (!paused) {
resume();
terminal.resume();
}
return terminal;
}

JansiWinSysTerminal(Writer writer, String name, String type, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler) throws IOException {
super(writer, name, type, encoding, codepage, nativeSignals, signalHandler);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ public Pty open(Attributes attributes, Size size) throws IOException {

@Override
public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler) throws IOException {
return new JnaWinSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler);
return winSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, false);
}

@Override
public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused) throws IOException {
return new JnaWinSysTerminal(name, type, ansiPassThrough, encoding, codepage, nativeSignals, signalHandler, paused);
return JnaWinSysTerminal.createTerminal(name, type, encoding, codepage, nativeSignals, signalHandler, paused);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,59 @@

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.function.IntConsumer;

import com.sun.jna.LastErrorException;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import org.jline.terminal.Cursor;
import org.jline.terminal.Size;
import org.jline.terminal.Terminal;
import org.jline.terminal.impl.AbstractWindowsTerminal;
import org.jline.utils.InfoCmp;
import org.jline.utils.OSUtils;

public class JnaWinSysTerminal extends AbstractWindowsTerminal {

private static final Pointer consoleIn = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_INPUT_HANDLE);
private static final Pointer consoleOut = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_OUTPUT_HANDLE);

public JnaWinSysTerminal(String name, boolean nativeSignals) throws IOException {
this(name, TYPE_WINDOWS, false, null, 0, nativeSignals, SignalHandler.SIG_DFL);
}

public JnaWinSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler) throws IOException {
this(name, TYPE_WINDOWS, false, null, 0, nativeSignals, signalHandler, false);
}

public JnaWinSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler, boolean paused) throws IOException {
super(ansiPassThrough
? new JnaWinConsoleWriter(consoleOut)
: new WindowsAnsiWriter(new BufferedWriter(new JnaWinConsoleWriter(consoleOut)), consoleOut),
name, type, encoding, codepage, nativeSignals, signalHandler);
strings.put(InfoCmp.Capability.key_mouse, "\\E[M");

public static JnaWinSysTerminal createTerminal(String name, String type, Charset encoding, int codepage, boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused) throws IOException {
Writer writer;
IntByReference mode = new IntByReference();
Kernel32.INSTANCE.GetConsoleMode(consoleOut, mode);
try {
Kernel32.INSTANCE.SetConsoleMode(consoleOut, mode.getValue() | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING);
if (type == null) {
type = TYPE_WINDOWS_VTP;
}
writer = new JnaWinConsoleWriter(consoleOut);
} catch (LastErrorException e) {
if (OSUtils.IS_CONEMU) {
if (type == null) {
type = TYPE_WINDOWS_256_COLOR;
}
writer = new JnaWinConsoleWriter(consoleOut);
} else {
if (type == null) {
type = TYPE_WINDOWS;
}
writer = new WindowsAnsiWriter(new BufferedWriter(new JnaWinConsoleWriter(consoleOut)), consoleOut);
}
}
JnaWinSysTerminal terminal = new JnaWinSysTerminal(writer, name, type, encoding, codepage, nativeSignals, signalHandler);
// Start input pump thread
if (!paused) {
resume();
terminal.resume();
}
return terminal;
}

JnaWinSysTerminal(Writer writer, String name, String type, Charset encoding, int codepage, boolean nativeSignals, SignalHandler signalHandler) throws IOException {
super(writer, name, type, encoding, codepage, nativeSignals, signalHandler);
strings.put(InfoCmp.Capability.key_mouse, "\\E[M");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,9 +317,6 @@ private Terminal doBuild() throws IOException {
if (OSUtils.IS_WINDOWS) {
boolean cygwinTerm = "cygwin".equals(System.getenv("TERM"));
boolean ansiPassThrough = OSUtils.IS_CONEMU;
if (type == null) {
type = OSUtils.IS_CONEMU ? TYPE_WINDOWS_256_COLOR : TYPE_WINDOWS;
}
//
// Cygwin support
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {

public static final String TYPE_WINDOWS = "windows";
public static final String TYPE_WINDOWS_256_COLOR = "windows-256color";
public static final String TYPE_WINDOWS_VTP = "windows-vtp";

public static final int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;

private static final int UTF8_CODE_PAGE = 65001;

Expand Down
3 changes: 2 additions & 1 deletion terminal/src/main/java/org/jline/utils/InfoCmp.java
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,8 @@ static String loadDefaultInfoCmp(String name) {

static {
for (String s : Arrays.asList("dumb", "ansi", "xterm", "xterm-256color",
"windows", "windows-256color", "screen", "screen-256color")) {
"windows", "windows-256color", "windows-vtp",
"screen", "screen-256color")) {
setDefaultInfoCmp(s, () -> loadDefaultInfoCmp(s));
}
}
Expand Down
33 changes: 33 additions & 0 deletions terminal/src/main/resources/org/jline/utils/windows-vtp.caps
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
windows-vtp|windows with virtual terminal processing,
am, mc5i, mir, msgr,
colors#256, cols#80, it#8, lines#24, ncv#3, pairs#64,
bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, clear=\E[H\E[J,
cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B,
cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH,
cuu=\E[%p1%dA, cuu1=\E[A,
il=\E[%p1%dL, il1=\E[L,
dl=\E[%p1%dM, dl1=\E[M,
ech=\E[%p1%dX,
el=\E[K, ed=\E[2K,
el1=\E[1K, home=\E[H, hpa=\E[%i%p1%dG,
ind=^J,
invis=\E[8m, kbs=^H, kcbt=\E[Z,
kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
khome=\E[H,
op=\E[39;49m,
rev=\E[7m,
rmacs=\E[10m, rmpch=\E[10m, rmso=\E[m, rmul=\E[m,
setab=\E[4%p1%dm, setaf=\E[3%p1%dm,
sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,
sgr0=\E[0;10m,
smso=\E[7m,
smul=\E[4m,
kdch1=\E[3~, kich1=\E[2~, kend=\E[4~, knp=\E[6~, kpp=\E[5~,
kf1=\EOP, kf2=\EOQ, kf3=\EOR, kf4=\EOS, kf5=\E[15~, kf6=\E[17~,
kf7=\E[18~, kf8=\E[19~, kf9=\E[20~, kf10=\E[21~, kf11=\E[23~, kf12=\E[24~,
smcup=\E[?1049h, rmcup=\E[?1049l, indn=\E[%p1%dS, rin=\E[%p1%dT,
ich=\E[%p1%d@, dch=\E[%p1%dP, ech=\E[%p1%dX, il=\E[%p1%dL, dl=\E[%p1%dM,
sc=\E7, rc=\E8, cnorm=\E[?12l\E[?25h, civis=\E[?25l, cvvis=\E[?12h\E[?25h,
smkx=\E[?1h\E=, rmkx=\E[?1l\E>, u6=\E[%i%d;%dR, u7=\E[6n,
hts=\EH, smacs=\E(0, rmacs=\E(B,
csr=\E[%i%p1%d;%p2%dr,

0 comments on commit d2cc0e3

Please sign in to comment.