Skip to content

Commit

Permalink
Merge remote-tracking branch 'mattirn/less-help'
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Jul 4, 2019
2 parents 864f206 + c3f81e2 commit fe07684
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 16 deletions.
97 changes: 81 additions & 16 deletions builtins/src/main/java/org/jline/builtins/Less.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.jline.builtins.Source.ResourceSource;
import org.jline.keymap.BindingReader;
import org.jline.keymap.KeyMap;
import org.jline.terminal.Attributes;
Expand Down Expand Up @@ -113,15 +114,16 @@ public void run(List<Source> sources) throws IOException, InterruptedException {
if (sources == null || sources.isEmpty()) {
throw new IllegalArgumentException("No sources");
}
sources.add(0, new ResourceSource("less-help.txt", "HELP -- Press SPACE for more, or q when done"));
this.sources = sources;

sourceIdx = 0;
sourceIdx = 1;
openSource();

try {
size.copy(terminal.getSize());

if (quitIfOneScreen && sources.size() == 1) {
if (quitIfOneScreen && sources.size() == 2) {
if (display(true)) {
return;
}
Expand Down Expand Up @@ -296,13 +298,15 @@ else if (buffer.length() > 0 && (buffer.charAt(0) == '/' || buffer.charAt(0) ==
moveBackward(halfWindow);
break;
case GO_TO_FIRST_LINE_OR_N:
// TODO: handle number
firstLineToDisplay = firstLineInMemory;
offsetInLine = 0;
moveTo(getStrictPositiveNumberInBuffer(1) - 1);
break;
case GO_TO_LAST_LINE_OR_N:
// TODO: handle number
moveForward(Integer.MAX_VALUE);
int lineNum = getStrictPositiveNumberInBuffer(0) - 1;
if (lineNum < 0) {
moveForward(Integer.MAX_VALUE);
} else {
moveTo(lineNum);
}
break;
case LEFT_ONE_HALF_SCREEN:
firstColumnToDisplay = Math.max(0, firstColumnToDisplay - size.getColumns() / 2);
Expand Down Expand Up @@ -355,21 +359,26 @@ else if (buffer.length() > 0 && (buffer.charAt(0) == '/' || buffer.charAt(0) ==
message = ignoreCaseAlways ? "Ignore case in searches and in patterns" : "Case is significant in searches";
break;
case NEXT_FILE:
if (sourceIdx < sources.size() - 1) {
sourceIdx++;
int next = getStrictPositiveNumberInBuffer(1);
if (sourceIdx < sources.size() - next) {
sourceIdx += next;
openSource();
} else {
message = "No next file";
}
break;
case PREV_FILE:
if (sourceIdx > 0) {
sourceIdx--;
int prev = getStrictPositiveNumberInBuffer(1);
if (sourceIdx > prev) {
sourceIdx -= prev;
openSource();
} else {
message = "No previous file";
}
break;
case HELP:
help();
break;
}
buffer.setLength(0);
}
Expand Down Expand Up @@ -404,16 +413,57 @@ else if (buffer.length() > 0 && (buffer.charAt(0) == '/' || buffer.charAt(0) ==
}
}

private void help() throws IOException {
int saveSourceIdx = sourceIdx;
int saveFirstLineToDisplay = firstLineToDisplay;
int saveFirstColumnToDisplay = firstColumnToDisplay;
int saveOffsetInLine = offsetInLine;
boolean savePrintLineNumbers = printLineNumbers;

printLineNumbers = false;
sourceIdx = 0;
try {
openSource();
display(false);
Operation op = null;
do {
checkInterrupted();

op = bindingReader.readBinding(keys, null, false);
if (op != null) {
switch (op) {
case FORWARD_ONE_WINDOW_OR_LINES:
moveForward(getStrictPositiveNumberInBuffer(window));
break;
case BACKWARD_ONE_WINDOW_OR_LINES:
moveBackward(getStrictPositiveNumberInBuffer(window));
break;
}
}
display(false);
} while (op != Operation.EXIT);
} catch (IOException|InterruptedException exp) {
// Do nothing
} finally {
sourceIdx = saveSourceIdx;
openSource();
firstLineToDisplay = saveFirstLineToDisplay;
firstColumnToDisplay = saveFirstColumnToDisplay;
offsetInLine = saveOffsetInLine;
printLineNumbers = savePrintLineNumbers;
}
}

protected void openSource() throws IOException {
if (reader != null) {
reader.close();
}
Source source = sources.get(sourceIdx);
InputStream in = source.read();
if (sources.size() == 1) {
if (sources.size() == 2 || sourceIdx == 0) {
message = source.getName();
} else {
message = source.getName() + " (file " + (sourceIdx + 1) + " of " + sources.size() + ")";
message = source.getName() + " (file " + sourceIdx + " of " + (sources.size() - 1)+ ")";
}
reader = new BufferedReader(new InputStreamReader(new InterruptibleInputStream(in)));
firstLineInMemory = 0;
Expand All @@ -423,6 +473,19 @@ protected void openSource() throws IOException {
offsetInLine = 0;
}

void moveTo(int lineNum) throws IOException {
AttributedString line = getLine(lineNum);
if (line != null){
if (firstLineInMemory > lineNum) {
openSource();
}
firstLineToDisplay = lineNum;
offsetInLine = 0;
} else {
message = "Cannot seek to line number " + (lineNum + 1);
}
}

private void moveToNextMatch() throws IOException {
Pattern compiled = getPattern();
if (compiled != null) {
Expand Down Expand Up @@ -531,7 +594,7 @@ void moveBackward(int lines) throws IOException {

private void eof() {
nbEof++;
if (sourceIdx < sources.size() - 1) {
if (sourceIdx > 0 && sourceIdx < sources.size() - 1) {
message = "(END) - Next: " + sources.get(sourceIdx + 1).getName();
} else {
message = "(END)";
Expand Down Expand Up @@ -568,6 +631,7 @@ synchronized boolean display(boolean oneScreen) throws IOException {
AttributedString curLine = null;
Pattern compiled = getPattern();
boolean fitOnOneScreen = false;
boolean eof = false;
for (int terminalLine = 0; terminalLine < height - 1; terminalLine++) {
if (curLine == null) {
curLine = getLine(inputLine++);
Expand All @@ -576,7 +640,8 @@ synchronized boolean display(boolean oneScreen) throws IOException {
fitOnOneScreen = true;
break;
}
curLine = new AttributedString("");
eof = true;
curLine = new AttributedString("~");
}
if (compiled != null) {
curLine = curLine.styleMatches(compiled, AttributedStyle.DEFAULT.inverse());
Expand All @@ -600,7 +665,7 @@ synchronized boolean display(boolean oneScreen) throws IOException {
curLine = null;
}
}
if (printLineNumbers) {
if (printLineNumbers && !eof) {
AttributedStringBuilder sb = new AttributedStringBuilder();
sb.append(String.format("%7d ", inputLine));
sb.append(toDisplay);
Expand Down
24 changes: 24 additions & 0 deletions builtins/src/main/java/org/jline/builtins/Source.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,28 @@ public StdInSource(InputStream in) {
}

}

class ResourceSource implements Source {
final String resource;
final String name;

public ResourceSource(String resource) {
this(resource, resource);
}

public ResourceSource(String resource, String name) {
this.resource = Objects.requireNonNull(resource);
this.name = name;
}

@Override
public String getName() {
return name;
}

@Override
public InputStream read() throws IOException {
return getClass().getResourceAsStream(resource);
}
}
}
77 changes: 77 additions & 0 deletions builtins/src/main/resources/org/jline/builtins/less-help.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@

SUMMARY OF LESS COMMANDS

Commands marked with * may be preceded by a number, N.
Notes in parentheses indicate the behavior if N is given.
A key preceded by a caret indicates the Ctrl key; thus ^K is ctrl-K.

h H Display this help.
q :q Q :Q ZZ Exit.
---------------------------------------------------------------------------

MOVING

e ^E j ^N CR * Forward one line (or N lines).
y ^Y k ^K ^P * Backward one line (or N lines).
f ^F ^V SPACE * Forward one window (or N lines).
b ^B ESC-v * Backward one window (or N lines).
z * Forward one window (and set window to N).
w * Backward one window (and set window to N).
ESC-SPACE * Forward one window, but don't stop at end-of-file.
d ^D * Forward one half-window (and set half-window to N).
u ^U * Backward one half-window (and set half-window to N).
ESC-) RightArrow * Left one half screen width (or N positions).
ESC-( LeftArrow * Right one half screen width (or N positions).
g < ESC-< * Go to first line in file (or line N).
G > ESC-> * Go to last line in file (or line N).
---------------------------------------------------
Default "window" is the screen height.
Default "half-window" is half of the screen height.
---------------------------------------------------------------------------

SEARCHING

/pattern * Search forward for (N-th) matching line.
?pattern * Search backward for (N-th) matching line.
n N * Repeat previous search (for N-th occurrence).
ESC-n ESC-N * Repeat previous search, spanning files.
ESC-u Undo (toggle) search highlighting.
---------------------------------------------------------------------------

CHANGING FILES

:n * Examine the (N-th) next file from the command line.
:p * Examine the (N-th) previous file from the command line.
---------------------------------------------------------------------------

MISCELLANEOUS COMMANDS

-<flag> Toggle a command line option [see OPTIONS below].
--<name> Toggle a command line option, by name.
---------------------------------------------------------------------------

OPTIONS

Most options may be changed either on the command line,
or from within less by using the - or -- command.
Options may be given in one of two forms: either a single
character preceded by a -, or a name preceded by --.

-? ........ --help
Display help (from command line).
-e ........ --quit-at-eof
Quit at second end of file.
-E ........ --QUIT-AT-EOF
Quit at end of file.
-i ........ --ignore-case
Ignore case in searches that do not contain uppercase.
-I ........ --IGNORE-CASE
Ignore case in all searches.
-N ........ --LINE-NUMBERS
Display line numbers.
-q -Q .... --quiet --QUIET --silent --SILENT
Quiet the terminal bell.
-S ........ --chop-long-lines
Chop (truncate) long lines rather than wrapping.
-x [N[,...]] --tabs=[N[,...]]
Set tab stops (from command line).

0 comments on commit fe07684

Please sign in to comment.