use of com.maddyhome.idea.vim.common.Mark in project ideavim by JetBrains.
the class MarkGroup method readData.
public void readData(@NotNull Element element) {
// We need to keep the filename for now and create the virtual file later. Any attempt to call
// LocalFileSystem.getInstance().findFileByPath() results in the following error:
// Read access is allowed from event dispatch thread or inside read-action only
// (see com.intellij.openapi.application.Application.runReadAction())
Element marksElem = element.getChild("globalmarks");
if (marksElem != null) {
List markList = marksElem.getChildren("mark");
for (Object aMarkList : markList) {
Element markElem = (Element) aMarkList;
Mark mark = new Mark(markElem.getAttributeValue("key").charAt(0), Integer.parseInt(markElem.getAttributeValue("line")), Integer.parseInt(markElem.getAttributeValue("column")), markElem.getAttributeValue("filename"));
globalMarks.put(mark.getKey(), mark);
HashMap<Character, Mark> fmarks = getFileMarks(mark.getFilename());
fmarks.put(mark.getKey(), mark);
}
}
if (logger.isDebugEnabled()) {
logger.debug("globalMarks=" + globalMarks);
}
Element fileMarksElem = element.getChild("filemarks");
if (fileMarksElem != null) {
List fileList = fileMarksElem.getChildren("file");
for (Object aFileList : fileList) {
Element fileElem = (Element) aFileList;
String filename = fileElem.getAttributeValue("name");
Date timestamp = new Date();
try {
long date = Long.parseLong(fileElem.getAttributeValue("timestamp"));
timestamp.setTime(date);
} catch (NumberFormatException e) {
// ignore
}
FileMarks<Character, Mark> fmarks = getFileMarks(filename);
List markList = fileElem.getChildren("mark");
for (Object aMarkList : markList) {
Element markElem = (Element) aMarkList;
Mark mark = new Mark(markElem.getAttributeValue("key").charAt(0), Integer.parseInt(markElem.getAttributeValue("line")), Integer.parseInt(markElem.getAttributeValue("column")), filename);
fmarks.put(mark.getKey(), mark);
}
fmarks.setTimestamp(timestamp);
}
}
if (logger.isDebugEnabled()) {
logger.debug("fileMarks=" + fileMarks);
}
jumps.clear();
Element jumpsElem = element.getChild("jumps");
if (jumpsElem != null) {
List jumpList = jumpsElem.getChildren("jump");
for (Object aJumpList : jumpList) {
Element jumpElem = (Element) aJumpList;
Jump jump = new Jump(Integer.parseInt(jumpElem.getAttributeValue("line")), Integer.parseInt(jumpElem.getAttributeValue("column")), jumpElem.getAttributeValue("filename"));
jumps.add(jump);
}
}
if (logger.isDebugEnabled()) {
logger.debug("jumps=" + jumps);
}
}
use of com.maddyhome.idea.vim.common.Mark in project ideavim by JetBrains.
the class MarkGroup method updateMarkFromInsert.
/**
* This updates all the marks for a file whenever text is inserted into the file. If the line that contains a mark
* that is after the start of the insertion point, shift the mark by the number of new lines added.
*
* @param editor The editor that was updated
* @param marks The editor's marks
* @param insStartOff The insertion point
* @param insLength The length of the insertion
*/
public static void updateMarkFromInsert(@Nullable Editor editor, @Nullable HashMap<Character, Mark> marks, int insStartOff, int insLength) {
if (marks != null && marks.size() > 0 && editor != null) {
int insEndOff = insStartOff + insLength;
LogicalPosition insStart = editor.offsetToLogicalPosition(insStartOff);
LogicalPosition insEnd = editor.offsetToLogicalPosition(insEndOff);
if (logger.isDebugEnabled())
logger.debug("mark insert. insStart = " + insStart + ", insEnd = " + insEnd);
int lines = insEnd.line - insStart.line;
if (lines == 0)
return;
for (Mark mark : marks.values()) {
if (logger.isDebugEnabled())
logger.debug("mark = " + mark);
// Shift the mark if the insertion began on a line prior to the marked line.
if (insStart.line < mark.getLogicalLine()) {
mark.setLogicalLine(mark.getLogicalLine() + lines);
if (logger.isDebugEnabled())
logger.debug("Shifting mark by " + lines + " lines");
}
}
}
}
use of com.maddyhome.idea.vim.common.Mark in project ideavim by JetBrains.
the class MarkGroup method updateMarkFromDelete.
/**
* This updates all the marks for a file whenever text is deleted from the file. If the line that contains a mark
* is completely deleted then the mark is deleted too. If the deleted text is before the marked line, the mark is
* moved up by the number of deleted lines.
*
* @param editor The modified editor
* @param marks The editor's marks to update
* @param delStartOff The offset within the editor where the deletion occurred
* @param delLength The length of the deleted text
*/
public static void updateMarkFromDelete(@Nullable Editor editor, @Nullable HashMap<Character, Mark> marks, int delStartOff, int delLength) {
// Skip all this work if there are no marks
if (marks != null && marks.size() > 0 && editor != null) {
// Calculate the logical position of the start and end of the deleted text
int delEndOff = delStartOff + delLength - 1;
LogicalPosition delStart = editor.offsetToLogicalPosition(delStartOff);
LogicalPosition delEnd = editor.offsetToLogicalPosition(delEndOff + 1);
if (logger.isDebugEnabled())
logger.debug("mark delete. delStart = " + delStart + ", delEnd = " + delEnd);
// Now analyze each mark to determine if it needs to be updated or removed
for (Character ch : marks.keySet()) {
Mark mark = marks.get(ch);
if (logger.isDebugEnabled())
logger.debug("mark = " + mark);
// proper number of lines.
if (delEnd.line < mark.getLogicalLine()) {
int lines = delEnd.line - delStart.line;
if (logger.isDebugEnabled())
logger.debug("Shifting mark by " + lines + " lines");
mark.setLogicalLine(mark.getLogicalLine() - lines);
} else // If the deleted text begins before the mark and ends after the mark then it may be shifted or deleted
if (delStart.line <= mark.getLogicalLine() && delEnd.line >= mark.getLogicalLine()) {
int markLineStartOff = EditorHelper.getLineStartOffset(editor, mark.getLogicalLine());
int markLineEndOff = EditorHelper.getLineEndOffset(editor, mark.getLogicalLine(), true);
Command command = CommandState.getInstance(editor).getCommand();
// If text is being changed from the start of the mark line (a special case for mark deletion)
boolean changeFromMarkLineStart = command != null && command.getType() == Command.Type.CHANGE && delStartOff == markLineStartOff;
// If the marked line is completely within the deleted text, remove the mark (except the special case)
if (delStartOff <= markLineStartOff && delEndOff >= markLineEndOff && !changeFromMarkLineStart) {
VimPlugin.getMark().removeMark(ch, mark);
logger.debug("Removed mark");
} else // on a line prior to the marked line (which means the deletion must end on the marked line).
if (delStart.line < mark.getLogicalLine()) {
// shift mark
mark.setLogicalLine(delStart.line);
if (logger.isDebugEnabled())
logger.debug("Shifting mark to line " + delStart.line);
}
}
}
}
}
use of com.maddyhome.idea.vim.common.Mark in project ideavim by JetBrains.
the class MarkGroup method saveData.
public void saveData(@NotNull Element element) {
Element marksElem = new Element("globalmarks");
for (Mark mark : globalMarks.values()) {
if (!mark.isClear()) {
Element markElem = new Element("mark");
markElem.setAttribute("key", Character.toString(mark.getKey()));
markElem.setAttribute("line", Integer.toString(mark.getLogicalLine()));
markElem.setAttribute("column", Integer.toString(mark.getCol()));
markElem.setAttribute("filename", StringUtil.notNullize(mark.getFilename()));
marksElem.addContent(markElem);
if (logger.isDebugEnabled()) {
logger.debug("saved mark = " + mark);
}
}
}
element.addContent(marksElem);
Element fileMarksElem = new Element("filemarks");
List<FileMarks<Character, Mark>> files = new ArrayList<FileMarks<Character, Mark>>(fileMarks.values());
Collections.sort(files, new Comparator<FileMarks<Character, Mark>>() {
public int compare(@NotNull FileMarks<Character, Mark> o1, @NotNull FileMarks<Character, Mark> o2) {
return o1.timestamp.compareTo(o2.timestamp);
}
});
if (files.size() > SAVE_MARK_COUNT) {
files = files.subList(files.size() - SAVE_MARK_COUNT, files.size());
}
for (String file : fileMarks.keySet()) {
FileMarks<Character, Mark> marks = fileMarks.get(file);
if (!files.contains(marks)) {
continue;
}
if (marks.size() > 0) {
Element fileMarkElem = new Element("file");
fileMarkElem.setAttribute("name", file);
fileMarkElem.setAttribute("timestamp", Long.toString(marks.timestamp.getTime()));
for (Mark mark : marks.values()) {
if (!mark.isClear() && !Character.isUpperCase(mark.getKey()) && SAVE_FILE_MARKS.indexOf(mark.getKey()) >= 0) {
Element markElem = new Element("mark");
markElem.setAttribute("key", Character.toString(mark.getKey()));
markElem.setAttribute("line", Integer.toString(mark.getLogicalLine()));
markElem.setAttribute("column", Integer.toString(mark.getCol()));
fileMarkElem.addContent(markElem);
}
}
fileMarksElem.addContent(fileMarkElem);
}
}
element.addContent(fileMarksElem);
Element jumpsElem = new Element("jumps");
for (Jump jump : jumps) {
if (!jump.isClear()) {
Element jumpElem = new Element("jump");
jumpElem.setAttribute("line", Integer.toString(jump.getLogicalLine()));
jumpElem.setAttribute("column", Integer.toString(jump.getCol()));
jumpElem.setAttribute("filename", StringUtil.notNullize(jump.getFilename()));
jumpsElem.addContent(jumpElem);
if (logger.isDebugEnabled()) {
logger.debug("saved jump = " + jump);
}
}
}
element.addContent(jumpsElem);
}
use of com.maddyhome.idea.vim.common.Mark in project ideavim by JetBrains.
the class MarkGroup method getAllFileMarks.
@Nullable
private HashMap<Character, Mark> getAllFileMarks(@NotNull final Document doc) {
VirtualFile vf = FileDocumentManager.getInstance().getFile(doc);
if (vf == null) {
return null;
}
HashMap<Character, Mark> res = new HashMap<Character, Mark>();
FileMarks<Character, Mark> fileMarks = getFileMarks(doc);
if (fileMarks != null) {
res.putAll(fileMarks);
}
for (Character ch : globalMarks.keySet()) {
Mark mark = globalMarks.get(ch);
if (vf.getPath().equals(mark.getFilename())) {
res.put(ch, mark);
}
}
return res;
}
Aggregations