# aifei-enjoy-plugin **Repository Path**: jfinal/aifei-enjoy-plugin ## Basic Information - **Project Name**: aifei-enjoy-plugin - **Description**: 让IDEA支持enjoy语法 - **Primary Language**: Kotlin - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-05-11 - **Last Updated**: 2026-05-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Enjoy Template - IntelliJ IDEA 插件 [![JetBrains Plugin](https://img.shields.io/badge/JetBrains-Plugin-blue?logo=intellij-idea)](https://plugins.jetbrains.com) [![Version](https://img.shields.io/badge/version-1.0.0-green)]() [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE) **Enjoy Template** 是一款 IntelliJ IDEA 插件,为 [JFinal Enjoy](https://jfinal.com) 模板引擎提供完整的语言支持。Enjoy 是 JFinal 框架内置的高性能模板引擎,语法简洁优雅,广泛应用于 Java Web 开发中的页面渲染。 ## 功能特性 ### 语法高亮 - Enjoy 指令(`#if`、`#for`、`#define`、`#switch` 等)和表达式的完整语法高亮 - HTML 模板内容与 Enjoy 指令的分层高亮显示 - 自定义颜色方案:`Settings → Editor → Color Scheme → Enjoy` - 支持块注释、行注释、字符串的语法着色 ### 代码补全 - 输入 `#` 时自动弹出指令补全列表 - 支持所有 Enjoy 指令的智能补全: - 控制流:`#if`、`#else if`、`#else`、`#end`、`#switch`、`#case`、`#default` - 循环:`#for`、`#break`、`#continue` - 函数定义:`#define` - 输出:`#()`、`#(expr)` - 注释:`##`(行注释)、`#** #`(块注释) - 其他:`#include`、`#set`、`#return`、`#render` 等 - 模板内自定义函数(`#define` 定义的函数)的跨文件补全 ### 跳转到定义 - `Ctrl + 点击`(macOS: `Cmd + 点击`)`#define` 或 `#@` 函数调用,可跳转到函数定义处 - 支持跨文件的函数定义解析 - 支持 `#@name(...)` 和 `#@name?(...)`(空安全调用)两种语法 ### 括号匹配 - 自动匹配 `{}`、`()`、`[]` 括号对 - 高亮显示匹配的括号 ### 代码格式化 - Enjoy 代码块的自动缩进和格式化 - `Ctrl + Alt + L`(macOS: `Cmd + Alt + L`)格式化当前文件 ### 语法检查(Annotator) - `#else` / `#else if` 必须出现在 `#if` 块内 - `#break` / `#continue` 必须出现在 `#for` 循环内 - `#case` / `#default` 必须出现在 `#switch` 块内 - `#return` 必须出现在 `#define` 函数内 - 函数调用是否匹配已定义的模板函数 ### 注释切换 - `Ctrl + /`(macOS: `Cmd + /`)切换行注释 `##` - `Ctrl + Shift + /`(macOS: `Cmd + Shift + /`)切换块注释 `#** #` ### 可自定义文件扩展名 - 默认关联 `.enjoy` 文件 - 可在设置中添加任意扩展名(如 `.html`、`.tpl`、`.jfinal` 等) - 配置路径:`Settings → Tools → Enjoy Template` ## 使用方法 ### 基本使用 打开任意 `.enjoy` 文件即可自动激活所有功能。Enjoy 指令和 HTML 内容将分别以不同的语法高亮显示。 ### 配置文件扩展名 如果你的项目中使用了非 `.enjoy` 的扩展名(例如 `.html` 或 `.tpl`),可以手动关联: 1. 打开 `Settings → Tools → Enjoy Template` 2. 点击 **+** 按钮添加新的扩展名(不带点号,如 `html`) 3. 选中扩展名后点击 **-** 按钮可移除 4. 点击 **Apply** 或 **OK** 保存 > 注意:至少需要保留一个扩展名。 ### 定义和调用模板函数 **定义函数:** ```enjoy #define sayHello(name)

Hello, #(name)!

#end ``` **调用函数:** ```enjoy #@sayHello("World") ``` **空安全调用(函数不存在时不报错):** ```enjoy #@sayHello?("World") ``` 使用 `Ctrl + 点击`(macOS: `Cmd + 点击`)函数名即可跳转到定义处。 ### 代码补全 在 `.enjoy` 文件中输入 `#` 后,插件会自动弹出指令补全列表。对于项目中已定义的 `#define` 函数,也会出现在补全列表中。 ### 语法验证 插件会在编辑器中实时标记语法错误,例如: - 在 `#if` 块外使用 `#else` 会显示红色波浪线 - 在 `#for` 循环外使用 `#break` 会被标记 - 调用未定义的函数会显示警告 ## 项目结构 ``` src/main/kotlin/io/github/ysjsgzq/ ├── EnjoyFileType.kt 文件类型定义 ├── EnjoyIcons.kt 插件图标 ├── EnjoyLanguage.kt 语言定义(TemplateLanguage) ├── annotator/ │ └── EnjoyAnnotator.kt 语法检查器 ├── brace/ │ └── EnjoyBraceMatcher.kt 括号匹配 ├── comment/ │ └── EnjoyCommenter.kt 注释切换 ├── completion/ │ ├── EnjoyCompletionConfidence.kt 补全置信度(允许自动弹出) │ ├── EnjoyCompletionContributor.kt 代码补全贡献者 │ ├── EnjoyCompletionSupport.kt 补全支持 │ └── EnjoyTypedHandler.kt 输入 `#` 触发补全 ├── formatting/ │ ├── EnjoyBlock.kt 格式化块 │ └── EnjoyFormattingModelBuilder.kt 格式化模型 ├── highlight/ │ ├── EnjoyColorSettingsPage.kt 颜色方案配置页 │ ├── EnjoyEditorHighlighter.kt 编辑器高亮器(分层高亮) │ ├── EnjoySyntaxHighlighter.kt 语法高亮器 │ └── EnjoySyntaxHighlighterFactory.kt ├── lexer/ │ └── EnjoyLexer.kt 手写词法分析器(4 状态状态机) ├── parser/ │ ├── EnjoyElementTypes.kt PSI 元素类型 │ ├── EnjoyParser.kt 手写递归下降解析器 │ ├── EnjoyParserDefinition.kt 解析器定义 │ └── EnjoyTemplateFileElementTypes.kt 模板文件元素类型 ├── psi/ │ ├── EnjoyFile.kt 文件 PSI 元素 │ ├── EnjoyFileViewProvider.kt 双 PSI 树文件视图提供者 │ ├── EnjoyPsiElement.kt PSI 元素基类 │ ├── EnjoyTokenType.kt Token 类型 │ └── EnjoyTokens.kt Token 常量和 TokenSet ├── reference/ │ └── EnjoyFuncCallReference.kt 函数调用引用解析 └── settings/ ├── EnjoyConfigurable.kt 设置页面 UI └── EnjoySettings.kt 设置持久化 ``` ## 技术架构 ### 模板语言架构 本插件实现了 IntelliJ 的 **Template Language** 机制。`.enjoy` 文件拥有**双 PSI 树**: - **Enjoy PSI 树**:解析 Enjoy 指令和表达式 - **HTML PSI 树**:解析 HTML 模板内容 `EnjoyFileViewProvider` 继承自 `ConfigurableTemplateLanguageFileViewProvider`,负责创建和管理这两棵树。`EnjoyEditorHighlighter` 通过 `LayeredLexerEditorHighlighter` 将 HTML 高亮叠加到 `HTML_TEXT` Token 上。 ### 词法分析器 手写的 4 状态状态机(非 JFlex 生成),位于 `lexer/EnjoyLexer.kt`: - **HTML 状态**:解析 HTML 模板内容 - **EXPR 状态**:解析 `#(...)` 表达式 - **BLOCK_COMMENT 状态**:解析 `#** #` 块注释 - 状态编码:将解析模式、括号深度和 `awaitingOuterLParen` 标志编码为单个整数 ### 解析器 手写的递归下降解析器(非 Grammar-Kit BNF),位于 `parser/EnjoyParser.kt`。使用 `parseFileContent(builder, stopTokens)` 模式,每个块指令(如 `#if`)传递其停止 Token 集合(`ELSE_IF`、`ELSE`、`END`)以正确解析嵌套结构。 ## 开发指南 ### 环境要求 - JDK 17+ - IntelliJ IDEA(推荐使用 2025.3+) - Gradle 9.5.0(已内置 Gradle Wrapper) ### 常用命令 ```bash # 构建项目 ./gradlew build # 在沙箱 IDE 中运行插件(用于调试) ./gradlew runIde # 运行所有测试 ./gradlew check # 运行单个测试类 ./gradlew test --tests "io.github.ysjsgzq.lexer.EnjoyLexerTest" # 运行单个测试方法 ./gradlew test --tests "io.github.ysjsgzq.lexer.EnjoyLexerTest.testMethodName" # 验证插件兼容性 ./gradlew verifyPlugin ``` ## 兼容性 - **IntelliJ IDEA** 2025.3+ - **其他 JetBrains IDE**:支持所有包含 `com.intellij.modules.xml` 模块的 IDE - **依赖插件**:`com.intellij.java`、`com.intellij.modules.xml` ## 相关链接 - [JFinal 官方网站](https://jfinal.com) - [JFinal Enjoy 模板引擎文档](https://jfinal.com/doc) - [IntelliJ Platform SDK](https://plugins.jetbrains.com/docs/intellij) - [JetBrains Marketplace](https://plugins.jetbrains.com) ## 致谢 本项目 **完全由 AI 编程工具完成**,无任何人工编写代码: - **[Codex](https://openai.com/codex)** 完成了约 60% 的开发工作 - **[Claude Code](https://claude.ai/claude-code)** + **[mimo-v2.5-pro](https://platform.xiaomimimo.com/)**、**[Claude Code](https://claude.ai/claude-code)** + **[GLM](https://open.bigmodel.cn/)** 完成了剩余 40% 的开发工作 感谢 **小米公司** 赠送的 Token Plan Pro 月卡套餐,为本项目提供了强大的 AI 编程支持。 小米模型平台:[https://platform.xiaomimimo.com/](https://platform.xiaomimimo.com/) ## 许可证 [Apache License 2.0](LICENSE)