Restructured terminal APIs.

This commit is contained in:
Adam Murdoch
2012-08-04 05:54:58 +10:00
parent 433347491c
commit 9cfe2b1f24
5 changed files with 43 additions and 22 deletions

View File

@@ -1,20 +1,19 @@
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); TerminalAccess terminalAccess = Platform.get(TerminalAccess.class);
boolean stdoutIsTerminal = terminal.isTerminal(Terminal.Output.Stdout); boolean stdoutIsTerminal = terminalAccess.isTerminal(TerminalAccess.Output.Stdout);
boolean stderrIsTerminal = terminal.isTerminal(Terminal.Output.Stderr); boolean stderrIsTerminal = terminalAccess.isTerminal(TerminalAccess.Output.Stderr);
System.out.println("* stdout: " + (stdoutIsTerminal ? "terminal" : "not a terminal")); System.out.println("* stdout: " + (stdoutIsTerminal ? "terminal" : "not a terminal"));
System.out.println("* stderr: " + (stderrIsTerminal ? "terminal" : "not a terminal")); System.out.println("* stderr: " + (stderrIsTerminal ? "terminal" : "not a terminal"));
if (stdoutIsTerminal) { if (stdoutIsTerminal) {
TerminalSize terminalSize = terminal.getTerminalSize(Terminal.Output.Stdout); Terminal terminal = terminalAccess.getTerminal(TerminalAccess.Output.Stdout);
TerminalSize terminalSize = terminal.getTerminalSize();
System.out.println("* terminal size: " + terminalSize.getCols() + " cols x " + terminalSize.getRows() + " rows"); System.out.println("* terminal size: " + terminalSize.getCols() + " cols x " + terminalSize.getRows() + " rows");
} }
} }

View File

@@ -34,8 +34,8 @@ public class Platform {
if (type.equals(Process.class)) { if (type.equals(Process.class)) {
return type.cast(new DefaultProcess()); return type.cast(new DefaultProcess());
} }
if (type.equals(Terminal.class)) { if (type.equals(TerminalAccess.class)) {
return type.cast(new DefaultTerminal()); return type.cast(new DefaultTerminalAccess());
} }
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,19 +70,36 @@ public class Platform {
} }
} }
private static class DefaultTerminal implements Terminal { private static class DefaultTerminalAccess implements TerminalAccess {
@Override @Override
public boolean isTerminal(Output output) { public boolean isTerminal(Output output) {
return PosixTerminalFunctions.isatty(output.ordinal()); return PosixTerminalFunctions.isatty(output.ordinal());
} }
@Override @Override
public TerminalSize getTerminalSize(Output output) { public Terminal getTerminal(Output output) {
if (!isTerminal(output)) {
throw new NativeException(String.format("%s is not attached to a terminal.", output));
}
return new DefaultTerminal(output);
}
}
private static class DefaultTerminal implements Terminal {
private final TerminalAccess.Output output;
public DefaultTerminal(TerminalAccess.Output output) {
this.output = output;
}
@Override
public TerminalSize getTerminalSize() {
MutableTerminalSize terminalSize = new MutableTerminalSize(); MutableTerminalSize terminalSize = new MutableTerminalSize();
FunctionResult result = new FunctionResult(); FunctionResult result = new FunctionResult();
PosixTerminalFunctions.getTerminalSize(output.ordinal(), terminalSize, result); PosixTerminalFunctions.getTerminalSize(output.ordinal(), terminalSize, result);
if (result.isFailed()) { if (result.isFailed()) {
throw new NativeException(String.format("Could not get terminal size. Errno is %d.", result.getErrno())); throw new NativeException(String.format("Could not get terminal size. Errno is %d.",
result.getErrno()));
} }
return terminalSize; return terminalSize;
} }

View File

@@ -1,9 +1,5 @@
package net.rubygrapefruit.platform; package net.rubygrapefruit.platform;
public interface Terminal extends NativeIntegration { public interface Terminal {
enum Output {Stdout, Stderr} TerminalSize getTerminalSize();
boolean isTerminal(Output output);
TerminalSize getTerminalSize(Output output);
} }

View File

@@ -0,0 +1,9 @@
package net.rubygrapefruit.platform;
public interface TerminalAccess extends NativeIntegration {
enum Output {Stdout, Stderr}
boolean isTerminal(Output output);
Terminal getTerminal(Output output);
}

View File

@@ -6,20 +6,20 @@ import spock.lang.Specification
class TerminalTest extends Specification { class TerminalTest extends Specification {
@Rule TemporaryFolder tmpDir @Rule TemporaryFolder tmpDir
final Terminal terminal = Platform.get(Terminal.class) final TerminalAccess terminal = Platform.get(TerminalAccess.class)
def "can check if attached to terminal"() { def "can check if attached to terminal"() {
expect: expect:
!terminal.isTerminal(Terminal.Output.Stdout); !terminal.isTerminal(TerminalAccess.Output.Stdout);
!terminal.isTerminal(Terminal.Output.Stderr); !terminal.isTerminal(TerminalAccess.Output.Stderr);
} }
def "cannot determine terminal size from a test"() { def "cannot determine terminal size from a test"() {
when: when:
terminal.getTerminalSize(Terminal.Output.Stdout) terminal.getTerminal(TerminalAccess.Output.Stdout)
then: then:
NativeException e = thrown() NativeException e = thrown()
e.message.startsWith('Could not get terminal size. Errno is ') e.message.startsWith('Stdout is not attached to a terminal.')
} }
} }