@Override
        public void caretPositionChanged(CaretEvent event) {

          if (project.isDisposed()) {
            return;
          }

          VirtualFile file =
              FileDocumentManager.getInstance().getFile(event.getEditor().getDocument());

          // Make sure file exists
          if (file == null) {
            return;
          }

          // Make sure file is in the project
          if (!ProjectFileIndex.SERVICE.getInstance(project).isInSource(file)) {
            return;
          }

          int offset = event.getEditor().logicalPositionToOffset(event.getNewPosition());

          // Get path relative to project root (e.g. src/Sample.java)
          Path basePath = Paths.get(project.getBasePath());
          Path absoluteFilePath = Paths.get(file.getPath());
          String relativeFilePath = basePath.relativize(absoluteFilePath).toString();

          CursorMovement cursorMovement = new CursorMovement(-1, relativeFilePath, offset);

          for (EditorEvent editorEvent : events) {
            editorEvent.sendCursorMovement(cursorMovement);
          }
        }
        @Override
        public void beforeDocumentChange(DocumentEvent event) {

          if (project.isDisposed()) {
            return;
          }

          if (!isListening) {
            System.out.println("Ignoring change.");
            return;
          }

          VirtualFile file = FileDocumentManager.getInstance().getFile(event.getDocument());

          // Make sure file exists
          if (file == null) {
            return;
          }

          // Make sure file is in the project
          if (!ProjectFileIndex.SERVICE.getInstance(project).isInSource(file)) {
            return;
          }

          String dummyIdentifier = "IntellijIdeaRulezzz";

          if (!event.getNewFragment().toString().contains(dummyIdentifier)) {
            if (!event.isWholeTextReplaced()) {

              // Get path relative to project root (e.g. src/Sample.java)
              Path basePath = Paths.get(project.getBasePath());
              Path absoluteFilePath = Paths.get(file.getPath());
              String relativeFilePath = basePath.relativize(absoluteFilePath).toString();

              String documentText = event.getDocument().getText();
              String oldFragment = event.getOldFragment().toString();
              String newFragment = event.getNewFragment().toString();
              int offset = event.getOffset();

              IOPatcher patcher = new IOPatcher();
              LinkedList<Patch> patches =
                  patcher.makePatchAsList(documentText, oldFragment, newFragment, offset);

              UserEdit edit = new UserEdit(0, relativeFilePath, patches);

              for (EditorEvent editorEvent : events) {
                editorEvent.sendChange(edit);
              }
            }
          }
        }