2006年03月25日
http://my.donews.com/leal
2005年12月31日

Life Topic学了些什么,做了些什么,感悟了些什么?

Vim Topicscoming soon

2005年10月28日

Java尽管gigix在序言里说“还负责全书的文字修润”,但是如果首次的翻译已经不堪入目,那么再加修润无疑是愈行愈远,毫无帮助;何况从某些章节的翻译来看,根本就是脱离了英文原文在那儿做盲目的所谓修润(如果有的话)。而技术书籍的根本我个人以为“忠实原文,行文流畅”是至少应具备的。
  
  可惜,8个人参与翻译的这个中文版再次让人失望,尽管许多人对它的总体评价尚可。但是这么多人参与,无疑必会有鱼目混杂嫌疑,何况“国内J2EE技术圈里小有名气的人物”未必一定有过硬甚至基本的英文翻译水平。
  
  在顺畅的阅读之余,拿起英文原版书来对照一番吧,以便对中文的质量心里有底。我们不相信权威,更不应相信经过“翻译”的权威。看看第9/10章的翻译和原文对比,相信你会对此作出自己的判断。我只对比了第9章部分中英文(有两到三页),但是漏译、误译数量相当可观,绝非所谓勘误所能解决。
  
  (译者维护的勘误表)
  
  鉴于此,我有理由怀疑Robbin负责的全部翻译(即9/10章)。
  
  看来多人合作也要慎重啊。
  
  (尽管我初学J2EE,并无太多这方面的基础知识和技术积累,但看到9章第二段里的transaction demarcation译成“声明式事务”时,无论如何也无法容忍。)
  
  建议读过本书中文版或未开始读的朋友重读或直接阅读英文版9/10章。
  
  其它章节的翻译有待进一步观察。
  
  在讨论区里对第16章做了部分校对,也就五六页的样子,但是误译/待改进之处已数十计,没有心情再继续校对下去。这部分是 刘天北 负责翻译的。
  
  让我们记住JavaEye吧……不知道责编们是干什么的,无语。
  
  中文版还是要谨慎购买……

 最初发表地址

2005年10月18日

Emacs主要涉及Emacs学习从初级到高级的一些文档/书籍

从初级到高级排列;也可参看我的豆列

  ❑ Emacs Beginner’s HOWTO

  http://jeremy.zawodny.com/emacs/

  

  对Emacs有一个基本的认识和了解,比较全面缺又不拘泥于细节,同时有部分命令快速参考。

  

  ❑ Learning GNU Emacs 3/e

  http://www.douban.com/subject/1431970/

  

  国内已翻译出版了2/e,非常适合初学者,一个个命令和概念娓娓道来,辅之以截屏,甚至可以让你躺在床上学Emacs,不过要让你的手指习惯Emacs最好还是乖乖坐在电脑前边看边实践的好。

  

  ❑ Sams Teach Yourself Emacs in 24 Hours

  http://www.douban.com/subject/1432323/

  

  国内有不少朋友极力推荐此书,没细看。不过一天学惯Emacs的诱惑也挺吸引人的。不凡一天看一小时吧,反正Emacs是这辈子学不完的东东,急个啥。和上面一书属同一层次,截屏也多,每个hour后辅之以练习。

  

  ❑ Writing GNU Emacs Extensions

  http://www.douban.com/subject/1432819/

  

  大致翻了一下内容,涉及Emacs本身(当然主要是剖析一些基本概念而非陷在具体命令/操作上)和Lisp。当然本书也不是要教你Lisp,只是一些基本知识。如果你要进行一些高难度的定制,或许可以从本书开始。上面的HOWTO指南推荐。

  

  ❑ An Introduction to Programming in Emacs Lisp

  http://www.douban.com/subject/1432501/

  

  一本基础级的Emacs Lisp编程介绍,不是专门写给程序员的,不知道这一点是否会让你不那么排斥这本书。Emacs的定制?哦,也可以从此开始嘛。上面的HOWTO指南也推荐了此书。

  

  ❑ Gnu Emacs Lisp Reference Manual

  http://www.douban.com/subject/1432583/

  

  Richard Stallman写(还有其它作者)的,还有的说?Emacs Lisp编程的绝对指南,不过900多页的书啊,你要有思想准备。还好现在的搜索技术了得。全书可自由获取。

  

  ❑ GNU Emacs Manual

  http://www.douban.com/subject/1432361/

  

  又一本官方指南……

Emacs(主要涉及Emacs buffer相关主题)

怎么才能知道Emacs中活动buffer的数量?有三种方法:buffer列表(键入C-x C-b时显示在一窗口中),Buffers菜单(它列出了活动的buffer和浏览这些buffer的命令),还有Buffer弹出菜单(按住Ctrl,单击鼠标左键访问,它根据模式列出buffer)。

Emacs会创建它自己的专用buffer。这些内部buffer的名字一般来说格式为 *buffer name* 。*Help*、*scratch*和*Buffer List*就是Emacs创建的其中一些buffer。

当你启动Emacs时,它会建立两个buffer:

*Messages*
*scratch*

*Messages* buffer存储了Emacs收集自它启动时从minibuffer里显示的消息;*scratch*是个临时的scratchpad(涂鸦板),以便你有地方输入东西。除非你使用C-x C-w明确的把它写到文件中,否则它不会被保存下来。

当然,一般来说你用Emacs编辑文件时,这些文件就会被拷贝到同名的buffer中。如果你需要获得帮助,则会进入 *Help* buffer。

能在Emacs里打开的buffer数量实际上没有限制。大多数情况下,只显示一个或两个buffer;不过即使你无法看到全部,你在某个Emacs会话里创建的buffer仍处于活动状态。你可以把这些buffer想象成一叠纸,只有放在最上面的那页才显示在你眼前。不过任何时候,你都可以翻到另一页(另一个buffer),或者也可以创建一个新页。

每个buffer都关联一个主模式(major mode),它决定了Emacs在这个buffer里的行为。例如,设计用来书写文本的文本模式(text mode),和Lisp模式的表现就不一样,后者被设计用来编写Lisp程序。

如何操作多个buffer

如果要新建包含一个文件的buffer,只需键入 C-x C-f 找到该文件。Emacs就会自动新建一个buffer并定位到该buffer。如果该文件已打开,C-x C-f 只是定位到已有buffer中,这一点很有意义,可以避免同一文件存在多个buffer导致混乱。如果键入 C-x C-f 后输入的文件名不存在,Emacs认为你想新建一个文件,并定位到一个空白buffer中。

C-x b:在多个buffer之间进行切换;键入命令后输入buffer名,回车。如果已存在该buffer,则切换到该buffer中;否则以输入的buffer名新建一个buffer,但是注意这个buffer并没有和文件相关,因此关闭Emacs,它不会给你任何提示。

C-mouse 1:按住Ctrl并单击鼠标左键,会弹出一个Buffer Menu,它会按主模式类型列出活动的buffer供你选择。

C-x ->(<-):按下C-x后(放开)再按向右(左)方向键可以定位到下(上)一个buffer中。

如何删除buffer

注意:如果你修改了一个buffer(且该buffer和一个文件相关),则Emacs会在删除buffer前询问你是否保存所做修改;如果这个buffer和文件不相关,则你在该buffer里所做任何修改都会丢失,Emacs认为你不在乎这些buffer因此不作任何提示。因此编辑重要的buffer之前最好先 C-x C-w 写到文件中,或者用 C-x C-f 新建buffer。

C-x k:kill-buffer命令,删除一个buffer;

M-x kill-some-buffers:删除一些buffer;

如果删除了当前会话里的所有buffer,Emacs会新建一个 *scratch* buffer,总得有个东西显示在屏幕上不是?:P

如何保存buffer

C-x C-s:保存当前buffer;

C-x s:即save-some-buffers命令,一次保存所有buffer;

如何重命名buffer

M-x rename-buffer:重命名buffer;

如何使buffer只读

C-x C-q:切换buffer的read-only和read-write状态;

buffer和window的关系

buffer和window并不是一一对应的,同一个buffer可以有多个window,比如你可以同时在多个window里查看同一buffer的不同部分。Mark是和buffer关联的;而point是和window关联的。

C-x 2:即split-window-vertically命令,水平切分窗口;

C-x 3:垂直切分窗口;

C-x 4 b(f):在另一个窗口选择另一个buffer(查找另一个文件),这样你可以不用切换到另一个window,就改变其buffer或打开文件;

C-M-v:滚动另一个window(C-v是滚动当前window);

C-x o:此处 o 表示other(其它),移动光标到另一个window;

C-x 0:删除当前所在的window;

C-x 1:删除当前所在window之外的所有window;

C-x 5 2:新建一个frame;


2005年10月17日

Emacs(主要涉及 Emacs LISP初步)

参考:Learning GNU Emacs 3/e,9.8.The Lisp Modes,11.Emacs Lisp Programming

Emacs有三种Lisp模式,其命令名称如下:


 emacs-lisp-mode  用于Emacs Lisp代码的编辑(文件名.emacs或后缀.el)
 lisp-mode  用来编辑另一个Lisp系统的Lisp代码(后缀.l或.lisp)
 lisp-interaction-mode  用来编辑和运行Emacs Lisp代码(交互模式)


本文只讨论 lisp-interaction-mode模式。

缺省情况下*scratch*就是处于这种模式,无后缀的文件名一般也会让Emacs进入Lisp交互模式,当然你可以使用变量auto-mode-alist进行设置。

键入 M-x lisp-interaction-mode Enter(回车)可以让任何buffer进入Lisp交互模式;如要新建一个Lisp交互buffer,只需键入C-x b(即switch-to-buffer命令),输入buffer名,然后令该buffer进入Lisp交互模式。

Lisp交互模式和Emacs Lisp模式完全一致,除一个重要特性外:C-j已绑定到eval-print-last-sexp命令上。该命令提取point之前的那个S-expression,对其进行评估,然后在buffer里打印结果。如果要使用其它模式里绑定到C-j的常见功能newline-and-indent,你必须按下Enter,并紧跟Tab键。

记住 S-expression是任何符合Lisp语法的表达式。因此,可以使用 Lisp交互模式的C-j来检查变量的值,确认函数定义,运行函数等等。比如,如果你输入auto-save-interval并按下C-j,就会显示该变量的值(缺省为300)。如果你输入一个defun并在其最右边的括号后按下C-j,Emacs会保存所定义的函数(供以后调用)并输出其名称;这种情况下,C-j类似C-M-x(即eval-defun命令),不过光标必须位于所定义的函数之后(因为有可能在定义前或中间)。如果你调用了一个函数,Emacs就会评估(运行)该表达式并显示函数的所有返回值。

Lisp交互模式的C-j提供了很棒的功能,你可以用它来增量方式开发和调试Emacs Lisp代码;因为Emacs Lisp是种“真正的”Lisp,它甚至可用来开发其它Lisp系统的代码片断。

基本Lisp实体

你需要熟悉Lisp基本元素包括函数、变量和atom(原子)。函数是Lisp的唯一程序单元(program unit),涵盖了其它语言的过程、子程序、程序甚至操作符等标记。

函数被定义作上述实体的列表(list),通常是对其它现存函数调用的列表。所有函数都有返回值(return value)(类似Perl函数和non-void Java函数);函数的返回值就是list里最后一项的值,一般是最后调用的函数返回的值。在其它函数里的函数调用等价于其它语言的语句(statement),函数的语法如下:

function-name argument1 argument2 …)

等价于Java的:

method_name (argument1, argument2, …);

这一语法用于所有函数,包括那些等价于其它语言的算术或比较运算符。例如,在Java或Perl里2加4,你会用表达式2+4,而在Lisp里你会使用如下写法:

(+ 2 4)

类似的,4 >= 2的Lisp方式:

(>= 4 2)

Lisp中的变量和其它语言的相似,不过没有类型。Lisp变量能够推测任何类型的值(值本身没有类型,不过变量对其能存放的内容不加任何限制)。

原子(atom)是个任意类型的值,包括整数、浮点(实)数、字符、字符串、布尔值、符号(symbol)和Emacs特殊类型如buffer、window和process。各种atom的语法如下:

  • 整数:和你常用的一样,有符号,范围-2+27至2+27 – 1;
  • 浮点数:可用十进制和科学计数法表示的实数。例如5489可写成5489、5.489e3、546.9e1等;
  • 字符:以问号开头,如 ?a 。Esc、Newline和Tab可分别简写为\e、\n和\t;其它控制字符可以加\C-前缀来表示,例如C-a表示为?\C-a。整数也可用来表示字符,如ASCII表等。
  • 字符串:用双引号包围;字符串里的引号标记和\需要加上\,"Jane said, \"See Dick run.\""是个合法字符串。字符串可以分割成多行,不需特殊语法。结束引号前的所有内容包括所有断行符都是字符串值的一部分。
  • 布尔值:大部分情况下真值为t,假值为nil,如果能预估到布尔值,则任何非nil值都被看作真值。nil也被用作null或nonvalue。

  • 符号:Lisp实体名,如变量或函数名。有时需要引用实体的名字而非其值,这时可以在名字前加上单引号(’)。

setq用来赋值给变量,是个函数,而不象其它语言里用来赋值的专门语法=或:=。setq接收两个参数:一个变量名和一个值。也可以进行多次赋值,如:

(setq thisvar thisvalue
     thatvar thatvalue
     theothervar theothervalue)

也可用其它方法设置值或变量,不过setq是使用最广的方法。

函数定义

首先熟悉一下Lisp语法的特殊表示。- 用作“割断”字符用来分隔变量、函数等名称里的字(word),这是Lisp编程惯用法,类似C和Ada里的“_”。

A more important issue has to do with all of the parentheses in Lisp code. Lisp is an old language that was designed before anyone gave much thought to language syntax (it was still considered amazing that you could use any language other than the native processor’s binary instruction set), so its syntax is not exactly programmer-friendly. Yet Lisp’s heavy use of lists¡ªand thus its heavy use of parentheses¡ªhas its advantages, as we’ll see toward the end of this chapter.

让我们从一个实例开始。

1  (defun count-words-buffer ( )
2    (let ((count 0))
3      (save-excursion
4        (goto-char (point-min))
5        (while (< (point) (point-max))
6          (forward-word 1)
7          (setq count (1+ count)))
8        (message "buffer contains %d words." count))))

defun:指定函数名和参数来定义函数。注意defun本身是一个函数――被调用时,定义一个新函数。(defun返回把所定义的函数作为一个symbol返回。)函数的参数显示为在括号内的一个名字list;本例,函数没有参数。如果在参数前加关键字&optional就表示参数是optional(可选的)。如果参数是optional的,在函数调用时未指定该参数,则认为其值为nil。

(let ((var1 value1) (var2 value2) … )
  statement-block)

let:1.定义(或声明)一个变量list;2.变量设置初始值,同setq;3.创建一个语句块(类似函数体),在此块内这些变量可用,let块即这些变量的scope(作用域)。let里定义的变量可用setq改变其值,不过要小心使用setq。

save-excursion:Emacs内建函数,保存光标原来的位置(因为 count-words-buffer函数要移动光标以便计算字数)。调用 save-excursion就是要求Emacs记住实例函数开始执行时的光标位置,并在执行完函数体内的所有语句后返回至初始光标位置。

goto-char:Emacs内建函数,其参数是个(内嵌)函数调用,调用内建函数point-min。point是Emacs内部名称,表示光标的当前位置。point-min返回当前buffer里第一个字符的位置值,几乎总是1;这样goto-char调用时其参数值为1,效果等同于把point移至buffer起始处。

(while condition     statement-block)

和let及save-excursion一样,while也建立了一个语句块。condition是个值(atom、变量或返回一个值的函数)。while对这个值进行测试,如果其值不是nil,则认为条件(condition)为真,语句块得以执行,然后condition再次被测试,之后重复上述过程。当然也可以写个无限循环,如果你试图执行这样的语句,Emacs会挂起,键入C-g终止。

在实例函数中,condition是函数 < ,即带两个参数的小于函数,类似Java或Perl里的<运算符。第一个参数是另一个函数,它返回point的当前字符位置;第二个参数返回buffer里的最大(最后)字符位置,即buffer的长度。函数 < (和其它关系函数)返回一个布尔值,t 或 nil。

上述循环的语句块由两条语句组成。第6行会把point往前移动一个字(word,即相当于M-f)。第7行,循环计数器加一;函数 1+ 是(+ 1 variable-name)的简写方式。注意第三个右括号(第7行)和while前面的左括号匹配。这样,在计算字数时,while循环会让Emacs一次一个字(word)遍历整个当前buffer。

实例函数的最后一个语句使用内建函数message在minibuffer里打印一行信息,提示buffer所含的字数。message函数的格式类似C语言。


Message格式字符串
 格式字符串  含义
 %s  字符串或symbol
 %c  字符
 %d  整数
 %e  科学计数法表示的浮点数
 %f  十进制表示的浮点数
 %g  任意格式的浮点数,产生最短的字符串


将Lisp函数变为Emacs命令

函数 count-words-buffer已编写完成,接下来该如何运行?在交互模式中,可以把光标移到函数的结束括号,然后键入C-j(或Linefeed),让Emacs执行函数定义。你应该看到该函数的名字会再次出现在buffer里;defun函数的返回值就是已定义的符号(即函数名称)。

函数定义之后,可以在Lisp交互窗口中输入一行 (count-words-buffer) ,然后在结束括号后再次按下 C-j 。

如果你象其它Emacs命令一样用M-x来执行上述函数,M-x count-words-buffer Enter,会得到错误提示信息 [No match]。这是因为你并未在Emacs中“注册”该函数,使其可供交互(interactive)使用。实现这一功能的函数是 interactive ,形式如下:

(interactive "prompt-string")

上述语句必须出现在函数开始处,即紧随defun和文档说明字符串所在行之后。使用 interactive 会让Emacs把函数注册为一个命令,并提示用户输入defun语句中声明的参数。提示字符串为可选。

提示字符串有一个特殊的格式:你要为想提示用户输入的每个参数都提供一段提示字符串,这些段用“\n”分隔。


用于interactive函数的参数代码
代 码
提示用户输入
  b 
 现存buffer的名称
  e 
 事件(鼠标动作或 function key press)
  f 
 现存文件的名称
  n 
  数字(整数)
  s 
 字符串
   上述代码都有一个大写的变种
  B    可能不存在的buffer名称
  F  可能不存在的文件名称
  N 
 数字,unless command is invoked with a prefix argument, in which case use the prefix argument and skip this prompt
  S   符号

 
示例:

(defun replace-string (from to)
  (interactive "sReplace string: \nsReplace string %s with: ")
  …)

回到 count-words-buffer 命令:它不需参数,因此 interactive 命令不需要提示字符串。另外可以再给我们的命令添加一个文档说明字符串(doc string),它会显示在describe-function(C-h f)之类的在线帮助工具中。Doc string是普通的Lisp字符串,可选,行数长度任意,不过一般来说,第一行是个简要完整的句子,说明命令的功能。注意字符串里的任意双引号前必须加上 \ 。

(defun count-words-buffer ( )
  "Count the number of words in the current buffer;
print a message in the minibuffer with the result."

  (interactive)
  (save-excursion
    (let ((count 0))
      (goto-char (point-min))
      (while (< (point) (point-max))
        (forward-word 1)
        (setq count (1+ count)))
      (message "buffer contains %d words." count))))

2005年10月16日

Vim译自 Vim [2005-10-15]

(正如10-09的公告所说,一切顺利就在一周内发布6.4版,真的来了!:))

距上次Vim 6.3版本发布已经过去了一年多。到现在为止,数十个bugs已被修复,runtime(运行时)文件也做了增补和更新。该版本并没有增加新特性,等到Vim 7发布才会有(目前仍在开发中)。这是个稳定的Vim发布版,欢迎也鼓励所有用户升级到6.4版。可在 通告(the announcement)里或安装后执行“:help version-6.4”命令查看发布备忘录(release notes)。Happy Vimming! (Bram Moolenaar

2005年10月15日

Emacs本文主要说明 Emacs on Windows(XP,相信也使用2K以上其它版本)的安装和配置(涉及部分配置文件)的整个流程,作为记录保存。另外推荐安装 CygwinEmacs 提供强大的Shell。

本文写作时参考了EMACS在windows下的配置 一文。

1.  我可不想在Windows下编译 Emacs,因此第一选择是获取别人已编译好的二进制文件。推荐使用 nqmacs,目前版本为22.0.50.1。它是一个zip压缩包,无需安装,解压后运行 emacs/bin/runemacs.exe即可(emacs.exe为console版<->emacs -nw on linux)。不过要让它乖乖就范,还需要做一些设置。

2. Emacs通过HOME变量来查找.emacs配置文件(或_emacs on Windows,如果两者都存在,则用.emacs),如果不设置该变量,Emacs会在C:\目录下查找配置文件。显然这不怎么安全,也不怎么爽。那就来设置HOME变量吧:
    • 系统环境变量:新建系统环境变量HOME,指向自己喜欢的文件夹路径;
    • 修改注册表:运行emacs/bin/addpm.exe,把Emacs相关信息添加到注册表中,然后在注册表(命令:regedit)中查找Emacs项,新建“可扩充字符串值”(REG_EXPAND_SZ),“数据”设为自己喜欢的文件夹路径。这样就可以把.emacs扔到这个路径下了。
3. 中文支持。该版本Emacs不作任何设置即可支持中文(需进一步确认),不过缺省情况下字体可能不如意,如何设置呢?(Need Improvement)某些病态的软件如雅信CAT会修改系统字体,导致无法自定义Emacs里中文字体。(需进一步研究)

;; setup chinese language support

;; GB2312 settings
(set-language-environment ‘Chinese-GB)
(set-keyboard-coding-system ‘chinese-iso-8bit)
(set-clipboard-coding-system ‘chinese-iso-8bit)

(create-fontset-from-fontset-spec
 (concat "-*-Courier New-normal-r-*-*-13-*-*-*-c-*-fontset-chinese,"
         "-*-Courier New-bold-r-*-*-13-*-*-*-c-*-fontset-chinesebold,"
         "chinese-gb2312:-*-MS Song-normal-r-*-*-14-*-*-*-c-*-gb2312*-*,"
         "chinese-big5-1:-*-MingLiU-normal-r-*-*-14-*-*-*-c-*-big5-*,"
         "chinese-big5-2:-*-MingLiU-normal-r-*-*-14-*-*-*-c-*-big5-*"))

4. XXX

5. Emacs新手?快速参考推荐看看王春宇的Wiki
2005年10月14日

Emacs有这么一个通讯簿,在 Emacs 中如何将其按字母顺序排序?




李四      (212)555-7812
张三      (904)555-0332
王五      (703)555-2112
小薇      (814)555-7878

定位到第一行,M-a到句首,C-@设置Mark(标记),用C-n选取四行,最终这四行选中成为一个Region(区域)。最后使用C-u M-| sort把Shell Command On Region:sort (M-| sort)的结果插入到当前buffer的Mark位置处(C-u)。结果如下:

李四      (212)555-7812
王五      (703)555-2112
小薇      (814)555-7878
张三      (904)555-0332

参考书籍:Learning GNU Emacs 3rd Edition 2.3,5.1(章.节)