use of org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition in project rstudio by rstudio.
the class TextEditingTarget method onExtractLocalVariable.
@Handler
void onExtractLocalVariable() {
if (!isCursorInRMode()) {
showRModeWarning("Extract Variable");
return;
}
docDisplay_.focus();
String initialSelection = docDisplay_.getSelectionValue();
final String refactoringName = "Extract local variable";
final String pleaseSelectCodeMessage = "Please select the code to " + "extract into a variable.";
if (checkSelectionAndAlert(refactoringName, pleaseSelectCodeMessage, initialSelection))
return;
docDisplay_.fitSelectionToLines(false);
final String code = docDisplay_.getSelectionValue();
if (checkSelectionAndAlert(refactoringName, pleaseSelectCodeMessage, code))
return;
// get the first line of the selection and calculate it's indentation
String firstLine = docDisplay_.getLine(docDisplay_.getSelectionStart().getRow());
final String indentation = extractIndentation(firstLine);
// used to parse the code
server_.detectFreeVars(code, new RefactorServerRequestCallback(refactoringName) {
@Override
void doExtract(JsArrayString response) {
globalDisplay_.promptForText(refactoringName, "Variable Name", "", new OperationWithInput<String>() {
public void execute(String input) {
final String extractedCode = indentation + input.trim() + " <- " + code + "\n";
InputEditorPosition insertPosition = docDisplay_.getSelection().extendToLineStart().getStart();
docDisplay_.replaceSelection(input.trim());
docDisplay_.insertCode(insertPosition, extractedCode);
}
});
}
});
}
use of org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition in project rstudio by rstudio.
the class TextEditingTarget method reflowComments.
private void reflowComments(String commentPrefix, final boolean multiParagraphIndent, InputEditorSelection selection, final InputEditorPosition cursorPos) {
String code = docDisplay_.getCode(selection);
String[] lines = code.split("\n");
String prefix = StringUtil.getCommonPrefix(lines, true, false);
Pattern pattern = Pattern.create("^\\s*" + commentPrefix + "+('?)\\s*");
Match match = pattern.match(prefix, 0);
// Selection includes non-comments? Abort.
if (match == null)
return;
prefix = match.getValue();
final boolean roxygen = match.hasGroup(1);
int cursorRowIndex = 0;
int cursorColIndex = 0;
if (cursorPos != null) {
cursorRowIndex = selectionToPosition(cursorPos).getRow() - selectionToPosition(selection.getStart()).getRow();
cursorColIndex = Math.max(0, cursorPos.getPosition() - prefix.length());
}
final WordWrapCursorTracker wwct = new WordWrapCursorTracker(cursorRowIndex, cursorColIndex);
int maxLineLength = prefs_.printMarginColumn().getValue() - prefix.length();
WordWrap wordWrap = new WordWrap(maxLineLength, false) {
@Override
protected boolean forceWrapBefore(String line) {
String trimmed = line.trim();
if (roxygen && trimmed.startsWith("@") && !trimmed.startsWith("@@")) {
// Roxygen tags always need to be at the start of a line. If
// there is content immediately following the roxygen tag, then
// content should be wrapped until the next roxygen tag is
// encountered.
indent_ = "";
if (TAG_WITH_CONTENTS.match(line, 0) != null) {
indentRestOfLines_ = true;
}
return true;
} else // empty line disables indentation
if (!multiParagraphIndent && (line.trim().length() == 0)) {
indent_ = "";
indentRestOfLines_ = false;
}
return super.forceWrapBefore(line);
}
@Override
protected void onChunkWritten(String chunk, int insertionRow, int insertionCol, int indexInOriginalString) {
if (indentRestOfLines_) {
indentRestOfLines_ = false;
// TODO: Use real indent from settings
indent_ = " ";
}
wwct.onChunkWritten(chunk, insertionRow, insertionCol, indexInOriginalString);
}
private boolean indentRestOfLines_ = false;
private Pattern TAG_WITH_CONTENTS = Pattern.create("@\\w+\\s+[^\\s]");
};
for (String line : lines) {
String content = line.substring(Math.min(line.length(), prefix.length()));
if (content.matches("^\\s*\\@examples\\b.*$"))
wordWrap.setWrappingEnabled(false);
else if (content.trim().startsWith("@"))
wordWrap.setWrappingEnabled(true);
wwct.onBeginInputRow();
wordWrap.appendLine(content);
}
String wrappedString = wordWrap.getOutput();
StringBuilder finalOutput = new StringBuilder();
for (String line : StringUtil.getLineIterator(wrappedString)) finalOutput.append(prefix).append(line).append("\n");
// Remove final \n
if (finalOutput.length() > 0)
finalOutput.deleteCharAt(finalOutput.length() - 1);
String reflowed = finalOutput.toString();
docDisplay_.setSelection(selection);
if (!reflowed.equals(code)) {
docDisplay_.replaceSelection(reflowed);
}
if (cursorPos != null) {
if (wwct.getResult() != null) {
int row = wwct.getResult().getY();
int col = wwct.getResult().getX();
row += selectionToPosition(selection.getStart()).getRow();
col += prefix.length();
Position pos = Position.create(row, col);
docDisplay_.setSelection(docDisplay_.createSelection(pos, pos));
} else {
docDisplay_.collapseSelection(false);
}
}
}
use of org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition in project rstudio by rstudio.
the class AceInputEditorPosition method skipEmptyLines.
/**
*
* @param upwards True if the position should be moved upwards. If true, the
* resulting position (if non-null) will be at the end of a non-empty
* line. If false, the resulting position (if non-null) will be at the
* beginning of a non-empty line.
* @param boundary If non-null, provides a boundary point beyond which the
* skipping may not pass.
* @return A position that's on a non-empty line, or else, null if such a
* position couldn't be found before hitting the beginning/end of the
* document or a boundary position.
*/
@Override
public InputEditorPosition skipEmptyLines(boolean upwards, InputEditorPosition boundary) {
Position position = Position.create(getRow(), getPosition());
while (isLineEmpty(position, upwards)) {
if (upwards) {
if (position.getRow() <= 0)
return null;
position = Position.create(position.getRow() - 1, session_.getLine(position.getRow() - 1).length());
} else {
if (position.getRow() >= session_.getLength() - 1)
return null;
position = Position.create(position.getRow() + 1, 0);
}
}
InputEditorPosition pos = new AceInputEditorPosition(session_, position);
return boundary == null ? pos : (upwards && pos.compareTo(boundary) >= 0) ? pos : (!upwards && pos.compareTo(boundary) <= 0) ? pos : null;
}
use of org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition in project rstudio by rstudio.
the class RCompletionManager method previewKeyDown.
public boolean previewKeyDown(NativeEvent event) {
suggestTimer_.cancel();
if (sigTipManager_.previewKeyDown(event))
return true;
if (isDisabled())
return false;
/**
* KEYS THAT MATTER
*
* When popup not showing:
* Tab - attempt completion (handled in Console.java)
*
* When popup showing:
* Esc - dismiss popup
* Enter/Tab - accept current selection
* Up-arrow/Down-arrow - change selected item
* [identifier] - narrow suggestions--or if we're lame, just dismiss
* All others - dismiss popup
*/
nativeEvent_ = event;
int keycode = event.getKeyCode();
int modifier = KeyboardShortcut.getModifierValue(event);
if (!popup_.isShowing()) {
// don't allow ctrl + space for completions in Emacs mode
if (docDisplay_.isEmacsModeOn() && event.getKeyCode() == KeyCodes.KEY_SPACE)
return false;
if (CompletionUtils.isCompletionRequest(event, modifier)) {
if (initFilter_ == null || initFilter_.shouldComplete(event)) {
// '[](', or '`r |' contexts
if (DocumentMode.isCursorInMarkdownMode(docDisplay_)) {
String currentLine = docDisplay_.getCurrentLineUpToCursor();
if (!(Pattern.create("^```{[rR]").test(currentLine) || Pattern.create(".*\\[.*\\]\\(").test(currentLine) || (Pattern.create(".*`r").test(currentLine) && StringUtil.countMatches(currentLine, '`') % 2 == 1)))
return false;
}
// If we're in tex mode, only provide completions in chunks
if (DocumentMode.isCursorInTexMode(docDisplay_)) {
String currentLine = docDisplay_.getCurrentLineUpToCursor();
if (!Pattern.create("^<<").test(currentLine))
return false;
}
return beginSuggest(true, false, true);
}
} else if (event.getKeyCode() == KeyCodes.KEY_TAB && modifier == KeyboardShortcut.SHIFT) {
return snippets_.attemptSnippetInsertion(true);
} else if (// F1
keycode == 112 && modifier == KeyboardShortcut.NONE) {
goToHelp();
return true;
} else if (// F2
keycode == 113 && modifier == KeyboardShortcut.NONE) {
goToFunctionDefinition();
return true;
}
} else {
// bail on modifier keys
if (KeyboardHelper.isModifierKey(keycode))
return false;
// allow emacs-style navigation of popup entries
if (modifier == KeyboardShortcut.CTRL) {
switch(keycode) {
case KeyCodes.KEY_P:
return popup_.selectPrev();
case KeyCodes.KEY_N:
return popup_.selectNext();
}
} else if (modifier == KeyboardShortcut.NONE) {
if (keycode == KeyCodes.KEY_ESCAPE) {
invalidatePendingRequests();
return true;
}
// had originally requested completions at e.g. "stats::".
if (popup_.hasCompletions() && !popup_.isOffscreen()) {
if (keycode == KeyCodes.KEY_ENTER) {
QualifiedName value = popup_.getSelectedValue();
if (value != null) {
context_.onSelection(value);
return true;
}
} else if (keycode == KeyCodes.KEY_TAB) {
QualifiedName value = popup_.getSelectedValue();
if (value != null) {
if (value.type == RCompletionType.DIRECTORY)
context_.suggestOnAccept_ = true;
context_.onSelection(value);
return true;
}
} else if (keycode == KeyCodes.KEY_UP)
return popup_.selectPrev();
else if (keycode == KeyCodes.KEY_DOWN)
return popup_.selectNext();
else if (keycode == KeyCodes.KEY_PAGEUP)
return popup_.selectPrevPage();
else if (keycode == KeyCodes.KEY_PAGEDOWN)
return popup_.selectNextPage();
else if (keycode == KeyCodes.KEY_HOME)
return popup_.selectFirst();
else if (keycode == KeyCodes.KEY_END)
return popup_.selectLast();
if (// F1
keycode == 112) {
context_.showHelpTopic();
return true;
} else if (// F2
keycode == 113) {
goToFunctionDefinition();
return true;
}
}
}
if (canContinueCompletions(event))
return false;
// pop up completions
if (keycode == 191 && modifier == KeyboardShortcut.NONE) {
input_.insertCode("/");
return beginSuggest(true, true, false);
}
// continue showing completions on backspace
if (keycode == KeyCodes.KEY_BACKSPACE && modifier == KeyboardShortcut.NONE && !docDisplay_.inMultiSelectMode()) {
int cursorColumn = input_.getCursorPosition().getColumn();
String currentLine = docDisplay_.getCurrentLine();
// also halt suggestions if we're about to remove the only character on the line
if (cursorColumn > 0) {
char ch = currentLine.charAt(cursorColumn - 2);
char prevCh = currentLine.charAt(cursorColumn - 3);
boolean isAcceptableCharSequence = isValidForRIdentifier(ch) || (ch == ':' && prevCh == ':') || ch == '$' || ch == '@' || // for file completions
ch == '/';
if (currentLine.length() > 0 && cursorColumn > 0 && isAcceptableCharSequence) {
// manually remove the previous character
InputEditorSelection selection = input_.getSelection();
InputEditorPosition start = selection.getStart().movePosition(-1, true);
InputEditorPosition end = selection.getStart();
if (currentLine.charAt(cursorColumn) == ')' && currentLine.charAt(cursorColumn - 1) == '(') {
// flush cache as old completions no longer relevant
requester_.flushCache();
end = selection.getStart().movePosition(1, true);
}
input_.setSelection(new InputEditorSelection(start, end));
input_.replaceSelection("", false);
return beginSuggest(false, false, false);
}
} else {
invalidatePendingRequests();
return true;
}
}
invalidatePendingRequests();
return false;
}
return false;
}
use of org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition in project rstudio by rstudio.
the class TextEditingTargetCompilePdfHelper method ensureRnwConcordance.
public void ensureRnwConcordance() {
RnwWeave rnwWeave = getActiveRnwWeave();
if ((rnwWeave != null) && rnwWeave.getInjectConcordance()) {
if (!hasConcordanceDirective(docDisplay_.getCode())) {
InputEditorSelection doc = docDisplay_.search("\\\\begin{document}", // backwards
false, // wrap
true, // case sensitive
false, // whole word
false, // from selection
null, // range (search all)
null, // regexp mode
true);
if (doc != null) {
InputEditorPosition pos = doc.getEnd().moveToNextLine();
docDisplay_.insertCode(pos, "\\SweaveOpts{concordance=TRUE}\n");
}
}
}
}
Aggregations