setStatus("-- VISUAL (char) --");
inVisualMode = true;
visualMoveUnit = MoveUnit.CHARACTER;
// select the character the cursor is over now
SelectionModel selectionModel = getInputController().getEditor().getSelection();
LineInfo cursorLineInfo =
new LineInfo(selectionModel.getCursorLine(), selectionModel.getCursorLineNumber());
int cursorColumn = selectionModel.getCursorColumn();
selectionModel.setSelection(cursorLineInfo, cursorColumn, cursorLineInfo, cursorColumn + 1);
return true;
}
});
/*
* V - Switch to visual mode (line)
*/
/*
* TODO: Doesn't exactly match vim's visual-line mode, force
* selections of entire lines.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, 'V') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
setStatus("-- VISUAL (line) --");
inVisualMode = true;
visualMoveUnit = MoveUnit.LINE;
// move cursor to beginning of current line, select to column 0 of next
// line
SelectionModel selectionModel = getInputController().getEditor().getSelection();
LineInfo cursorLineInfo =
new LineInfo(selectionModel.getCursorLine(), selectionModel.getCursorLineNumber());
LineInfo nextLineInfo =
new LineInfo(cursorLineInfo.line().getNextLine(), cursorLineInfo.number() + 1);
selectionModel.setSelection(cursorLineInfo, 0, nextLineInfo, 0);
return true;
}
});
/*
* i - Switch to insert mode
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, 'i') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
switchMode(Modes.INSERT);
return true;
}
});
/*
* A - Jump to end of line, enter insert mode.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, 'A') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
SelectionModel selectionModel = getInputController().getEditor().getSelection();
LineInfo cursorLineInfo =
new LineInfo(selectionModel.getCursorLine(), selectionModel.getCursorLineNumber());
int lastColumn = LineUtils.getLastCursorColumn(cursorLineInfo.line());
selectionModel.setCursorPosition(cursorLineInfo, lastColumn);
switchMode(Modes.INSERT);
return true;
}
});
/*
* O - Insert line above, enter insert mode.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, 'O') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
SelectionModel selectionModel = getInputController().getEditor().getSelection();
Document document = getInputController().getEditor().getDocument();
Line cursorLine = selectionModel.getCursorLine();
int cursorLineNumber = selectionModel.getCursorLineNumber();
document.insertText(cursorLine, 0, "\n");
selectionModel.setCursorPosition(new LineInfo(cursorLine, cursorLineNumber), 0);
switchMode(Modes.INSERT);
return true;
}
});
/*
* o - Insert line below, enter insert mode.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, 'o') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
SelectionModel selectionModel = getInputController().getEditor().getSelection();
Document document = getInputController().getEditor().getDocument();
Line cursorLine = selectionModel.getCursorLine();
int cursorLineNumber = selectionModel.getCursorLineNumber();
document.insertText(cursorLine, LineUtils.getLastCursorColumn(cursorLine), "\n");
selectionModel.setCursorPosition(new LineInfo(cursorLine.getNextLine(),
cursorLineNumber + 1), 0);
switchMode(Modes.INSERT);
return true;
}
});
/*
* : - Switch to colon capture mode for commands.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, ':') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
switchMode(Modes.COMMAND_CAPTURE);
return true;
}
});
/*
* "/" - Switch to search mode.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, '/') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
switchMode(Modes.SEARCH_CAPTURE);
return true;
}
});
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, '*') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
SelectionModel selectionModel = getInputController().getEditor().getSelection();
String word =
TextUtils.getWordAtColumn(selectionModel.getCursorLine().getText(),
selectionModel.getCursorColumn());
if (word == null) {
return true;
}
switchMode(Modes.SEARCH_CAPTURE);
searchTerm.append(word);
doPartialSearch();
drawSearchTerm();
return true;
}
});
/*
* Movement
*/
/*
* ^,0 - Move to first character in line.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, '^') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
SelectionModel selectionModel = getInputController().getEditor().getSelection();
LineInfo cursorLineInfo =
new LineInfo(selectionModel.getCursorLine(), selectionModel.getCursorLineNumber());
selectionModel.setCursorPosition(cursorLineInfo, 0);
return true;
}
});
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, '0') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
if (tryAddNumericPrefix('0')) {
return true;
}
SelectionModel selectionModel = getInputController().getEditor().getSelection();
LineInfo cursorLineInfo =
new LineInfo(selectionModel.getCursorLine(), selectionModel.getCursorLineNumber());
selectionModel.setCursorPosition(cursorLineInfo, 0);
return true;
}
});
/*
* $ - Move to end of line.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, '$') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
SelectionModel selectionModel = getInputController().getEditor().getSelection();
Line cursorLine = selectionModel.getCursorLine();
LineInfo cursorLineInfo = new LineInfo(cursorLine, selectionModel.getCursorLineNumber());
selectionModel.setCursorPosition(cursorLineInfo, LineUtils.getLastCursorColumn(cursorLine));
return true;
}
});
/*
* w - move the cursor to the first character of the next word.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, 'w') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
SelectionModel selectionModel = getInputController().getSelection();
LineInfo cursorLineInfo =
new LineInfo(selectionModel.getCursorLine(), selectionModel.getCursorLineNumber());
String text = selectionModel.getCursorLine().getText();
int column = selectionModel.getCursorColumn();
column = TextUtils.moveByWord(text, column, true, false);
if (column == -1) {
Line cursorLine = cursorLineInfo.line().getNextLine();
if (cursorLine != null) {
cursorLineInfo = new LineInfo(cursorLine, cursorLineInfo.number() + 1);
column = 0;
} else {
column = LineUtils.getLastCursorColumn(cursorLine); // at last character
// in document
}
}
selectionModel.setCursorPosition(cursorLineInfo, column);
return true;
}
});
/*
* b - move the cursor to the first character of the previous word.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, 'b') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
SelectionModel selectionModel = getInputController().getSelection();
LineInfo cursorLineInfo =
new LineInfo(selectionModel.getCursorLine(), selectionModel.getCursorLineNumber());
String text = selectionModel.getCursorLine().getText();
int column = selectionModel.getCursorColumn();
column = TextUtils.moveByWord(text, column, false, false);
if (column == -1) {
Line cursorLine = cursorLineInfo.line().getPreviousLine();
if (cursorLine != null) {
cursorLineInfo = new LineInfo(cursorLine, cursorLineInfo.number() - 1);
column = LineUtils.getLastCursorColumn(cursorLine);
} else {
column = 0; // at first character in document
}
}
selectionModel.setCursorPosition(cursorLineInfo, column);
return true;
}
});
/*
* e - move the cursor to the last character of the next word.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, 'e') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
SelectionModel selectionModel = getInputController().getSelection();
LineInfo cursorLineInfo =
new LineInfo(selectionModel.getCursorLine(), selectionModel.getCursorLineNumber());
String text = selectionModel.getCursorLine().getText();
int column = selectionModel.getCursorColumn();
column = TextUtils.moveByWord(text, column, true, true);
if (column == -1) {
Line cursorLine = cursorLineInfo.line().getNextLine();
if (cursorLine != null) {
cursorLineInfo = new LineInfo(cursorLine, cursorLineInfo.number() + 1);
column = 0;
} else {
// at the last character in the document
column = LineUtils.getLastCursorColumn(cursorLine);
}
}
selectionModel.setCursorPosition(cursorLineInfo, column);
return true;
}
});
/*
* % - jump to the next matching {}, [] or () character if the cursor is
* over one of the two.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, '%') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
final SelectionModel selectionModel = getInputController().getSelection();
Document document = getInputController().getEditor().getDocument();
LineInfo cursorLineInfo =
new LineInfo(selectionModel.getCursorLine(), selectionModel.getCursorLineNumber());
String text = selectionModel.getCursorLine().getText();
final char cursorChar = text.charAt(selectionModel.getCursorColumn());
final char searchChar;
final boolean searchingForward = OPENING_GROUPS.indexOf(cursorChar) >= 0;
final Position searchingTo;
if (searchingForward) {
searchChar = CLOSING_GROUPS.charAt(OPENING_GROUPS.indexOf(cursorChar));
searchingTo =
new Position(new LineInfo(document.getLastLine(), document.getLastLineNumber()),
document.getLastLine().length());
} else if (CLOSING_GROUPS.indexOf(cursorChar) >= 0) {
searchChar = OPENING_GROUPS.charAt(CLOSING_GROUPS.indexOf(cursorChar));
searchingTo = new Position(new LineInfo(document.getFirstLine(), 0), 0);
} else {
return true; // not on a valid starting character
}
Position startingPosition = new Position(cursorLineInfo, selectionModel.getCursorColumn()
+ (searchingForward ? 0 : 1));
PositionUtils.visit(new LineUtils.LineVisitor() {
// keep a stack to match the correct corresponding bracket
ScopeMatcher scopeMatcher = new ScopeMatcher(searchingForward, cursorChar, searchChar);
@Override
public boolean accept(Line line, int lineNumber, int beginColumn, int endColumn) {
int column;
String text = line.getText().substring(beginColumn, endColumn);
column = scopeMatcher.searchNextLine(text);
if (column >= 0) {
selectionModel
.setCursorPosition(new LineInfo(line, lineNumber), column + beginColumn);
return false;
}
return true;
}
}, startingPosition, searchingTo);
return true;
}
});
/*
* } - next paragraph.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, '}') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
SelectionModel selectionModel = getInputController().getSelection();
LineInfo cursorLineInfo =
new LineInfo(selectionModel.getCursorLine(), selectionModel.getCursorLineNumber());
int lineNumber = cursorLineInfo.number();
boolean skippingEmptyLines = true;
Line line;
for (line = cursorLineInfo.line(); line.getNextLine() != null; line = line.getNextLine(),
lineNumber++) {
String text = line.getText();
text = text.substring(0, text.length() - (text.endsWith("\n") ? 1 : 0));
boolean isEmptyLine = text.trim().length() > 0;
if (skippingEmptyLines) {
// check if this line is empty
if (isEmptyLine) {
skippingEmptyLines = false; // non-empty line
}
} else {
// check if this line is not empty
if (!isEmptyLine) {
break;
}
}
}
selectionModel.setCursorPosition(new LineInfo(line, lineNumber), 0);
return true;
}
});
/*
* TODO: merge both paragraph searching blocks together.
*/
/*
* { - previous paragraph.
*/
commandMode.addShortcut(new EventShortcut(ModifierKeys.NONE, '{') {
@Override
public boolean event(InputScheme scheme, SignalEvent event) {
SelectionModel selectionModel = getInputController().getSelection();
LineInfo cursorLineInfo =
new LineInfo(selectionModel.getCursorLine(), selectionModel.getCursorLineNumber());
int lineNumber = cursorLineInfo.number();
boolean skippingEmptyLines = true;
Line line;
for (line = cursorLineInfo.line(); line.getPreviousLine() != null; line =
line.getPreviousLine(), lineNumber--) {
String text = line.getText();
text = text.substring(0, text.length() - (text.endsWith("\n") ? 1 : 0));
if (skippingEmptyLines) {
// check if this line is empty
if (text.trim().length() > 0) {
skippingEmptyLines = false; // non-empty line
}
} else {
// check if this line is not empty
if (text.trim().length() > 0) {
// not empty, continue
} else {
break;
}
}
}
selectionModel.setCursorPosition(new LineInfo(line, lineNumber), 0);
return true;
}
});
/*