usr_46

usr_46.txt 适用于 Vim 8.2 版本。 最近更新: 2020年7月 VIM 用户手册 - by Bram Moolenaar 译者: Willis 编写使用 Vim9 脚本的插件 Vim9 脚本语言可用于编写插件,尤其是使用多个文件的大型插件。本章解释如何把插件 分割为模块、导入和导出项目,并保持其余部分在局部。 46.1 介绍 46.2 变量声明 46.3 函数和类型 46.? 在老式脚本中使用 Vim9 脚本 下一章: usr_90.txt 安装 Vim 前一章: usr_45.txt 选择你的语言 (locale) 目录: usr_toc.txt

46.1 介绍 vim9-script-intro

Vim9 脚本设计使大型 Vim 脚本的编写更为容易。它看来更像其它脚本语言,尤其是 Typescript。另外,函数被编译为指令以快速执行。这使 Vim9 脚本快很多,多达百倍。 这里的基本想法是脚本文件包含只用于脚本文件内部的私有项目,和可被脚本文件之外使 用的导出项目。然后,这些导出项目可用于导入它们的脚本里。这样什么在哪里定义就会 很清晰。 让我们从一个例子开始,有一个导出函数和有一个私有函数的脚本: vim9script " 指示这是 Vim9 脚本文件。 export def GetMessage(): string let result = '' ... result = GetPart(count) ... return result enddef def GetPart(nr: number): string if nr == 4 return 'yes' else return 'no' endif enddef vim9script 命令必须是文件最开头的命令。不然,Vim 会假定老式脚本语法。 `export def GetMessage(): string` 行以 export 开始,意味着此函数可以被其它脚 本导入和调用。行 `def GetPart(...` 不以 export 开头,这是局部于脚本的函数, 只能在此脚本文件中使用。 在 `export def GetMessage(): string` 行,注意到冒号和返回类型。 def 定义的 Vim9 函数必须指定参数类型和返回类型。这样 Vim 才能有效地编译代码。GetPart 函数 定义了参数 "nr",带类型 "number"。 注意到赋值 `result = GetPart(count)` 不使用 let 命令。下一小节有解释。

46.2 变量声明 vim9-declarations

Vim9 脚本变量使用 :let:const 命令声明一次。赋值不使用 :let ,也不能用 :unlet 取消变量的声明。 多数情况下,你希望同时进行变量声明和初始化: let myText = 'some text' ... myText = 'other text' 变量类型会从表达式中推断。在此例中是字符串。如果用数值初始化,则类型为数值: let myNumber = 1234 ... myNumber = 0 如果试图给此变量赋值字符串,会报错: let myNumber = 'this fails!' 少数情况下你希望变量可接受任何类型的值,那就要显式说明类型: let myVar: any = 1234 myVar = 'text also works' 也可先声明变量而不赋值。此时 Vim 会初始化该变量为零或空: let word: string if condition word = 'yes' else word = 'no' endif 另管有更短的形式: let word = condition ? 'yes' : 'no'

46.3 函数和类型

老式 Vim 脚本有类型检查,但在运行时进行,也就是代码执行时。而且是容错的,通常 计算会返回一个意外的值而不是报错。这样在函数定义时你可能会认为没问题,仅在之后 调用该函数时才发现问题存在: let s:collected = '' func ExtendAndReturn(add) let s:collected += a:add return s:collected endfunc 能发现错误吗?试试: echo ExtendAndReturn('text') 会看到零。为什么?因为老式 Vim 脚本中 "+=" 会把参数转换为数值,而没有数字的字 符串会转换为零! 用 :def 时,类型检查在函数编译时发生。为此,需要指定参数类型和返回类型。还要 注意到使用参数时没有 "a:" 前缀: let s:collected = '' def ExtendAndReturn(add: string): string s:collected += add return s:collected enddef defcompile 这里我们用 :defcompile 立即进行编译,否则编译只在函数调用时才会进行。Vim 此 时会告知你出错了: E1013: type mismatch, expected number but got string Vim9 脚本是严格的 "+" 操作符只能用于数值和浮点。字符串连接必须使用 ".."。这避 免错误和导致上述意外结果的自动转换。如果把函数的首行换成: s:collected ..= add 一切就好了。 如果函数不返回任何值,只要省略返回类型就可以: def ReportResult(result: string) echo 'The result is: ' .. result enddef 这也会检查,试图返回任何值时会报错。 如果你不关心类型,或者函数需要接受多种类型,可用 "any" 类型: def Store(key: string, value: any) resultDict[key] = value enddef

46.? 在老式脚本中使用 Vim9 脚本 source-vim9-script

有些情况下,在老式脚本里你会想使用 Vim9 脚本里的项目。例如在 .vimrc 里初始化插 件。最好的方法是用 :import 。例如: import Init as NiceInit from 'myNicePlugin.vim' call NiceInit('today') 这会找到 Vim9 脚本文件里的 "Init" 导出函数,并使之成为局部于脚本的项目 "NiceInit"。即使不给出 "s:", :import 也总使用脚本命名空间,如果 "myNicePlugin.vim" 已经执行过,不会再次执行。 除了避免把任何项目放进全局命名空间 (因为命名冲突会导致意料之外的错误) 以外,这 也意味着无论其中的项目被导入多少次,一份脚本只执行一次。 有些情况下,例如为了测试用途,可能就想要直接执行 Vim9 脚本。这没问题,但你只能 得到其中的全局项目。该 Vim9 脚本要确保这些全局项目使用独一无二的名字。例如: source ~/.vim/extra/myNicePlugin.vim call g:NicePluginTest()

下一章: usr_90.txt 安装 Vim 版权: 参见 manual-copyright vim:tw=78:ts=8:noet:ft=help:norl: