if_mzsch

if_mzsch.txt 适用于 Vim 9.2 版本。 最近更新: 2025年10月 VIM 参考手册 by Bram Moolenaar 译者: Willis Vim 的 MzScheme 接口 mzscheme MzScheme 1. 命令 mzscheme-commands 2. 示例 mzscheme-examples 3. 线程 mzscheme-threads 4. 从 MzScheme 访问 Vim mzscheme-vim 5. mzeval() Vim 函数 mzscheme-mzeval 6. 使用函数引用 mzscheme-funcref 7. 动态调入 mzscheme-dynamic 8. MzScheme 设置 mzscheme-setup {仅当 Vim 编译时加入 +mzscheme 特性才有效} 此接口主要基于 Brent Fulgham 的贡献。 动态调入部分则由 Sergey Khorev 加入。 MzScheme 和 PLT Scheme 已经被重新命名为 Racket。详情可查阅 http://racket-lang.org。 在 Racket 5.x 系列中,直至 5.3.1 (含) 为止,futures 和 places 机制无法和 Vim 创建的进程协同工作。为此,最简单的解决方法是自行编译 Racket,关闭以下特性: ./configure --disable-futures --disable-places --prefix=your-install-prefix 要加快进程的速度,也可考虑使用 --disable-gracket 和 --disable-docs。

1. 命令 mzscheme-commands

:mzscheme :mz :[range]mz[scheme] {stmt} 执行 MzScheme 语句 {stmt}。 :[range]mz[scheme] << [trim] [{endmarker}] {script} {endmarker} 执行内联的 MzScheme 脚本 {script}注意: 如果编译时没有加入 MzScheme 特性,此命令不能工 作。要避免错误,见 script-here 。 如果 "<<" 之后省略了 [endmarker]{script} 结束后必须 加上一个句号 '.',类似于 :append:insert 命令。 详见 :let-heredoc :mzfile :mzf :[range]mzf[ile] {file} 执行 {file} 文件里的 MzScheme 脚本。 以上命令本质上在做同样一件事 - 执行一段 MzScheme 代码。并将 "当前范围" 设为给 定的行范围。 :mzscheme 执行的代码来自命令行。 :mzfile 执行的代码来自给定文件的内容。 MzScheme 接口定义从 exn 派生的 exn:vim 异常。若干 Vim 错误会抛出此异常。 编译时,MzScheme 接口会记住当前 MzScheme collection 路径。要指定额外路径,可用 "current-library-collection-paths" 参数,例如,要附加 (cons) 用户局部 MzScheme collection 路径: :mz << EOF (current-library-collection-paths (cons (build-path (find-system-path 'addon-dir) (version) "collects") (current-library-collection-paths))) EOF 所有功能由 vimext 模块提供。 无需显式导入 (import) exn:vim。 为了避免和 MzScheme 冲突,require 模块时请考虑使用 prefix。例如: :mzscheme (require (prefix vim- vimext)) 以下例子都使用此命名方案。 mzscheme-sandbox 在沙盘 sandbox 里执行时,对一些文件系统和 Vim 接口过程的访问会受到限制。

2. 示例 mzscheme-examples

:mzscheme (display "Hello") :mz (display (string-append "使用 MzScheme 版本 " (version))) :mzscheme (require (prefix vim- vimext)) ; 用于 MzScheme < 4.x :mzscheme (require (prefix-in vim- 'vimext)) ; MzScheme 4.x :mzscheme (vim-set-buff-line 10 "这是第 #10 行") 要查看正在运行的 MzScheme 版本: :mzscheme (display (version)) 内联脚本示例: function! <SID>SetFirstLine() :mz << EOF (display "!!!") (require (prefix vim- vimext)) ; 更新的版本需用 (require (prefix-in vim- 'vimext)) (vim-set-buff-line 1 "这是第 #1 行") (vim-beep) EOF endfunction nmap <F9> :call <SID>SetFirstLine() <CR> 文件执行: :mzfile supascript.scm Vim 异常处理: :mz << EOF (require (prefix vim- vimext)) ; 更新的版本需用 (require (prefix-in vim- 'vimext)) (with-handlers ([exn:vim? (lambda (e) (display (exn-message e)))]) (vim-eval "无意义字符串")) EOF 自动实例化 vimext 模块 (可放入 vimrc ): function! MzRequire() :redir => l:mzversion :mz (version) :redir END if strpart(l:mzversion, 1, 1) < "4" " MzScheme 版本号 < 4.x: :mz (require (prefix vim- vimext)) else " 更新的版本: :mz (require (prefix-in vim- 'vimext)) endif endfunction if has("mzscheme") silent call MzRequire() endif

3. 线程 mzscheme-threads

MzScheme 接口提供线程支持。它们和操作系统的线程相互独立,因此有必要进行调度。 'mzquantum' 选项决定 Vim 轮询可用 MzScheme 线程的时间间隔。 备注 Vim 控制台版本在进行线程调度时,通常不如 GUI 版本可靠。

4. 从 MzScheme 访问 Vim mzscheme-vim

mzscheme-vimext 'vimext' 模块提供 MzScheme 接口中定义的过程的访问。 通用

(command {command-string}) 执行 Vim ":Ex" 风格的命令。 (eval {expr-string}) 计算 vim 表达式,并将结果返回为对应的 MzScheme 对象: Vim 的 List 对应 Scheme 列表, Dictionary 对应哈希表, Funcref 对应函数 (另见 mzscheme-funcref ) 注意 这和 MzScheme 自带的 eval 有冲突,可 以使用模块限定符来避免。 (range-start) 传递给 Scheme 命令的范围的开始行 (range-end) 和结束行。 (beep) 响铃 (get-option {option-name} [buffer-or-window]) 获取 Vim 选项值 (局部或全局值,见 set-option )。 (set-option {string} [buffer-or-window]) 设置 Vim 选项。字符串 {string} 必须为用于 设置 Vim 选项的命令形式 (optname=optval 或 optname+=optval 等)。给出 {buffer}{window} 时,会设置相应的局部选项。在 {buffer-or-window} 的位置也可用符号 'global,此时会用 :setglobal 来设置全局 选项。 缓冲区 mzscheme-buffer

(buff? {object}) 对象是否为缓冲区? (buff-valid? {object}) 对象是否为合法的缓冲区 (也就是,对应真正 Vim 缓冲区)? (get-buff-line {linenr} [buffer]) 获取缓冲区中的指定行。 (set-buff-line {linenr} {string} [buffer]) 设置缓冲区中的指定行。{string} 为 #f 或 null 时,删除该行。 [buffer] 参数可选。省 略时默认使用当前缓冲区。 (get-buff-line-list {start} {end} [buffer]) 获取缓冲区中的多行列表。{start}{end} 从 1 开始计数,且为闭区间 (两者都包含)。 (set-buff-line-list {start} {end} {string-list} [buffer]) 设置缓冲区的多行内容列表。{string-list} 为 #f 或 null 时,删除所选范围中的所有行。如 果列表长度小于 {end}-{start},不足部分对应 的行被删除。 (get-buff-name [buffer]) 获取缓冲区名。 (get-buff-num [buffer]) 获取缓冲区的编号。 (get-buff-size [buffer]) 获取缓冲区的总行数。 (insert-buff-line-list {linenr} {string/string-list} [buffer]) 在缓冲区第 {linenr} 行之后插入多行内容列 表。{linenr} 为 0 时,从缓冲区开头插入。 (curr-buff) 获取当前缓冲区。可用 MzScheme 接口的其他过 程来修改该缓冲区。 (buff-count) 获取编辑器中缓冲区的总数。 (get-next-buff [buffer]) 获取下一个缓冲区。 (get-prev-buff [buffer]) 获取前一个缓冲区。如果没有更多缓冲区,返回 #f。 (open-buff {filename}) 打开新缓冲区 (并编辑指定文件名)。 (get-buff-by-name {buffername}) 根据文件名获取缓冲区,如果没有相应的缓冲 区,返回 #f。 (get-buff-by-num {buffernum}) 根据缓冲区号获取缓冲区,如果没有相应的缓冲 区,返回 #f。 窗口 mzscheme-window

(win? {object}) 对象是否为窗口? (win-valid? {object}) 对象是否为合法的窗口 (也就是,对应真正 Vim 窗口)? (curr-win) 获取当前窗口。 (win-count) 获取窗口总数。 (get-win-num [window]) 获取窗口的编号。 (get-win-by-num {windownum}) 根据窗口号获取窗口。 (get-win-buffer [window]) 获取窗口中包含的缓冲区。 (get-win-height [window]) 获取窗口高度。 (set-win-height {height} [window]) 设置窗口高度。 (get-win-width [window]) 获取窗口宽度。 (set-win-width {width} [window]) 设置窗口宽度。 (get-win-list [buffer]) 获取包含缓冲区的所有窗口的列表。 (get-cursor [window]) 获取窗口光标位置,以组对 (行号 . 列号) 形 式出现。 (set-cursor (line . col) [window]) 设置光标位置。

5. mzeval() Vim 函数 mzscheme-mzeval

Vim 中的 mzeval() 函数提供了反向接口,它用于计算 MzScheme 表达式,并将计算结 果返回给 Vim 脚本。

6. 使用函数引用 mzscheme-funcref

MzScheme 接口允许在 Schema 里使用 Funcref 直接调用 Vim 函数。例如: function! MyAdd2(arg) return a:arg + 2 endfunction mz (define f2 (vim-eval "function(\"MyAdd2\")")) mz (f2 7) 或 : :mz (define indent (vim-eval "function('indent')")) " 返回 Vim 第 12 行的缩进量 :mz (indent 12)

7. 动态调入 mzscheme-dynamic E815

MS-Windows 上,可动态调入 MzScheme 库。此时 :version 输出会包含 +mzscheme/dyn 。 此时,Vim 仅在必要时才会寻找 MzScheme DLL 文件。不使用 MzScheme 接口时,就不需 要库文件。因此,即使没有这些 DLL 文件,仍然可以使用 Vim。 注意 较新版本的 MzScheme (Racket) 要求在较早的时间点通过 scheme_main_setup 进 行 (蹦床式的) 初始化。此时,Vim 在启动时总会载入 MzScheme DLL (只要可能)。但这 会减慢 Vim 启动速度。 要使用 MzScheme 接口,必须确保 MzScheme DLL 位于系统搜索路径中。可以在控制台窗 口里输入 "path",查看当前使用的搜索路径。 MS-Windows 上,可用 'mzschemadll''mzschemagcdll' 选项指定载入库名。选项初 始值在编译时提供。 DLL 的版本号必须匹配 Vim 编译时所使用的 MzScheme 版本。以 MzScheme 209 版本为 例,上述两选项的名字分别为 "libmzsch209_000.dll" 和 "libmzgc209_000.dll"。要查 看编译时使用的版本,可察看 ":version" 命令的输出中 "编译方式" 信息里的 -DDYNAMIC_MZSCH_DLL= "..." 和 -DDYNAMIC_MZGC_DLL="..." 部分的内容。 例如,假定 MzScheme (Racket) 安装在 C:\Racket63,可能需要设置以下的环境变量: PATH=%PATH%;C:\Racket63\lib PLTCOLLECTS=C:\Racket63\collects PLTCONFIGDIR=C:\Racket63\etc

8. MzScheme 设置 mzscheme-setup E895

Vim 的 if_mzsch 核心部分需要 "racket/base" 模块 (如果不存在,"scheme/base" 作 为后备),测试需要 "r5rs" 模块,Vim 编译时则需要 "raco ctool" 命令。如果 MzScheme 没有提供这些模块,可以通过 MzScheme 的 raco 命令安装: raco pkg install scheme-lib # scheme/base 模块 raco pkg install r5rs-lib # r5rs 模块 raco pkg install cext-lib # raco ctool 命令

vim:tw=78:ts=8:noet:sts=4:ft=help:norl: