IntelliJ IDE 插件开发 | (六)内部模式的使用

系列文章

前言

前几篇文章主要介绍了 IntelliJ IDE 插件开发的基础知识和实战内容,作为后续内容的过渡,本文会讲解前几篇文章中提到过的内部模式的使用。内部模式通过菜单形式提供了一系列实用工具,能够帮助初学 IntelliJ IDE 插件的同学极大提升开发效率,由于内部模式提供的工具过多,本文则会挑选几个比较实用的工具进行介绍。

启用内部模式

首先在帮助菜单中找到Edit Custom Properties...

image-20240205104923509

然后加入如下配置:

idea.is.internal=true

保存后重启 IDEA,就可以在 Tools 菜单中发现多了一个 Internal Actions:

image-20240205105443548

下面介绍的工具都是基于 Internal Actions 下的,按照实用性,顺序会有所差异。

UI Debugger

在 Internal Actions 下找到 UI Debugger 菜单,点击后会出现以下弹框:

image-20240205134500788

可以发现这里有 Playback 和 Actions 两个标签页,其中 Playback 用于执行给定的脚本,例如以下脚本会自动执行 CTRL + F 显示搜索框,然后先开启大写,最后输入 HELLO:

%[control F]
%type 20:16;72:16;69:16;76:16;76:16;79:16

第一行用于执行 CTRL + F,第二行中的所有的数字都对应键盘编码(不是ASCII码),例如 20代表开启大写,72代表字符 h,所有的输入用 ; 进行分割,: 前表示字符编码,: 后表示控制字符的编码。所有支持的命令和语法规则可以参考源码,由于这个功能在插件开发中用处不大,这里就不展开介绍了。

效果如下:

动画

上面关于 Playback 的使用了解即可,这里主要讲解一下 Actions 的使用,通过前面的文章我们可以知道,在 IntelliJ IDE 中各种操作(不管是点击菜单项还是通过快捷键)都有相对应的 Action,而 Actions 这个菜单就是用于帮助我们查看每个操作所对应的 Action 类名和 id(如果存在),而知道了 Action 的 id,我们就可以调用相应的操作,这样就实现了对 IDEA 自带功能的使用(也可以直接根据 Action 的类名去找相应的文件去看实现方式),下面以一个具体的例子去介绍使用方式:

例如我们想实现一个根据 Kotlin 类定位到对应的 class 文件并打开的功能,我们首先通过 UI Debugger 去查看 IDEA 定位文件并打开对应的 Action:

动画

这里可以看到该操作对应的 ActionId 为 SelectInProjectView,然后我们只需要实现根据 Kotlin 文件名找到同名的 class 文件的逻辑即可,最终实现方式如下:

class FindClassAction: AnAction() {
   
    
    override fun actionPerformed(e: AnActionEvent) {
   
        val project = e.project ?: return
        val file = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY)?.get(0) ?: return
        val kotlinSuffix = ".kt"
        val classSuffix = ".class"
        
        if (!file.name.endsWith(kotlinSuffix)) {
   
            Utils.info("请选择 Kotlin 文件")
            return
        }
        // 查找 class 文件路径
        val className = file.name.replace(kotlinSuffix, classSuffix)
        val fileList = findFiles(project.basePath.toString(), className, setOf(".idea"))
        if (fileList.isEmpty()) {
   
            Utils.info("未找到对应类文件")
            return
        }
        val classFile = fileList[0]
        LocalFileSystem.getInstance().findFileByIoFile(classFile)
            ?.let {
   
                // 打开文件
                FileEditorManager.getInstance(project).openFile(it, true)
                // 定位文件
                ActionManager.getInstance().getAction("SelectInProjectView").actionPerformed(e)
            }
    }
    
    // 在指定路径递归查询某个文件, 同时排除指定的路径
    private fun findFiles(rootDir: String, targetFileName: String, excludedDirs: Set<String> = emptySet()): List<File> {
    
        val result = mutableListOf<File>()
        fun searchFiles(directory: File) {
   
            val files = directory.listFiles() ?: return
            for (file in files) {
   
                if (file.isDirectory) {
   
                    if (file.name !in excludedDirs) {
   
                        searchFiles(file)
                    }
                } else {
   
                    if (file.name == targetFileName && file.path.contains("classes")) {
   
                        result.add(file)
                    }
                }
            }
        }
        searchFiles(File(rootDir))
        return result
    }
}

假如我们想知道格式化代码的实现方式,也是先去获取对应的 action:

动画

这里可以看到对应的 Action 类路径是 com.intellij.codeInsight.actions.ReformatCodeAction,这样我们就可以去找对应的源代码,查看其实现方式:

image-20240205150729549

通过这种方式,我们就可以在对 IDEA 自带功能有某些定制化需求的时候,通过继承原有类,然后重写某些逻辑去实现我们的需求。

UI Inspector

通过 UI -> UI Inspector 可以找到该菜单,不过我们在实际使用的时候并不需要从菜单里点击,只需要选择 IDEA 界面中某个 UI 组件,然后使用 CTRL + ALT + 点击鼠标左键即可显示该组件的 UI 信息,如下所示:

动画

这里查看的是 debug 按钮所对应的布局信息,具体如下:

image-20240205152021642

可以发现这里也有 Action ID 和 Action Class 属性,因此上面想查找定位按钮的 Action ID 也可以通过这种方式进行查看:

image-20240205152549992

可以看到这里的 id 和我们通过 UI Debugger 获取的内容一样,当然除了 Action 相关的信息,根据查看的组件类型不同,所对应的属性也会有区别(例如设置页面和这里的按钮属性就有些不同),具体的不同可以查看官网

LaF Defaults

通过 UI -> LaF Defaults 可以找到该菜单,点击后会出现以下弹框:

image-20240205154635942

这里展示了 IDEA 中所有的颜色和外观设置(例如各种间距),我们可以点击对应的 Value 值进行修改,同时修改的设置会立即生效,因此如果有开发主题类插件需求的时候,我们就可以很方便地先通过该工具获取实时的预览效果,例如我们去修改按钮的圆角大小为 0:

image-20240205155316347

修改完就可以发现按钮的圆角消失了:

image-20240205155349887

或者是修改按钮的背景色:

image-20240205155719598

点击 OK 后会出现以下效果:

image-20240205155754512

Kotlin UI DSL

image-20240205155852946

在前几篇文章中我们有简单地使用 Kotlin UI DSL 去实现一些 UI 界面,如果是初学者对相关的使用方式不熟悉,就可以通过该菜单去查看一些组件地使用用例,点击View source就可以查看相应的源码:

image-20240205160104843

总结

本文主要讲解了内部模式中几个比较实用的工具,希望能给大家提供一些帮助,如果你发现了一些插件开发中的小技巧,也欢迎一起交流讨论~~~

题外话

从下篇文章开始会逐步介绍 PSI、自定义语言以及一些常用插件的开发思路和实现方式,敬请期待,同时也祝各位新年快乐,在新的一年里,事业有成,身体健康,家庭幸福,万事如意!

相关推荐

  1. Qt开发与QPluginLoader使用

    2024-02-06 07:12:03       55 阅读
  2. 安卓开发Gson使用

    2024-02-06 07:12:03       36 阅读
  3. :qrcode使用

    2024-02-06 07:12:03       32 阅读
  4. 如何使用vue开发vscode

    2024-02-06 07:12:03       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-06 07:12:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-06 07:12:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-02-06 07:12:03       87 阅读
  4. Python语言-面向对象

    2024-02-06 07:12:03       96 阅读

热门阅读

  1. 百度语音合成API

    2024-02-06 07:12:03       49 阅读
  2. Vue 本地存储

    2024-02-06 07:12:03       56 阅读
  3. C语言:公式求和

    2024-02-06 07:12:03       57 阅读
  4. go c 通过内存原始二进制内容直接传递结构体

    2024-02-06 07:12:03       54 阅读
  5. 12118 - Inspector‘s Dilemma (UVA)

    2024-02-06 07:12:03       55 阅读
  6. 图论:合适的环

    2024-02-06 07:12:03       54 阅读
  7. 【算法练习】leetcode算法题合集之动态规划篇

    2024-02-06 07:12:03       63 阅读
  8. DNS服务器异常有什么影响,怎么处理

    2024-02-06 07:12:03       49 阅读
  9. Golang gorm 结构体定义使用

    2024-02-06 07:12:03       46 阅读