Last active
May 9, 2021 16:26
-
-
Save dkandalov/db4c400d69be423545e294654475c9aa to your computer and use it in GitHub Desktop.
Markdown links with custom actions (see https://github.com/dkandalov/live-plugin)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler | |
import com.intellij.lang.LanguageAnnotators | |
import com.intellij.lang.LanguageExtensionPoint | |
import com.intellij.lang.annotation.Annotator | |
import com.intellij.lang.annotation.HighlightSeverity.INFORMATION | |
import com.intellij.openapi.application.ApplicationManager | |
import com.intellij.openapi.editor.Editor | |
import com.intellij.openapi.editor.colors.CodeInsightColors.INACTIVE_HYPERLINK_ATTRIBUTES | |
import com.intellij.openapi.extensions.DefaultPluginDescriptor | |
import com.intellij.openapi.util.TextRange | |
import com.intellij.patterns.PsiElementPattern | |
import com.intellij.psi.PsiElement | |
import com.intellij.psi.PsiReferenceBase | |
import com.intellij.psi.PsiReferenceProvider | |
import com.intellij.psi.SyntheticElement | |
import com.intellij.psi.impl.FakePsiElement | |
import com.intellij.psi.impl.source.resolve.reference.PsiReferenceRegistrarImpl | |
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry | |
import com.intellij.util.ProcessingContext | |
import liveplugin.show | |
val markdown = com.intellij.lang.Language.findLanguageByID("Markdown")!! | |
val psiPattern = object : PsiElementPattern.Capture<PsiElement>(PsiElement::class.java) { | |
override fun accepts(o: Any?, context: ProcessingContext?) = (o as? PsiElement)?.text == "hello" | |
} | |
val psiReferenceProvider = object : PsiReferenceProvider() { | |
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext) = | |
arrayOf(PsiReferenceTo(PsiElementWithAction(element, "action text") { | |
show("hello from element: $element") | |
})) | |
} | |
(ReferenceProvidersRegistry.getInstance().getRegistrar(markdown) as PsiReferenceRegistrarImpl) | |
.registerReferenceProvider(psiPattern, psiReferenceProvider, 1.0, pluginDisposable) | |
class PsiReferenceTo(private val ref: PsiElement) : PsiReferenceBase<PsiElement>(ref.parent, true) { | |
override fun resolve(): PsiElement = ref | |
} | |
class PsiElementWithAction( | |
private val _parent: PsiElement, | |
private val _text: String, | |
private val action: () -> Unit | |
) : FakePsiElement(), SyntheticElement { | |
override fun navigate(requestFocus: Boolean) = action() | |
override fun getParent() = _parent | |
override fun getPresentableText() = _text | |
override fun getName() = _text | |
override fun getTextRange(): TextRange = _parent.textRange | |
} | |
if (false) { | |
fun annotator() = Annotator { element, holder -> | |
val text = element.text | |
text.indices | |
.filter { i -> text.substring(i, minOf(i + 5, text.length)) == "hello" } | |
.forEach { i -> | |
holder.newAnnotation(INFORMATION, "Hello!") | |
.range(TextRange(i, i + 5)) | |
.textAttributes(INACTIVE_HYPERLINK_ATTRIBUTES) | |
.create() | |
} | |
} | |
val pluginDescriptor = DefaultPluginDescriptor("hello-world") | |
ApplicationManager.getApplication().extensionArea.getExtensionPoint(LanguageAnnotators.EP_NAME) | |
.registerExtension( | |
LanguageExtensionPoint(markdown.id, annotator()).also { it.pluginDescriptor = pluginDescriptor }, | |
pluginDescriptor, | |
pluginDisposable | |
) | |
LanguageAnnotators.INSTANCE.clearCache(markdown) | |
val declarationHandler = GotoDeclarationHandler { element: PsiElement?, _: Int, _: Editor -> | |
val i = element?.text?.indexOf("hello") | |
if (i == null || i == -1) arrayOf() | |
else arrayOf(PsiElementWithAction(element, "foooo") { | |
show("hello") | |
}) | |
} | |
ApplicationManager.getApplication().extensionArea.getExtensionPoint(GotoDeclarationHandler.EP_NAME) | |
.registerExtension(declarationHandler, pluginDisposable) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment