Skip to content

Commit

Permalink
Merge remote-tracking branch 'mattirn/less-command'
Browse files Browse the repository at this point in the history
# Conflicts:
#	builtins/src/main/java/org/jline/builtins/Nano.java
  • Loading branch information
gnodet committed Jul 4, 2019
2 parents 2655e1d + 31d7d9d commit b4f594e
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 24 deletions.
13 changes: 8 additions & 5 deletions builtins/src/main/java/org/jline/builtins/Commands.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public static void less(Terminal terminal, InputStream in, PrintStream out, Prin
" -S --chop-long-lines Do not fold long lines",
" -i --ignore-case Search ignores lowercase case",
" -I --IGNORE-CASE Search ignores all case",
" -x --tabs Set tab stops",
" -x --tabs=N[,...] Set tab stops",
" -N --LINE-NUMBERS Display line number for each line"
};

Expand All @@ -135,17 +135,20 @@ public static void less(Terminal terminal, InputStream in, PrintStream out, Prin
throw new HelpException(opt.usage());
}

Less less = new Less(terminal);
List<Integer> tabs = new ArrayList<>();
if (opt.isSet("tabs")) {
for (String s: opt.get("tabs").split(",")) {
tabs.add(parseInteger(s));
}
}
Less less = new Less(terminal).tabs(tabs);
less.quitAtFirstEof = opt.isSet("QUIT-AT-EOF");
less.quitAtSecondEof = opt.isSet("quit-at-eof");
less.quiet = opt.isSet("quiet");
less.veryQuiet = opt.isSet("QUIET");
less.chopLongLines = opt.isSet("chop-long-lines");
less.ignoreCaseAlways = opt.isSet("IGNORE-CASE");
less.ignoreCaseCond = opt.isSet("ignore-case");
if (opt.isSet("tabs")) {
less.tabs = opt.getNumber("tabs");
}
less.printLineNumbers = opt.isSet("LINE-NUMBERS");
List<Source> sources = new ArrayList<>();
if (opt.args().isEmpty()) {
Expand Down
17 changes: 15 additions & 2 deletions builtins/src/main/java/org/jline/builtins/Less.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.jline.utils.Display;
import org.jline.utils.InfoCmp.Capability;
import org.jline.utils.NonBlockingReader;
import org.jline.utils.Status;

import static org.jline.keymap.KeyMap.alt;
import static org.jline.keymap.KeyMap.ctrl;
Expand All @@ -57,8 +58,8 @@ public class Less {
public boolean ignoreCaseAlways;
public boolean noKeypad;
public boolean noInit;
public int tabs = 4;


protected List<Integer> tabs = Arrays.asList(4);
protected final Terminal terminal;
protected final Display display;
protected final BindingReader bindingReader;
Expand Down Expand Up @@ -96,6 +97,11 @@ public Less(Terminal terminal) {
this.bindingReader = new BindingReader(terminal.reader());
}

public Less tabs(List<Integer> tabs) {
this.tabs = tabs;
return this;
}

public void handle(Signal signal) {
size.copy(terminal.getSize());
try {
Expand All @@ -119,8 +125,12 @@ public void run(List<Source> sources) throws IOException, InterruptedException {

sourceIdx = 1;
openSource();
Status status = Status.getStatus(terminal, false);

try {
if (status != null) {
status.suspend();
}
size.copy(terminal.getSize());

if (quitIfOneScreen && sources.size() == 2) {
Expand Down Expand Up @@ -410,6 +420,9 @@ else if (buffer.length() > 0 && (buffer.charAt(0) == '/' || buffer.charAt(0) ==
}
} finally {
reader.close();
if (status != null) {
status.restore();
}
}
}

Expand Down
10 changes: 9 additions & 1 deletion builtins/src/main/java/org/jline/builtins/Nano.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.jline.utils.AttributedStringBuilder;
import org.jline.utils.AttributedStyle;
import org.jline.utils.Display;
import org.jline.utils.Status;
import org.jline.utils.InfoCmp.Capability;
import org.mozilla.universalchardet.UniversalDetector;

Expand Down Expand Up @@ -994,8 +995,12 @@ public void run() throws IOException {
this.shortcuts = standardShortcuts();

SignalHandler prevHandler = null;
Status status = Status.getStatus(terminal, false);
try {
size.copy(terminal.getSize());
if (status != null) {
status.suspend();
}
buffer.open();
if (buffer.file != null) {
setMessage("Read " + buffer.lines.size() + " lines");
Expand Down Expand Up @@ -1139,7 +1144,10 @@ public void run() throws IOException {
terminal.flush();
terminal.setAttributes(attributes);
terminal.handle(Signal.WINCH, prevHandler);
}
if (status != null) {
status.restore();
}
}
}

boolean write() throws IOException {
Expand Down
21 changes: 16 additions & 5 deletions demo/src/main/java/org/apache/felix/gogo/jline/Posix.java
Original file line number Diff line number Diff line change
Expand Up @@ -942,7 +942,7 @@ protected void less(CommandSession session, Process process, String[] argv) thro
" -S --chop-long-lines Do not fold long lines",
" -i --ignore-case Search ignores lowercase case",
" -I --IGNORE-CASE Search ignores all case",
" -x --tabs Set tab stops",
" -x --tabs=N[,...] Set tab stops",
" -N --LINE-NUMBERS Display line number for each line",
" --no-init Disable terminal initialization",
" --no-keypad Disable keypad handling"
Expand Down Expand Up @@ -978,17 +978,20 @@ protected void less(CommandSession session, Process process, String[] argv) thro
return;
}

Less less = new Less(Shell.getTerminal(session));
List<Integer> tabs = new ArrayList<>();
if (opt.isSet("tabs")) {
for (String s: opt.get("tabs").split(",")) {
tabs.add(parseInteger(s));
}
}
Less less = new Less(Shell.getTerminal(session)).tabs(tabs);
less.quitAtFirstEof = opt.isSet("QUIT-AT-EOF");
less.quitAtSecondEof = opt.isSet("quit-at-eof");
less.quiet = opt.isSet("quiet");
less.veryQuiet = opt.isSet("QUIET");
less.chopLongLines = opt.isSet("chop-long-lines");
less.ignoreCaseAlways = opt.isSet("IGNORE-CASE");
less.ignoreCaseCond = opt.isSet("ignore-case");
if (opt.isSet("tabs")) {
less.tabs = opt.getNumber("tabs");
}
less.printLineNumbers = opt.isSet("LINE-NUMBERS");
if (hasExtendedOptions) {
Less.class.getField("quitIfOneScreen").set(less, opt.isSet("quit-if-one-screen"));
Expand All @@ -998,6 +1001,14 @@ protected void less(CommandSession session, Process process, String[] argv) thro
less.run(sources);
}

private int parseInteger(String s) throws IllegalArgumentException {
try {
return Integer.parseInt(s);
} catch (NumberFormatException ex) {
throw new IllegalArgumentException();
}
}

protected void sort(CommandSession session, Process process, String[] argv) throws Exception {
final String[] usage = {
"sort - writes sorted standard input to standard output.",
Expand Down
7 changes: 6 additions & 1 deletion terminal/src/main/java/org/jline/utils/AttributedString.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import java.security.InvalidParameterException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -98,6 +99,10 @@ public static AttributedString fromAnsi(String ansi) {
}

public static AttributedString fromAnsi(String ansi, int tabs) {
return fromAnsi(ansi, Arrays.asList(tabs));
}

public static AttributedString fromAnsi(String ansi, List<Integer> tabs) {
if (ansi == null) {
return null;
}
Expand All @@ -106,7 +111,7 @@ public static AttributedString fromAnsi(String ansi, int tabs) {
.ansiAppend(ansi)
.toAttributedString();
}

public static String stripAnsi(String ansi) {
if (ansi == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/
package org.jline.utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
Expand All @@ -25,7 +26,7 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
private char[] buffer;
private int[] style;
private int length;
private int tabs = 0;
private TabStops tabs = new TabStops(0);
private int lastLineLength = 0;
private AttributedStyle current = AttributedStyle.DEFAULT;

Expand Down Expand Up @@ -152,7 +153,7 @@ public AttributedStringBuilder append(AttributedCharSequence str, int start, int
for (int i = start; i < end; i++) {
char c = str.charAt(i);
int s = str.styleCodeAt(i) & ~current.getMask() | current.getStyle();
if (tabs > 0 && c == '\t') {
if (tabs.defined() && c == '\t') {
insertTab(new AttributedStyle(s, 0));
} else {
ensureCapacity(length + 1);
Expand Down Expand Up @@ -333,7 +334,7 @@ public AttributedStringBuilder ansiAppend(String ansi) {
// This is not a SGR code, so ignore
ansiState = 0;
}
} else if (c == '\t' && tabs > 0) {
} else if (c == '\t' && tabs.defined()) {
insertTab(current);
} else {
ensureCapacity(length + 1);
Expand All @@ -351,7 +352,7 @@ public AttributedStringBuilder ansiAppend(String ansi) {
}

protected void insertTab(AttributedStyle s) {
int nb = tabs - lastLineLength % tabs;
int nb = tabs.spaces(lastLineLength);
ensureCapacity(length + nb);
for (int i = 0; i < nb; i++) {
buffer[length] = ' ';
Expand All @@ -374,16 +375,20 @@ public void setLength(int l) {
* @return this
*/
public AttributedStringBuilder tabs(int tabsize) {
if (length > 0) {
throw new IllegalStateException("Cannot change tab size after appending text");
}
if (tabsize < 0) {
throw new IllegalArgumentException("Tab size must be non negative");
}
this.tabs = tabsize;
return this;
return tabs(Arrays.asList(tabsize));
}

public AttributedStringBuilder tabs(List<Integer> tabs) {
if (length > 0) {
throw new IllegalStateException("Cannot change tab size after appending text");
}
this.tabs = new TabStops(tabs);
return this;
}

public AttributedStringBuilder styleMatches(Pattern pattern, AttributedStyle s) {
Matcher matcher = pattern.matcher(this);
while (matcher.find()) {
Expand All @@ -406,5 +411,48 @@ public AttributedStringBuilder styleMatches(Pattern pattern, List<AttributedStyl
}
return this;
}

private class TabStops {
private List<Integer> tabs = new ArrayList<>();
private int lastStop = 0;
private int lastSize = 0;

public TabStops(int tabs) {
this.lastSize = tabs;
}

public TabStops(List<Integer> tabs) {
this.tabs = tabs;
int p = 0;
for (int s: tabs) {
if (s <= p) {
continue;
}
lastStop = s;
lastSize = s - p;
p = s;
}
}

boolean defined() {
return lastSize > 0;
}

int spaces(int lastLineLength) {
int out = 0;
if (lastLineLength >= lastStop) {
out = lastSize - (lastLineLength - lastStop) % lastSize;
} else {
for (int s: tabs) {
if (s > lastLineLength) {
out = s - lastLineLength;
break;
}
}
}
return out;
}

}

}
36 changes: 35 additions & 1 deletion terminal/src/main/java/org/jline/utils/Status.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ public class Status {
protected final AbstractTerminal terminal;
protected final boolean supported;
protected List<AttributedString> oldLines = Collections.emptyList();
protected List<AttributedString> linesToRestore = Collections.emptyList();
protected int rows;
protected int columns;
protected boolean force;
protected boolean suspended = false;

public static Status getStatus(Terminal terminal) {
return getStatus(terminal, true);
Expand Down Expand Up @@ -62,20 +64,33 @@ public void reset() {
}

public void hardReset() {
if (suspended) {
return;
}
List<AttributedString> lines = new ArrayList<>(oldLines);
update(null);
update(lines);
}

public void redraw() {
if (suspended) {
return;
}
update(oldLines);
}

public void update(List<AttributedString> lines) {
if (!supported) {
return;
}
if (lines == null) {
lines = Collections.emptyList();
}
if (!supported || (oldLines.equals(lines) && !force)) {
if (suspended) {
linesToRestore = new ArrayList<>(lines);
return;
}
if (oldLines.equals(lines) && !force) {
return;
}
int nb = lines.size() - oldLines.size();
Expand All @@ -100,4 +115,23 @@ public void update(List<AttributedString> lines) {
oldLines = new ArrayList<>(lines);
force = false;
}

public void suspend() {
if (suspended) {
return;
}
linesToRestore = new ArrayList<>(oldLines);
update(null);
suspended = true;
}

public void restore() {
if (!suspended) {
return;
}
suspended = false;
update(linesToRestore);
linesToRestore = Collections.emptyList();
}

}

0 comments on commit b4f594e

Please sign in to comment.