Skip to content

Commit

Permalink
Jansi native support for external terminals
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Apr 28, 2017
1 parent d2cea60 commit 3f255ae
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;

import static org.fusesource.jansi.internal.CLibrary.TCSANOW;
import static org.jline.terminal.impl.jansi.JansiSupportImpl.JANSI_MAJOR_VERSION;
Expand Down Expand Up @@ -144,4 +145,14 @@ public String toString() {
return "JansiNativePty[" + getName() + "]";
}

protected static FileDescriptor newDescriptor(int fd) {
try {
Constructor<FileDescriptor> cns = FileDescriptor.class.getDeclaredConstructor(int.class);
cns.setAccessible(true);
return cns.newInstance(fd);
} catch (Throwable e) {
throw new RuntimeException("Unable to create FileDescriptor", e);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
package org.jline.terminal.impl.jansi;

import org.fusesource.jansi.Ansi;
import org.jline.terminal.Attributes;
import org.jline.terminal.Size;
import org.jline.terminal.Terminal;
import org.jline.terminal.impl.jansi.freebsd.FreeBsdNativePty;
import org.jline.terminal.impl.jansi.linux.LinuxNativePty;
Expand Down Expand Up @@ -68,6 +70,27 @@ else if (osName.startsWith("FreeBSD")) {
throw new UnsupportedOperationException();
}

@Override
public Pty open(Attributes attributes, Size size) throws IOException {
if (JANSI_MAJOR_VERSION > 1 || JANSI_MAJOR_VERSION == 1 && JANSI_MINOR_VERSION >= 16) {
String osName = System.getProperty("os.name");
if (osName.startsWith("Linux")) {
return LinuxNativePty.open(attributes, size);
}
else if (osName.startsWith("Mac") || osName.startsWith("Darwin")) {
return OsXNativePty.open(attributes, size);
}
else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) {
// Solaris is not supported by jansi
// return SolarisNativePty.current();
}
else if (osName.startsWith("FreeBSD")) {
return FreeBsdNativePty.open(attributes, size);
}
}
throw new UnsupportedOperationException();
}

@Override
public Terminal winSysTerminal(String name, boolean nativeSignals, Terminal.SignalHandler signalHandler) throws IOException {
if (JANSI_MAJOR_VERSION > 1 || JANSI_MAJOR_VERSION == 1 && JANSI_MINOR_VERSION >= 12) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@

import org.fusesource.jansi.internal.CLibrary;
import org.jline.terminal.Attributes;
import org.jline.terminal.Size;
import org.jline.terminal.impl.jansi.JansiNativePty;
import org.jline.terminal.impl.jansi.osx.OsXNativePty;

import java.io.FileDescriptor;
import java.io.IOException;
import java.util.EnumMap;
import java.util.EnumSet;

import static org.jline.utils.ExecHelper.exec;

public class FreeBsdNativePty extends JansiNativePty {

public static FreeBsdNativePty current() throws IOException {
Expand All @@ -30,6 +30,21 @@ public static FreeBsdNativePty current() throws IOException {
}
}

public static OsXNativePty open(Attributes attr, Size size) throws IOException {
int[] master = new int[1];
int[] slave = new int[1];
byte[] buf = new byte[64];
CLibrary.openpty(master, slave, buf,
attr != null ? termios(attr) : null,
size != null ? new CLibrary.WinSize((short) size.getRows(), (short) size.getColumns()) : null);
int len = 0;
while (buf[len] != 0) {
len++;
}
String name = new String(buf, 0, len);
return new OsXNativePty(master[0], newDescriptor(master[0]), slave[0], newDescriptor(slave[0]), name);
}

public FreeBsdNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, String name) {
super(master, masterFD, slave, slaveFD, name);
}
Expand Down Expand Up @@ -110,6 +125,10 @@ public FreeBsdNativePty(int master, FileDescriptor masterFD, int slave, FileDesc
private static final int NOFLSH = 0x8000000;

protected CLibrary.Termios toTermios(Attributes t) {
return termios(t);
}

static CLibrary.Termios termios(Attributes t) {
CLibrary.Termios tio = new CLibrary.Termios();
tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNBRK), IGNBRK, tio.c_iflag);
tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.BRKINT), BRKINT, tio.c_iflag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

import org.fusesource.jansi.internal.CLibrary;
import org.jline.terminal.Attributes;
import org.jline.terminal.Size;
import org.jline.terminal.impl.jansi.JansiNativePty;
import org.jline.terminal.impl.jansi.osx.OsXNativePty;

import java.io.FileDescriptor;
import java.io.IOException;
Expand All @@ -28,6 +30,21 @@ public static LinuxNativePty current() throws IOException {
}
}

public static OsXNativePty open(Attributes attr, Size size) throws IOException {
int[] master = new int[1];
int[] slave = new int[1];
byte[] buf = new byte[64];
CLibrary.openpty(master, slave, buf,
attr != null ? termios(attr) : null,
size != null ? new CLibrary.WinSize((short) size.getRows(), (short) size.getColumns()) : null);
int len = 0;
while (buf[len] != 0) {
len++;
}
String name = new String(buf, 0, len);
return new OsXNativePty(master[0], newDescriptor(master[0]), slave[0], newDescriptor(slave[0]), name);
}

public LinuxNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, String name) {
super(master, masterFD, slave, slaveFD, name);
}
Expand Down Expand Up @@ -149,6 +166,10 @@ public LinuxNativePty(int master, FileDescriptor masterFD, int slave, FileDescri
private static final int EXTPROC = 0x0010000;

protected CLibrary.Termios toTermios(Attributes t) {
return termios(t);
}

static CLibrary.Termios termios(Attributes t) {
CLibrary.Termios tio = new CLibrary.Termios();
tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNBRK), IGNBRK, tio.c_iflag);
tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.BRKINT), BRKINT, tio.c_iflag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import org.fusesource.jansi.internal.CLibrary;
import org.jline.terminal.Attributes;
import org.jline.terminal.Size;
import org.jline.terminal.impl.jansi.JansiNativePty;

import java.io.FileDescriptor;
Expand All @@ -28,6 +29,21 @@ public static OsXNativePty current() throws IOException {
}
}

public static OsXNativePty open(Attributes attr, Size size) throws IOException {
int[] master = new int[1];
int[] slave = new int[1];
byte[] buf = new byte[64];
CLibrary.openpty(master, slave, buf,
attr != null ? termios(attr) : null,
size != null ? new CLibrary.WinSize((short) size.getRows(), (short) size.getColumns()) : null);
int len = 0;
while (buf[len] != 0) {
len++;
}
String name = new String(buf, 0, len);
return new OsXNativePty(master[0], newDescriptor(master[0]), slave[0], newDescriptor(slave[0]), name);
}

public OsXNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, String name) {
super(master, masterFD, slave, slaveFD, name);
}
Expand Down Expand Up @@ -120,6 +136,10 @@ public OsXNativePty(int master, FileDescriptor masterFD, int slave, FileDescript
private static final int NOFLSH = 0x80000000;

protected CLibrary.Termios toTermios(Attributes t) {
return termios(t);
}

static CLibrary.Termios termios(Attributes t) {
CLibrary.Termios tio = new CLibrary.Termios();
tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNBRK), IGNBRK, tio.c_iflag);
tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.BRKINT), BRKINT, tio.c_iflag);
Expand Down
16 changes: 12 additions & 4 deletions terminal/src/main/java/org/jline/terminal/TerminalBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ private Terminal doBuild() throws IOException {
return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
} catch (IOException e) {
// Ignore if not a tty
Log.debug("Error creating exec based pty: ", e.getMessage(), e);
Log.debug("Error creating EXEC based terminal: ", e.getMessage(), e);
exception.addSuppressed(e);
}
}
Expand Down Expand Up @@ -261,7 +261,7 @@ else if (OSUtils.IS_WINDOWS) {
pty = load(JnaSupport.class).current();
} catch (Throwable t) {
// ignore
Log.debug("Error creating JNA based pty: ", t.getMessage(), t);
Log.debug("Error creating JNA based terminal: ", t.getMessage(), t);
exception.addSuppressed(t);
}
}
Expand All @@ -278,7 +278,7 @@ else if (OSUtils.IS_WINDOWS) {
pty = ExecPty.current();
} catch (Throwable t) {
// Ignore if not a tty
Log.debug("Error creating exec based pty: ", t.getMessage(), t);
Log.debug("Error creating EXEC based terminal: ", t.getMessage(), t);
exception.addSuppressed(t);
}
}
Expand Down Expand Up @@ -307,7 +307,15 @@ else if (OSUtils.IS_WINDOWS) {
Pty pty = load(JnaSupport.class).open(attributes, size);
return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler);
} catch (Throwable t) {
Log.debug("Error creating JNA based pty: ", t.getMessage(), t);
Log.debug("Error creating JNA based terminal: ", t.getMessage(), t);
}
}
if (jansi) {
try {
Pty pty = load(JansiSupport.class).open(attributes, size);
return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler);
} catch (Throwable t) {
Log.debug("Error creating JANSI based terminal: ", t.getMessage(), t);
}
}
Terminal terminal = new ExternalTerminal(name, type, in, out, encoding, signalHandler);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.jline.terminal.spi;

import org.jline.terminal.Attributes;
import org.jline.terminal.Size;
import org.jline.terminal.Terminal;

import java.io.IOException;
Expand All @@ -8,6 +10,8 @@ public interface JansiSupport {

Pty current() throws IOException;

Pty open(Attributes attributes, Size size) throws IOException;

Terminal winSysTerminal(String name, boolean nativeSignals, Terminal.SignalHandler signalHandler) throws IOException;

}

0 comments on commit 3f255ae

Please sign in to comment.