Runnable (final Editor editor, char shortcutChar, @Nullable final PairProcessor<? super String, ? super String> processor) { if (editor.getSelectionModel().hasSelection()) { return null; } PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, myProject); if (file == null || file instanceof PsiCompiledElement) return null; Map<TemplateImpl, String> template2argument = findMatchingTemplates(file, editor, shortcutChar, TemplateSettings.getInstance()); TemplateActionContext templateActionContext = TemplateActionContext.expanding(file, editor); boolean multiCaretMode = editor.getCaretModel().getCaretCount() > 1; List<CustomLiveTemplate> customCandidates = ContainerUtil.findAll(CustomLiveTemplate.EP_NAME.getExtensions(), customLiveTemplate -> shortcutChar == customLiveTemplate.getShortcut() && (!multiCaretMode || supportsMultiCaretMode(customLiveTemplate)) && isApplicable(customLiveTemplate, templateActionContext)); if (!customCandidates.isEmpty()) { int caretOffset = editor.getCaretModel().getOffset(); CustomTemplateCallback templateCallback = new CustomTemplateCallback(editor, file); for (CustomLiveTemplate customLiveTemplate : customCandidates) { String key = customLiveTemplate.computeTemplateKey(templateCallback); if (key != null) { int offsetBeforeKey = caretOffset - key.length(); CharSequence text = editor.getDocument().getImmutableCharSequence(); if (template2argument == null || !containsTemplateStartingBefore(template2argument, offsetBeforeKey, caretOffset, text)) { return () -> { customLiveTemplate.expand(key, templateCallback); if (multiCaretMode) { PsiDocumentManager.getInstance(templateCallback.getProject()).commitDocument(editor.getDocument()); } }; } } } } return startNonCustomTemplates(template2argument, editor, processor); }