Jacky Liu's Blog
FileSystemExplorer 终于成形了
---- 外部的 Vim 插件我基本都是装上试试然后就卸掉,用到的基本都自己写。在文件操作方面,因为自带的 Netrw 实在不够用,一些 VimScript 写的外部插件(比如 NerdTree)又有慢的问题。自己写的 FileSystemExplorer 这个插件自从起个头以后名不副实了很久,现在终于成形了。
---- 主体还是 Python 写的(通过 Vim 的 Python 接口),纯 VimScript 写的太慢。但是目前还是很菜。以下是设想中,准备逐步添加的功能:
1. 刷新(也可以用于删除、新建操作之后)
2. 改变排序方式(也可以用于递归式打开目录之后)
3. 删除目录或文件
4. 批量删除
5. 转移目录或文件
6. 改名
7. 递归式打开目录
8. 新建目录或文件
9. 快速定位(到同级上一个/下一个节点,到上级节点)
10. 智能化开启文件(通过后台调用其它程序)
---- 基本上 Vim 和 Python 折腾到现在,不确定性已经越来越少。接下来的事可能跟工厂做工差不多。继续开工 。。。
上线两个新模块
---- 前一阵子花了些时间,把以前写的几乎所有的 Vim 插件都用 Python 接口改 写了一遍,主体结构全部放在脚本的 Python 部分,效果非常好。实际上 Vim 的编程语言接口是早就有了的,而现在 Vim 自带的 VimScript 语言基本上是 7.0 版以后才成形,所以 Vim 的本意实际上是让用户使用已有的语言来编写 Vim 上使用的脚本,而不是想要再发明一种新的语言。Vim 的作者在接受访谈时也表达过这个意思。两个新的模块也是用 Python 接口写的,使用了 Python 语言的一些关键特性。
---- 第一个是 FileSystemExplorer,名头起的很大,因为开始想得比较复杂,但实际上现在只有一个类似于收藏夹的功能。把常用的目录和文件分类收集起来,方便一键打开。本来还想 实现像 NerdTree 那样的树形文件结构浏览的功能,但后来想想算了,就停留在这样一个名不副实的状态。顺便说下,NerdTree 虽然用起来速度比较慢(因为用 VimScript 的内部数据结构来模拟了文件系统的结构),但是插件本身写得非常好。虽然以前我也上过 C++ 的课,但是关于 OOP 的概念还是从 NerdTree 里学到的最多。
---- 第二个是 WebFileBrowser,同样是好大喜功的一个名字。原本的设想是这样:
1. 通过自定义命令, :Get {url} 可以把网页下载下来,将源文件显示在 output buffer 里面。
2. 有一个 index 子模块,可以分析下载的网页文件,形成一个 element 的目录,显示在辅助窗口里。目录的内容应该具有很顺眼的颜色,能清楚地显示网页的内容结构,而且具有跳转功能,能跳到源文件里对应的地方。
3. 在 output buffer 里有一些快捷键操作,可以跳转到 start tag,end tag 等等,可以提取 tag 内容或属性,或许还能通过自定义命令执行更复杂的 Xpath 查找操作,还有像浏览器那样的跳转功能,等等。
4. 有一个 cache 子模块,像浏览器的历史栏那样,保存已下载的网页文件和它们的 url。必要时重新打开。
---- 而现在实现的只有 1 和 2, 至于 3 和 4 以后再说(“再说” == 永远都没有)。
---- 写这个插件最初是为了学习网络相关的东西,html,javascript,flash 这些,尤其想弄明白一个问题:flash 到底是怎么显示出来的?有没有可能通过包含 flash 的网页下载到决定了 flash 内容的那些原始数据?而且这些原始数据必须是能读懂的,可用的才行。比方说新浪的网页能用 flash 显示股票 K 线图,能通过这些 flash 直接下载到背后的行情和技术指标数据吗?
---- 这个问题基本解决了,不过是通过 Google 解决的,研究 html 本身并没有多大帮助。看起来好像是这样:浏览器解读了含有 flash 的网页之后,会下载背后的 swf 文件,然后浏览器内部的 flash 插件负责解读这些 swf 文件并根据它的内容显示 flash 图形。swf 是二进制格式的图形描述文件,并不含有形成这些图形的原始数据。
---- 第一个插件使用了 Python 的 pickle 特性,用来存放 “收藏夹” 的内容,下次开启 Vim 时自动读入。第二个插件使用 Python 标准库里的 urllib.request 模块下载网页文件,然后使用第三方模块 lxml 来 parse 网页内容。lxml 这个模块很强,关键是什么网页都能吃,包括有问题的网页。而且它是支持 Python 3 的(内牛满面 :-(...),要不然这个插件只能停留在设想中。
PS:图看起来太大了。怎么让它用原始尺寸显示啊?!
怎样让 Vim 帮助你阅读和理解文档
Vim 是一款高效的文本编辑器,许多人对它强大的编辑功能都有体会,而实际上 Vim 能做的不仅仅是编辑,它还能使原本枯燥的文档变得“鲜活”起来:
这个图显示了 gvim 对普通的 txt 文本的显示效果,内容是 Python 的帮助文件。里面的颜色,缩进和标题是阅读时根据自己的理解随手加上去的。在 vim 里进行这些编辑操作并不麻烦,甚至比较享受。最为关键的是,一切都由自己控制,文档像这样读过一遍以后,就会印象比较深,而且只读一遍就好,以后回头找起来,因为有先前的注释在,就会非常快。我发现这样对于快速地掌握文档的内容特别有用。所以,现在我最喜欢的文档格式不是 pdf 或 html,而是 txt。
看一下背后所用到的特性: 实际上也不复杂,就是些 Vim 的基本特性:
首先是颜色。Vim 支持多少种颜色? 对 GUI 版来说,是 256 x 256 x 256 种,这跟 html 的颜色特性是完全一样的,包括颜色的定义方式。比如 #000000 代表纯黑,#ffffff 代表纯白,等等。(建议不要拿纯白或者其它很亮的颜色当背景色,看久了眼睛受不了)。实际当然用不到这么多,就在几个主要色系里面选些典型的就好了。颜色选定了以后就可以跟格式结合起来,定义成一些语法项,用在平时的文档里面。这个主要在 Vim 的文档 "syntax.txt" 里有讲。下面是我自己定义的一些语法项,主要用于一般的文档:
接下来需要用到的特性是自定义按键。因为时常需要添加一些自己定义的格式字符,所以最好把这些操作映射到一些快捷键上。比如在 Visual 模式下选中一段感兴趣的文本,再按一两个键,就能给它加上格式/颜色,这样的操作用起来感觉很爽。
如果想要更高级些的功能,那就需要了解更复杂的特性了: Vim Script。在第一个图中,左侧的窗口里加载的是 CustomTextIndexer 功能模块,这是用 Vim Script 写的一个插件,用来提取主窗口内的标题形成文档目录,并且具有简单的跳转功能。实际上背后的操作主要是文本匹配和字符串处理 ———— 都是 Vim 的本职工作,平时使用时也经常碰到。
彻底颓了—— Vim Python 3 接口不支持中文
折腾了好久才编译出来一个支持 Python 3 的 Vim,谁知居然有这么多问题。
除了 vim.current.buffer 对象不再支持 slice 类型参数以外,今天又发现这个:
:py3 vim.current.buffer.append('XXX 模块的控制面板')
结果在 Vim 里加进去的一行看起来是这样:
XXX 模块<e7>
也就是,遇到有的中文字符会无法解释,成为乱码。用 依云 发来的她编译的版本,结果也一样。是不是因为 Python 3 接口对 Unicode 字符的宽度理解有问题,遇到有些字符会认不得 ? 这给人感觉并不是个发布版的软件,问题好多。
想到一种可能——因为对自由软件来说,并不存在所谓质量控制的问题,也没法做大规模完善的测试,而且写作和维护的人手比商业软件一般也少得多,所以有可能作者是有意在还不完善的状况下就发布出来,然后大家就会发现问题,还有一些等不及更新的牛人就会发布 patch,然后作者或者维护者就只要把这些 patch 打进去就可以了。这样可以使自由软件保持比较快的更新速度,可能在维护的人手比较少的情况下,这也是唯一可行的做法。
对我来讲这几天吃螃蟹的经验就比较让人失望。还是回去用 7.2 吧。
Vim 里的上下左右,给玩惯了游戏的 Vimmer
Vim 里的上下左右默认是 hjkl 四个键,这是与 vi 兼容的设置。如果你玩惯了赛车一类的游戏,相信打死你也适应不了这样的设置。我就是这样。所以当初学用 Vim 的时候,我第一件要看的就是怎样定义按键映射。实际上只要很简单的几行设置,就可以把方向键映射到 ikjl 四个键上,这样跟小键盘上的方向键位置吻合,用起来就舒服得多。以下是我放在 .vimrc 里面的代码,用下来很久了,没出过什么问题。
"------------------------------------------------------------------------------------ "------- 所有模式下 "------------------------------------------------------------------------------------ no i k no k j no j h no h i no I H no H I "------------------------------------------------------------------------------------ "------- Visual 模式 "------------------------------------------------------------------------------------ vno h( i( vno h) i) vno h< i< vno h> i> vno hB iB vno hW iW vno h[ i[ vno h] i] vno hb ib vno hp ip vno hs is vno hw iw vno h{ i{ vno h} i}
定义了这些按键以后,i 就是向上,k 是向下,j 和 l 是左和右。另外只要记着,任何时候原来该按 i 的地方就按 h,Visual Block (列编辑)模式下该按 I 的地方就按 H,就行了。
基于 Vim 的窗口布局管理和用户界面实现
第一篇,写个关于 Vim 的。
今天花了点时间,增强了 ModuleManager 中的窗口布局类的功能。现在辅助窗口的数量已经不受限制了。
这个 Vim 界面里一共有 13 个窗口。左右各 3 个,下面 6 个,还有中间一个大的。可以同时显示很多信息。但是布局并不凌乱。实际上这个类里面定义了多个窗口布局方案,打一个命令就把所有窗口自动划分好。上面这个只是其中一种。窗口大小会根据光标的移动自动调整,使用自动命令(AutoCmd)机制。进入窗口时自动变大,离开时自动缩小。许多窗口都压到 了最小。试了一下,效果跟预期的完全一样。我表示非常地满意 :)
当然如果只是分分窗口的话并没什么太大用处。实际上整个的想法比这个要大,主要是想拿 Vim 当做一个应用程序的用户界面,这个窗口布局类只是其中一部分,算是用户界面的形式。形式有了以后就要跟功能接合起来,而功能主要依靠 Vim buffer 来实现。
Vim buffer 是在 Vim 基础上用来搭建用户界面的绝好组件。因为首先它显示了要给用户看的信息(颜色与格式在 Vim 里当然不是问题),其次,它里面定义了用户可以进行的操作(通过按键映射和自定义命令)。这不就是用户界面么?按照 Vim 的设计,按键映射和自定义命令都是跟着 buffer 走的。窗口里换了一个 buffer,操作也就跟着换一套。想想使用 IDE 的时候,你在文件目录窗口和在调试输出窗口内按 Enter 键自然具有不同的含义。有了 Vim 这种设计的强大支持以后,只需要把这些 Vim Buffer 定义成类(写成 Vim Script 类或者利用 Python 接口写成 Python 类,都可以),一个类实现一个具体功能,比如相关文件结构浏览,又比如针对主窗口内显示的内容来提取它的目录,同时再定义一套独有的操作,然后这些前台类组合在一起,加上一些后台的执行类形成用户界面,然后用户界面再跟更多,更实质性的功能类放在一起,形成整个程序。
另外要知道一点,按照 Vim 的设计,不是一个窗口只能加载一个 buffer,而是任一个窗口都能加载任一个 buffer。觉得 13 个窗口够多了吗?实际上它能加载的功能模块是根本没有数目限制的。当你看到某个 IDE 有一个很好的功能,OK,只要以 Vim Buffer 为基础再定义一个类,实现这个功能,加到用户界面里面,再给它分配个窗口就行。觉得窗口太多太乱?换个窗口少点的布局,那些 Vim Buffer 只是转为 hidden 而已,随时可以加载进窗口里,为你服务。
IDE 是一个比较典型的例子。如果我想弄个 IDE,我就要把它弄成上面的样子,但是程序开发不是我的方向,我要拿它做别的事情。
实际上在我看来,这个最大的意义在于显示了技术是怎样能帮你省钱的,要显示同样多的信息,并不用跟一般操盘的一样搞个三四台显示器放在面前,可能还要架起来。很好很好,以后的外部程序界面就用它 !:)