mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-05-08 15:34:07 +02:00
Lots of little fixes to avoid errors running commands on empty files
This commit is contained in:
parent
cb5a3d495c
commit
e4386f52f7
src/com/maddyhome/idea/vim
@ -132,8 +132,8 @@ public class Ranges
|
||||
public TextRange getTextRange(Editor editor, DataContext context, int count)
|
||||
{
|
||||
LineRange lr = getLineRange(editor, context, count);
|
||||
int start = editor.getDocument().getLineStartOffset(lr.getStartLine());
|
||||
int end = editor.getDocument().getLineEndOffset(lr.getEndLine()) + 1;
|
||||
int start = EditorHelper.getLineStartOffset(editor, lr.getStartLine());
|
||||
int end = EditorHelper.getLineEndOffset(editor, lr.getEndLine()) + 1;
|
||||
|
||||
return new TextRange(start, Math.min(end, EditorHelper.getFileSize(editor)));
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import com.maddyhome.idea.vim.ex.CommandName;
|
||||
import com.maddyhome.idea.vim.ex.ExCommand;
|
||||
import com.maddyhome.idea.vim.ex.ExException;
|
||||
import com.maddyhome.idea.vim.group.CommandGroups;
|
||||
import com.maddyhome.idea.vim.helper.EditorHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -44,7 +45,7 @@ public class MarkHandler extends CommandHandler
|
||||
{
|
||||
char mark = cmd.getArgument().charAt(0);
|
||||
int line = cmd.getLine(editor, context);
|
||||
int offset = editor.getDocument().getLineStartOffset(line);
|
||||
int offset = EditorHelper.getLineStartOffset(editor, line);
|
||||
|
||||
return CommandGroups.getInstance().getMark().setMark(editor, context, mark, offset);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import com.maddyhome.idea.vim.ex.ExException;
|
||||
import com.maddyhome.idea.vim.group.CommandGroups;
|
||||
import com.maddyhome.idea.vim.group.MotionGroup;
|
||||
import com.maddyhome.idea.vim.group.RegisterGroup;
|
||||
import com.maddyhome.idea.vim.helper.EditorHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -60,7 +61,7 @@ public class PutLinesHandler extends CommandHandler
|
||||
CommandGroups.getInstance().getRegister().selectRegister(RegisterGroup.REGISTER_DEFAULT);
|
||||
}
|
||||
|
||||
MotionGroup.moveCaret(editor, context, editor.getDocument().getLineStartOffset(line));
|
||||
MotionGroup.moveCaret(editor, context, EditorHelper.getLineStartOffset(editor, line));
|
||||
if (before)
|
||||
{
|
||||
return CommandGroups.getInstance().getCopy().putTextBeforeCursor(editor, context, 1);
|
||||
|
@ -650,6 +650,10 @@ public class ChangeGroup extends AbstractActionGroup
|
||||
public boolean deleteMotion(Editor editor, DataContext context, int count, int rawCount, Argument argument)
|
||||
{
|
||||
TextRange range = MotionGroup.getMotionRange(editor, context, count, rawCount, argument, false);
|
||||
if (range == null && EditorHelper.getFileSize(editor) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return deleteRange(editor, context, range, argument.getMotion().getFlags());
|
||||
}
|
||||
@ -737,7 +741,7 @@ public class ChangeGroup extends AbstractActionGroup
|
||||
char[] chars = editor.getDocument().getChars();
|
||||
for (int i = range.getStartOffset(); i < range.getEndOffset(); i++)
|
||||
{
|
||||
if ('\n' != chars[i])
|
||||
if (i < chars.length && '\n' != chars[i])
|
||||
{
|
||||
replaceText(editor, context, i, i + 1, Character.toString(ch));
|
||||
}
|
||||
@ -819,7 +823,8 @@ public class ChangeGroup extends AbstractActionGroup
|
||||
String id = ActionManager.getInstance().getId(argument.getMotion().getAction());
|
||||
if (id.equals("VimMotionWordRight"))
|
||||
{
|
||||
if (!Character.isWhitespace(editor.getDocument().getChars()[editor.getCaretModel().getOffset()]))
|
||||
if (EditorHelper.getFileSize(editor) > 0 &&
|
||||
!Character.isWhitespace(editor.getDocument().getChars()[editor.getCaretModel().getOffset()]))
|
||||
{
|
||||
argument.getMotion().setAction(ActionManager.getInstance().getAction("VimMotionWordEndRight"));
|
||||
argument.getMotion().setFlags(MotionGroup.INCLUSIVE);
|
||||
@ -827,7 +832,8 @@ public class ChangeGroup extends AbstractActionGroup
|
||||
}
|
||||
else if (id.equals("VimMotionWORDRight"))
|
||||
{
|
||||
if (!Character.isWhitespace(editor.getDocument().getChars()[editor.getCaretModel().getOffset()]))
|
||||
if (EditorHelper.getFileSize(editor) > 0 &&
|
||||
!Character.isWhitespace(editor.getDocument().getChars()[editor.getCaretModel().getOffset()]))
|
||||
{
|
||||
argument.getMotion().setAction(ActionManager.getInstance().getAction("VimMotionWORDEndRight"));
|
||||
argument.getMotion().setFlags(MotionGroup.INCLUSIVE);
|
||||
@ -962,6 +968,11 @@ public class ChangeGroup extends AbstractActionGroup
|
||||
char[] chars = editor.getDocument().getChars();
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
if (i >= chars.length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
char ch = CharacterHelper.changeCase(chars[i], type);
|
||||
if (ch != chars[i])
|
||||
{
|
||||
@ -1022,7 +1033,7 @@ public class ChangeGroup extends AbstractActionGroup
|
||||
|
||||
for (int l = sline; l <= eline; l++)
|
||||
{
|
||||
int soff = editor.getDocument().getLineStartOffset(l);
|
||||
int soff = EditorHelper.getLineStartOffset(editor, l);
|
||||
int woff = CommandGroups.getInstance().getMotion().moveCaretToLineStartSkipLeading(editor, l);
|
||||
int col = editor.offsetToVisualPosition(woff).column;
|
||||
int newCol = Math.max(0, col + dir * tabSize * count);
|
||||
|
@ -32,6 +32,7 @@ import com.intellij.openapi.editor.event.EditorFactoryEvent;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.maddyhome.idea.vim.common.Mark;
|
||||
import com.maddyhome.idea.vim.helper.EditorData;
|
||||
import com.maddyhome.idea.vim.helper.EditorHelper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@ -410,8 +411,8 @@ public class MarkGroup extends AbstractActionGroup
|
||||
// If the deleted text begins before the mark and ends after the mark then it may be shifted or deleted
|
||||
else if (delStart.line <= mark.getLogicalLine() && delEnd.line >= mark.getLogicalLine())
|
||||
{
|
||||
int markLineStartOff = editor.getDocument().getLineStartOffset(mark.getLogicalLine());
|
||||
int markLineEndOff = editor.getDocument().getLineEndOffset(mark.getLogicalLine());
|
||||
int markLineStartOff = EditorHelper.getLineStartOffset(editor, mark.getLogicalLine());
|
||||
int markLineEndOff = EditorHelper.getLineEndOffset(editor, mark.getLogicalLine());
|
||||
// If the marked line is completely within the deleted text, remove the mark
|
||||
if (delStartOff <= markLineStartOff && delEndOff >= markLineEndOff)
|
||||
{
|
||||
|
@ -393,6 +393,12 @@ public class MotionGroup extends AbstractActionGroup
|
||||
*/
|
||||
public int moveCaretToNextWordEnd(Editor editor, int count, boolean skipPunc)
|
||||
{
|
||||
if ((editor.getCaretModel().getOffset() == 0 && count < 0) ||
|
||||
(editor.getCaretModel().getOffset() >= EditorHelper.getFileSize(editor) - 1 && count > 0))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pos = SearchHelper.findNextWordEnd(editor, count, skipPunc);
|
||||
if (pos == -1)
|
||||
{
|
||||
@ -707,12 +713,17 @@ public class MotionGroup extends AbstractActionGroup
|
||||
|
||||
public int moveCaretToLineStartSkipLeading(Editor editor, int lline)
|
||||
{
|
||||
int start = editor.getDocument().getLineStartOffset(lline);
|
||||
int end = editor.getDocument().getLineEndOffset(lline);
|
||||
int start = EditorHelper.getLineStartOffset(editor, lline);
|
||||
int end = EditorHelper.getLineEndOffset(editor, lline);
|
||||
char[] chars = editor.getDocument().getChars();
|
||||
int pos = end;
|
||||
for (int offset = start; offset < end; offset++)
|
||||
{
|
||||
if (offset >= chars.length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Character.isWhitespace(chars[offset]))
|
||||
{
|
||||
pos = offset;
|
||||
@ -731,12 +742,17 @@ public class MotionGroup extends AbstractActionGroup
|
||||
|
||||
public int moveCaretToLineEndSkipLeading(Editor editor, int lline)
|
||||
{
|
||||
int start = editor.getDocument().getLineStartOffset(lline);
|
||||
int end = editor.getDocument().getLineEndOffset(lline);
|
||||
int start = EditorHelper.getLineStartOffset(editor, lline);
|
||||
int end = EditorHelper.getLineEndOffset(editor, lline);
|
||||
char[] chars = editor.getDocument().getChars();
|
||||
int pos = start;
|
||||
for (int offset = end; offset > start; offset--)
|
||||
{
|
||||
if (offset >= chars.length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Character.isWhitespace(chars[offset]))
|
||||
{
|
||||
pos = offset;
|
||||
@ -749,7 +765,7 @@ public class MotionGroup extends AbstractActionGroup
|
||||
|
||||
public int moveCaretToLineEnd(Editor editor, int lline)
|
||||
{
|
||||
int offset = EditorHelper.normalizeOffset(editor, lline, editor.getDocument().getLineEndOffset(lline) - 1,
|
||||
int offset = EditorHelper.normalizeOffset(editor, lline, EditorHelper.getLineEndOffset(editor, lline) - 1,
|
||||
false);
|
||||
|
||||
return offset;
|
||||
@ -757,7 +773,7 @@ public class MotionGroup extends AbstractActionGroup
|
||||
|
||||
public int moveCaretToLineEndAppend(Editor editor, int lline)
|
||||
{
|
||||
return editor.getDocument().getLineEndOffset(lline);
|
||||
return EditorHelper.getLineEndOffset(editor, lline);
|
||||
}
|
||||
|
||||
public int moveCaretToLineEndAppend(Editor editor)
|
||||
@ -768,7 +784,7 @@ public class MotionGroup extends AbstractActionGroup
|
||||
public int moveCaretToLineEndAppendOffset(Editor editor, int cntForward)
|
||||
{
|
||||
int line = EditorHelper.normalizeVisualLine(editor, EditorHelper.getCurrentVisualLine(editor) + cntForward);
|
||||
return editor.getDocument().getLineEndOffset(EditorHelper.visualLineToLogicalLine(editor, line));
|
||||
return EditorHelper.getLineEndOffset(editor, EditorHelper.visualLineToLogicalLine(editor, line));
|
||||
}
|
||||
|
||||
public int moveCaretToLineEndOffset(Editor editor, int cntForward)
|
||||
@ -790,7 +806,7 @@ public class MotionGroup extends AbstractActionGroup
|
||||
return EditorHelper.getFileSize(editor);
|
||||
}
|
||||
|
||||
int start = editor.getDocument().getLineStartOffset(lline);
|
||||
int start = EditorHelper.getLineStartOffset(editor, lline);
|
||||
return start;
|
||||
}
|
||||
|
||||
@ -873,25 +889,28 @@ public class MotionGroup extends AbstractActionGroup
|
||||
|
||||
saveJumpLocation(editor, context);
|
||||
return moveCaretToLineStartSkipLeading(editor, EditorHelper.normalizeLine(
|
||||
editor, (EditorHelper.getLineCount(editor) * count + 99) / 100) - 1);
|
||||
editor, (EditorHelper.getLineCount(editor) * count + 99) / 100 - 1));
|
||||
}
|
||||
|
||||
public int moveCaretGotoLineLast(Editor editor, DataContext context, int rawCount, int lline)
|
||||
{
|
||||
saveJumpLocation(editor, context);
|
||||
return moveCaretToLineStartSkipLeading(editor, rawCount == 0 ? EditorHelper.getLineCount(editor) - 1 : lline);
|
||||
return moveCaretToLineStartSkipLeading(editor, rawCount == 0 ?
|
||||
EditorHelper.normalizeLine(editor, EditorHelper.getLineCount(editor) - 1) : lline);
|
||||
}
|
||||
|
||||
public int moveCaretGotoLineLastEnd(Editor editor, DataContext context, int rawCount, int lline)
|
||||
{
|
||||
saveJumpLocation(editor, context);
|
||||
return moveCaretToLineEnd(editor, rawCount == 0 ? EditorHelper.getLineCount(editor) - 1 : lline);
|
||||
return moveCaretToLineEnd(editor, rawCount == 0 ?
|
||||
EditorHelper.normalizeLine(editor, EditorHelper.getLineCount(editor) - 1) : lline);
|
||||
}
|
||||
|
||||
public int moveCaretGotoLineLastEndAppend(Editor editor, DataContext context, int rawCount, int lline)
|
||||
{
|
||||
saveJumpLocation(editor, context);
|
||||
return moveCaretToLineEndAppend(editor, rawCount == 0 ? EditorHelper.getLineCount(editor) - 1 : lline);
|
||||
return moveCaretToLineEndAppend(editor, rawCount == 0 ?
|
||||
EditorHelper.normalizeLine(editor, EditorHelper.getLineCount(editor) - 1) : lline);
|
||||
}
|
||||
|
||||
public int moveCaretGotoLineFirst(Editor editor, DataContext context, int lline)
|
||||
@ -902,7 +921,7 @@ public class MotionGroup extends AbstractActionGroup
|
||||
|
||||
public static void moveCaret(Editor editor, DataContext context, int offset)
|
||||
{
|
||||
if (offset >= 0)
|
||||
if (offset >= 0 && offset < editor.getDocument().getTextLength())
|
||||
{
|
||||
editor.getCaretModel().moveToOffset(offset);
|
||||
EditorData.setLastColumn(editor, editor.getCaretModel().getVisualPosition().column);
|
||||
@ -973,8 +992,8 @@ public class MotionGroup extends AbstractActionGroup
|
||||
if (start != end)
|
||||
{
|
||||
int line = editor.offsetToLogicalPosition(start).line;
|
||||
int lstart = editor.getDocument().getLineStartOffset(line);
|
||||
int lend = editor.getDocument().getLineEndOffset(line);
|
||||
int lstart = EditorHelper.getLineStartOffset(editor, line);
|
||||
int lend = EditorHelper.getLineEndOffset(editor, line);
|
||||
logger.debug("start=" + start + ", end=" + end + ", lstart=" + lstart + ", lend=" + lend);
|
||||
if (lstart == start && lend + 1 == end)
|
||||
{
|
||||
|
@ -111,14 +111,15 @@ public class EditorHelper
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of visible lines in the editor. This will less then the actuall number of lines in the file
|
||||
* Gets the number of visible lines in the editor. This will less then the actual number of lines in the file
|
||||
* if there are any collapsed folds.
|
||||
* @param editor The editor
|
||||
* @return The number of visible lines in the file
|
||||
*/
|
||||
public static int getVisualLineCount(Editor editor)
|
||||
{
|
||||
return logicalLineToVisualLine(editor, getLineCount(editor));
|
||||
int count = getLineCount(editor);
|
||||
return count == 0 ? 0 : logicalLineToVisualLine(editor, count - 1) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -201,6 +202,50 @@ public class EditorHelper
|
||||
return editor.logicalToVisualPosition(new LogicalPosition(lline, 0)).line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offset of the start of the requested line.
|
||||
* @param editor The editor
|
||||
* @param lline The logical line to get the start offset for.
|
||||
* @return 0 if line is < 0, file size of line is bigger than file, else the start offset for the line
|
||||
*/
|
||||
public static int getLineStartOffset(Editor editor, int lline)
|
||||
{
|
||||
if (lline < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (lline >= getLineCount(editor))
|
||||
{
|
||||
return getFileSize(editor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return editor.getDocument().getLineStartOffset(lline);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offset of the end of the requested line.
|
||||
* @param editor The editor
|
||||
* @param lline The logical line to get the end offset for.
|
||||
* @return 0 if line is < 0, file size of line is bigger than file, else the end offset for the line
|
||||
*/
|
||||
public static int getLineEndOffset(Editor editor, int lline)
|
||||
{
|
||||
if (lline < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (lline >= getLineCount(editor))
|
||||
{
|
||||
return getFileSize(editor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return editor.getDocument().getLineEndOffset(lline);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the supplied visual line is within the range 0 (incl) and the number of visual lines in the file
|
||||
* (excl).
|
||||
@ -224,7 +269,7 @@ public class EditorHelper
|
||||
*/
|
||||
public static int normalizeLine(Editor editor, int lline)
|
||||
{
|
||||
lline = Math.min(Math.max(0, lline), getLineCount(editor) - 1);
|
||||
lline = Math.max(0, Math.min(lline, getLineCount(editor) - 1));
|
||||
|
||||
return lline;
|
||||
}
|
||||
@ -270,13 +315,13 @@ public class EditorHelper
|
||||
*/
|
||||
public static int normalizeOffset(Editor editor, int lline, int offset, boolean allowEnd)
|
||||
{
|
||||
if (lline == 0 && getFileSize(editor) == 0)
|
||||
if (getFileSize(editor) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int min = editor.getDocument().getLineStartOffset(lline);
|
||||
int max = editor.getDocument().getLineEndOffset(lline) - (allowEnd ? 0 : 1);
|
||||
int min = getLineStartOffset(editor, lline);
|
||||
int max = getLineEndOffset(editor, lline) - (allowEnd ? 0 : 1);
|
||||
offset = Math.max(Math.min(offset, max), min);
|
||||
|
||||
return offset;
|
||||
|
@ -38,7 +38,7 @@ public class SearchHelper
|
||||
{
|
||||
int res = -1;
|
||||
int line = EditorHelper.getCurrentLogicalLine(editor);
|
||||
int end = editor.getDocument().getLineEndOffset(line);
|
||||
int end = EditorHelper.getLineEndOffset(editor, line);
|
||||
char[] chars = editor.getDocument().getChars();
|
||||
int pos = editor.getCaretModel().getOffset();
|
||||
int loc = -1;
|
||||
@ -142,6 +142,11 @@ public class SearchHelper
|
||||
pos = skipSpace(chars, pos, step, size);
|
||||
}
|
||||
int res = pos;
|
||||
if (pos < 0 || pos >= size)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
|
||||
int type = CharacterHelper.charType(chars[pos], skipPunc);
|
||||
pos += step;
|
||||
while (pos >= 0 && pos < size && found < Math.abs(count))
|
||||
@ -212,6 +217,10 @@ public class SearchHelper
|
||||
pos = skipSpace(chars, pos, step, size);
|
||||
}
|
||||
int res = pos;
|
||||
if (pos < 0 || pos >= size)
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
int type = CharacterHelper.charType(chars[pos], skipPunc);
|
||||
pos += step;
|
||||
while (pos >= 0 && pos < size && found < Math.abs(count))
|
||||
@ -288,13 +297,13 @@ public class SearchHelper
|
||||
public static int findNextCharacterOnLine(Editor editor, int count, char ch)
|
||||
{
|
||||
int line = EditorHelper.getCurrentLogicalLine(editor);
|
||||
int start = editor.getDocument().getLineStartOffset(line);
|
||||
int end = editor.getDocument().getLineEndOffset(line);
|
||||
int start = EditorHelper.getLineStartOffset(editor, line);
|
||||
int end = EditorHelper.getLineEndOffset(editor, line);
|
||||
char[] chars = editor.getDocument().getChars();
|
||||
int found = 0;
|
||||
int step = count >= 0 ? 1 : -1;
|
||||
int pos = editor.getCaretModel().getOffset() + step;
|
||||
while (pos >= start && pos < end)
|
||||
while (pos >= start && pos < end && pos >= 0 && pos < chars.length)
|
||||
{
|
||||
if (chars[pos] == ch)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user