Added Terminal.getTerminalSize().
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
void markFailed(JNIEnv *env, jobject result) {
|
void markFailed(JNIEnv *env, jobject result) {
|
||||||
jclass destClass = env->GetObjectClass(result);
|
jclass destClass = env->GetObjectClass(result);
|
||||||
@@ -48,3 +49,18 @@ Java_net_rubygrapefruit_platform_internal_PosixTerminalFunctions_isatty(JNIEnv *
|
|||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_net_rubygrapefruit_platform_internal_PosixTerminalFunctions_getTerminalSize(JNIEnv *env, jclass target, jint output, jobject dimension, jobject result) {
|
||||||
|
struct winsize screen_size;
|
||||||
|
int retval = ioctl(output+1, TIOCGWINSZ, &screen_size);
|
||||||
|
if (retval != 0) {
|
||||||
|
markFailed(env, result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
jclass dimensionClass = env->GetObjectClass(dimension);
|
||||||
|
jfieldID widthField = env->GetFieldID(dimensionClass, "cols", "I");
|
||||||
|
env->SetIntField(dimension, widthField, screen_size.ws_col);
|
||||||
|
jfieldID heightField = env->GetFieldID(dimensionClass, "rows", "I");
|
||||||
|
env->SetIntField(dimension, heightField, screen_size.ws_row);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,21 @@
|
|||||||
package net.rubygrapefruit.platform;
|
package net.rubygrapefruit.platform;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Process process = Platform.get(Process.class);
|
Process process = Platform.get(Process.class);
|
||||||
System.out.println("* PID: " + process.getPid());
|
System.out.println("* PID: " + process.getPid());
|
||||||
|
|
||||||
Terminal terminal = Platform.get(Terminal.class);
|
Terminal terminal = Platform.get(Terminal.class);
|
||||||
System.out.println("* stdout: " + (terminal.isTerminal(Terminal.Output.Stdout) ? "terminal" : "not a terminal"));
|
|
||||||
System.out.println("* stderr: " + (terminal.isTerminal(Terminal.Output.Stderr) ? "terminal" : "not a terminal"));
|
boolean stdoutIsTerminal = terminal.isTerminal(Terminal.Output.Stdout);
|
||||||
|
boolean stderrIsTerminal = terminal.isTerminal(Terminal.Output.Stderr);
|
||||||
|
System.out.println("* stdout: " + (stdoutIsTerminal ? "terminal" : "not a terminal"));
|
||||||
|
System.out.println("* stderr: " + (stderrIsTerminal ? "terminal" : "not a terminal"));
|
||||||
|
if (stdoutIsTerminal) {
|
||||||
|
TerminalSize terminalSize = terminal.getTerminalSize(Terminal.Output.Stdout);
|
||||||
|
System.out.println("* terminal size: " + terminalSize.getCols() + " cols x " + terminalSize.getRows() + " rows");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,12 +31,7 @@ public class Platform {
|
|||||||
return type.cast(new DefaultProcess());
|
return type.cast(new DefaultProcess());
|
||||||
}
|
}
|
||||||
if (type.equals(Terminal.class)) {
|
if (type.equals(Terminal.class)) {
|
||||||
return type.cast(new Terminal(){
|
return type.cast(new DefaultTerminal());
|
||||||
@Override
|
|
||||||
public boolean isTerminal(Output output) {
|
|
||||||
return PosixTerminalFunctions.isatty(output.ordinal());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException(String.format("Cannot load unknown native integration %s.",
|
throw new UnsupportedOperationException(String.format("Cannot load unknown native integration %s.",
|
||||||
type.getName()));
|
type.getName()));
|
||||||
@@ -70,4 +65,22 @@ public class Platform {
|
|||||||
return PosixProcessFunctions.getPid();
|
return PosixProcessFunctions.getPid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class DefaultTerminal implements Terminal {
|
||||||
|
@Override
|
||||||
|
public boolean isTerminal(Output output) {
|
||||||
|
return PosixTerminalFunctions.isatty(output.ordinal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TerminalSize getTerminalSize(Output output) {
|
||||||
|
MutableTerminalSize terminalSize = new MutableTerminalSize();
|
||||||
|
FunctionResult result = new FunctionResult();
|
||||||
|
PosixTerminalFunctions.getTerminalSize(output.ordinal(), terminalSize, result);
|
||||||
|
if (result.isFailed()) {
|
||||||
|
throw new NativeException(String.format("Could not get terminal size. Errno is %d.", result.getErrno()));
|
||||||
|
}
|
||||||
|
return terminalSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,6 @@ public interface Terminal extends NativeIntegration {
|
|||||||
enum Output {Stdout, Stderr}
|
enum Output {Stdout, Stderr}
|
||||||
|
|
||||||
boolean isTerminal(Output output);
|
boolean isTerminal(Output output);
|
||||||
|
|
||||||
|
TerminalSize getTerminalSize(Output output);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.rubygrapefruit.platform;
|
||||||
|
|
||||||
|
public interface TerminalSize {
|
||||||
|
public int getCols();
|
||||||
|
|
||||||
|
public int getRows();
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package net.rubygrapefruit.platform.internal;
|
||||||
|
|
||||||
|
import net.rubygrapefruit.platform.TerminalSize;
|
||||||
|
|
||||||
|
public class MutableTerminalSize implements TerminalSize {
|
||||||
|
int rows;
|
||||||
|
int cols;
|
||||||
|
|
||||||
|
public int getCols() {
|
||||||
|
return cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRows() {
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package net.rubygrapefruit.platform.internal;
|
package net.rubygrapefruit.platform.internal;
|
||||||
|
|
||||||
public class PosixTerminalFunctions {
|
public class PosixTerminalFunctions {
|
||||||
public static native boolean isatty(int fildes);
|
public static native boolean isatty(int filedes);
|
||||||
|
|
||||||
|
public static native void getTerminalSize(int filedes, MutableTerminalSize size, FunctionResult result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,13 @@ class TerminalTest extends Specification {
|
|||||||
!terminal.isTerminal(Terminal.Output.Stdout);
|
!terminal.isTerminal(Terminal.Output.Stdout);
|
||||||
!terminal.isTerminal(Terminal.Output.Stderr);
|
!terminal.isTerminal(Terminal.Output.Stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def "cannot detemine terminal size from a test"() {
|
||||||
|
when:
|
||||||
|
terminal.getTerminalSize(Terminal.Output.Stdout)
|
||||||
|
|
||||||
|
then:
|
||||||
|
NativeException e = thrown()
|
||||||
|
e.message == 'Could not get terminal size. Errno is 25.'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user