use of org.jline.terminal.Attributes in project felix by apache.
the class Posix method ls.
protected void ls(CommandSession session, Process process, String[] argv) throws Exception {
final String[] usage = { "ls - list files", "Usage: ls [OPTIONS] [PATTERNS...]", " -? --help show help", " -1 list one entry per line", " -C multi-column output", " --color=WHEN colorize the output, may be `always', `never' or `auto'", " -a list entries starting with .", " -F append file type indicators", " -m comma separated", " -l long listing", " -S sort by size", " -f output is not sorted", " -r reverse sort order", " -t sort by modification time", " -x sort horizontally", " -L list referenced file for links", " -h print sizes in human readable form" };
Options opt = parseOptions(session, usage, argv);
String color = opt.isSet("color") ? opt.get("color") : "auto";
boolean colored;
switch(color) {
case "always":
case "yes":
case "force":
colored = true;
break;
case "never":
case "no":
case "none":
colored = false;
break;
case "auto":
case "tty":
case "if-tty":
colored = process.isTty(1);
break;
default:
throw new IllegalArgumentException("invalid argument ‘" + color + "’ for ‘--color’");
}
Map<String, String> colors = colored ? getLsColorMap(session) : Collections.emptyMap();
class PathEntry implements Comparable<PathEntry> {
final Path abs;
final Path path;
final Map<String, Object> attributes;
public PathEntry(Path abs, Path root) {
this.abs = abs;
this.path = abs.startsWith(root) ? root.relativize(abs) : abs;
this.attributes = readAttributes(abs);
}
@Override
public int compareTo(PathEntry o) {
int c = doCompare(o);
return opt.isSet("r") ? -c : c;
}
private int doCompare(PathEntry o) {
if (opt.isSet("f")) {
return -1;
}
if (opt.isSet("S")) {
long s0 = attributes.get("size") != null ? ((Number) attributes.get("size")).longValue() : 0L;
long s1 = o.attributes.get("size") != null ? ((Number) o.attributes.get("size")).longValue() : 0L;
return s0 > s1 ? -1 : s0 < s1 ? 1 : path.toString().compareTo(o.path.toString());
}
if (opt.isSet("t")) {
long t0 = attributes.get("lastModifiedTime") != null ? ((FileTime) attributes.get("lastModifiedTime")).toMillis() : 0L;
long t1 = o.attributes.get("lastModifiedTime") != null ? ((FileTime) o.attributes.get("lastModifiedTime")).toMillis() : 0L;
return t0 > t1 ? -1 : t0 < t1 ? 1 : path.toString().compareTo(o.path.toString());
}
return path.toString().compareTo(o.path.toString());
}
boolean isNotDirectory() {
return is("isRegularFile") || is("isSymbolicLink") || is("isOther");
}
boolean isDirectory() {
return is("isDirectory");
}
private boolean is(String attr) {
Object d = attributes.get(attr);
return d instanceof Boolean && (Boolean) d;
}
String display() {
String type;
String suffix;
String link = "";
if (is("isSymbolicLink")) {
type = "sl";
suffix = "@";
try {
Path l = Files.readSymbolicLink(abs);
link = " -> " + l.toString();
} catch (IOException e) {
// ignore
}
} else if (is("isDirectory")) {
type = "dr";
suffix = "/";
} else if (is("isExecutable")) {
type = "ex";
suffix = "*";
} else if (is("isOther")) {
type = "ot";
suffix = "";
} else {
type = "";
suffix = "";
}
String col = colors.get(type);
boolean addSuffix = opt.isSet("F");
if (col != null && !col.isEmpty()) {
return "\033[" + col + "m" + path.toString() + "\033[m" + (addSuffix ? suffix : "") + link;
} else {
return path.toString() + (addSuffix ? suffix : "") + link;
}
}
String longDisplay() {
String username;
if (attributes.containsKey("owner")) {
username = Objects.toString(attributes.get("owner"), null);
} else {
username = "owner";
}
if (username.length() > 8) {
username = username.substring(0, 8);
} else {
for (int i = username.length(); i < 8; i++) {
username = username + " ";
}
}
String group;
if (attributes.containsKey("group")) {
group = Objects.toString(attributes.get("group"), null);
} else {
group = "group";
}
if (group.length() > 8) {
group = group.substring(0, 8);
} else {
for (int i = group.length(); i < 8; i++) {
group = group + " ";
}
}
Number length = (Number) attributes.get("size");
if (length == null) {
length = 0L;
}
String lengthString;
if (opt.isSet("h")) {
double l = length.longValue();
String unit = "B";
if (l >= 1000) {
l /= 1024;
unit = "K";
if (l >= 1000) {
l /= 1024;
unit = "M";
if (l >= 1000) {
l /= 1024;
unit = "T";
}
}
}
if (l < 10 && length.longValue() > 1000) {
lengthString = String.format("%.1f", l) + unit;
} else {
lengthString = String.format("%3.0f", l) + unit;
}
} else {
lengthString = String.format("%1$8s", length);
}
@SuppressWarnings("unchecked") Set<PosixFilePermission> perms = (Set<PosixFilePermission>) attributes.get("permissions");
if (perms == null) {
perms = EnumSet.noneOf(PosixFilePermission.class);
}
// TODO: all fields should be padded to align
return (is("isDirectory") ? "d" : (is("isSymbolicLink") ? "l" : (is("isOther") ? "o" : "-"))) + PosixFilePermissions.toString(perms) + " " + String.format("%3s", (attributes.containsKey("nlink") ? attributes.get("nlink").toString() : "1")) + " " + username + " " + group + " " + lengthString + " " + toString((FileTime) attributes.get("lastModifiedTime")) + " " + display();
}
protected String toString(FileTime time) {
long millis = (time != null) ? time.toMillis() : -1L;
if (millis < 0L) {
return "------------";
}
ZonedDateTime dt = Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault());
// Less than six months
if (System.currentTimeMillis() - millis < 183L * 24L * 60L * 60L * 1000L) {
return DateTimeFormatter.ofPattern("MMM ppd HH:mm").format(dt);
} else // Older than six months
{
return DateTimeFormatter.ofPattern("MMM ppd yyyy").format(dt);
}
}
protected Map<String, Object> readAttributes(Path path) {
Map<String, Object> attrs = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
for (String view : path.getFileSystem().supportedFileAttributeViews()) {
try {
Map<String, Object> ta = Files.readAttributes(path, view + ":*", getLinkOptions(opt.isSet("L")));
ta.entrySet().forEach(e -> attrs.putIfAbsent(e.getKey(), e.getValue()));
} catch (IOException e) {
// Ignore
}
}
attrs.computeIfAbsent("isExecutable", s -> Files.isExecutable(path));
attrs.computeIfAbsent("permissions", s -> getPermissionsFromFile(path.toFile()));
return attrs;
}
}
Path currentDir = session.currentDir();
// Listing
List<Path> expanded = new ArrayList<>();
if (opt.args().isEmpty()) {
expanded.add(currentDir);
} else {
opt.args().forEach(s -> expanded.add(currentDir.resolve(s)));
}
boolean listAll = opt.isSet("a");
Predicate<Path> filter = p -> listAll || !p.getFileName().toString().startsWith(".");
List<PathEntry> all = expanded.stream().filter(filter).map(p -> new PathEntry(p, currentDir)).sorted().collect(Collectors.toList());
// Print files first
List<PathEntry> files = all.stream().filter(PathEntry::isNotDirectory).collect(Collectors.toList());
PrintStream out = process.out();
Consumer<Stream<PathEntry>> display = s -> {
boolean optLine = opt.isSet("1");
boolean optComma = opt.isSet("m");
boolean optLong = opt.isSet("l");
boolean optCol = opt.isSet("C");
if (!optLine && !optComma && !optLong && !optCol) {
if (process.isTty(1)) {
optCol = true;
} else {
optLine = true;
}
}
// One entry per line
if (optLine) {
s.map(PathEntry::display).forEach(out::println);
} else // Comma separated list
if (optComma) {
out.println(s.map(PathEntry::display).collect(Collectors.joining(", ")));
} else // Long listing
if (optLong) {
s.map(PathEntry::longDisplay).forEach(out::println);
} else // Column listing
if (optCol) {
toColumn(session, process, out, s.map(PathEntry::display), opt.isSet("x"));
}
};
boolean space = false;
if (!files.isEmpty()) {
display.accept(files.stream());
space = true;
}
// Print directories
List<PathEntry> directories = all.stream().filter(PathEntry::isDirectory).collect(Collectors.toList());
for (PathEntry entry : directories) {
if (space) {
out.println();
}
space = true;
Path path = currentDir.resolve(entry.path);
if (expanded.size() > 1) {
out.println(currentDir.relativize(path).toString() + ":");
}
display.accept(Stream.concat(Arrays.asList(".", "..").stream().map(path::resolve), Files.list(path)).filter(filter).map(p -> new PathEntry(p, path)).sorted());
}
}
use of org.jline.terminal.Attributes in project felix by apache.
the class Posix method watch.
protected void watch(final CommandSession session, Process process, String[] argv) throws Exception {
final String[] usage = { "watch - watches & refreshes the output of a command", "Usage: watch [OPTIONS] COMMAND", " -? --help Show help", " -n --interval Interval between executions of the command in seconds", " -a --append The output should be appended but not clear the console" };
Options opt = parseOptions(session, usage, argv);
List<String> args = opt.args();
if (args.isEmpty()) {
throw new IllegalArgumentException("usage: watch COMMAND");
}
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
final Terminal terminal = Shell.getTerminal(session);
final CommandProcessor processor = Shell.getProcessor(session);
try {
int interval = 1;
if (opt.isSet("interval")) {
interval = opt.getNumber("interval");
if (interval < 1) {
interval = 1;
}
}
final String cmd = String.join(" ", args);
Runnable task = () -> {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream os = new PrintStream(baos);
InputStream is = new ByteArrayInputStream(new byte[0]);
if (opt.isSet("append") || !terminal.puts(Capability.clear_screen)) {
terminal.writer().println();
}
try {
CommandSession ns = processor.createSession(is, os, os);
Set<String> vars = Shell.getCommands(session);
for (String n : vars) {
ns.put(n, session.get(n));
}
ns.execute(cmd);
} catch (Throwable t) {
t.printStackTrace(os);
}
os.flush();
terminal.writer().print(baos.toString());
terminal.writer().flush();
};
executorService.scheduleAtFixedRate(task, 0, interval, TimeUnit.SECONDS);
Attributes attr = terminal.enterRawMode();
terminal.reader().read();
terminal.setAttributes(attr);
} finally {
executorService.shutdownNow();
}
}
use of org.jline.terminal.Attributes in project flink by apache.
the class CliView method prepareTerminal.
private Tuple2<Attributes, Map<Signal, SignalHandler>> prepareTerminal() {
final Terminal terminal = client.getTerminal();
final Attributes prevAttributes = terminal.getAttributes();
// adopted from org.jline.builtins.Nano
// see also
// https://en.wikibooks.org/wiki/Serial_Programming/termios#Basic_Configuration_of_a_Serial_Interface
// no line processing
// canonical mode off, echo off, echo newline off, extended input processing off
Attributes newAttr = new Attributes(prevAttributes);
newAttr.setLocalFlags(EnumSet.of(LocalFlag.ICANON, LocalFlag.ECHO, LocalFlag.IEXTEN), false);
// turn off input processing
newAttr.setInputFlags(EnumSet.of(Attributes.InputFlag.IXON, Attributes.InputFlag.ICRNL, Attributes.InputFlag.INLCR), false);
// one input byte is enough to return from read, inter-character timer off
newAttr.setControlChar(Attributes.ControlChar.VMIN, 1);
newAttr.setControlChar(Attributes.ControlChar.VTIME, 0);
newAttr.setControlChar(Attributes.ControlChar.VINTR, 0);
terminal.setAttributes(newAttr);
final Map<Signal, SignalHandler> prevSignals = new HashMap<>();
prevSignals.put(Signal.WINCH, terminal.handle(Signal.WINCH, this::handleSignal));
prevSignals.put(Signal.INT, terminal.handle(Signal.INT, this::handleSignal));
prevSignals.put(Signal.QUIT, terminal.handle(Signal.QUIT, this::handleSignal));
return Tuple2.of(prevAttributes, prevSignals);
}
use of org.jline.terminal.Attributes in project samza by apache.
the class QueryResultLogView method setupTerminal.
private TerminalStatus setupTerminal() {
TerminalStatus prevStatus = new TerminalStatus();
// Signal handlers
prevStatus.handlerInt = terminal.handle(Terminal.Signal.INT, this::handleSignal);
prevStatus.handlerQuit = terminal.handle(Terminal.Signal.QUIT, this::handleSignal);
prevStatus.handlerTstp = terminal.handle(Terminal.Signal.TSTP, this::handleSignal);
prevStatus.handlerCont = terminal.handle(Terminal.Signal.CONT, this::handleSignal);
prevStatus.handlerWinch = terminal.handle(Terminal.Signal.WINCH, this::handleSignal);
// Attributes
prevStatus.attributes = terminal.getAttributes();
Attributes newAttributes = new Attributes(prevStatus.attributes);
// (003, ETX, Ctrl-C, or also 0177, DEL, rubout) Interrupt char‐
// acter (INTR). Send a SIGINT signal. Recognized when ISIG is
// set, and then not passed as input.
newAttributes.setControlChar(Attributes.ControlChar.VINTR, 0);
// (034, FS, Ctrl-\) Quit character (QUIT). Send SIGQUIT signal.
// Recognized when ISIG is set, and then not passed as input.
// newAttributes.setControlChar(Attributes.ControlChar.VQUIT, 0);
newAttributes.setControlChar(Attributes.ControlChar.VMIN, 1);
newAttributes.setControlChar(Attributes.ControlChar.VTIME, 0);
// Enables signals and SIGTTOU signal to the process group of a background
// process which tries to write to our terminal
newAttributes.setLocalFlags(EnumSet.of(Attributes.LocalFlag.ISIG, Attributes.LocalFlag.TOSTOP), true);
// No canonical mode, no echo, and no implementation-defined input processing
newAttributes.setLocalFlags(EnumSet.of(Attributes.LocalFlag.ICANON, Attributes.LocalFlag.ECHO, Attributes.LocalFlag.IEXTEN), false);
// Input flags
newAttributes.setInputFlags(EnumSet.of(Attributes.InputFlag.ICRNL, Attributes.InputFlag.INLCR, Attributes.InputFlag.IXON), false);
terminal.setAttributes(newAttributes);
// Capabilities
// tput smcup; use alternate screen
terminal.puts(InfoCmp.Capability.enter_ca_mode);
terminal.puts(InfoCmp.Capability.cursor_invisible);
terminal.puts(InfoCmp.Capability.cursor_home);
terminal.flush();
return prevStatus;
}
use of org.jline.terminal.Attributes in project accumulo by apache.
the class Shell method printLines.
public final void printLines(Iterator<String> lines, boolean paginate, PrintLine out) throws IOException {
double linesPrinted = 0;
String prompt = "-- hit any key to continue or 'q' to quit --";
int lastPromptLength = prompt.length();
int termWidth = terminal.getWidth();
int maxLines = terminal.getHeight();
String peek = null;
while (lines.hasNext()) {
String nextLine = lines.next();
if (nextLine == null) {
continue;
}
for (String line : nextLine.split("\\n")) {
if (out == null) {
if (peek != null) {
writer.println(peek);
if (paginate) {
linesPrinted += peek.isEmpty() ? 0 : Math.ceil(peek.length() * 1.0 / termWidth);
// scrolling off the screen
if (linesPrinted + Math.ceil(lastPromptLength * 1.0 / termWidth) + Math.ceil(prompt.length() * 1.0 / termWidth) + Math.ceil(line.length() * 1.0 / termWidth) > maxLines) {
linesPrinted = 0;
int numdashes = (termWidth - prompt.length()) / 2;
String nextPrompt = repeat("-", numdashes) + prompt + repeat("-", numdashes);
lastPromptLength = nextPrompt.length();
writer.print(nextPrompt);
writer.flush();
// Enter raw mode so character can be read without hitting 'enter' after
Attributes attr = terminal.enterRawMode();
int c = terminal.reader().read();
// Resets raw mode
terminal.setAttributes(attr);
if (Character.toUpperCase((char) c) == 'Q') {
writer.println();
return;
}
writer.println();
termWidth = terminal.getWidth();
maxLines = terminal.getHeight();
}
}
}
peek = line;
} else {
out.print(line);
}
}
}
if (out == null && peek != null) {
writer.println(peek);
}
}
Aggregations