IntelliJ IDE 插件开发 | (九)实现 Unicode 字符折叠预览

系列文章

本系列文章已收录到专栏,交流群号:689220994,也可点击链接加入。

前言

在上一篇文章中我们介绍了如何实现 i18n 的方式,其中提到官方建议我们在编写语言文件时将 ASCII 码范围外的字符都使用 Unicode 编码进行表示,这样就导致我们无法直观地看到原始文本,因此本文就来介绍如何实现对 Unicode 字符折叠预览的功能,最终实现效果如下,另外本文所涉及到的完整代码也已上传到GitHub

实现方式

在正式实现之前先说一下整体的实现思路:

  1. 引入com.intellij.properties插件用于处理properties格式的语言文件。
  2. 继承om.intellij.lang.folding.FoldingBuilderEx类,重写其中的方式实现折叠字符及预览文本。
  3. 将实现类注册到plugin.xml中。

实现步骤

首先是引入com.intellij.properties插件并进行配置:

  • build.gradle.kts
kotlin 复制代码
// 配置开发过程中运行的 IDEA 沙盒信息
intellij {
    // IDEA 的版本
    version.set("2023.2.5")
    // 这里 IU 是指付费版, 也可以选择 IC 对应社区版
    type.set("IU")
    
    // 用到的插件
    plugins.set(listOf("com.intellij.properties"))
}
  • plugin.xml
xml 复制代码
<depends>com.intellij.properties</depends>

经过上述配置后,我们就可以很方便地去处理properties文件了。

如果对这里的配置有疑问,建议先看一下本专栏中讲解 PSI 的部分,在 IntelliJ 插件开发中如果想去处理某种语言文件,除了 XML 这种内置的语言,其他都是需要引入相应的插件。

然后是继承FoldingBuilderEx类,并实现其中的方法:

kotlin 复制代码
class UnicodeFoldBuilder: FoldingBuilderEx() {

    override fun buildFoldRegions(root: PsiElement, document: Document, quick: Boolean) =
        // 对 properties 文件中的键值对进行遍历
        (root as? PropertiesFile)?.properties?.filter {
            // 只保留键值非空并且包含 Unicode 字符的键值对
            it.value != null && it.key != null && containsUnicodeEscapeSequence(it.value!!)
        }?.map {
            // 获取折叠区域,这里只截取键值对中的值部分
            val startOffset = it.psiElement.startOffset + it.key!!.length + 1
            val endOffset = startOffset + it.value!!.length
            FoldingDescriptor(it.psiElement.node, TextRange(startOffset, endOffset))
        }?.toTypedArray() ?: emptyArray()

    /**
     * 用于判断字符串中是否包含 Unicode 编码过的字符
     */
    private fun containsUnicodeEscapeSequence(str: String) =
        Regex("\\\\u[0-9a-fA-F]{4}").containsMatchIn(str)

    /**
     * 将 Unicode 编码的字符进行反编码
     * 这里只对键值对中的值进行反编码,通过截取原始文本中 = 后的内容
     */
    override fun getPlaceholderText(node: ASTNode) = 
        decodeUnicode(node.text.substring(node.text.indexOf("=") + 1))

    /**
     * 用于将字符串转为 Unicode 编码
     */
    private fun decodeUnicode(input: String) = input.replace("\\\\u([0-9a-fA-F]{4})".toRegex())
    {
        it.groupValues[1].toInt(16).toChar().toString()
    }

    /**
     * 默认将符合条件的文本进行折叠
     */
    override fun isCollapsedByDefault(node: ASTNode) = true

}

这里直接参照代码和相应的注释不难理解,其中buildFoldRegionsgetPlaceholderTextisCollapsedByDefault三个是我们重写的方法,buildFoldRegions方法用于收集所有的折叠块区域,getPlaceholderText用于设置折叠块的预览文本,isCollapsedByDefault用于设置默认对符合条件的文本进行折叠。

最后在plugin.xml中进行配置:

xml 复制代码
<lang.foldingBuilder
        language="Properties"
        implementationClass="cn.butterfly.unicode.fold.UnicodeFoldBuilder"/>

经过以上配置后,就已经实现了 Unicode 字符折叠预览的功能,不过对于刚编写的内容,还是没办法实现对 Unicode 字符进行折叠,因此这里再增加一个 Action 实现手动对 Unicode 字符进行折叠:

kotlin 复制代码
class UnicodeAction: AnAction() {
    
    override fun actionPerformed(e: AnActionEvent) {
        ActionManager.getInstance().getAction("CollapseRegion").actionPerformed(e)
    }

}

其实平台默认也已经为我们提供了相应的功能,在编辑器中也可以通过右键菜单中的选择来手动对代码块进行折叠和展开:

总结

本文介绍了如何通过 IntelliJ 提供的接口来实现对 Unicode 字符折叠预览的功能,整体实现方式也比较简单,下一篇文章将会介绍如何开发主题。

相关推荐
网安刚哥8 分钟前
雷池WAF的身份认证 - GitHub
后端
用户3414081991259 分钟前
android的网络守护进程netd
后端
敲代码的瓦龙10 分钟前
C++?动态内存管理!!!
c语言·开发语言·数据结构·c++·后端
陈唐其travel19 分钟前
如何搭建自己的gitlab私有仓库
后端
雷渊23 分钟前
深入分析dubbo的优雅停机
后端
Whbbit199924 分钟前
hono 集成 Better Auth
javascript·后端
雷渊36 分钟前
聊一聊Dubbo中的泛化调用
后端
雷渊1 小时前
深入分析RPC和HTTP的区别
后端
极客智谷1 小时前
Spring AI应用系列——基于DashScope平台自主Model配置的Chat应用
人工智能·后端
用户4099322502121 小时前
FastAPI数据库连接池配置与监控
后端·ai编程·trae