package edu.kit.pse.ws2013.routekit.controllers;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* A {@link CLI} that pretty-prints a progress bar using terminal escape
* characters. Falls back to {@link CLI} if the terminal doesn’t support moving
* the cursor around.
*/
public class TerminalCLI extends EasterEggCLI {
private final String cuu1;
private final String el;
private final int cols;
private final boolean isTerminal;
public TerminalCLI(String[] args) {
super(args);
if (actions == ManagementActions.noActions) {
// error in the options, don’t bother setting up the terminal
cuu1 = el = null;
cols = 0;
isTerminal = false;
return;
}
cuu1 = processOutput("tput", "cuu1"); // cursor up by one
el = processOutput("tput", "el"); // erase line
int _cols;
try {
_cols = Integer.parseInt(processOutput("tput", "cols"));
} catch (NumberFormatException f) {
_cols = 0;
}
cols = _cols;
isTerminal = cuu1 != null && el != null && cols != 0;
if (isTerminal) {
System.out.println(); // move the cursor down
System.out.println(); // we move it up each time we print something
}
}
private String task = "";
private float progress = 0f;
@Override
public void startRoot(String name) {
this.task = name;
if (isTerminal) {
print();
} else {
super.startRoot(name);
}
}
@Override
public void beginTask(String name) {
this.task = name;
if (isTerminal) {
print();
} else {
super.beginTask(name);
}
}
@Override
public void progress(float progress, String name) {
this.task = name;
this.progress = progress;
if (isTerminal) {
print();
} else {
super.progress(progress, name);
}
}
@Override
public void endTask(String name) {
this.task = name;
if (isTerminal) {
print();
} else {
super.endTask(name);
}
}
@Override
public void finishRoot(String name) {
this.task = name;
if (isTerminal) {
print();
} else {
super.finishRoot(name);
}
}
float lastPrintedProgress = -1f;
private void print() {
if (progress - lastPrintedProgress < .001f) {
return;
}
lastPrintedProgress = progress;
System.out.print(cuu1);
System.out.print(el);
System.out.print(cuu1);
System.out.print(el);
System.out.println(task);
// print progress bar
System.out.print(String.format("%3d%% [", (int) (progress * 100)));
final int width = cols - 7;
final int done = Math.round(progress * width);
final int remaining = width - done;
for (int i = 0; i < done - 1; i++) {
System.out.print("=");
}
if (done > 0) {
System.out.print(progress == 1f ? "=" : ">");
}
for (int i = 0; i < remaining; i++) {
System.out.print(" ");
}
System.out.println("]");
}
private static String processOutput(String... command) {
ProcessBuilder pb = new ProcessBuilder(command);
try {
Process p = pb.start();
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
// sb.append(System.getProperty("line.separator"));
}
if (p.waitFor() != 0) {
return null;
}
return sb.toString();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
return null;
}
}
}