Search in sources :

Example 1 with TextRange

use of com.maddyhome.idea.vim.common.TextRange in project ideavim by JetBrains.

the class SearchGroup method findIt.

@Nullable
private TextRange findIt(@NotNull Editor editor, int startOffset, int count, int dir, boolean noSmartCase, boolean wrap, boolean showMessages, boolean wholeFile) {
    TextRange res = null;
    if (lastSearch == null || lastSearch.length() == 0) {
        return res;
    }
    /*
    int pflags = RE.REG_MULTILINE;
    if (shouldIgnoreCase(lastSearch, noSmartCase))
    {
        pflags |= RE.REG_ICASE;
    }
    */
    //RE sp;
    RegExp sp;
    RegExp.regmmatch_T regmatch = new RegExp.regmmatch_T();
    regmatch.rmm_ic = shouldIgnoreCase(lastSearch, noSmartCase);
    sp = new RegExp();
    regmatch.regprog = sp.vim_regcomp(lastSearch, 1);
    if (regmatch == null) {
        if (logger.isDebugEnabled())
            logger.debug("bad pattern: " + lastSearch);
        return res;
    }
    /*
    int extra_col = 1;
    int startcol = -1;
    boolean found = false;
    boolean match_ok = true;
    LogicalPosition pos = editor.offsetToLogicalPosition(startOffset);
    LogicalPosition endpos = null;
    //REMatch match = null;
    */
    CharacterPosition lpos = EditorHelper.offsetToCharacterPosition(editor, startOffset);
    RegExp.lpos_T pos = new RegExp.lpos_T();
    pos.lnum = lpos.line;
    pos.col = lpos.column;
    int found;
    int lnum;
    /* no init to shut up Apollo cc */
    //RegExp.regmmatch_T regmatch;
    CharPointer ptr;
    int matchcol;
    int startcol;
    RegExp.lpos_T endpos = new RegExp.lpos_T();
    int loop;
    RegExp.lpos_T start_pos;
    boolean at_first_line;
    int extra_col = 1;
    boolean match_ok;
    long nmatched;
    //int         submatch = 0;
    int first_lnum;
    int lineCount = EditorHelper.getLineCount(editor);
    int startLine = 0;
    int endLine = lineCount;
    do /* loop for count */
    {
        start_pos = new RegExp.lpos_T(pos);
        /* remember start pos for detecting no match */
        found = 0;
        /* default: not found */
        at_first_line = true;
        /* default: start in first line */
        if (pos.lnum == -1) /* correct lnum for when starting in line 0 */
        {
            pos.lnum = 0;
            pos.col = 0;
            at_first_line = false;
        /* not in first line now */
        }
        /*
      * Start searching in current line, unless searching backwards and
      * we're in column 0.
      */
        if (dir == -1 && start_pos.col == 0) {
            lnum = pos.lnum - 1;
            at_first_line = false;
        } else {
            lnum = pos.lnum;
        }
        int lcount = EditorHelper.getLineCount(editor);
        for (loop = 0; loop <= 1; ++loop) /* loop twice if 'wrapscan' set */
        {
            if (!wholeFile) {
                startLine = lnum;
                endLine = lnum + 1;
            }
            for (; lnum >= startLine && lnum < endLine; lnum += dir, at_first_line = false) {
                /*
          * Look for a match somewhere in the line.
          */
                first_lnum = lnum;
                nmatched = sp.vim_regexec_multi(regmatch, editor, lcount, lnum, 0);
                if (nmatched > 0) {
                    /* match may actually be in another line when using \zs */
                    lnum += regmatch.startpos[0].lnum;
                    ptr = new CharPointer(EditorHelper.getLineBuffer(editor, lnum));
                    startcol = regmatch.startpos[0].col;
                    endpos = regmatch.endpos[0];
                    /*
            * Forward search in the first line: match should be after
            * the start position. If not, continue at the end of the
            * match (this is vi compatible) or on the next char.
            */
                    if (dir == 1 && at_first_line) {
                        match_ok = true;
                        /*
              * When match lands on a NUL the cursor will be put
              * one back afterwards, compare with that position,
              * otherwise "/$" will get stuck on end of line.
              */
                        while ((startcol - (startcol == ptr.strlen() ? 1 : 0)) < (start_pos.col + extra_col)) {
                            if (nmatched > 1) {
                                /* end is in next line, thus no match in
               * this line */
                                match_ok = false;
                                break;
                            }
                            matchcol = endpos.col;
                            /* for empty match: advance one char */
                            if (matchcol == startcol && ptr.charAt(matchcol) != '') {
                                ++matchcol;
                            }
                            if (ptr.charAt(matchcol) == '' || (nmatched = sp.vim_regexec_multi(regmatch, editor, lcount, lnum, matchcol)) == 0) {
                                match_ok = false;
                                break;
                            }
                            startcol = regmatch.startpos[0].col;
                            endpos = regmatch.endpos[0];
                            /* Need to get the line pointer again, a
        * multi-line search may have made it invalid. */
                            ptr = new CharPointer(EditorHelper.getLineBuffer(editor, lnum));
                        }
                        if (!match_ok) {
                            continue;
                        }
                    }
                    if (dir == -1) {
                        /*
              * Now, if there are multiple matches on this line,
              * we have to get the last one. Or the last one before
              * the cursor, if we're on that line.
              * When putting the new cursor at the end, compare
              * relative to the end of the match.
              */
                        match_ok = false;
                        for (; ; ) {
                            if (!at_first_line || (regmatch.startpos[0].col + extra_col <= start_pos.col)) {
                                /* Remember this position, we use it if it's
           * the last match in the line. */
                                match_ok = true;
                                startcol = regmatch.startpos[0].col;
                                endpos = regmatch.endpos[0];
                            } else {
                                break;
                            }
                            /*
                * We found a valid match, now check if there is
                * another one after it.
                * If vi-compatible searching, continue at the end
                * of the match, otherwise continue one position
                * forward.
                */
                            if (nmatched > 1) {
                                break;
                            }
                            matchcol = endpos.col;
                            /* for empty match: advance one char */
                            if (matchcol == startcol && ptr.charAt(matchcol) != '') {
                                ++matchcol;
                            }
                            if (ptr.charAt(matchcol) == '' || (nmatched = sp.vim_regexec_multi(regmatch, editor, lcount, lnum, matchcol)) == 0) {
                                break;
                            }
                            /* Need to get the line pointer again, a
        * multi-line search may have made it invalid. */
                            ptr = new CharPointer(EditorHelper.getLineBuffer(editor, lnum));
                        }
                        /*
              * If there is only a match after the cursor, skip
              * this match.
              */
                        if (!match_ok) {
                            continue;
                        }
                    }
                    pos.lnum = lnum;
                    pos.col = startcol;
                    endpos.lnum += first_lnum;
                    found = 1;
                    //search_match_endcol = endpos.col;
                    break;
                }
                if (loop != 0 && lnum == start_pos.lnum) {
                    break;
                /* if second loop, stop where started */
                }
            }
            at_first_line = false;
            /*
        * stop the search if wrapscan isn't set, after an interrupt and
        * after a match
        */
            if (!wrap || found != 0) {
                break;
            }
            /*
        * If 'wrapscan' is set we continue at the other end of the file.
        * If 'shortmess' does not contain 's', we give a message.
        * This message is also remembered in keep_msg for when the screen
        * is redrawn. The keep_msg is cleared whenever another message is
        * written.
        */
            if (dir == -1) /* start second loop at the other end */
            {
                lnum = lineCount - 1;
            //if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG))
            //    give_warning((char_u *)_(top_bot_msg), TRUE);
            } else {
                lnum = 0;
            //if (!shortmess(SHM_SEARCH) && (options & SEARCH_MSG))
            //    give_warning((char_u *)_(bot_top_msg), TRUE);
            }
        }
    //if (got_int || called_emsg || break_loop)
    //    break;
    } while (--count > 0 && found != 0);
    if (found == 0) /* did not find it */
    {
        //if ((options & SEARCH_MSG) == SEARCH_MSG)
        if (showMessages) {
            if (wrap) {
                VimPlugin.showMessage(MessageHelper.message(Msg.e_patnotf2, lastSearch));
            } else if (lnum <= 0) {
                VimPlugin.showMessage(MessageHelper.message(Msg.E384, lastSearch));
            } else {
                VimPlugin.showMessage(MessageHelper.message(Msg.E385, lastSearch));
            }
        }
        return null;
    }
    //    editor.logicalPositionToOffset(new LogicalPosition(endpos.lnum, 0)) + endpos.col);
    return new TextRange(EditorHelper.characterPositionToOffset(editor, new CharacterPosition(pos.lnum, pos.col)), EditorHelper.characterPositionToOffset(editor, new CharacterPosition(endpos.lnum, endpos.col)));
}
Also used : RegExp(com.maddyhome.idea.vim.regexp.RegExp) CharacterPosition(com.maddyhome.idea.vim.common.CharacterPosition) TextRange(com.maddyhome.idea.vim.common.TextRange) CharPointer(com.maddyhome.idea.vim.regexp.CharPointer) Nullable(org.jetbrains.annotations.Nullable)

Example 2 with TextRange

use of com.maddyhome.idea.vim.common.TextRange in project ideavim by JetBrains.

the class SearchGroup method highlightSearchLines.

private static void highlightSearchLines(@NotNull Editor editor, @NotNull String pattern, int startLine, int endLine, boolean ignoreCase) {
    final TextAttributes color = editor.getColorsScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
    Collection<RangeHighlighter> highlighters = EditorData.getLastHighlights(editor);
    if (highlighters == null) {
        highlighters = new ArrayList<RangeHighlighter>();
        EditorData.setLastHighlights(editor, highlighters);
    }
    for (TextRange range : findAll(editor, pattern, startLine, endLine, ignoreCase)) {
        final RangeHighlighter highlighter = highlightMatch(editor, range.getStartOffset(), range.getEndOffset());
        highlighter.setErrorStripeMarkColor(color.getBackgroundColor());
        highlighter.setErrorStripeTooltip(pattern);
        highlighters.add(highlighter);
    }
}
Also used : RangeHighlighter(com.intellij.openapi.editor.markup.RangeHighlighter) TextAttributes(com.intellij.openapi.editor.markup.TextAttributes) TextRange(com.maddyhome.idea.vim.common.TextRange)

Example 3 with TextRange

use of com.maddyhome.idea.vim.common.TextRange in project ideavim by JetBrains.

the class MotionGroup method resetVisual.

public void resetVisual(@NotNull final Editor editor, final boolean removeSelection) {
    final SelectionType selectionType = SelectionType.fromSubMode(CommandState.getInstance(editor).getSubMode());
    EditorData.setLastSelectionType(editor, selectionType);
    final TextRange visualMarks = VimPlugin.getMark().getVisualSelectionMarks(editor);
    if (visualMarks != null) {
        EditorData.setLastVisualRange(editor, visualMarks);
    }
    if (removeSelection) {
        editor.getSelectionModel().removeSelection();
        editor.getCaretModel().removeSecondaryCarets();
    }
    CommandState.getInstance(editor).setSubMode(CommandState.SubMode.NONE);
}
Also used : TextRange(com.maddyhome.idea.vim.common.TextRange)

Example 4 with TextRange

use of com.maddyhome.idea.vim.common.TextRange in project ideavim by JetBrains.

the class MotionGroup method swapVisualSelections.

public boolean swapVisualSelections(@NotNull Editor editor) {
    final SelectionType lastSelectionType = EditorData.getLastSelectionType(editor);
    final TextRange lastVisualRange = EditorData.getLastVisualRange(editor);
    if (lastSelectionType == null || lastVisualRange == null) {
        return false;
    }
    final SelectionType selectionType = SelectionType.fromSubMode(CommandState.getInstance(editor).getSubMode());
    EditorData.setLastSelectionType(editor, selectionType);
    visualStart = lastVisualRange.getStartOffset();
    visualEnd = lastVisualRange.getEndOffset();
    visualOffset = visualEnd;
    CommandState.getInstance(editor).setSubMode(lastSelectionType.toSubMode());
    updateSelection(editor, visualEnd);
    editor.getCaretModel().moveToOffset(visualOffset);
    editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
    return true;
}
Also used : TextRange(com.maddyhome.idea.vim.common.TextRange)

Example 5 with TextRange

use of com.maddyhome.idea.vim.common.TextRange in project ideavim by JetBrains.

the class MotionGroup method getMotionRange.

/**
   * This helper method calculates the complete range a motion will move over taking into account whether
   * the motion is FLAG_MOT_LINEWISE or FLAG_MOT_CHARACTERWISE (FLAG_MOT_INCLUSIVE or FLAG_MOT_EXCLUSIVE).
   *
   * @param editor     The editor the motion takes place in
   * @param context    The data context
   * @param count      The count applied to the motion
   * @param rawCount   The actual count entered by the user
   * @param argument   Any argument needed by the motion
   * @param incNewline True if to include newline
   * @return The motion's range
   */
@Nullable
public static TextRange getMotionRange(@NotNull Editor editor, DataContext context, int count, int rawCount, @NotNull Argument argument, boolean incNewline) {
    final Command cmd = argument.getMotion();
    if (cmd == null) {
        return null;
    }
    // Normalize the counts between the command and the motion argument
    int cnt = cmd.getCount() * count;
    int raw = rawCount == 0 && cmd.getRawCount() == 0 ? 0 : cnt;
    int start = 0;
    int end = 0;
    if (cmd.getAction() instanceof MotionEditorAction) {
        MotionEditorAction action = (MotionEditorAction) cmd.getAction();
        // This is where we are now
        start = editor.getCaretModel().getOffset();
        // Execute the motion (without moving the cursor) and get where we end
        end = action.getOffset(editor, context, cnt, raw, cmd.getArgument());
        // Invalid motion
        if (end == -1) {
            return null;
        }
    } else if (cmd.getAction() instanceof TextObjectAction) {
        TextObjectAction action = (TextObjectAction) cmd.getAction();
        TextRange range = action.getRange(editor, context, cnt, raw, cmd.getArgument());
        if (range == null) {
            return null;
        }
        start = range.getStartOffset();
        end = range.getEndOffset();
    }
    // If we are a linewise motion we need to normalize the start and stop then move the start to the beginning
    // of the line and move the end to the end of the line.
    int flags = cmd.getFlags();
    if ((flags & Command.FLAG_MOT_LINEWISE) != 0) {
        if (start > end) {
            int t = start;
            start = end;
            end = t;
        }
        start = EditorHelper.getLineStartForOffset(editor, start);
        end = Math.min(EditorHelper.getLineEndForOffset(editor, end) + (incNewline ? 1 : 0), EditorHelper.getFileSize(editor));
    } else // If characterwise and inclusive, add the last character to the range
    if ((flags & Command.FLAG_MOT_INCLUSIVE) != 0) {
        end++;
    }
    // Normalize the range
    if (start > end) {
        int t = start;
        start = end;
        end = t;
    }
    return new TextRange(start, end);
}
Also used : MotionEditorAction(com.maddyhome.idea.vim.action.motion.MotionEditorAction) TextObjectAction(com.maddyhome.idea.vim.action.motion.TextObjectAction) TextRange(com.maddyhome.idea.vim.common.TextRange) Nullable(org.jetbrains.annotations.Nullable)

Aggregations

TextRange (com.maddyhome.idea.vim.common.TextRange)46 Nullable (org.jetbrains.annotations.Nullable)8 LogicalPosition (com.intellij.openapi.editor.LogicalPosition)2 CharacterPosition (com.maddyhome.idea.vim.common.CharacterPosition)2 Register (com.maddyhome.idea.vim.common.Register)2 RegExp (com.maddyhome.idea.vim.regexp.RegExp)2 Document (com.intellij.openapi.editor.Document)1 RangeHighlighter (com.intellij.openapi.editor.markup.RangeHighlighter)1 TextAttributes (com.intellij.openapi.editor.markup.TextAttributes)1 FileType (com.intellij.openapi.fileTypes.FileType)1 Project (com.intellij.openapi.project.Project)1 VirtualFile (com.intellij.openapi.vfs.VirtualFile)1 CodeStyleSettings (com.intellij.psi.codeStyle.CodeStyleSettings)1 MotionEditorAction (com.maddyhome.idea.vim.action.motion.MotionEditorAction)1 TextObjectAction (com.maddyhome.idea.vim.action.motion.TextObjectAction)1 Command (com.maddyhome.idea.vim.command.Command)1 CommandState (com.maddyhome.idea.vim.command.CommandState)1 SelectionType (com.maddyhome.idea.vim.command.SelectionType)1 Mark (com.maddyhome.idea.vim.common.Mark)1 SearchHelper (com.maddyhome.idea.vim.helper.SearchHelper)1