aboutsummaryrefslogtreecommitdiff
path: root/.live-plugins/regexr/plugin.kts
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-03-19 10:50:48 +0100
committerGitHub <noreply@github.com>2024-03-19 10:50:48 +0100
commit30a6f963fe6a1a9478db26d0db47062f39422eef (patch)
tree58ae072dfeda5c5b1bfe2278ed1fbb1e27a40362 /.live-plugins/regexr/plugin.kts
parenta4946da8409040003d96c7d8d43ed394597bf675 (diff)
downloadskyhanni-30a6f963fe6a1a9478db26d0db47062f39422eef.tar.gz
skyhanni-30a6f963fe6a1a9478db26d0db47062f39422eef.tar.bz2
skyhanni-30a6f963fe6a1a9478db26d0db47062f39422eef.zip
Backend: Add open in regex101.com intention (#1210)
Diffstat (limited to '.live-plugins/regexr/plugin.kts')
-rw-r--r--.live-plugins/regexr/plugin.kts109
1 files changed, 109 insertions, 0 deletions
diff --git a/.live-plugins/regexr/plugin.kts b/.live-plugins/regexr/plugin.kts
new file mode 100644
index 000000000..128cadc7a
--- /dev/null
+++ b/.live-plugins/regexr/plugin.kts
@@ -0,0 +1,109 @@
+import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction
+import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo
+import com.intellij.openapi.diagnostic.Logger
+import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.project.Project
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiFile
+import com.intellij.psi.util.findParentOfType
+import liveplugin.openInBrowser
+import liveplugin.registerIntention
+import liveplugin.show
+import org.intellij.markdown.html.urlEncode
+import org.jetbrains.kotlin.kdoc.psi.api.KDoc
+import org.jetbrains.kotlin.psi.*
+
+// depends-on-plugin org.jetbrains.kotlin
+
+registerIntention(RenameKotlinFunctionToUseCamelCaseIntention())
+if (!isIdeStartup) show("Reloaded Regex intentions")
+val logger =
+ Logger.getInstance("SkyHanni")
+
+val regexTestPrefix = "REGEX-TEST: "
+
+class RegexInfo(
+ val regex: KtValueArgument,
+ val comment: KDoc?,
+) {
+ fun getRegexText(): String? {
+ val templateExpr = regex.getArgumentExpression() as? KtStringTemplateExpression ?: return null
+ val sb = StringBuilder()
+ for (x in templateExpr.entries) {
+ when (x) {
+ is KtEscapeStringTemplateEntry -> sb.append(x.unescapedValue)
+ is KtLiteralStringTemplateEntry -> sb.append(x.text)
+ else -> return null
+ }
+ }
+ return sb.toString()
+ }
+
+ val commentText by lazy {
+ comment?.text
+ ?.replace("/*", "")
+ ?.replace("*/", "")
+ ?.lines()
+ ?.map {
+ it.trim().trimStart('*').trim()
+ }
+ }
+
+ fun getExamples(): List<String> {
+ val examples = commentText?.filter { it.startsWith(regexTestPrefix) }
+ ?.map { it.substring(regexTestPrefix.length) }
+ if (examples == null) return listOf()
+ return examples
+ }
+}
+
+inner class RenameKotlinFunctionToUseCamelCaseIntention : PsiElementBaseIntentionAction() {
+ override fun isAvailable(project: Project, editor: Editor?, element: PsiElement): Boolean {
+ return findRegexInfo(element) != null
+ }
+
+ fun findRegexInfo(element: PsiElement): RegexInfo? {
+ val call = element.findParentOfType<KtCallExpression>() ?: return null
+ if (call.valueArguments.size != 2) return null
+ val methodName = call.calleeExpression as? KtSimpleNameExpression ?: return null
+ if (methodName.getReferencedName() != "pattern") return null
+ val field = call.findParentOfType<KtProperty>() ?: return null
+ val regex = call.valueArguments[1] ?: return null
+ val comment = field.docComment
+ return RegexInfo(regex, comment)
+ }
+
+ override fun invoke(project: Project, editor: Editor?, element: PsiElement) {
+ val info = findRegexInfo(element) ?: return
+ val regex = info.getRegexText()
+ if (regex == null) {
+ show("Regex needs to be a bare string literal in order to open it in the browser!")
+ return
+ }
+ openInBrowser(
+ "https://regex101.com/?regex=${urlEncode(regex)}&testString=${
+ urlEncode(
+ info.getExamples().joinToString("\n")
+ )
+ }"
+ )
+ }
+
+ override fun generatePreview(project: Project, editor: Editor, file: PsiFile): IntentionPreviewInfo {
+ val element = getElement(editor, file) ?: return IntentionPreviewInfo.EMPTY
+ val info = findRegexInfo(element) ?: return IntentionPreviewInfo.EMPTY
+ val exampleCount = info.getExamples().size
+ return IntentionPreviewInfo.Html(
+ """
+ Opens this regex on regex101.com with $exampleCount example${s(exampleCount)}.
+ """
+ )
+ }
+
+ override fun getText() = "Open regex101.com"
+ override fun getFamilyName() = "OpenRegexExplorerIntention"
+}
+
+fun s(count: Int): String {
+ return if (count == 1) "" else "s"
+}