Search in sources :

Example 1 with InputEditorPosition

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);
                }
            });
        }
    });
}
Also used : JsArrayString(com.google.gwt.core.client.JsArrayString) JsArrayString(com.google.gwt.core.client.JsArrayString) InputEditorPosition(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition) Handler(org.rstudio.core.client.command.Handler) ChangeFontSizeHandler(org.rstudio.studio.client.application.events.ChangeFontSizeHandler) RecordNavigationPositionHandler(org.rstudio.studio.client.workbench.views.source.events.RecordNavigationPositionHandler) EnsureHeightHandler(org.rstudio.core.client.events.EnsureHeightHandler) EnsureVisibleHandler(org.rstudio.core.client.events.EnsureVisibleHandler) HideMessageHandler(org.rstudio.studio.client.workbench.views.source.editors.text.status.StatusBar.HideMessageHandler) FileChangeHandler(org.rstudio.studio.client.workbench.views.files.events.FileChangeHandler)

Example 2 with InputEditorPosition

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);
        }
    }
}
Also used : Pattern(org.rstudio.core.client.regex.Pattern) InputEditorPosition(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition) Position(org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position) JsArrayString(com.google.gwt.core.client.JsArrayString) Breakpoint(org.rstudio.studio.client.common.debugging.model.Breakpoint) Match(org.rstudio.core.client.regex.Match)

Example 3 with InputEditorPosition

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;
}
Also used : InputEditorPosition(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition) InputEditorPosition(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition)

Example 4 with InputEditorPosition

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;
}
Also used : InputEditorSelection(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorSelection) QualifiedName(org.rstudio.studio.client.workbench.views.console.shell.assist.CompletionRequester.QualifiedName) InputEditorPosition(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition)

Example 5 with InputEditorPosition

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");
            }
        }
    }
}
Also used : RnwWeave(org.rstudio.studio.client.common.rnw.RnwWeave) InputEditorSelection(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorSelection) InputEditorPosition(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition)

Aggregations

InputEditorPosition (org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition)6 InputEditorSelection (org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorSelection)3 JsArrayString (com.google.gwt.core.client.JsArrayString)2 Position (org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position)2 Handler (org.rstudio.core.client.command.Handler)1 EnsureHeightHandler (org.rstudio.core.client.events.EnsureHeightHandler)1 EnsureVisibleHandler (org.rstudio.core.client.events.EnsureVisibleHandler)1 Match (org.rstudio.core.client.regex.Match)1 Pattern (org.rstudio.core.client.regex.Pattern)1 ChangeFontSizeHandler (org.rstudio.studio.client.application.events.ChangeFontSizeHandler)1 Breakpoint (org.rstudio.studio.client.common.debugging.model.Breakpoint)1 RnwWeave (org.rstudio.studio.client.common.rnw.RnwWeave)1 QualifiedName (org.rstudio.studio.client.workbench.views.console.shell.assist.CompletionRequester.QualifiedName)1 FileChangeHandler (org.rstudio.studio.client.workbench.views.files.events.FileChangeHandler)1 HideMessageHandler (org.rstudio.studio.client.workbench.views.source.editors.text.status.StatusBar.HideMessageHandler)1 RecordNavigationPositionHandler (org.rstudio.studio.client.workbench.views.source.events.RecordNavigationPositionHandler)1 SourcePosition (org.rstudio.studio.client.workbench.views.source.model.SourcePosition)1