- 后端
【免费下载链接】prql
PRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement
PRQL(Pipelined Relational Query Language)是一种面向数据转换的现代语言,致力于以简单、强大的管道式语法替代 SQL。要在 GNU Emacs 中舒适地编写.prql查询文件,官方仓库提供了基于 Font Lock 机制实现的prql-mode主模式。本指南以仓库 grammars/emacs/README.md 与 prql-mode.el 为核心,完整介绍该模式的安装步骤、语法高亮分类规则、数字与字符串词法,以及它与 prqlc 官方词法分析器之间的对应关系,帮助你快速搭建起可用的 PRQL 编辑环境。
一、安装 prql-mode:从复制文件到激活主模式
官方文档给出的安装流程非常简洁,共分两步:先把模式文件放到 Emacs 的 load-path 中,再在init.el里注册文件扩展名与主模式的关联。
1. 放置 prql-mode.el
将仓库中的 grammars/emacs/prql-mode.el 复制到 Emacs 的自定义模式目录:
~/.emacs.d/custom-modes/如果该目录尚不存在,可先创建。文件复制到位后,Emacs 才能通过require加载它。
2. 配置 init.el 并注册自动模式
编辑~/.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))add-to-list 'load-path将自定义模式目录加入加载路径,使require能检索到prql-mode.el;require 'prql-mode加载该文件并执行其中的define-derived-mode与provide声明;add-to-list 'auto-mode-alist将.prql扩展名映射到prql-mode主模式。注意这里的正则写法"\\.prql\\'"中\\'是 Emacs 正则中的"字符串结尾"锚点,表示只匹配以.prql结尾的文件名。
保存并重启 Emacs(或执行M-x eval-buffer重新加载init.el)后,打开任意.prql文件即可看到语法高亮自动生效;也可在已打开的文件中通过M-x prql-mode手动切换。
二、prql-mode 的实现解剖:一个基于 Font Lock 的主模式
prql-mode.el 只有约 74 行,却完整覆盖了主模式所需的全部要素:语法表、高亮关键词列表、字体锁定(font-lock)规则和派生模式定义。下面按源码顺序逐层拆解。
1. 语法表:定义注释语法
(defvar prql-mode-syntax-table (let ((table (make-syntax-table))) ;; Define comment syntax (modify-syntax-entry ?# "<" table) (modify-syntax-entry ?\n ">" table) table) "Syntax table for `prql-mode'.")对应 prql-mode.el:#被定义为注释起始符(<),换行符被定义为注释结束符(>),这与 PRQL 的#单行注释语法完全一致——官方词法分析器 lexer/mod.rs 中同样将#识别为注释。因此#之后到行尾的内容会以注释样式显示。
2. 六类高亮关键词列表
prql-mode 通过defconst定义了六组被高亮的词法单元,这是整个模式的"词表核心":
| 变量 | 内容 | 对应 face | 源码位置 |
|---|---|---|---|
prql-constants | truefalsethisthatnull | font-lock-constant-face | prql-mode.el#L21-L23 |
prql-data-types | boolfloatintint8int16int32int64textdatetimetimestamp | font-lock-type-face | prql-mode.el#L25-L27 |
prql-builtin-functions | aggregatederivefilterfromgroupjoinselectsorttakewindow | font-lock-builtin-face | prql-mode.el#L29-L31 |
prql-operators | !=&&\|\|+-*/%<>~= | font-lock-builtin-face | prql-mode.el#L33-L37 |
prql-numbers | 0o[0-7]+0x[0-9a-fA-F]+0b[01]+[0-9]+ | font-lock-constant-face | prql-mode.el#L39-L44 |
prql-other-keywords | letintocaseprqltypemoduleinternalfuncimportenum | font-lock-keyword-face | prql-mode.el#L46-L48 |
其中几个细节值得注意:
this/that被列入常量:这是 PRQL 中引用当前行(this)与目标行(that)的特殊标识符;- 内建函数列表恰好对应 PRQL 的十大转换(transform):
from、select、filter、derive、aggregate、sort、take、join、group、window; - 数字正则覆盖了八进制、十六进制、二进制和普通十进制四类字面量,与词法分析器测试 lexer/test.rs 中验证的
0b1111000011110000、0xff、0o777等用例相互印证。
3. 组装 font-lock 关键词规则
(defvar prql-font-lock-keywords `( ,(cons (regexp-opt prql-constants 'words) 'font-lock-constant-face) ,(cons (regexp-opt prql-other-keywords 'words) 'font-lock-keyword-face) ,(cons (regexp-opt prql-builtin-functions 'words) 'font-lock-builtin-face) ,(cons (regexp-opt prql-data-types 'words) 'font-lock-type-face) ,@(mapcar (lambda (kw) (cons kw 'font-lock-builtin-face)) prql-operators) ,@(mapcar (lambda (kw) (cons kw 'font-lock-constant-face)) prql-numbers)))对应 prql-mode.el#L50-L58。实现要点:
- 对单词类列表调用
regexp-opt自动生成高效的交替正则,并启用'words选项保证按"整词"匹配,避免from误伤from_text之类的子串(Emacs 的regexp-opt默认会按最长词优先排序匹配,配合词边界语义达到精确匹配); - 运算符与数字正则直接以字符串形式逐条加入规则列表,不经过
regexp-opt; - 数字正则
0o[0-7]+等未加词边界断言,在实际使用中可能出现前缀匹配的边角情况,这是该模式已知的简化处理。
4. 派生主模式与缩进设置
(define-derived-mode prql-mode prog-mode "PRQL" "Major mode for editing PRQL code." (set-syntax-table prql-mode-syntax-table) (setq font-lock-defaults '((prql-font-lock-keywords))) (setq indent-tabs-mode nil) (setq tab-width 2))对应 prql-mode.el#L60-L68:
- 从
prog-mode派生,天然继承编程语言的通用行为(如注释高亮基础设施、语法表层次结构); font-lock-defaults指向上面组装好的关键词规则,(setq font-lock-defaults '((prql-font-lock-keywords)))这种"以列表包裹列表"的写法是 Font Lock 的标准传参方式;indent-tabs-mode设为nil表示缩进使用空格而非制表符,tab-width设为 2,即 PRQL 惯用的 2 空格缩进风格(与官方格式化的默认缩进一致);- 文件末尾的
(provide 'prql-mode)使require能够正确完成加载。
三、与官方词法分析器的对应关系:语法高亮为何与编译器一致
PRQL 仓库刻意保持了各编辑器语法定义与 prqlc 词法分析器的同步。在 prqlc/prqlc-parser/src/lexer/mod.rs 中,词法分析器将以下 10 个词保留为TokenKind::Keyword:
pub const KEYWORDS: [&str; 10] = [ "let", "into", "case", "prql", "type", "module", "internal", "func", "import", "enum", ];并保留字面量:
pub const RESERVED_LITERALS: [&str; 3] = ["true", "false", "null"];对照可见,prql-mode.el中的prql-other-keywords与KEYWORDS逐项完全一致,prql-constants中的true/false/null也与RESERVED_LITERALS吻合(this/that则是高亮模式额外覆盖的语义标识符)。这意味着:凡是关键字,都会同时被编译器保留和编辑器高亮——不会出现"语法高亮为关键词、但编译器当作普通标识符"的误导。源码注释也明确指出,grammars/目录下的各语法文件需要手工跟随这份词表(参见 lexer/mod.rs 的文档注释)。
仓库 grammars/README.md 的索引进一步说明,PRQL 为十余种编辑器/工具维护了语法定义(CotEditor、GtkSourceView、KSyntaxHighlighting、nano、Raku、Lezer 等),其中 emacs 模式由 grammars/emacs/ 目录承载;而 GtkSourceView 的 prql.lang 中同样以"Keep in sync with the lexer'skeywordparser in prqlc/prqlc-parser/src/lexer/mod.rs"的注释标注了这份同步关系,CotEditor 的 PRQL.yaml 也引用了同一处词法分析器。这从侧面印证了 emacs 模式词表设计的可靠性。
四、进阶配置与常见问题
1. 调整缩进与配色
prql-mode默认使用 2 空格缩进、不使用制表符。若你偏好其他风格,可在加载模式后通过setq-local覆盖:
(add-hook 'prql-mode-hook (lambda () (setq-local tab-width 4) (setq-local indent-tabs-mode t)))注意indent-tabs-mode为t时缩进将改用制表符,但 PRQL 编译器对空白并不敏感(换行才是语句边界),因此该调整不会影响编译。
2. 缩进能力的边界
prql-mode从prog-mode派生但未定义indent-line-function,这意味着目前它只提供语法高亮,不提供智能缩进——按 Tab 仍使用 Emacs 默认行为。如需更完整的编辑体验,可自行通过add-hook接入其他缩进方案,或以 grammars/prql-lezer/ 等更完整的解析器语法作为参考。
3. 关键词与扩展名覆盖范围
- 模式只对以
.prql结尾的文件自动启用;auto-mode-alist也可额外添加,例如同时覆盖大写扩展名或特定目录下的 PRQL 文件; - 若打开文件时未出现高亮,请依次检查:
prql-mode.el是否在 load-path 目录中、init.el中require是否位于add-to-list 'auto-mode-alist之前、以及缓冲区是否已切换到该主模式(C-h m可查看当前模式信息)。
五、小结
grammars/emacs/README.md 虽只有一份简洁的安装说明,但配合 prql-mode.el 的完整实现,你可以得到一套开箱即用的 PRQL 高亮方案:#注释、十大数据类型、十大转换函数、运算符、四类数字字面量以及全部保留关键字均按语义分类着色,且词表与 prqlc 词法分析器保持严格同步。对于以 Emacs 为主要编辑环境的 PRQL 用户而言,这份不到百行的模式文件是目前最轻量的官方高亮实现,安装即用,无需额外依赖。
- 后端
【免费下载链接】prql
PRQL is a modern language for transforming data — a simple, powerful, pipelined SQL replacement
相关推荐
CotEditor 中配置 PRQL 语法高亮:PRQL.yaml 语法样式文件完全指南
CotEditor 中配置 PRQL 语法高亮:PRQL.yaml 语法样式文件完全指南 PRQL(Pipelined Relational Query Lan
后端PRQL S-string 完全指南:在 PRQL 中安全内嵌 SQL 的插值语法
PRQL S string 完全指南:在 PRQL 中安全内嵌 SQL 的插值语法 S string(s string)是 PRQL 提供的 SQL 逃生舱机制
后端Lattigo加密安全指南:理解IND-CPA与CPA-D安全机制的3个关键要点
Lattigo加密安全指南:理解IND CPA与CPA D安全机制的3个关键要点 Lattigo是一个基于格的多方同态加密Go语言库,为开发者提供了强大的加密工
密码学
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考