Skip to content

Commit

Permalink
nano command: implemented 'go to line' operation
Browse files Browse the repository at this point in the history
  • Loading branch information
mattirn committed Jul 28, 2019
1 parent 7e4263e commit 127212d
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 64 deletions.
197 changes: 133 additions & 64 deletions builtins/src/main/java/org/jline/builtins/Nano.java
Original file line number Diff line number Diff line change
Expand Up @@ -719,11 +719,15 @@ public void moveTo(int x, int y) {
}

public void gotoLine(int x, int y) {
if (printLineNumbers) {
x = Math.max(x - 8, 0);
}
line = y < lines.size() ? y : lines.size() - 1;
x = x <= lines.get(line).length() ? x : lines.get(line).length();
firstLineToDisplay = line > 0 ? line - 1 : line;
offsetInLine = 0;
offsetInLineToDisplay = 0;
column = 0;
moveRight(x);
ensureCursorVisible();
curPos();
}

public int getDisplayedCursor() {
Expand Down Expand Up @@ -1182,6 +1186,9 @@ public void run() throws IOException {
case UNCUT:
buffer.uncut();
break;
case GOTO:
gotoLine();
break;
default:
setMessage("Unsupported " + op.name().toLowerCase().replace('_', '-'));
break;
Expand All @@ -1203,6 +1210,30 @@ public void run() throws IOException {
}
}

private int editInputBuffer(Operation operation, int curPos) {
switch (operation) {
case INSERT:
editBuffer.insert(curPos++, bindingReader.getLastBinding());
break;
case BACKSPACE:
if (curPos > 0) {
editBuffer.deleteCharAt(--curPos);
}
break;
case LEFT:
if (curPos > 0) {
curPos--;
}
break;
case RIGHT:
if (curPos < editBuffer.length()) {
curPos++;
}
break;
}
return curPos;
}

boolean write() throws IOException {
KeyMap<Operation> writeKeyMap = new KeyMap<>();
if (!restricted) {
Expand Down Expand Up @@ -1236,25 +1267,8 @@ boolean write() throws IOException {
this.shortcuts = writeShortcuts();
display(curPos);
while (true) {
switch (readOperation(writeKeyMap)) {
case INSERT:
editBuffer.insert(curPos++, bindingReader.getLastBinding());
break;
case BACKSPACE:
if (curPos > 0) {
editBuffer.deleteCharAt(--curPos);
}
break;
case LEFT:
if (curPos > 0) {
curPos--;
}
break;
case RIGHT:
if (curPos < editBuffer.length()) {
curPos++;
}
break;
Operation op = readOperation(writeKeyMap);
switch (op) {
case CANCEL:
editMessage = null;
this.shortcuts = standardShortcuts();
Expand Down Expand Up @@ -1290,6 +1304,9 @@ boolean write() throws IOException {
case TOGGLE_SUSPENSION:
toggleSuspension();
break;
default:
curPos = editInputBuffer(op, curPos);
break;
}
editMessage = getWriteMessage();
display(curPos);
Expand Down Expand Up @@ -1449,25 +1466,8 @@ void read() {
this.shortcuts = readShortcuts();
display(curPos);
while (true) {
switch (readOperation(readKeyMap)) {
case INSERT:
editBuffer.insert(curPos++, bindingReader.getLastBinding());
break;
case BACKSPACE:
if (curPos > 0) {
editBuffer.deleteCharAt(--curPos);
}
break;
case LEFT:
if (curPos > 0) {
curPos--;
}
break;
case RIGHT:
if (curPos < editBuffer.length()) {
curPos++;
}
break;
Operation op = readOperation(readKeyMap);
switch (op) {
case CANCEL:
editMessage = null;
this.shortcuts = standardShortcuts();
Expand Down Expand Up @@ -1509,8 +1509,8 @@ void read() {
case MOUSE_EVENT:
mouseEvent();
break;
case TOGGLE_SUSPENSION:
toggleSuspension();
default:
curPos = editInputBuffer(op, curPos);
break;
}
editMessage = getReadMessage();
Expand All @@ -1528,6 +1528,89 @@ private String getReadMessage() {
return sb.toString();
}

void gotoLine() throws IOException {
KeyMap<Operation> readKeyMap = new KeyMap<>();
readKeyMap.setUnicode(Operation.INSERT);
for (char i = 32; i < 256; i++) {
readKeyMap.bind(Operation.INSERT, Character.toString(i));
}
readKeyMap.bind(Operation.BACKSPACE, del());
readKeyMap.bind(Operation.ACCEPT, "\r");
readKeyMap.bind(Operation.HELP, ctrl('G'), key(terminal, Capability.key_f1));
readKeyMap.bind(Operation.CANCEL, ctrl('C'));
readKeyMap.bind(Operation.RIGHT, key(terminal, Capability.key_right));
readKeyMap.bind(Operation.LEFT, key(terminal, Capability.key_left));
readKeyMap.bind(Operation.FIRST_LINE, ctrl('Y'));
readKeyMap.bind(Operation.LAST_LINE, ctrl('V'));
readKeyMap.bind(Operation.SEARCH, ctrl('T'));

editMessage = "Enter line number, column number: ";
editBuffer.setLength(0);
int curPos = editBuffer.length();
this.shortcuts = gotoShortcuts();
display(curPos);
while (true) {
Operation op = readOperation(readKeyMap);
switch (op) {
case CANCEL:
editMessage = null;
this.shortcuts = standardShortcuts();
return;
case FIRST_LINE:
editMessage = null;
buffer.firstLine();
this.shortcuts = standardShortcuts();
return;
case LAST_LINE:
editMessage = null;
buffer.lastLine();
this.shortcuts = standardShortcuts();
return;
case SEARCH:
search();
return;
case ACCEPT:
editMessage = null;
String[] pos = editBuffer.toString().split(",", 2);
int[] args = { 0, 0 };
try {
for(int i = 0; i < pos.length; i++) {
if (pos[i].trim().length() > 0) {
args[i] = Integer.parseInt(pos[i]) - 1;
if (args[i] < 0) {
throw new NumberFormatException();
}
}
}
buffer.gotoLine(args[1], args[0]);
} catch (NumberFormatException ex) {
setMessage("Invalid line or column number");
} catch (Exception ex) {
setMessage("Internal error: " + ex.getMessage());
}
this.shortcuts = standardShortcuts();
return;
case HELP:
help("nano-goto-help.txt");
break;
default:
curPos = editInputBuffer(op, curPos);
break;
}
display(curPos);
}
}

private LinkedHashMap<String, String> gotoShortcuts() {
LinkedHashMap<String, String> shortcuts = new LinkedHashMap<>();
shortcuts.put("^G", "Get Help");
shortcuts.put("^Y", "First Line");
shortcuts.put("^T", "Go To Text");
shortcuts.put("^C", "Cancel");
shortcuts.put("^V", "Last Line");
return shortcuts;
}

private LinkedHashMap<String, String> readShortcuts() {
LinkedHashMap<String, String> shortcuts = new LinkedHashMap<>();
shortcuts.put("^G", "Get Help");
Expand Down Expand Up @@ -1698,25 +1781,8 @@ void search() throws IOException {
display(curPos);
try {
while (true) {
switch (readOperation(searchKeyMap)) {
case INSERT:
editBuffer.insert(curPos++, bindingReader.getLastBinding());
break;
case BACKSPACE:
if (curPos > 0) {
editBuffer.deleteCharAt(--curPos);
}
break;
case LEFT:
if (curPos > 0) {
curPos--;
}
break;
case RIGHT:
if (curPos < editBuffer.length()) {
curPos++;
}
break;
Operation op = readOperation(searchKeyMap);
switch (op) {
case UP:
searchTermId++;
if (searchTermId >= 0 && searchTermId < searchTerms.size()) {
Expand Down Expand Up @@ -1783,7 +1849,10 @@ void search() throws IOException {
case TOGGLE_SUSPENSION:
toggleSuspension();
break;
}
default:
curPos = editInputBuffer(op, curPos);
break;
}
editMessage = getSearchMessage();
display(curPos);
}
Expand Down Expand Up @@ -2160,7 +2229,7 @@ protected void bindKeys() {
keys.bind(Operation.MARK, ctrl('^'), key(terminal, Capability.key_f15), alt('a'));
keys.bind(Operation.NEXT_SEARCH, key(terminal, Capability.key_f16), alt('w'));

keys.bind(Operation.COPY, alt('^'));
keys.bind(Operation.COPY, alt('^'), alt('6'));
keys.bind(Operation.INDENT, alt('}'));
keys.bind(Operation.UNINDENT, alt('{'));

Expand Down
14 changes: 14 additions & 0 deletions builtins/src/main/resources/org/jline/builtins/nano-goto-help.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Go To Line Help Text

Enter the line number that you wish to go to and hit Enter. If there are
fewer lines of text than the number you entered, you will be brought to
the last line of the file.

The following function keys are available in Go To Line mode:

^G (F1) Display this help text
^C Cancel the current function
^Y Go to the first line of the file
^V Go to the last line of the file

^T Search for a string or a regular expression

1 comment on commit 127212d

@mattirn
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.