YASnippet 是 Emacs 的一个缩略词 (abbreviation) 模板替换系统,可以把一个预先设定好的缩略词扩展成模板。刚开始用 YASnippet 的时候,一般感觉无从下手,现在就简单介绍一下 YASnippet 最基本的使用方法。
YASnippet 有两种安装方法,可以视个人情况选用。
1). 单个 yasnippet-bundle.el 文件安装方式
如果想快速地试用、了解一下 YASnippet 这个系统,从官方网站下载 yasnippet-bundle.el 这个文件,放到 Emacs 扩展目录里,然后把下面的代码放到 .emacs 文件里:
(add-to-list 'load-path
"~/.emacs.d/plugins")
(require 'yasnippet-bundle)
本方法适合于快速地试用一下 YASnippet 系统,当然,如果你需要修改模板或是定制自己的扩展模板,你就需要用下面介绍的完全安装方法。
2). 完全安装方法
需要完全安装 YASnippet 的话,先从官方网站上下载完整的 yasnippet-x.y.z.tar.bz2 包,把包解压放到 Emacs 的扩展目录,然后添加下面的语句到 .emacs 文件里:
(add-to-list 'load-path
"~/.emacs.d/plugins/yasnippet-x.y.z")
(require 'yasnippet) ;; not yasnippet-bundle
(yas/initialize)
(yas/load-directory "~/.emacs.d/plugins/yasnippet-x.y.z/snippets")
正确安装好 YASnippet 后,重新启动 Emacs 就可以看到菜单栏里多了一个 YASnippet 的菜单(图1所示),

mini buffer 上也会显示出类似于 (org yas) 的字样(这里是指 yas 作为子模式存在于主模式 org 里)如图2所示。

总的来说,正确安装好 YASnippet 后,只要输入缩略词,然后用 TAB 键或是 C-i 就可以完成扩展了。
在 Emacs 启动后,YASnippet 模式是作为一个子模式 (minor mode) 存在于各个模式之中。要用 YASnippet 进行缩略词补全有好多种方法,最常用的补全方法有三种:
有关 YASnippet 使用的更详细叙述,可以参考官方文档 Expanding snippets。
虽然 YASnippet 已经自带了许多常用的扩展模板,但是很多情况下,我们需要根据自己的实际情况,来进行模板定制。以下是扩展 YASnippet 常用的一些命令:
下面就用一个实例,结合 YASnippet 的语法规则,来简单介绍一下 YASnippet 最基本的使用。
我在 org 模式里写笔记或是发布网页的时候,经常需要添加一个有关版权声明的文字(或为公司,或为自己)。因为公司和私人的内容都混在一起,所以我需要有多个模板。下面就以添加我个人版权声明的模板为例,介绍一下配置 YASnippet 的完整步骤。
1). 添加一个有关个人版权的 snippet
首先,在 org 模式里,用命令 M-x yas/new-snippet 来添加一个 snippet,输入你想要的 snippet 名称,我这里输入
Copyright
YASnippet 会自动生成一个名叫 Copyright.yasnippet 的文件,生成的内容如下:
# -*- mode: snippet -*- # name: Copyright # key: # binding: "keybinding" # expand-env: ((some-var some-value)) # --
2). 现在我们只需要根据 YASnippet 的相关语法来修改这个文件就可以了。上面文件关键词的基本语法含义如下:
3). 因为我们这里是配置一个最简单的模板,所以,我们删掉 # key:,# binding:,# expand-env: 这三个高级定制功能。最后,我们写成类似下面的东西:
# -*- mode: snippet -*- # name: Copyright # -- #+BEGIN_HTML <p style="TEXT-ALIGN: center"> 原创文章,如转载请注明:转载自细节之锤 [ <a href="http://blog.waterlin.org/">http://blog.waterlin.org/</a> ] </p> <p style="TEXT-ALIGN: center"> Copyright © WaterLin.org. All rights reserved. </p> #+END_HTML
4). 重启 Emacs 让修改生效,然后我们再回到 org 文件里,这个时候,可以直接输入一个 Copyright (注意:缩略词大小写敏感),然后用 C-i 进行替换(原本可以用 TAB 键的,但是 Emacs23 里的 org 模式把 TAB 键给霸占了),就可以把 Copyright 这个词替换成上面用 html 写成的版权声明。
在 org 模式里,我们可以用同样的方法来插入 #+begin_example,#+begin_ditaa,#+begin_dot,#+begin_src 等标记,这样可以节省一大笔时间。
一般来讲,用 YASnippet 来进行替换与自动插入,比直接用 elisp 写一个函数、命令来进行插入要简单、方便得多,并且容易管理。
YASnippet 的模板语言 (Template syntax) 还有着更加灵活的用法,参见官方文档 Writing snippets。
原创文章,如转载请注明:转载自细节之锤 [ http://blog.waterlin.org/ ]
Copyright © WaterLin.org. All rights reserved.
我平常记笔记以 org 为主,碰到觉得以后可能有用、却容易忘记的东西,就往 org 里扔。时间一久,积累得多了,org 文件显得很乱,很多内容都是随手从书上、网上摘下来拼在一起的,时间一久,很难有系统性。于是,积累到一定程度后,我会把部分内容整理成文章,发布到博客里,就像是日记一样,方便以后工作中查找相关资料。
在整理的过程中,我把 org 里的某些条目写成博客文章的原稿,再转贴到专门的博客发布工具 (Scribefire, Zoundry Raven等) 里发布到 WordPress 搭建的博客(尽管我能熟练使用 Emacs 的 org 或是 muse 模式,我依然觉得专用的 WordPress 更适合作博客系统!)。就这样,博客上有了一份随时随地可以查阅的资料,org 里也保存了一份副本(不要说我活得太小心,笔记数据是最重要的,我以前就经常为找不到硬盘里的某一条笔记而懊恼不已)。
但是我实在是太喜欢 Emacs 这个编辑工具,在 WordPress 或是其发布工具里进行排版与编辑,实在是让我痛不欲生!没有了定制好的诸多快捷键,就只能走而不能跑了!总的来说,这样的过程,有两点比较麻烦:
每次如此繁琐的步骤,很累并且容易出错!
要是能一次性地在 Emacs org 里把所有东西写好,直接发布成 html 的源代码,我就可以直接把这些源代码拷贝到到博客发布工具里进行发布,那该有多好啊!
Emacs org 提供了几乎你能想到的所有功能,发布成 html 页面也不例外!
当我编辑完 org 文档后,选择好我需要发布的内容,用命令
C-u M-x org-export-region-as-html
或是快捷键
C-u C-c C-e R
就可以把这一部分内容发布成 html 的源代码。剩下的事,只是把这个源代码拷到 WordPress 的发布工具里去。现在的流程简单多了,并且有了更漂亮的排版!
PS: 用命令 M-x org-export-region-ad-html 也能把 org 里选定的内容发布成 html 页面,那么,它和命令 C-u M-x org-export-region-as-html 有什么区别呢?
前者会发布完整的 html 页面,而后者只生成当前选定区域的 html 代码,即不包括 header 、css style 等多余的代码。如果我们需要一个完整的 html 页面用来展示你选定的内容,则我们需要用前者。
原创文章,如转载请注明:转载自细节之锤 [ http://blog.waterlin.org/ ]
Copyright © WaterLin.org. All rights reserved.
Drupal 默认是用一个一个的 node 来表示内容的,node 是 Drupal 里最基本的页面元素。几乎所有的内容都能称为 node,当然,它的 URL 并不友好,默认是下面的形式:
http://yourdomain/node/37
这种类型的 URL 并不能一目了然地理解页面的性质,最好能给页面设置有规律的别名 (alias)。
要让 Drupal 具备重写 URL aliases 功能的话,可以在管理后台激活 path 模块,然后再安装 pathauto 模块,安装前的效果如下图所示:

安装完成后,在 Home >> Administer >> Site building >> URL aliases 里,就可以看到多了一个 Automated alias settings 选项页,在这里可以根据任意喜好,随便修改 URL alias 设置。安装后的效果如下图所示:

在我们定制完规则要生成 aliases 的时候,记得把最下面这个选项勾上:
Bulk generate aliases for nodes that are not aliased
要删除某一类别的 aliases 的话,可以在 Home >> Administer >> Site building >> URL aliases 里的 Delete aliases 选项页里进行操作。
原创文章,如转载请注明:转载自细节之锤 [ http://blog.waterlin.org/ ]
Copyright © WaterLin.org. All rights reserved.
补充一下昨天总结的查询本地已经安装了哪些 Perl 模块的方法,还有两种方法可以用:
$ perl -mSmart::Comments -el
如果提示了类似下面的错误, Can’t locate Smart/Comments.pm in @INC (@INC contains: c:/strawberry/perl/lib c:/strawberry/perl/site/lib .).
则表明你的 Perl 并没有安装这个模块。如果已经安装了该模块,则不会发生任何事情。
还可以用相类似的方法来测试,比如说,直接从 shell 里运行一下 Perl 的 use 命令:
$ perl -e "use Smart::Comments;"
直接在后面使用 use 语句,如果这个模块存在的话,则不会报错;如果这个模块不存在的话,会提示出错信息。
要查询本地已经安装了哪些 Perl 模块 (module),我们可以用命令
$ perldoc perllocal
来查询,这个命令会显示出你系统里所有已经安装上的模块名称、安装路径等信息。
同样,如果是 ActivePerl,可以用命令
C:\>ppm query
来检查已安装的模块信息。
最近用 Perl 写了不少自动化测试工具,用到了一些模块,有几个觉得挺好的,记录下来,以后说不定还有需要用到呢。
Smart comments 提供了一个调试与追踪代码的简单方法,可以打印一个变量值,也可以追踪、显示一个循环的进度等。
最巧妙的是,当你完成了程序的编写,不需要这些调试代码的时候,只需要注释掉
use Smart::Comments;
这行就可以了。下次还需要再次调试代码的时候,不需要再添加一遍追踪代码,只要把上面那行代码重新激活就可以了。
如果你不在程序里用上面的语句显式的激活 smart comments,我们也可以在运行脚本的时候,显示地激活 smart comments 模块:
$ perl -MSmart::Comments $application.pl
如果有一段代码,需要在多个地方重复用到,但是写成函数却并不是很合适,这个时候,最好的办法,是用类似于 C++ 的宏定义,在需要的地方插入这个宏即可。可以用 Filter::cpp 这个模块来实现,安装这个模块后,用起来和 C++ 的宏就没有什么区别了。
现在很多测试用的测试用例 (test case) 以及测试报告都是用 Excel 来写的,要完成自动化测试,Perl 脚本最好能够自动从 Excel 读入数据、并在相应位置上记录测试结果。与这相关的工作,可以用下面的模块来完成:
如果我们需要读入 (parse) 一个已有的 Excel 文件,可以使用 Spreadsheet::ParseExcel,适用于 Excel 95-2003 版本。如果你用的是 Excel 2007 版本,则你需要用 Spreadsheet::XLSX 这个模块。
如果我们需要创建一个全新的 Excel 文件并写入数据,我们可以用 Spreadsheet::WriteExcel 模块。
如果我们需要打开一个 Excel 文件读入测试数据、再输出测试数据到这个 Excel 文件,我们需要使用 Spreadsheet::ParseExcel::SaveParser 这个模块,它综合了 Spreadsheet::ParseExcel 和 Spreadsheet::WriteExcel 的功能。这里特别强调一下,不管是修改 (overwrite) 已有的 Excel 数据,还是创建 (add) 新的 Excel 数据,均可以使用 AddCell 这个方法,如下所示:
# Overwrite the string in cell A1
$worksheet->AddCell( $row, $col, 'New string' );
# Add a new string in cell B1
$worksheet->AddCell( $row, $col + 1, 'Newer' );
最重要的是,在用 AddCell 修改或是添加了新数据后,一定要记得保存 Excel 文件,否则修改不会被保存下来!保存文件用下面的语句:
# Write over the existing file or write a new file.
$template->SaveAs('newfile.xls');
如果是同一个文件名,则把数据保存到原来的文件;如果是新文件名,则把数据保存到新的文件里。
用 Badger::Timestamp 模块可以很方便地对时间戳 (timestamp) 进行修改、比较等操作,相当方便。
假如我有一个子过程,定义如下:
sub test_sub { print "test"; }
我又有一个变量:
$test = "test_sub";
这个 $test 的值刚好就是上面子过程的名称。既然我通过 $test 知道了这个子过程名称,我可以通过 $test 达到调用这个子过程的目的吗?也就是说,我让用户从命令行里输入一个子过程的名称,然后就可以根据这个名称来调用相对应的子过程。
方法一,直接根据用户输入的子过程名来调用该子过程。
完整的例子代码如下:
use warnings; no strict 'refs'; sub test_sub { print "test"; } $test = "test_sub"; $test->(); &{$test}(); #anyway to invoke the subroutine
这里要注意,需要用
no strict 'refs';
这个语句,否则脚本不能运行,Perl 解释器会提示类似于下面的错误:
Global symbol “$test” requires explicit package name at test2.pl line 10.
方法二,更常规的做法是专门用一个起分派作用的散列,根据用户输入的请示而调用相应的子过程。例如下面的 %dispatcher 就起到了绑定识别标记与相应子过程引用的作用,通过这个唯一的标记 (key),我们可以很容易地找到对应的子过程引用。
my %dispatcher = ( sub_test => sub { print "test" }, );
然后可以用和方法一相同的语法来调用这个子过程:
$dispatcher{$sub_name}->();
下面是方法二的一个完整的例子:
use warnings; use strict; sub test_sub { print "test\n"; } sub test_other { print "test other\n"; } my %dispatcher = ( "test_sub" => \&test_sub, "test_other" => \&test_other, ); print "\nPlease enter the test case you want to test:\n"; while( my $cmd = <> ) { chomp($cmd); $dispatcher{$cmd}->() if exists $dispatcher{$cmd}; }
当然,方法二要比方法一优秀得多,它可以避免用户输入错误的子过程名而导致一系列的麻烦。
今天用 VirtualBox 的时候,运行到一半,突然 VirtualBox 弹出如下图的错误提示框:

上面提到的错误是硬盘空间不足:
Host system reported disk full. VM execution is suspended. You can resume after freeing some space.
刚碰上这个问题的时候,我也找了很久原因。明明虚拟机的硬盘设成了 16 G,Host 机器上的硬盘空间也还有几十G,怎么会不够呢?
这个原因很可能是你使用的是 FAT32 文件格式,不支持超过 4GB 的文件。解决的办法很简单,把文件系统从 FAT32 升级到 NTFS 即可。
用 Thunderbird Portable 版本,的确是很方便,我换了一台电脑,只要把它拷过来就可以用了,最重要的是,一切配置都在!
把 Thunderbird Portable 整个拷过来后,基本的功能如发送接收邮件都没啥问题,可是不知道为什么,当我编辑邮件过滤规则(Message filters)时,虽然新增加的过滤规则能立即生效,但是下次重新启动 Thunderbird Portable 后,过滤规则列表又会恢复到修改前的状态。也就是说,新增加的邮件过滤规则(Message filters)全部没有保存下来。
我反复尝试了好几次,结果都是一样。我不禁在怀疑,很可能是 Windows 的 NTFS 文件格式在捣乱。
我试着手动修改、保存 Message Filters 的配置文件 msgFilterRules.dat(针对不同 Thunderbird 版本,配置文件的存放路径各不相同,可查阅官方手册),在我的电脑上,大致是这样一个路径:
e:\PortableApps\ThunderbirdPortable\Data\profile\ImapMail\10.67.10.10\msgFilterRules.dat
结果发现 Windows 的 NTFS 文件格式并没有限制我对 msgFilterRules.dat 文件的访问,并且当我通过手动修改这个文件并添加了一些邮件过滤规则后,在 Thunderbird 里面也能获得更新。看来,肯定是其它问题。
经过多方打探,终于在 Thunderbird 的官方论坛找到解决办法:
先退出 Thunderbird,然后在你帐号里的配置文件目录(profile folder)里,找到并删除 tmprules.dat 这个文件,重启进入 Thunderbird,应该就可以了。
虽然我用的是 Thunderbird Portable 版本,但如果这样的问题也发生在正常的 Thunderbird 版本上,可以用同样的方法解决问题。唯一需要注意的是,你当前帐号的配置文件路径(profile folder)可能不一样。