private static void init(final AbstractFileType abstractFileType) {
    SyntaxTable table = abstractFileType.getSyntaxTable();
    CompletionUtil.registerCompletionData(abstractFileType, new SyntaxTableCompletionData(table));

    if (!isEmpty(table.getStartComment()) && !isEmpty(table.getEndComment())
        || !isEmpty(table.getLineComment())) {
      abstractFileType.setCommenter(new MyCommenter(abstractFileType));
    }

    if (table.isHasBraces() || table.isHasBrackets() || table.isHasParens()) {
      BraceMatchingUtil.registerBraceMatcher(abstractFileType, new CustomFileTypeBraceMatcher());
    }

    TypedHandler.registerQuoteHandler(abstractFileType, new CustomFileTypeQuoteHandler());
  }
  @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
  @Override
  public Result beforeCharTyped(
      final char charTyped, Project project, final Editor editor, PsiFile file, FileType fileType) {
    assert !inside;
    inside = true;
    try {
      final LookupImpl lookup = (LookupImpl) LookupManager.getActiveLookup(editor);
      if (lookup == null) {
        return Result.CONTINUE;
      }

      if (charTyped == ' '
          && ChooseItemReplaceAction.hasTemplatePrefix(lookup, TemplateSettings.SPACE_CHAR)) {
        return Result.CONTINUE;
      }

      final CharFilter.Result result = getLookupAction(charTyped, lookup);
      if (lookup.isLookupDisposed()) {
        return Result.CONTINUE;
      }

      if (!lookup.performGuardedChange(
          new Runnable() {
            @Override
            public void run() {
              EditorModificationUtil.deleteSelectedText(editor);
            }
          })) {
        return Result.STOP;
      }
      if (result == CharFilter.Result.ADD_TO_PREFIX) {
        Document document = editor.getDocument();
        long modificationStamp = document.getModificationStamp();

        if (!lookup.performGuardedChange(
            new Runnable() {
              @Override
              public void run() {
                EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(
                    editor, String.valueOf(charTyped), true);
              }
            })) {
          return Result.STOP;
        }
        lookup.appendPrefix(charTyped);
        if (lookup.isStartCompletionWhenNothingMatches() && lookup.getItems().isEmpty()) {
          final CompletionProgressIndicator completion =
              CompletionServiceImpl.getCompletionService().getCurrentCompletion();
          if (completion != null) {
            completion.scheduleRestart();
          } else {
            AutoPopupController.getInstance(editor.getProject()).scheduleAutoPopup(editor, null);
          }
        }

        AutoHardWrapHandler.getInstance()
            .wrapLineIfNecessary(
                editor,
                DataManager.getInstance().getDataContext(editor.getContentComponent()),
                modificationStamp);

        final CompletionProgressIndicator completion =
            CompletionServiceImpl.getCompletionService().getCurrentCompletion();
        if (completion != null) {
          completion.prefixUpdated();
        }
        return Result.STOP;
      }

      if (result == CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP && lookup.isFocused()) {
        LookupElement item = lookup.getCurrentItem();
        if (item != null) {
          if (completeTillTypedCharOccurrence(charTyped, lookup, item)) {
            return Result.STOP;
          }

          inside = false;
          ((CommandProcessorEx) CommandProcessor.getInstance()).enterModal();
          try {
            finishLookup(charTyped, lookup);
          } finally {
            ((CommandProcessorEx) CommandProcessor.getInstance()).leaveModal();
          }
          return Result.STOP;
        }
      }

      lookup.hide();
      TypedHandler.autoPopupCompletion(editor, charTyped, project);
      return Result.CONTINUE;
    } finally {
      inside = false;
    }
  }