// Copyright © 2010, Esko Luontola <www.orfjackal.net>
// This software is released under the Apache License 2.0.
// The license text is at http://www.apache.org/licenses/LICENSE-2.0
package net.orfjackal.sbt.plugin;
import com.intellij.execution.process.*;
import com.intellij.openapi.diagnostic.Logger;
import net.orfjackal.sbt.runner.OutputReader;
import java.io.*;
public class SbtProcessHandler extends ProcessHandler {
private static final Logger logger = Logger.getInstance(SbtProcessHandler.class.getName());
private final SbtRunnerComponent sbt;
private final OutputReader output;
public SbtProcessHandler(SbtRunnerComponent sbt, OutputReader output) {
this.sbt = sbt;
this.output = output;
}
public void startNotify() {
final NotifyWhenTextAvailable outputNotifier = new NotifyWhenTextAvailable(this, output);
addProcessListener(new ProcessAdapter() {
public void startNotified(ProcessEvent event) {
Thread t = new Thread(outputNotifier);
t.setDaemon(true);
t.start();
}
});
super.startNotify();
}
public OutputStream getProcessInput() {
return new ExecuteUserEnteredActions(sbt);
}
protected void destroyProcessImpl() {
sbt.destroyProcess();
}
protected void detachProcessImpl() {
throw new UnsupportedOperationException("SBT cannot be detached");
}
public boolean detachIsDefault() {
return false;
}
private static class NotifyWhenTextAvailable implements Runnable {
private final SbtProcessHandler process;
private final Reader output;
public NotifyWhenTextAvailable(SbtProcessHandler process, Reader output) {
this.process = process;
this.output = output;
}
public void run() {
try {
char[] cbuf = new char[100];
int len;
while ((len = output.read(cbuf)) != -1) {
String text = new String(cbuf, 0, len);
String withoutCr = text.replace("\r", "");
process.notifyTextAvailable(withoutCr, ProcessOutputTypes.STDOUT);
}
} catch (IOException e) {
logger.error(e);
} finally {
process.notifyProcessTerminated(0);
}
}
}
private static class ExecuteUserEnteredActions extends OutputStream {
private final SbtRunnerComponent sbt;
private final StringBuilder commandBuffer = new StringBuilder();
public ExecuteUserEnteredActions(SbtRunnerComponent sbt) {
this.sbt = sbt;
}
public void write(int b) {
char ch = (char) b;
if (ch == '\n') {
sbt.executeInBackground(buildCommand());
} else {
commandBuffer.append(ch);
}
}
private String buildCommand() {
String command = commandBuffer.toString().trim();
commandBuffer.setLength(0);
return command;
}
}
}