简介

尽管 Vim 的界面非常简单,但它是所有风格的 UNIX® 中最流行的两种编辑器之一。可以轻松地扩展它,从而满足各种软件开发和系统管理需求。Vim 甚至有自己的脚本语言,可以使用它编写脚本并把脚本装载到 Vim 中。也可以使用 Perl 或 Python 等外部脚本语言扩展编辑器的功能。这些脚本统称为 Vim 插件。

定制插件能够提供帮助的最常见的方面是编程语言的语法高亮显示。Vim 在安装时附带对 CC++、Perl 和 Tcl 的预定义语法支持(请查看 Vim_Installation_Folder/vim72/syntax),但是有时候需要对定制的或新的编程语言的支持,或者希望扩展插件以便实施组织特有的编码标准。

同样,从编辑器内编译源代码也是不错的特性。可以为 Perl 或 Python 代码创建用于从编辑器内编译源代码的定制插件,还可以把光标放在有错误的地方,这有助于节省大量开发时间。

本文讨论为了高亮显示定制编程语言的语法 Vim 必须提供什么。然后讨论通过使用简单的正则表达式实施编码标准,再转到 Vim 的 Perl 脚本编程。最后,讲解如何从 Vim 内编译源代码。

注意:本文假设读者基本了解 Vim、Perl、make 和正则表达式。我们将使用 Vim version 7.2 和 Perl version 5.8。

回页首

语法高亮显示

我们将使用 Vim 的内部脚本引擎高亮显示您创建的定制语言的语法。清单 1 包含这种定制语言的一些关键字。

清单 1. 定制编程语言的关键字
foreach if then else elsif while repeat until disable
integer unsigned signed byte
always initial

Vim 使用以下格式把特定的单词标识为关键字:syntax keyword <group name> <keyword list>

因此,对于您的定制语言,使用 清单 2 中的伪代码。

清单 2. 在 Vim 中定义关键字
syntax keyword group1 foreach if then else elsif while repeat until disable integer unsigned signed byte always initial

接下来,把此文件保存在 $HOME 下,命名为 lang.vim。现在,用您定制的语言编写一小段代码(见 清单 3)。

清单 3. 用定制编程语言编写的代码
integer k=0;
repeat (k < 3) beginprint “hello world” + k + “\n”;k = k + 1;
end

在 Vim 编辑器中,作为 :source $HOME/lang.vim 装载 lang.vim。但是,有一个问题,什么变化也没有。尽管指定了语法,但是没有指定应该如何高亮显示语法。清单 4 给出 lang.vim 文件的改进版。

清单 4. 支持语法高亮显示的 lang.vim 改进版
syntax keyword type1 integer unsigned signed byte
syntax keyword statement1 foreach if then else elsif while repeat until disable always initial
highlight link type1 Type
highlight link statement1 Statement

重新装载 lang.vim,清单 3 中代码的语法现在高亮显示(见 图 1)。在图 1 中,高亮显示关键字 integer 和 repeat。

图 1. 定制代码中高亮显示的语法

在 清单 4 中究竟做了什么?有两个方面需要理解:

  • 用户通常希望程序中的语句(if-then-elserepeat 等)与数据类型(integerbyte 等)以不同的方式高亮显示,这样可读性更好。因此,把语法划分为组,每个组包含适当的内容:type1 组包含 integerunsignedsigned 和 byte 关键字。
  • Vim 已经预定义了 TypeStatementComment 和 Identifier 组以及相应的颜色方案。highlight 命令把 type1 与 Vim 的 Type 组关联起来,这样就会使用相同的颜色方案显示 byte 等关键字。

回页首

更多语法支持

您可能希望自己的语言是不区分大小写的,所以 integer 和 INTEGER 都应该高亮显示。还希望支持 // C++ 风格的注释。清单 5 给出修改后的 lang.vim 文件。

清单 5. 支持语法高亮显示的 lang.vim 改进版
syntax case ignore
syntax keyword type1 integer unsigned signed byte
syntax keyword statement1 foreach if then else elsif while repeat until disable always initial
syntax match comment1 /\/\/.*/
highlight link type1 Type
highlight link statement1 Statement
highlight link comment1 Comment

syntax case ignore 语句处理不区分大小写。不能使用关键字处理注释,所以需要一个正则表达式,然后把它与 Vim Comment 组关联起来。使用 syntax match <identifier> /<pattern>/ 定义正则表达式。在两个前向斜杠 (/) 之间,定义模式 \/\/.*,这表示从 // 开始直到行末的所有内容。因此,图 2 所示的定制语言代码会正确地高亮显示。

图 2. 对注释和不区分大小写的支持

回页首

定制编码标准支持

很容易通过扩展定制的插件处理组织特有的编码标准。下面是一些典型的编码规则:

  • 代码中不应该有制表符。
  • 变量名长度不应该超过 14 个字符。
  • 一行上的字符数不应该超过 80 个。
  • 函数不能超过 100 行。

代码中不应该有制表符

我们先来处理最简单的规则,代码中不应该有制表符。只需为 tab 定义标识符,然后把这个标识符与 Vim 预定义的 Error 标记关联起来:

syntax match identifier1 “\t”
highlight link identifier1 Error

那么,如果代码中有制表符,会发生什么情况?图 3 给出 图 2 中的代码加上制表符之后的情况。

图 3. Vim 用红色高亮显示制表符

在图 3 中,用红色高亮显示 repeat 后面的制表符;这明确地警告用户这里有错误。

变量名长度不应该超过 14 个字符

对变量名长度的支持需要进一步了解如何使用正则表达式进行语法匹配:

syntax match longword1 “\w\{14,}”
highlight link longword1 Error

在这里,\w 定义字符类 [0-9A-Za-z_]— 即允许任何数字、字母字符(大写或小写)或下划线 (_)。后面是 \{14,},这意味着需要匹配最少 14 个连续的字符。因此,this_is_a_REAL_long_word1 会导致高亮显示,因为标识符长度超过 14 个字符,而 this_is_ok_2 没问题。图 4 给出错误情况的显示方式。

图 4. 用红色高亮显示超过 14 个字符的变量名

在图 4 中,用红色高亮显示变量 this_is_a_REAL_long_word1(再次采用 Vim 的默认颜色方案),这警告用户这里有错误。

一行上的字符数不应该超过 80 个

一行上的字符数超过 80 个会导致混乱,让阅读更困难。再次使用 syntax match 为一个正则表达式定义标识符,然后把标识符与 Error 关联起来。理解这个正则表达式应该不难:脱机符 (^) 表示行的开头;美元符号 ($) 表示行的末尾;这两者之间的内容超过 80 个字符就识别为错误匹配。注意,点号 (.) 表示匹配除换行符外的任何字符:

syntax match longline1 “^.\{80,}$”
highlight link longline1 Error

图 5 给出一个由于超过 80 个字符高亮显示的代码行。

图 5. 禁止行长度超过 80 个字符的规则

在图 5 中,由于复杂的公式导致超过 80 个字符,所以 Vim 用红色高亮显示一整行。删除一个字符,把行长度从 80 减少到 79,高亮显示就会消失了。

函数不能超过 100 行

定制编码标准的最后一条规则是函数的长度必须少于 100 行。清单 6 给出一个用定制编程语言编写的函数。

清单 6. 用定制编程语言编写的函数
function f (int k, int l) returns float
beginf = k * l;for (int i=0; i<10; i++)beginf += sqrt(k) * sqrt(l);endreturn f + 2;
endfunction

与设计复杂的正则表达式或调用 Vim 预定义的内部函数相比,把整个函数传递给 Perl 以检查行数可能更容易(而且肯定更快)。下一节讨论这个主题。

回页首

使用外部脚本语言创建 Vim 插件

Vim 很容易与 Perl、Python、Tcl 和 Ruby 脚本连接。尽管这里只涉及 Perl,但是与 Python、Tcl 和 Ruby 连接的方法是相似的。清单 7 给出一个 Vim 插件,如果任何函数的长度超过 100 行,它就会显示错误消息。

清单 7. 使用 Perl 为 Vim 创建定制的插件
perl << EOF
sub checksize
{my $count = 0;my $startfunc = 0;my $filelen = scalar @_;while ($count < $filelen) {if ($_[$count] =~ /^function/) {$startfunc = $count;}elsif ($_[$count] =~ /endfunction/){if ($count - $startfunc > 100){Vim::Msg($_[$startfunc], "Error");}}++$count;}
}
EOFfunction! L1( )perl checksize($curbuf->Get(1..$curbuf->Count()))
endfunction

这些代码都放在前面使用过的 lang.vim 文件中。下面是这个插件的一些注意事项:

  1. 使用标志把 Perl 代码嵌入在 Vim 脚本中。这些标志可以是任何名称,可以不是全大写的。在 清单 7 中,使用的标志是 perl << EOF … EOF 中的 EOF。第二个 EOF 必须从行的第一列开始。标志不一定要命名为 EOF(任何名称都可以),但是必须遵守第一列规则。
  2. 把文件的全部内容传递给 Perl 代码。Perl 子例程 checksize 处理整个文件(作为 Perl 数组 @_ implicit 的一部分)并检查函数长度。当遇到关键字 function 时,它把计数器设置为 0;当遇到关键字 endfunction 时,它检查计数器是否大于 100。如果函数长度超过 100 行,就显示错误消息。
  3. 不能使用一般的 Perl 输出例程显示错误消息,因为需要在 Vim 内部显示消息。Vim 提供了连接 Perl 的接口,可以在 参考资料 中找到详细信息。Vim::Msg 在编辑器窗口内显示消息。在 清单 7 中,显示正在处理的函数的第一行。Vim::Msg 的第二个参数是显示的信息的类型:error 意味着此信息用红色高亮显示。
  4. 在 Vim 中编写一个函数,它把文件源代码传递给 Perl 代码。$curbuf->Count( ) 指出在当前的缓冲区中有多少行;$curbuf->Get(<line1>..<line2>) 返回 line1 和 line2 所指定的两行之间的文本。在这个脚本中,传递当前缓冲区中从第一行到最后一行的所有内容。现在,在 ESC 模式下输入 :call L1(),应该会立即看到正在处理的函数。

回页首

从 Vim 内编译源代码

可以从 Vim 编辑器内部编译源代码。这个特性(加上语法高亮显示和定制代码检查)让 Vim 更接近定制的集成开发环境 (IDE)。清单 8 给出一个包含若干错误的 C++ 文件。

清单 8. 非常糟糕的 C++ 代码
#include <iostream>
using namespace stdlclass mytags { public:int getid(int id=0);void setid(int)protectd: list<int> tags;const list<int>::iterator tag_i;
}

在 Vim 脚本中添加 清单 9 所示的五行代码,就可以在编辑器中执行编译。

清单 9. 把 F3 键映射为在编辑器中执行编译并显示错误
function! build()make cl  “list the errors
endfunction
map <F3> :call build()<CR>

在 ESC 模式下按 F3 键即可编译源代码。build() 函数从 Vim 内部调用 make,然后调用 cl 以显示错误。在 ESC 模式下输入 :cfirst 跳到第一个错误;使用 :cn 跳到后续的错误;使用 :clast 跳到最后一个错误。注意,在默认情况下假设 Makefile 在与源代码相同的文件夹中。尽管这么说,但这不是必需的,可以修改 清单 9 中的 build() 函数,让它转到 Makefile 所在的文件夹。另外,向 make 传递参数也很容易。清单 10 证明了这一点。

清单 10. 使用 make 编译源代码的 Vim 脚本改进版
function! build()cd /home/arpan/ibm/scripts “go to the folder where Makefile ismake CC=g++cd /home/sources “back to sourcescl  “list the errors
endfunction
map <F3> :call build()<CR>

现在,在编译代码时,清单 11 中的错误会在 Vim 中显示。

清单 11. 在 Vim 环境内显示编译错误
#include <iostream>
using namespace stdlclass mytags { public:int getid(int id=0);void setid(int)protectd: list<int> tags;const list<int>::iterator tag_i;
}t.cpp:4: error: expected namespace-name before "class"
t.cpp:4: error: `<type error>' is not a namespace
t.cpp:4: error: expected `;' before "class"
t.cpp:8: error: expected `;' before "protectd"
t.cpp:10: error: ISO C++ forbids declaration of `list' with no type
t.cpp:10: error: expected `;' before '<' token
t.cpp:6: error: expected unqualified-id at end of input
t.cpp:6: error: expected `,' or `;' at end of input
Press ENTER or type command to continue

回页首

安装语法文件

在 $HOME/.vim 下面创建名为 syntax 的文件夹,把定制的插件复制到其中。如果您的定制语言名为 ml2,那么把此文件命名为 ml2.vim。然后编辑 $HOME/.vimrc 并添加 syntax on 行。这样就可以了:现在,每当在 Vim 中打开扩展名为 ml2 的文件时,会自动地高亮显示语法。这种行为不包括显式的函数调用;建议为子例程长度检查等快速定制代码检查设置键映射。

回页首

结束语

进行快速开发并不一定需要高级的 IDE,Vim 就能够满足需要。通过使用到 Ruby 和 Python 等语言的接口,甚至可能使用 Vim 连接 web。要想进一步研究这个主题,请参见 参考资料。

参考资料

学习

  • Vim 文档:查阅关于 Vim 编辑器的更多信息。
  • Vim regular expressions:寻找对于 Vim 有用的正则表达式。
  • Vim Table of Contents:Peruse Swaroop C H 的 Vim 目录。
  • 使用脚本编写 Vim 编辑器,第 1 部分: 变量、值和表达式(Damian Conway,developerWorks,2009 年 5 月):了解 Vimscript 编程语言的基本组件。
from: https://www.ibm.com/developerworks/cn/aix/library/au-vimplugin/

为 Vim 编辑器开发定制插件相关推荐

  1. linux下vim编辑器插件,为你介绍Linux系统中vim编辑器的实用插件!

    今天小编要跟大家分享的文章是关于Linux系统中vim编辑器的实用插件.Vim 是 Linux 下的常用文本编辑器,但也经常被称为是一个上古神器,因为它对于初学者而言相当不友好,也不好入门. Linu ...

  2. linux系统中VIM编辑器推荐安装插件

    k-vim VERSION: 9.0 LAST_UPDATE_TIME: 2015-05-02 作者 wklken (凌岳/pythoner/vim党预备党员) Email: wklken@yeah. ...

  3. bashsupport插件_如何用 bash-support 插件将 Vim 编辑器打造成编写 Bash 脚本的 IDE

    IDE(集成开发环境)就是这样一个软件,它为了最大化程序员生产效率,提供了很多编程所需的设施和组件. IDE 将所有开发工作集中到一个程序中,使得程序员可以编写.修改.编译.部署以及调试程序. 在这篇 ...

  4. Shell开发环境vim编辑器的配置文件vimrc的参数优化

    Linux环境下为了方便Shell的开发,对配置文件vimrc的参数需要进行一些的优化,vim编辑器的配置文件默认路径为:~/.vimrc(全局路径为/etc/vimrc). 参数如下: " ...

  5. nmon结果分析工具_Jmeter测试工具实践:如何为Jmeter开发测试插件定制专属取样器?...

    JMeter原生支持多种不同的取样器(HTTP.TCP.JDBC.JMS等),每一种不同类型的取样器可以向服务器发送不同协议类型的请求.除了开箱即用的协议支持以外,JMeter还支持用户自己开发新协议 ...

  6. Linux嵌入式开发——vim编辑器

    文章目录 Linux嵌入式开发--vim编辑器 准备操作 使用 打开 工作模式 一般模式 编辑模式 命令行模式 保存退出 其他操作方式 Linux嵌入式开发--vim编辑器 准备操作 首先我们需要安装 ...

  7. Java bho插件_VC++开发BHO插件——定制你的浏览器  作者 陆其明

    关键字 BHO Browser COM ATL 网址过滤 原作者姓名 陆其明 文章原始出处 http://hqtech.nease.net 读者评分 18 评分次数 4 正文 在Windows操作系统 ...

  8. 针对Java开发环境的VIM 配置 ---安装 javacomplete插件

    以Linux用户tucson为例,总结下Java开发中如何实现VIM的自动补全功能: 1> mkdir /home/tucson/.vim 2> 下载javacomplete插件,将 ja ...

  9. 使用脚本编写 Vim 编辑器,第 5 部分: 事件驱动的脚本编写和自动化

    Vim 的事件模型 Vim 编辑功能的运行方式是事件驱动的.但由于性能上的原因,实际的实现要远比这个复杂,还需要进行许多事件处理优化或者处理事件循环下面的几层,但是您仍然可以将编辑器看成一个简单循环, ...

最新文章

  1. dell 回复 win10 8DW88B2
  2. VMware网络选项分析
  3. Java集合源码学习(五)几种常用集合类的比较
  4. subShell与代码块
  5. 激活函数:sigmoid、Tanh、ReLU
  6. 剑指offer之3-10题解
  7. Spring MVC No converter found for return value of type
  8. 博客园上海地区活动——LinkCoder主题社区第二期:淘宝服务化架构的设计和实践...
  9. Python3读取kafka消息写入HBASE
  10. python编写程序判断数据类型_python中如何判断一个变量的数据类型
  11. php parse_url,pathinfo,basename函数
  12. 增强for循环(foreach解析)—带冒号的for循环
  13. 红帽rhce考试自带补考吗_红帽RHCE认证考试注意事项
  14. 数据结构与算法——左程云07
  15. linux cp命令改名字,Linux cp命令复制文件
  16. KITTI数据集简介(一)—— 传感器介绍
  17. 组态王 6.55 启停plc_成套设备PLC编程深圳PLC编程
  18. C++多线程--std::packaged_task
  19. 联想R720使用kali安装NVIDIA显卡驱动
  20. ionic4开发微信小程序_15个适用于Ionic应用程序开发人员的资源

热门文章

  1. V神又在操心区块链技术落地,以太坊大涨!
  2. AlphaGo之父哈萨比斯: 先解决智能 再用智能解决一切
  3. Python做文本挖掘的情感极性分析
  4. BM算法的shift1表是在所有情况下移动都是最快的吗?
  5. wchar.h not found
  6. Spring Boot2.x-04Spring Boot基础-使用注解装配bean
  7. TabLayout-Android M新控件
  8. Java线程池的拒绝策略
  9. MySQL与Redis一致性解决同步问题
  10. excel 复制数据 sql server 粘贴_数据资料复制粘贴麻烦?教你硬盘对拷资料