- 后端
【免费下载链接】prql
PRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement
PRQL(Pipelined Relational Query Language)作为一种面向数据转换的现代查询语言,其语法高亮支持覆盖了从 GUI 编辑器到终端编辑器的庞大生态。本文以仓库根目录下的 grammars/README.md 为核心索引,系统梳理 PRQL 在各编辑器中的语法定义文件位置、安装方式与底层实现要点,并深入源码解释这些语法定义如何与 PRQL 词法分析器保持同步。读完本文,你将掌握在 CotEditor、GtkSourceView、KSyntaxHighlighting、Emacs、nano、CodeMirror(Lezer)、Raku 等环境中启用 PRQL 语法高亮的完整方法,并理解高亮规则的词法依据。
一、总体设计:一份语言,多套语法定义
PRQL 的语法定义并非集中存放在单一文件中,而是"分散在代码库各处"(如 grammars/README.md 所述),由根目录的grammars/目录统一索引。这种设计的目标很明确:让 PRQL 在任何主流编辑器中都获得与语言能力相匹配的高亮体验,而不是只服务某一两个编辑器。
从维护模式上,这些语法定义可分为两大类:
- 仓库内直接维护:语法文件就放在
grammars/各子目录中,随 PRQL 主仓库一起演进,包括 CotEditor、GtkSourceView、KSyntaxHighlighting、Emacs、nano、prql-lezer(CodeMirror)、Raku。 - 上游/外部维护:语法文件已合入对应编辑器或其插件生态的上游仓库,PRQL 侧只记录支持状态与位置,包括 Ace、chroma、Helix、Kakoune、micro、Sublime Text、TextMate(VS Code 扩展)、Monarch(Monaco/Playground)、Pygments、TEA、Tree-Sitter、vim/Neovim,以及 Handlebars 高亮脚本。
一个值得注意的细节是:语法定义之间并非各自为政。多份语法文件(如 CotEditor 的PRQL.yaml与 GtkSourceView 的prql.lang)都在注释中明确写着 "Keep in sync with the lexer'skeywordparser",指向 prqlc/prqlc-parser/src/lexer/mod.rs。也就是说,关键词集合的权威来源是编译器前端的词法分析器,编辑器语法文件只是它的"镜像"。这是理解后续所有规则清单的一把钥匙。
二、仓库内维护的语法定义详解
1. CotEditor(macOS 文本编辑器):grammars/CotEditor/PRQL.yaml
CotEditor 是 macOS 平台的原生文本编辑器,其语法样式文件采用 YAML 格式,核心文件为 grammars/CotEditor/PRQL.yaml,配套说明见 grammars/CotEditor/README.md。
安装步骤(摘自 README):
- 打开 CotEditor 的Preferences > Format(偏好设置 > 格式)。
- 在样式列表下方的齿轮图标菜单中选择Import…(导入)。
- 选择仓库中的
PRQL.yaml文件即可。
语法文件结构解析:该 YAML 以kind: code声明为代码类型,并通过extensions声明关联.prql扩展名。其高亮分类体系可以看作是"词汇表驱动"的,主要分组如下:
| YAML 字段 | 作用 | 内容要点 |
|---|---|---|
attributes | 装饰器高亮 | 正则@{\w+(=\w+)?},对应 PRQL 的@{...}属性语法 |
keywords | 语言关键字 | 转换算子aggregate、derive、filter、from、group、join、select、sort、take、window;语言级关键字case、let、module、prql、into、type、internal、func、import、enum |
commands | 函数/命令 | 聚合类abs、any、average、concat_array、count、every、min、max、stddev、sum;文件读取read_csv、read_json、read_parquet、from_text;列表类all、map、zip;文本类lower、upper;窗口类lead、lag、first、last、rank、rank_dense、row_number |
types | 数据类型 | bool、float、int、int8、int16、int32、int64、time、timestamp、text、date,以及内置对象math |
values | 特殊值 | true、false、null |
numbers | 数字字面量 | 十进制(含科学计数法与j/l后缀)、二进制\b0b[01][01_]*l?、八进制\b0o[0-7][0-7_]*l?、十六进制\b0x[0-9a-f][0-9a-f_]*l?,均忽略大小写 |
strings | 字符串 | 单/双引号、三引号("""、''')、带前缀的\b(r|f|s|)['"](对应 PRQL 的 r-字符串、f-字符串、s-字符串)、反引号 |
commentDelimiters | 注释 | 行注释定界符# |
可以看到,这份文件几乎把 PRQL 词法层的关键字、类型、字面量规则完整映射了一遍,是其"尽可能提供语法所支持的良好体验"理念的直接体现。
2. GtkSourceView(GNOME 生态):grammars/GtkSourceView/prql.lang
GtkSourceView 是 GNOME 平台广泛使用的语法高亮组件,被 GNOME Text Editor、GNOME Builder 等编辑器/IDE 采用,语法文件见 grammars/GtkSourceView/prql.lang,说明见 grammars/GtkSourceView/README.md。
安装方式(README 提供两条路径):
- 系统级安装:将语法文件复制到
/usr/share/gtksourceview-5/language-specs/ - 用户级安装:将语法文件复制到
~/.local/share/gtksourceview-5/language-specs/
注意:README 中文字描述为
prql.xml,但仓库内实际文件名为prql.lang。按 GtkSourceView 的惯例,语言文件需要以<language id>命名,因此安装时请以仓库中实际存在的 prql.lang 为准。
嵌入自有 GTK 应用:如果你在自己的 GTK 程序中基于GtkSourceView组件开发,需要把语言文件注册进LanguageManager,再将其设置到Buffer上(对应 GtkSourceView 5 的GtkSourceLanguageManager与GtkSourceBuffer.set_languageAPI)。
XML 结构要点:文件头部声明了language id="prql"、name="PRQL"、version="2.0",并定义了三种 MIME 类型(application/x.prql、application/prs.prql、application/vnd.prql)与*.prqlglob 匹配。高亮上下文(context)体系非常完整,值得注意的实现细节包括:
- 样式映射:所有样式都映射到 GtkSourceView 的默认样式主题(如
def:keyword、def:string、def:type、def:decimal、def:floating-point、def:base-n-integer、def:error等),从而自动适配浅色/深色主题。 - 字符串家族:覆盖双引号、单引号、三引号(
"""/'''),以及 PRQL 特有的前缀字符串——f"..."/f'...'(f-字符串,{}内嵌套 PRQL 表达式,见f-string-curly-braces上下文)、r"..."/r'...'(r-字符串)、s"..."/s'...'(s-字符串)。 - 转义字符:支持
\'"\b\f\n\r\t、Unicode 转义\u{hhhhhh}与十六进制转义\xhh。 - 安全防护:专门定义了
unicode-bdi上下文,匹配\u202A等双向文本控制字符并映射为def:error样式,防止"双向文本欺骗"(bidi spoofing)注入;同时用illegal-string上下文标记不带前缀的裸引号。 - 数字与时间维度:整数、浮点数(含指数)、二进制
0b、八进制0o、十六进制0x均有独立正则;dimension上下文则为数字附加时间单位关键字(microseconds到years)。 - 函数分组:聚合函数(
any、average、concat_array、count、every、max|min、stddev、sum)、文件读取(read_csv、read_json、read_parquet)、列表函数(all、map、zip、_eq、_is_null)、文本函数(contains、ends_with、extract、length、lower、ltrim、replace、rtrim、starts_with、trim、upper)、窗口函数(lag|lead、first|last、rank、rank_dense、row_number)、日期函数(now、to_text、diff、trunc)、数学函数(abs、acos、asin、atan、ceil、cos、degrees、exp、floor、ln、log、log10、pi、pow、radians、round、sin、sqrt、tan)。
这份文件在仓库中是对 PRQL 词法覆盖最详尽的一份,甚至包含了#!块注释支持(block-comment上下文)。
3. KSyntaxHighlighting(KDE 生态):grammars/KSyntaxHighlighting/prql.xml
KSyntaxHighlighting 是 KDE 的语法高亮框架,被 Kate、KWrite、KDevelop 等 Qt 编辑器/IDE 使用,语法文件为 grammars/KSyntaxHighlighting/prql.xml,安装说明见 grammars/KSyntaxHighlighting/README.md。
各平台安装路径(README 提供的完整表格):
| 系统/场景 | 路径 |
|---|---|
| 本地用户(Linux) | $HOME/.local/share/org.kde.syntax-highlighting/syntax/ |
| Flatpak 打包应用 | $HOME/.var/app/PACKAGE_NAME/data/org.kde.syntax-highlighting/syntax/ |
| Snap 打包应用 | $HOME/snap/PACKAGE_NAME/current/.local/share/org.kde.syntax-highlighting/syntax/ |
| Windows | %USERPROFILE%\AppData\Local\org.kde.syntax-highlighting\syntax\ |
| macOS | $HOME/Library/Application Support/org.kde.syntax-highlighting/syntax/ |
其中 Flatpak 与 Snap 场景下的PACKAGE_NAME形如org.kde.kate、org.kde.kwrite或org.kde.kdevelop,即对应应用包名。安装时把prql.xml复制到上述目录后重启编辑器即可生效。
4. GNU Emacs:grammars/emacs/prql-mode.el
Emacs 的 PRQL 高亮以 major mode 形式提供,文件为 grammars/emacs/prql-mode.el,说明见 grammars/emacs/README.md。
安装步骤(摘自 README):
- 将
prql-mode.el复制到~/.emacs.d/custom-modes/目录。 - 在
~/.emacs.d/init.el中添加如下配置:
(add-to-list 'load-path "~/.emacs.d/custom-modes/") (require 'prql-mode) (add-to-list 'auto-mode-alist '("\\.prql\\'" . prql-mode))这样打开.prql文件时 Emacs 会自动切换到prql-mode并启用高亮。若使用如use-package等配置框架,也可将上述逻辑包在对应的配置块中。
5. GNU nano:grammars/nano/prql.nanorc
nano 的语法文件为 grammars/nano/prql.nanorc,说明见 grammars/nano/README.md。
安装方式:将prql.nanorc放到~/.nano/目录,然后在.nanorc中 include 该文件:
include "~/.nano/prql.nanorc"README 还给出了快捷命令:
echo 'include "~/.nano/prql.nanorc"' >> ~/.nanorc规则要点(来自 nanorc 文件本身):文件首行以syntax prql "\.prql$"声明匹配规则,并设置magic "PRQL script"与行注释comment "#"。配色方案包括:
- 类型(绿色):
int(8|16|32|64|128)?、float(32|64)?、bool、text、date、time、timestamp - 关键字(黄色):
let、into、case、prql、type、module、internal、func、import、enum - 转换算子(亮青色):
aggregate、derive、filter、from、group、join、select、sort、take、window - 特殊值(亮品红):
false、null、true、this、that - 装饰器(青色):
@{到} - 字符串:单/双引号与
f/r/s前缀字符串、三引号字符串 - 转义(青柠色):反斜杠转义与
\u{...}/\N{...}Unicode 转义 - 注释(灰色)与TODO/FIXME 提醒(亮白+黄),以及行尾空白高亮
nano 这份文件还提供了 PRQL 的两种官方注释形式支持:#行注释。
6. prql-lezer(CodeMirror / Lezer):grammars/prql-lezer/
Lezer 是 CodeMirror 6 的解析系统。PRQL 的 Lezer 语法位于 grammars/prql-lezer/,核心文件是 grammars/prql-lezer/src/prql.grammar(一个 Lezer 文法定义文件)与 grammars/prql-lezer/src/highlight.js,说明见 grammars/prql-lezer/README.md。
项目状态:README 说明该文法"大体上已功能完整"(largely fully-functioning),grammar 文件中仍留有少量 TODO;目前仓库内还没有配套的 JS 发布机制,尚未发布到任何包管理器,后续可能独立成库。
使用与开发:
- 安装依赖:
npm install - 构建:
npm run build - 测试:
npm run test
测试覆盖:test/目录下的测试按 PRQL 语法主题拆分,包括arithmetics.txt、arrays.txt、datetime.txt、full_queries.txt、identifiers.txt、misc.txt、numbers.txt、operators.txt、strings.txt、tuples.txt,配合 test-prql.js 与 test-highlight.js 分别验证解析树与高亮标记。
为什么重要:CodeMirror 语法是若干下游工具的前置依赖,README 明确指出 Jupyter 的 PRQL 语法高亮就依赖它(对应 PRQL 生态中的 Jupyter 集成需求)。交互式开发时,README 建议使用 Lezer Playground:粘贴示例查询 → 粘贴当前 grammar → 修复问题 → 把 grammar 复制回仓库,形成快速迭代闭环。
7. Raku:grammars/raku/
Raku 语言本身以 grammar 机制著称,PRQL 为其提供了一份真正的 Raku Grammar 实现,核心文件为 grammars/raku/lib/prql.rakumod,说明见 grammars/raku/README.md。
基本用法(摘自 README):
use lib '.'; use prql; say PRQL.parse('from employees'); say PRQL.parsefile('employees.prql');安装:从源码安装运行zef install .。
测试体系:测试位于 grammars/raku/t/,按语法主题拆分(arithmetics、arrays、datetime、full_queries、identifiers、misc、numbers、operators、strings、tuples),可单独运行:
raku t/arithmetics.rakutest全量运行需先通过zef安装App::Prove6,然后执行:
zef install App::Prove6 prove6 --lib t/测试的独特之处:Raku 测试不仅断言"查询能被解析",还断言语法树的结构形状。例如:
parses-to 'filter 10 * 10', 'statement(pipeline-statement(pipeline(call-expression(identifier«filter»,test(test-inner(binary-test(expression(number(integer«10»)),arith-op«*»,expression(number(integer«10»)))))))))';这里的parses-to来自 grammars/raku/t/lib/PRQLTest.rakumod:它把Match对象渲染成rule(child,child)形式的字符串,叶子捕获的文本放在«…»中;失败时会按缩进逐行打印两侧形状以便对比。编写断言前,可先用shape函数查看任意查询的树形:
raku -I lib -I t/lib -e 'use PRQLTest; use prql; say shape(PRQL.parse("filter 1 + 1"))'三、上游维护与其他位置的语法定义
除grammars/目录外,PRQL 的高亮生态还延伸到了多个上游项目与仓库内的其他位置(均为 grammars/README.md 记录的支持状态):
| 编辑器/框架 | 支持方式 | 语法所在位置 |
|---|---|---|
| Ace | 支持,语法已合入上游 | Ace 仓库中的prql_highlight_rules.js,另有官方 demo 可在线体验 |
| chroma(Go) | 支持,语法已合入上游 | chroma 仓库lexers/embedded/prql.xml,被 Hugo 静态站点生成器使用,可在 chroma playground 试玩 |
| Handlebars | 仓库内维护(两份,当前有重复) | 书(book)用 web/book/highlight-prql.js;网站(book 与 playground 之外)用 web/website/themes/prql-theme/static/plugins/highlight/prql.js |
| Helix | 支持,语法已合入上游 | Helix 仓库runtime/queries/prql |
| Kakoune | 支持,语法已合入上游 | Kakoune 仓库rc/filetype/prql.kak |
| micro | 支持,语法已合入上游 | micro 仓库runtime/syntax/prql.yaml |
| Sublime Text | 独立仓库维护 | 位于sublime-prql仓库 |
| TextMate(VS Code 扩展) | 独立仓库维护 | prql-vscode仓库的syntaxes/prql.tmLanguage.json |
| Monarch(Monaco) | 仓库内维护 | web/playground/src/workbench/prql-syntax.js,供 PRQL Playground 的 Monaco 编辑器使用 |
| Pygments | 支持,语法已合入上游 | Pygments 仓库pygments/lexers/prql.py,被 Wikipedia、Bitbucket、Sphinx 等使用,可在 Pygments 官方 demo 验证 |
| TEA | 支持,语法已合入上游 | TEA 仓库hls/prql.xml |
| Tree-Sitter | 独立仓库维护 | 位于tree-sitter-prql仓库,供 Neovim 与 Helix 使用 |
| vim | 支持,语法已合入上游 | vim 仓库runtime/syntax/prql.vim;Neovim 同样支持,语法同样在上游 |
其中 Monarch 语法值得特别留意:它直接服务于仓库内的 Playground(web/playground/),如果你希望在浏览器端体验 PRQL 并研究其高亮 token 划分,web/playground/src/workbench/prql-syntax.js 是最直接的参考实现。
四、共同的词法基石:语法文件如何与 lexer 保持同步
如果同时打开上述多份语法文件,会发现关键词清单高度一致。这不是巧合——多份文件都带有指向 prqlc/prqlc-parser/src/lexer/mod.rs 的注释(如 CotEditor 的PRQL.yaml与 GtkSourceView 的prql.lang均写着 "Keep in sync with the lexer'skeywordparser")。这意味着:
- 权威来源是编译器前端的词法分析器(
prqlc-parsercrate 的 lexer 模块),PRQL 关键字集合以 lexer 的实现为准; - 编辑器语法文件是它的下游镜像,新增关键字时,各语法文件需要同步更新。
综合各语法文件,可以归纳出 PRQL 高亮背后的统一词法约定:
- 语言关键字:
let、into、case、prql、type、module、internal、func、import、enum - 转换算子(transforms):
aggregate、derive、filter、from、group、join、select、sort、take、window - 数据类型:
bool、float、int及int8/int16/int32/int64、text、date、time、timestamp - 特殊值:
true、false、null - 字符串前缀:
f(f-字符串,可内嵌{}表达式)、r(r-字符串,原生文本)、s(s-字符串,直接生成 SQL);三引号用于多行字符串 - 数字字面量:十进制(支持科学计数法)、二进制
0b、八进制0o、十六进制0x,并支持下划线分隔与后缀 - 注释:
#行注释(GtkSourceView 版本还支持#!块注释) - 装饰器:
@{...}语法(CotEditor 与 nano 均有对应高亮)
如果你准备为某个尚未覆盖的编辑器编写 PRQL 语法文件,最稳妥的做法就是:以上述清单为关键词基准,参考 GtkSourceView 的 prql.lang(覆盖最全)作为规则模板,再对照 lexer 源码确认细节。
五、选择与部署建议
按使用场景选择:
- 终端重度用户:nano(
~/.nano/prql.nanorc)、vim/Neovim(上游已内置)、Helix(上游已内置)、Kakoune(上游已内置)、micro(上游已内置)、Emacs(prql-mode.el)均可用。 - GUI 编辑器用户:macOS 选 CotEditor(PRQL.yaml);GNOME 系选 GtkSourceView(prql.lang);KDE 系选 KSyntaxHighlighting(prql.xml);VS Code 用户使用官方扩展(TextMate 语法在扩展仓库内)。
- 浏览器/文档场景:Playground 使用 Monarch 语法(prql-syntax.js);book 与网站使用 Handlebars 高亮脚本;Hugo 站点可用 chroma。
- 程序化高亮:Python 用 Pygments,Go 用 chroma,Raku 项目可直接引用 prql.rakumod。
部署后的验证建议:安装完成后,打开一个包含转换算子(如from、select、filter)、关键字(如let)、不同类型字面量(十进制、0x十六进制、0b二进制)以及 f-字符串的.prql示例文件,观察各 token 是否按预期着色;若某些类别未区分,优先检查语法文件版本与 prqlc/prqlc-parser/src/lexer/mod.rs 中的关键字集合是否一致。
六、总结
PRQL 的语法高亮生态遵循"以 lexer 为词法权威、以多格式语法文件为镜像"的清晰架构:grammars/README.md 作为索引,grammars/目录维护了 CotEditor、GtkSourceView、KSyntaxHighlighting、Emacs、nano、Lezer/CodeMirror、Raku 七套可直接使用的定义;Ace、chroma、Helix、Kakoune、micro、Pygments、vim/Neovim、TEA 等则通过上游合入获得支持;Handlebars、Monarch 等服务于 PRQL 官方文档站与 Playground。任何高亮体验的不足,都可以按 grammars/README.md 的说明通过 GitHub issue 反馈给 PRQL 项目,从而让这一"尽可能提供语法所支持的良好体验"的目标持续演进。
- 后端
【免费下载链接】prql
PRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement
相关推荐
PRQL 语法高亮生态解析:从编辑器语法定义到词法分析器的一致性维护
PRQL 语法高亮生态解析:从编辑器语法定义到词法分析器的一致性维护 PRQL(Pipelined Relational Query Language)是一个用
后端PRQL 语言在 GtkSourceView 中的语法高亮:prql.lang 定义文件安装、嵌入与实现解析
PRQL 语言在 GtkSourceView 中的语法高亮:prql.lang 定义文件安装、嵌入与实现解析 PRQL(Pipelined Relational
后端PRQL 语法高亮在 GNU nano 中的安装与配置指南
PRQL 语法高亮在 GNU nano 中的安装与配置指南 本篇技术指南围绕 PRQL 仓库中 grammars/nano/ https://link.gitc
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考