重装系统后,Emacs 打开以前的文件,都显示为乱码,着实吓了我一跳。这个时候千万不要慌张,也不要随便地保存乱码的文件。
其实这只是 Emacs 读取文件的编码格式与你的文件格式不一样。我们可以用 M-x describe-coding-system 这个命令来查看一下 Emacs 是用什么编码来读取当前文件的。
比如说我的 org 文件都是用 UTF-8 来保存的,而打开某个 org 文件显示乱码,用命令 M-x describe-coding-system 显示当前解读的编码为:
1 -- iso-latin-1-unix (alias: iso-8859-1-unix latin-1-unix)
Emacs 错把 UTF-8 的编码解读成了 latin 编码格式,难怪会乱码!
这个时候,有两种解决办法。
在 .emacs 文件里放入下面这段代码:
;; set the default text coding system (setq default-buffer-file-coding-system 'utf-8)
可是即使我加了上面这条语句,为什么 Emacs 依然显示 org 文件为乱码呢?
原来上面这一行,只是适用于写文件的情况。当你读取一个文件的时候,可能依然会显示出乱码,因为 Emacs 读文件也是按照一定的编码规律来解读文件的。我们再用命令 M-x describe-coding-system 仔细观察一下结果里面的内容,是不是有类似下面这样一段:
Priority order for recognizing coding systems when reading files:
1. iso-latin-1 (alias: iso-8859-1 latin-1)
2. utf-8 (alias: mule-utf-8)
3. iso-2022-7bit
4. iso-2022-7bit-lock (alias: iso-2022-int-1)
5. iso-2022-8bit-ss2
6. emacs-mule
7. raw-text
8. iso-2022-jp (alias: junet)
9. in-is13194-devanagari (alias: devanagari)
10. chinese-iso-8bit (alias: cn-gb-2312 euc-china euc-cn cn-gb gb2312)
11. utf-8-auto
12. utf-8-with-signature
13. utf-16
14. utf-16be-with-signature (alias: utf-16-be)
15. utf-16le-with-signature (alias: utf-16-le)
16. utf-16be
17. utf-16le
18. japanese-shift-jis (alias: shift_jis sjis cp932)
19. undecided
这就是 Emacs 在读文件时候的解码顺序!如果你的文件是以英文开头,自然会套用第一种方法。这个时候,我们还需要调整一下这个编码的先后次序。用命令 M-x prefer-coding-system 就可以调整这些顺序。调整完顺序,再打开 org 文件看一看,终于恢复原貌了。
如果你只是用命令 M-x prefer-coding-system 来设置,下次重启 Emacs 的时候,这个设置就会自动清除。如果需要每次都采用这个设置,可以把下面这行扔到 .emacs 里指定优先用 utf-8 来解码:
(prefer-coding-system 'utf-8)
另外,碰到文件编码混乱的时候,最重要的一点,看到乱码的文件,不要随便保存。有关 Emacs 编码格式的详情可以看看官方文档。
原创文章,如转载请注明:转载自细节之锤 [ http://blog.WaterLin.org/ ]
Copyright © WaterLin.org. All rights reserved.
如果使用 Tabbar 而又不喜欢它默认的文档分组功能 ( group ),想自己控制哪些文档应该分成一组、哪些文档应该放到另外一组,可以参考下面的代码,重新定制 Tabbar 的分组规则:
(defun tabbar-buffer-groups (buffer) "Define tabbar groups depending on major mode and buffer name" (with-current-buffer (get-buffer buffer) (cond ((or (get-buffer-process (current-buffer)) (memq major-mode '(comint-mode compilation-mode))) '("Misc") ) ((eq major-mode 'org-mode) '("org") ) ((eq major-mode 'muse-mode) '("muse") ) ((memq major-mode '(fundamental-mode help-mode apropos-mode Info-mode Man-mode)) '("Misc") ) ((memq major-mode '(c-mode c++-mode)) '("Cpp") ) ((eq major-mode 'emacs-lisp-mode) '("Emacs-lisp") ) ((memq major-mode '(php-mode nxml-mode nxhtml-mode)) '("WebDev") ) ((memq major-mode '(tex-mode latex-mode text-mode snippet-mode)) '("Text") ) ((memq major-mode '(rmail-mode rmail-edit-mode vm-summary-mode vm-mode mail-mode mh-letter-mode mh-show-mode mh-folder-mode gnus-summary-mode message-mode gnus-group-mode gnus-article-mode score-mode gnus-browse-killed-mode)) '("Mail") ) ((string-equal "*" (substring (buffer-name) 0 1)) '("Emacs Buffer") ) (t '("Main") ) )))
代码的基本原则就是,根据 mode 来进行分组,比如说把基于 org-mode 的所有文件放到一个组里,把和 Web 开发有关的 mode (如 php-mode,nxml-mode 及 nxhtml-mode)放到一个组里。我觉得这样分组,更加有利于编辑效率的提高。
原创文章,如转载请注明:转载自细节之锤 [ http://blog.WaterLin.org/ ]
Copyright © WaterLin.org. All rights reserved.
在用 Emacs 编辑文档的时候,使用命令时经常会碰到大量的错误信息。但是,默认情况下,对于错误的提示信息不是很详细,我们很难分析究竟是哪里出错了。
这个时候,我们可以试着使用 Emacs 的 debug on error 特性。先用命令
M-x toggle-debug-on-error RET
激活当前缓冲区的 debug on error 功能,然后再运行之前出错的命令,则出错的时候会调用 Lisp 调试器 ( Lisp debugger )显示详细地调试信息,方便进一步地查找出错的真正原因。
这里要注意的是,每次需要 Lisp 调试器去捕捉错误信息的时候,就要用命令 M-x toggle-debug-on-error RET 激活一次,也就是说,该命令成功激活 debug on error 功能后,只有有效地使用一次!
如果你还不能解决问题的话,就把 Messages 缓冲区 ( buffer ) 里的全部内容(而不是一部分),以及 Lisp 调试器里的错误信息,一股脑地拷到新闻组或是论坛里去和别人讨论吧!
原创文章,如转载请注明:转载自细节之锤 [ http://blog.WaterLin.org/ ]
Copyright © WaterLin.org. All rights reserved.
如果你是用 Emacs Muse 来写文档、记笔记的话,直接在 Emacs Muse 里贴代码,会生成很混乱的风格。这个时候,我们需要灵活地使用 Muse 提供的标签 ( tag ) 功能。
Muse 标签的语法,基本上和 XML 里的差不多,大体上有以下几种情形:
<tagname arg1="string1" arg2="string2">
<tagname arg1="string1" arg2="string2" />
<tagname>Some text</tagname>
或者分成几行:
<tagname> Some text. Some more text. </tagname>
如果你要对 Muse 里的代码进行排版,则可以在 Muse 里使用 example 标签,基本形式如下:
<example> put code here </example>
这样,我们就可以在 CSS 文件里对 .example 类单独定义显示风格,从而这段代码、例子就不会受其他风格属性的影响。
如果我们需要对代码进行着色,则需要用 src 标签配合 htmlize.el 来对代码进行着色。所有包含在标签 src 里的内容,都会通过 htmlize.el 工具进行着色,我们可以对 CSS 文件里的 pre 进行定义,从而规定 src 生成后的相关属性。下面是一个例子:
<src lang="perl">
#!/usr/bin/perl
use strict;
use warnings;
my %hash = (frogs => sub {print "Frogs\n"});
$hash{$frogs}->();
</src>
我个人习惯用 src 标签来给代码着色,用 example 标签来发布代码运行的结果,并针对这两个区域设置不同的背景颜色,看起来会舒服多了,有兴趣可以看看这个例子。
我们也可以用 div 标签来给某一段内容单独设置 CSS 属性。因为中文的习惯是每段开头空两格,所以,我在 CSS 文件里默认就是每行开头空两格。但是,有一些内容,我不需要开头空两格,怎么办呢?我们可以在 CSS 文件里新建一个名叫 NoIndent 的 id 名称,然后通过 div 来使用这个 CSS 属性:
<div id="NoIndent"> put no indent content here </div>
我们可以在 CSS 文件里定义这个 NoIndent 的属性、任意定义我们需要的风格。比如说,下面就定义了不同的背景颜色与缩进:
#NoIndent { background-color: #F0F0F0; text-indent: 0em; } #NoIndent p { text-indent: 0em; }
也可以直接在 div 标签里使用 CSS 属性,例如下面的 div 标签就是让该段文字以 20 磅的黑体居中:
<div style="text-align:center;font-size:20pt;font-weight: bold;">
居中的标题
</div>
在发布文档的时候,有时我们需要在文档里插入一些程序运行的结果,这时可以使用<lisp> <perl> <python> <ruby>等标签。
除了上面提供到有关代码着色等的标签外,我们还经常会使用下面这些标签:
不进行解析,原文是什么内容,就是什么内容,这对于发布包含了大量特殊字符的段落特别有用。
引用标记,可以缩进。
在 Muse 里编辑文档,默认的情况下,如果只有一个换行符,则表明依然还是一段内容;有一个空行才表示是新的段落。用了 verse 后,就能完整保留编辑时的段落格式了。
发布时在当前位置插入指定的文件,习惯用法如下所示(当然,需要把”included_file”替换成实际的文件):
<include file="included_file">
如果能灵活地掌握这些标签的用法,我们就可以在 Muse 里进行有效地排版。如果你对使用某个标签发布后的结果不是太有把握,可以在 Firefox 里用 Firebug 来查看发布后的 html 页面代码,从而修订你的 Muse 文件或是 CSS 文件。
原创文章,如转载请注明:转载自细节之锤 [ http://blog.WaterLin.org/ ]
Copyright © WaterLin.org. All rights reserved.
当我们用 Emacs org 记了大量的笔记、写了大量的经验总结,我们当然会想着把它们发布成网站。通过把笔记发布成网页,我们可以方便地与他人分享我们的经验。总的来说,比较常用的方法有下面三类:
第一,如果只是发布成静态网页,使用 org 内置的页面发布功能就足够了(或查看这个文档)。
第二,如果我们需要更加复杂、抽象的功能,可以使用 blorg 或是 blorgit 工具。
第三,通过使用下面 Manoj Srivastav 提供的 Ikiwiki 插件,我们可以让 org 作为我们的 Ikiwiki 输入引擎。
#!/usr/bin/perl
# File: org.pm
# Time-stamp: <2009-02-06 12:10:28 srivasta>
#
# Copyright (C) 2008 by Manoj Srivastava
#
# Author: Manoj Srivastava
#
# Description:
# This allows people to write Ikiwiki content using Emacs and org-mode
# (requires Emacs 23), and uses the html export facility of org-mode to
# create the output. Some bits based on otl.pm.
package IkiWiki::Plugin::org;
use warnings;
use strict;
use Carp;
use IkiWiki 3.00;
use File::Temp qw/ tempfile tempdir /;
# ------------------------------------------------------------
sub import {
hook(type => "getsetup", id => "org", call => \&getsetup);
hook(type => "htmlize", id => "org", call => \&htmlize);
} #
sub getsetup () {
return
plugin => {
safe => 0,
rebuild => undef,
advanced => 1,
},
emacs_binary => {
type => "string",
example => "/usr/bin/emacs-snapshot",
description => "location of an emacs binary with org-mode",
advanced => 1,
safe => 0,
rebuild => undef,
},
}
sub htmlize (@) {
my %params = @_;
my $dir = File::Temp->newdir();
my $ret = open(INPUT, ">$dir/contents.org");
unless (defined $ret) {
debug("failed to open $dir/contents.org: $@");
return $params{content};
}
my $emacs = '/usr/bin/emacs-snapshot';
if (exists $config{emacs_binary} && -x $config{emacs_binary}) {
$emacs = $config{emacs_binary};
}
print INPUT $params{content};
close INPUT;
$ret = open(INPUT, ">/tmp/contents.org");
print INPUT $params{content};
close INPUT;
my $args = "$emacs --batch -l org " .
"--eval '(setq org-export-headline-levels 3 org-export-with-toc nil org-export-author-info nil )' " .
"--visit=$dir/contents.org " .
'--funcall org-export-as-html-batch >/dev/null 2>&1';
if (system($args)) {
debug("failed to convert $params{page}: $@");
return $params{content};
}
$ret = open(OUTPUT, "$dir/contents.html");
unless (defined $ret) {
debug("failed find html output for $params{page}: $@");
return $params{content};
}
local $/ = undef;
$ret = <OUTPUT>;
close OUTPUT;
$ret=~s/(.*<h1 class="title">){1}?//s;
$ret=~s/^(.*<\/h1>){1}?//s;
$ret=~s/<div id="postamble">.*//s;
$ret=~s/(<\/div>\s*$)//s;
open(OUTPUT, ">/tmp/contents.html");
print OUTPUT $ret;
close OUTPUT;
return $ret;
}
# ------------------------------------------------------------
1; # modules have to return a true value
我使用第一种方法,比较简单,缺点是与读者的互动性比较差。
原创文章,如转载请注明:转载自细节之锤 [ http://blog.waterlin.org/ ]
Copyright © WaterLin.org. All rights reserved.
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.
总的来说,Emacs的默认配置文件放在变量HOME所指的路径下,所以,只要我们把.emacs扔到HOME所指向的目录就可以了,下面就简单介绍一下在Windows下设置home目录的几种方法,并进行简单的对比。
第一种方法,改变home环境变量的值。
这种方法,改变了$home变量,也会影响Cygwin或是其他一些应用程序,因为有一些程序会根据Windows的home环境变量来寻找数据存放的路径。
第二种方法,不改变Windows默认的home值,设置默认的.emacs文件读取你自己的Emacs配置文件,并重新设定Emacs的home目录。
你可以在Emacs中输入C-x C-f,然后打开路径~(即当前的home环境变量所指的路径,一般来说是这样的路径:C:/Documents and Settings/water/Application Data)。
看看显示的是哪个目录,如果此目录下没有.emacs,可以创建一个.emacs或_emacs,然后在这个.emacs文件里,加入如下语句:
(load-file “E:/water/.emacs”)
文件 E:/water/.emacs 才是我们真正的Emacs配置文件,我们可以在这个真正的配置文件里用如下语句设置我们的home目录:
(setenv “HOME” “E:/water”)
(setenv “PATH” “E:/water”)
;;set the default file path
(setq default-directory “~/”)
(add-to-list ‘load-path “~/emacs/site-lisp”)
这个方法的优点是比较简单同样也方便对.emacs文件备份,不会对其它应用程序产生任何影响。
第三种方法,修改注册表,在注册表中进行如下设置:
HKEY_LOCAL_MACHINE\SOFTWARE\GNU\Emacs\HOME=%emacs_dir%
以上三种方法都可以设置好Emacs的Home目录,但是,系统是按什么顺序来解析它们的呢?大体上的顺序是这样的:
1) 如果设置了环境变量HOME,则使用HOME指定的目录。
2) 如果设置了注册表里的值HKCU\SOFTWARE\GNU\Emacs\HOME,则使用这个值所指定的目录作为home目录。并不是太推荐使用这种方法,因为会导致用户共享一个home目录。
3) 如果 C:\.emacs 文件存在,则使用 C:\.emacs 这个文件。这个是为了向低版本的Emacs兼容,因为低版本的Emacs就是默认用这个文件作为配置文件。
4) 把用户的AppData目录作为home目录(通常来说,就是类似这样的目录 C:/Documents and Settings/water/Application Data ),这个用户的数据目录根据Windows版本的不同而有所不同。
我个人比较喜欢用第二种方法,即简单又方便备份。
今天下午上班的时候,公司居然断电了。等电来了之后,发现Emacs死活启动不了,也就是说,没有办法顺利读入配置文件,Emacs会提示如下图所示的错误:

仔细地查看了一下Emacs的home目录,发现多了一个叫.emacs.desktop.lock的文件,我估计这个文件是和Desktop扩展有关。我把这个文件删掉之后,Emacs就可以正常启动了。看来,以前碰到的类似情况,多半也是这个原因。
仔细地试了一下,原来Emacs在跑的时候,会产生这个文件,应该是用来缓存当前打开的文件名信息之类的数据。当Emacs正常退出时,这个文件会随着消失;但是如果Emacs非法退出,这个文件可能就没办法处理了。
删除应该不是最正确的处理方法,但是我目前也不知道应该怎样处理会更好一些。