zwz 那些事

点滴记录

在 emacs 中进行文本编辑时,经常为了美观和方便编辑,通过 M-q 对段落内容进行重排。这时, emacs 会自动根据 fill-column 的大小,在合适的位置插入换行符,使得文字不会过长。这种换行称之为软换行。通常,软换行不会带来什么问题。但是在一个软件和另一个软件进行数据交换,或者一种格式转换为另一种格式的时候,这个问题就开始突显出来了。

org-mode 作为一个能够导出成其他多种格式的强大工具,对软换行进行了格外的照顾,引入了如下一个选项,用于控制在导出时是否在软换行处产生一个换行。

#+OPTIONS: \n:nil

显然,默认的大部分情况下,我们不希望产生一个硬换行,正如上面的设置一样。比如,如果将下面的文档导出为 html ,每个软换行都产生一个硬换行的话,结果看起来将会非常不美观,因为每一(段)行都很短。

* test
This is a test about soft
line-breaks for ox. 这里有一个软
换行。

因此在默认情况下, org-mode 将软换行替换为一个空格。因此下面这个文档默认导出 html 时,其实只有一段。

This is a test about soft line-breaks for ox. 这里有一个软 换行。

注意,“软”和“换”之间存在一个空格。org-mode 对软换行的这种处理是根据西方的语言特点设计的,对于中文、日文等东方语言来讲,这会产生一个不必要的空格。这个问题在新闻组里已经被多人指出,如作为一个 bug 提出有截图说明

这其实是一个国际化问题,希望 org-mode 能够尽快就该问题给出一个官方的解决方案。我目前对这个问题的解决方法就是, 认为中文字符与中文字符之间的换行都是没有必要的,在 org-mode 完成 html 导出时,将所有的这种换行去掉。代码如下, 就不解释了,没有难度。采用循环的原因是因为类似 replace-regexp-in-string 这样的函数不能正确处理隔一个中文字符就有软换行这种情况。

(defun clear-single-linebreak-in-cjk-string (string)
  "clear single line-break between cjk characters that is usually soft line-breaks"
  (let* ((regexp "\\([\u4E00-\u9FA5]\\)\n\\([\u4E00-\u9FA5]\\)")
         (start (string-match regexp string)))
    (while start
      (setq string (replace-match "\\1\\2" nil nil string)
            start (string-match regexp string start))))
  string)

(defun ox-html-clear-single-linebreak-for-cjk (string backend info)
  (when (org-export-derived-backend-p backend 'html)
    (clear-single-linebreak-in-cjk-string string)))

(add-to-list 'org-export-filter-final-output-functions
             'ox-html-clear-single-linebreak-for-cjk)

以上代码只用于 org-mode 8.0 以上版本,对于低版本来说,可以参考此文自行给出。关于中文字符和英语字符之间的软换行, 可能还需要考虑更多情况。以上代码仅仅通过初步测试,而且也只是很片面的考虑了我常用的几种导出格式而已,可能还存在问题,欢迎指出。

blog comments powered by Disqus