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

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

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

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

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中进行配置:

<lang.foldingBuilder
        language="Properties"
        implementationClass="cn.butterfly.unicode.fold.UnicodeFoldBuilder"/>

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

class UnicodeAction: AnAction() {
    
    override fun actionPerformed(e: AnActionEvent) {
        ActionManager.getInstance().getAction("CollapseRegion").actionPerformed(e)
    }

}

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

image-20240413210823687

总结

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

  • 25
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值