aboutsummaryrefslogtreecommitdiff
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
parenta4946da8409040003d96c7d8d43ed394597bf675 (diff)
downloadskyhanni-30a6f963fe6a1a9478db26d0db47062f39422eef.tar.gz
skyhanni-30a6f963fe6a1a9478db26d0db47062f39422eef.tar.bz2
skyhanni-30a6f963fe6a1a9478db26d0db47062f39422eef.zip
Backend: Add open in regex101.com intention (#1210)
-rw-r--r--.live-plugins/regexr/plugin.kts109
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/repopatterns/RepoPattern.kt5
3 files changed, 117 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"
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt
index 31f06ca01..7ba5102bc 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt
@@ -271,6 +271,9 @@ class ChatFilter {
"§eObtain a §r§6Booster Cookie §r§efrom the community shop in the hub!",
)
+ /**
+ * REGEX-TEST: §e[NPC] Jacob§f: §rYour §9Anita's Talisman §fis giving you §6+25☘ Carrot Fortune §fduring the contest!
+ */
private val anitaFortunePattern by RepoPattern.pattern(
"chat.jacobevent.accessory",
"§e\\[NPC] Jacob§f: §rYour §9Anita's \\w+ §fis giving you §6\\+\\d{1,2}☘ .+ Fortune §fduring the contest!"
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/repopatterns/RepoPattern.kt b/src/main/java/at/hannibal2/skyhanni/utils/repopatterns/RepoPattern.kt
index 715c907e4..2e1259343 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/repopatterns/RepoPattern.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/repopatterns/RepoPattern.kt
@@ -84,6 +84,11 @@ interface RepoPattern : ReadOnlyProperty<Any?, Pattern> {
/**
* Obtain a reference to a [Pattern] backed by either a local regex, or a remote regex.
* Check the documentation of [RepoPattern] for more information.
+ *
+ * This method supports "Open regex101.com" using [LivePlugin](https://plugins.jetbrains.com/plugin/7282-liveplugin).
+ * To use it, install LivePlugin, enable "Run plugins on IDE start" and "Run project specific plugins".
+ * Now you can use ALT+ENTER while hovering over a [pattern] call using your text cursor to access the "Open in regex101.com" intention.
+ * Add a KDoc comment to the associated variable containing lines starting with `REGEX-TEST: ` to pre-fill examples.
*/
fun pattern(key: String, @Language("RegExp") fallback: String): RepoPattern {
return RepoPatternManager.of(key, fallback)