Emacs Org 是什么,这里就不介绍了。

记得前不久我还用muse做笔记的,而现在就要用org,还是相当的纠结的。制作PDF最烦的就是中文显示了,周六用一整天折腾,终于搞定,现将过程记录下来。(仅在windows下测试通过,linux还未测试。)

本文只关注于使用Emacs Org生成PDF文档(尤其是中文显示问题),并假设读者对Emacs以及Emacs Org有一定的使用经历。

有任何问题,欢迎交流。邮件:wuyao721@163.com 微博:weibo.com/wuyao721 QQ:289811390 技术博客:blog.csdn.net/wuyao721

1 工具包

1.1 Linux(Emacs + texlive + gbk2uni)

除了Emacs之外,还要安装texlive,它是Latex在Linux下的一个发行版,我们要用到它的一个程序pdflatex,用它将tex文件转成pdf。在ubuntu下这样安装:

sudo apt-get install emacs23 texlive-latex-recommended latex-cjk-chinese

1.2 Windows(Emacs + MinGW + CTeX + gbk2uni)

CTeX是Latex在Windows下的一个发行版,同样的,它提供了程序pdflatex。

MinGW是GNU在Winodws下的一个发行版,我们要用到它的一个程序iconv。如果字符编码是GBK,就不用iconv了。

2 把org给黑了

既然org-mode没有考虑中文问题,那么只能黑它一下了。1

2.1 添加新的latex文档类型

latex默认的文档类型有article, report, book和beamer,我们这里要新建一个支持中文的article,叫cjk-article,这个类型里,我们不使用默认的latex package(也就是org-export-latex-default-packages-alist),而使用自己定义的latex package(也就是org-export-latex-packages-alist)。

(add-to-list 'org-export-latex-classes'("cjk-article""\\documentclass{article}[NO-DEFAULT-PACKAGES][PACKAGES][EXTRA]"("\\section{%s}" . "\\section*{%s}")("\\subsection{%s}" . "\\subsection*{%s}")("\\subsubsection{%s}" . "\\subsubsection*{%s}")("\\paragraph{%s}" . "\\paragraph*{%s}")("\\subparagraph{%s}" . "\\subparagraph*{%s}")))

2.2 自定义latex package

上面说到,要用自定义latex package,那么它是怎样的呢,请看:

(setq org-export-latex-packages-alist '((""   "CJK"   t)(""     "indentfirst"  nil)("pdftex"     "graphicx"  t)(""     "fancyhdr" nil)("CJKbookmarks=true"     "hyperref"  nil)
"%% Define a museincludegraphics command, which is
%%   able to handle escaped special characters in image filenames.
\\def\\museincludegraphics{%\\begingroup\\catcode`\\\|=0\\catcode`\\\\=12\\catcode`\\\#=12\\includegraphics[width=0.75\\textwidth]
}"))

考察上面的配置,我们关注两个要点:latex包CJK提供了中文支持,CJKbookmarks=true让中文书签得以显示。这样生成的tex文件就大概是下面的样子:

\usepackage{CJK}
\usepackage{indentfirst}
\usepackage[pdftex]{graphicx}
\usepackage{fancyhdr}
\usepackage[CJKbookmarks=true]{hyperref}

2.3 重定义生成pdf的命令

用pdflatex生成的pdf书签会有乱码问题,使用gbk2uni能解决这个问题。流程大概是这样的:

  1. pdflatex生成乱码书签的pdf
  2. iconv将utf-8格式的书签文本(也就是.out文件)转成gbk格式
  3. gbk2uni将书签文本转成指定格式
  4. pdflatex使用正确的书签文本生成没有乱码书签的pdf

如果org文件的格式是GBK,那么就不用第二步了。

(setq org-latex-to-pdf-process'("pdflatex -interaction nonstopmode -output-directory %o %f""iconv -f utf-8 -t gbk %b.out > %b.out.bak""mv %b.out.bak %b.out""gbk2uni %b.out""pdflatex -interaction nonstopmode -output-directory %o %f""rm %b.out.bak %b.tex"))

2.4 其它的小小改动

到目前为止,生成的tex文件头部分已经没有问题了,下面就要解决正文的问题。生成的tex文件正文必须是这样的:

\begin{document}
\begin{CJK*}{UTF8}{gbsn}
.....
\end{CJK*}
\end{document}

参考函数org-export-latex-make-header和org-export-as-latex,我们可以看到要插入=\begin{CJK*}{UTF8}{gbsn}=这样的tex代码的正确的位置,还是比较麻烦的。2 所以,我们要对这两个函数做小小的修改。(修改的el配置在后面贴出)

2.5 配置汇总(org-hack.el)

(require 'org)
(require 'org-latex)(add-to-list 'org-export-latex-classes'("cjk-article""\\documentclass{article}[NO-DEFAULT-PACKAGES][PACKAGES][EXTRA]"("\\section{%s}" . "\\section*{%s}")("\\subsection{%s}" . "\\subsection*{%s}")("\\subsubsection{%s}" . "\\subsubsection*{%s}")("\\paragraph{%s}" . "\\paragraph*{%s}")("\\subparagraph{%s}" . "\\subparagraph*{%s}")))(setq org-export-latex-packages-alist '((""   "CJK"   t)(""     "indentfirst"  nil)("pdftex"     "graphicx"  t)(""     "fancyhdr" nil)("CJKbookmarks=true"     "hyperref"  nil)
"%% Define a museincludegraphics command, which is
%%   able to handle escaped special characters in image filenames.
\\def\\museincludegraphics{%\\begingroup\\catcode`\\\|=0\\catcode`\\\\=12\\catcode`\\\#=12\\includegraphics[width=0.75\\textwidth]
}"))(setq org-latex-to-pdf-process'("pdflatex -interaction nonstopmode -output-directory %o %f""iconv -f utf-8 -t gbk %b.out > %b.out.bak""mv %b.out.bak %b.out""gbk2uni %b.out""pdflatex -interaction nonstopmode -output-directory %o %f""rm %b.out.bak %b.tex"))(defun org-export-latex-make-header (title opt-plist)"Make the LaTeX header and return it as a string.
TITLE is the current title from the buffer or region.
OPT-PLIST is the options plist for current buffer."(let ((toc (plist-get opt-plist :table-of-contents))(author (org-export-apply-macros-in-string(plist-get opt-plist :author)))(email (replace-regexp-in-string"_" "\\\\_"(org-export-apply-macros-in-string(plist-get opt-plist :email)))))(concat(if (plist-get opt-plist :time-stamp-file)(format-time-string "%% Created %Y-%m-%d %a %H:%M\n"));; insert LaTeX custom header and packages from the list(org-splice-latex-header(org-export-apply-macros-in-string org-export-latex-header)org-export-latex-default-packages-alistorg-export-latex-packages-alist nil(org-export-apply-macros-in-string(plist-get opt-plist :latex-header-extra)));; append another special variable(org-export-apply-macros-in-string org-export-latex-append-header);; define alert if not yet defined"\n\\providecommand{\\alert}[1]{\\textbf{#1}}";; changed by wuyao721@163.com;; beginning of the document"\n\\begin{document}\n\n""\n\\begin{CJK*}{UTF8}{gbsn}\n\n";; insert the title(format"\n\n\\title{%s}\n"(org-export-latex-fontify-headline title));; insert author info(if (plist-get opt-plist :author-info)(format "\\author{%s%s}\n"(org-export-latex-fontify-headline (or author user-full-name))(if (and (plist-get opt-plist :email-info) email(string-match "\\S-" email))(format "\\thanks{%s}" email)""))(format "%%\\author{%s}\n"(org-export-latex-fontify-headline (or author user-full-name))));; insert the date(format "\\date{%s}\n"(format-time-string(or (plist-get opt-plist :date)org-export-latex-date-format)));; insert the title command(when (string-match "\\S-" title)(if (string-match "%s" org-export-latex-title-command)(format org-export-latex-title-command title)org-export-latex-title-command))"\n\n";; table of contents(when (and org-export-with-toc(plist-get opt-plist :section-numbers))(funcall org-export-latex-format-toc-function(cond ((numberp toc)(min toc (plist-get opt-plist :headline-levels)))(toc  (plist-get opt-plist :headline-levels))))))))(defun org-export-as-latex (arg &optional hidden ext-plistto-buffer body-only pub-dir)"Export current buffer to a LaTeX file.
If there is an active region, export only the region.  The prefix
ARG specifies how many levels of the outline should become
headlines.  The default is 3.  Lower levels will be exported
depending on `org-export-latex-low-levels'.  The default is to
convert them as description lists.
HIDDEN is obsolete and does nothing.
EXT-PLIST is a property list with
external parameters overriding org-mode's default settings, but
still inferior to file-local settings.  When TO-BUFFER is
non-nil, create a buffer with that name and export to that
buffer.  If TO-BUFFER is the symbol `string', don't leave any
buffer behind but just return the resulting LaTeX as a string.
When BODY-ONLY is set, don't produce the file header and footer,
simply return the content of \\begin{document}...\\end{document},
without even the \\begin{document} and \\end{document} commands.
when PUB-DIR is set, use this as the publishing directory."(interactive "P")(when (and (not body-only) arg (listp arg)) (setq body-only t))(run-hooks 'org-export-first-hook);; Make sure we have a file name when we need it.(when (and (not (or to-buffer body-only))(not buffer-file-name))(if (buffer-base-buffer)(org-set-local 'buffer-file-name(with-current-buffer (buffer-base-buffer)buffer-file-name))(error "Need a file name to be able to export")))(message "Exporting to LaTeX...")(org-unmodified(let ((inhibit-read-only t))(remove-text-properties (point-min) (point-max)'(:org-license-to-kill nil))))(org-update-radio-target-regexp)(org-export-latex-set-initial-vars ext-plist arg)(setq org-export-opt-plist org-export-latex-options-plistorg-export-footnotes-data (org-footnote-all-labels 'with-defs)org-export-footnotes-seen nilorg-export-latex-footmark-seen nil)(org-install-letbind)(run-hooks 'org-export-latex-after-initial-vars-hook)(let* ((wcf (current-window-configuration))(opt-plist(org-export-process-option-filters org-export-latex-options-plist))(region-p (org-region-active-p))(rbeg (and region-p (region-beginning)))(rend (and region-p (region-end)))(subtree-p(if (plist-get opt-plist :ignore-subtree-p)nil(when region-p(save-excursion(goto-char rbeg)(and (org-at-heading-p)(>= (org-end-of-subtree t t) rend))))))(opt-plist (setq org-export-opt-plist(if subtree-p(org-export-add-subtree-options opt-plist rbeg)opt-plist)));; Make sure the variable contains the updated values.(org-export-latex-options-plist (setq org-export-opt-plist opt-plist));; The following two are dynamically scoped into other;; routines below.(org-current-export-dir(or pub-dir (org-export-directory :html opt-plist)))(org-current-export-file buffer-file-name)(title (or (and subtree-p (org-export-get-title-from-subtree))(plist-get opt-plist :title)(and (not(plist-get opt-plist :skip-before-1st-heading))(org-export-grab-title-from-buffer))(and buffer-file-name(file-name-sans-extension(file-name-nondirectory buffer-file-name)))"No Title"))(filename(and (not to-buffer)(concat(file-name-as-directory(or pub-dir(org-export-directory :LaTeX ext-plist)))(file-name-sans-extension(or (and subtree-p(org-entry-get rbeg "EXPORT_FILE_NAME" t))(file-name-nondirectory ;sans-extension(or buffer-file-name(error "Don't know which export file to use")))))".tex")))(filename(and filename(if (equal (file-truename filename)(file-truename (or buffer-file-name "dummy.org")))(concat filename ".tex")filename)))(buffer (if to-buffer(cond((eq to-buffer 'string) (get-buffer-create"*Org LaTeX Export*"))(t (get-buffer-create to-buffer)))(find-file-noselect filename)))(odd org-odd-levels-only)(header (org-export-latex-make-header title opt-plist))(skip (cond (subtree-p nil)(region-p nil)(t (plist-get opt-plist :skip-before-1st-heading))))(text (plist-get opt-plist :text))(org-export-preprocess-hook(cons`(lambda () (org-set-local 'org-complex-heading-regexporg-export-latex-complex-heading-re))org-export-preprocess-hook))(first-lines (if skip "" (org-export-latex-first-linesopt-plist(if subtree-p(save-excursion(goto-char rbeg)(point-at-bol 2))rbeg)(if region-p rend))))(coding-system (and (boundp 'buffer-file-coding-system)buffer-file-coding-system))(coding-system-for-write (or org-export-latex-coding-systemcoding-system))(save-buffer-coding-system (or org-export-latex-coding-systemcoding-system))(region (buffer-substring(if region-p (region-beginning) (point-min))(if region-p (region-end) (point-max))))(text(and text (string-match "\\S-" text)(org-export-preprocess-stringtext:emph-multiline t:for-backend 'latex:comments nil:tags (plist-get opt-plist :tags):priority (plist-get opt-plist :priority):footnotes (plist-get opt-plist :footnotes):drawers (plist-get opt-plist :drawers):timestamps (plist-get opt-plist :timestamps):todo-keywords (plist-get opt-plist :todo-keywords):tasks (plist-get opt-plist :tasks):add-text nil:skip-before-1st-heading skip:select-tags nil:exclude-tags nil:LaTeX-fragments nil)))(string-for-export(org-export-preprocess-stringregion:emph-multiline t:for-backend 'latex:comments nil:tags (plist-get opt-plist :tags):priority (plist-get opt-plist :priority):footnotes (plist-get opt-plist :footnotes):drawers (plist-get opt-plist :drawers):timestamps (plist-get opt-plist :timestamps):todo-keywords (plist-get opt-plist :todo-keywords):tasks (plist-get opt-plist :tasks):add-text (if (eq to-buffer 'string) nil text):skip-before-1st-heading skip:select-tags (plist-get opt-plist :select-tags):exclude-tags (plist-get opt-plist :exclude-tags):LaTeX-fragments nil)))(set-buffer buffer)(erase-buffer)(org-install-letbind)(and (fboundp 'set-buffer-file-coding-system)(set-buffer-file-coding-system coding-system-for-write));; insert the header and initial document commands(unless (or (eq to-buffer 'string) body-only)(insert header));; insert text found in #+TEXT(when (and text (not (eq to-buffer 'string)))(insert (org-export-latex-contenttext '(lists tables fixed-width keywords))"\n\n"));; insert lines before the first headline(unless (or skip (string-match "^\\*" first-lines))(insert first-lines));; export the content of headlines(org-export-latex-global(with-temp-buffer(insert string-for-export)(goto-char (point-min))(when (re-search-forward "^\\(\\*+\\) " nil t)(let* ((asters (length (match-string 1)))(level (if odd (- asters 2) (- asters 1))))(setq org-export-latex-add-level(if odd (1- (/ (1+ asters) 2)) (1- asters)))(org-export-latex-parse-global level odd)))));; changed by wuyao721@163.com;; finalization;;(unless body-only (insert "\n\\end{document}"))(unless body-only (insert "\n\\end{CJK*}")(insert "\n\\end{document}"));; Attach description terms to the \item macro(goto-char (point-min))(while (re-search-forward "^[ \t]*\\\\item\\([ \t]+\\)\\[" nil t)(delete-region (match-beginning 1) (match-end 1)));; Relocate the table of contents(goto-char (point-min))(when (re-search-forward "\\[TABLE-OF-CONTENTS\\]" nil t)(goto-char (point-min))(while (re-search-forward "\\\\tableofcontents\\>[ \t]*\n?" nil t)(replace-match ""))(goto-char (point-min))(and (re-search-forward "\\[TABLE-OF-CONTENTS\\]" nil t)(replace-match "\\tableofcontents" t t)));; Cleanup forced line ends in items where they are not needed(goto-char (point-min))(while (re-search-forward"^[ \t]*\\\\item\\>.*\\(\\\\\\\\\\)[ \t]*\\(\n\\\\label.*\\)*\n\\\\begin"nil t)(delete-region (match-beginning 1) (match-end 1)))(goto-char (point-min))(while (re-search-forward"^[ \t]*\\\\item\\>.*\\(\\\\\\\\\\)[ \t]*\\(\n\\\\label.*\\)*"nil t)(if (looking-at "[\n \t]+")(replace-match "\n")))(run-hooks 'org-export-latex-final-hook)(if to-buffer(unless (eq major-mode 'latex-mode) (latex-mode))(save-buffer))(org-export-latex-fix-inputenc)(run-hooks 'org-export-latex-after-save-hook)(goto-char (point-min))(or (org-export-push-to-kill-ring "LaTeX")(message "Exporting to LaTeX...done"))(prog1(if (eq to-buffer 'string)(prog1 (buffer-substring (point-min) (point-max))(kill-buffer (current-buffer)))(current-buffer))(set-window-configuration wcf))))

3 注意要点

如果你怎么整都是乱码的pdf,那么考虑以下几点

3.1 字符编码是否一致

看看是否把org文件保存成了GBK格式,而配置里却用了UTF-8。

3.2 分步实现

试试先生成tex文件,再用命令pdflatex生成pdf。这样能帮你发现问题所在。

3.3 emacs能否调用pdflatex,mv等命令

设置好环境变量,确保emacs能调用到这些命令

4 未解问题

有一些未解问题,请高手指点

4.1 示例超出pdf界限

以下的示例生成的pdf超出界限,怎么办呢?

apt-get install texlive-latex-base texlive-latex-recommended latex-cjk-chinese latex-cjk-chinese latex-cjk-chinese

4.2 pdf超链接有红色框框

pdf超链接有红色框框,这样的显示效果不怎么好。怎么办?

5 参考资料

  • http://orgmode.org/manual/LaTeX-and-PDF-export.html
  • http://orgmode.org/worg/org-tutorials/org-latex-export.html
  • http://orgmode.org/worg/org-contrib/babel/examples/article-class.html
  • http://blog.csdn.net/ywj1225/article/details/7407316
  • http://comments.gmane.org/gmane.emacs.orgmode/52201

Footnotes:

1 网上好像是说xelatex可以解决utf-8的问题,但是我真的不知道该怎么整。

2 参考http://blog.csdn.net/ywj1225/article/details/7407316 和 http://comments.gmane.org/gmane.emacs.orgmode/52201

Date: 2012-06-17 02:07:17 中国标准时间

Author: 吴遥

Org version 7.7 with Emacs version 24

Validate XHTML 1.0

使用Emacs Org制作PDF文档相关推荐

  1. pdf文件如何生成目录 wps_wps制作pdf文档的详细方法

    一些用户在使用wps软件的时候,wps怎样制作pdf文档?你们知道怎么操作的吗?对此感兴趣的伙伴们可以去下文看看wps制作pdf文档的详细方法. wps制作pdf文档的详细方法 一.打开或生成原始文件 ...

  2. 四款PDF文档制作软件横向评测

    PDF文档是大家非常熟悉的一种电子文档格式,由Adobe公司开发.PDF文档能够完整保留源文档中的所有字体.格式.颜色和图形等内容,已成为全世界各种标准组织分发和交换电子文档的出版规范.如今,不管是浏 ...

  3. pdf文档打不开是怎么回事?

    当您无法打开PDF时,可能是Acrobat Reader有问题,也可能是更复杂的故障,需要采取综合措施.先来了解一下pdf文档打不开是怎么回事?:以下是 PDF 无法打开的主要原因: 不支持的文件类型 ...

  4. 如何轻松把Word、pdf文档制作成翻页电子书,电子画册?

    如何Word.pdf文档制作成翻页电子书 使用友益文书软件9.5.1版可以轻松把图片.pdf.word格式文档制作成翻页电子画册或电子杂志(电脑阅读exe格式或安卓手机apk格式电子书或可微信分享的网 ...

  5. 该死!辛苦制作的PDF文档被人随意传播,甚至还被拿去卖钱?

    大家好,我是小一 不知道你有没有这样的经历:自己辛辛苦苦.通宵熬夜做的 PDF 文档被别人随意拿来传播,更有甚者被用来卖钱. 我们都说传播无罪,但是做这种事的人,你的良心不会痛吗? 今天就来说说如何保 ...

  6. PDF文字怎么编辑,PDF文档编辑方法

    有时候遇到PDF文件不是自己制作的或者是制作的有点匆忙,会有文字遗漏或者打错的时候,我们使用就会有点麻烦就需要把文件中的文字进行编辑修改,那么具体怎么做呢?小伙伴们都挺好奇吧,今天就来跟大家分享一下. ...

  7. C++ PDF文档相关操作

    人生总是在赶着一个又一个的期限,直到最后的大限. 近来基本没更新过博客,实在是准备雅思看英语加上调节老看英语后的烦躁心情闹的.本来以为考完研就与大考再也不见了,这种想法实在是 Too young,To ...

  8. 【PDF】java使用Itext生成pdf文档--详解

    [API接口] 一.Itext简介 API地址:javadoc/index.html:如 D:/MyJAR/原JAR包/PDF/itext-5.5.3/itextpdf-5.5.3-javadoc/i ...

  9. 怎样在PDF文档中添加插入图片

    制作编辑文档的时候经常需要在文档中添加一些图片内容,这样可以使文档更生动.像word.ppt这些文档可以直接通过复制粘贴就可以了,那么编辑pdf文件的时候怎样在文件中插入图片呢? 方法/步骤 首先是需 ...

最新文章

  1. ubuntu 发行版升级注意事项
  2. 推荐一款Java开发的精美个人博客
  3. 谷爱凌的父亲不是谷歌5号员工,但母亲一家都是高学历的运动健将
  4. 四-1、Cadence Allegro推荐操作方式和视图命令
  5. [蓝桥杯][2018年第九届真题]整理玩具(树状数组)
  6. resteasy_RESTEasy教程第2部分:Spring集成
  7. js foreach 跳出循环_VUE.js
  8. niginx的高可用配置(HA)
  9. laravel auth::check 后session失败_01.laravel简介
  10. 如何在不联网的情况下安装 Silverlight Tools
  11. 恩恩,庆祝一下,我也开博了。
  12. 提高Android应用辅助功能的方法Accessibility
  13. SQL Server数据库查询优化【转】
  14. matlab啁啾信号,啁啾信号chirp(扫频余弦信号)
  15. PDF Converter 注册码
  16. 扫二维码登录的实现原理
  17. 小明左、右手中分别拿两张纸牌:黑桃10和红桃8.现在交换手中的牌。
  18. w7无法訪问计算机上硬盘分区,Win7/win10双系统无法打开磁盘分区提示拒绝访问怎么解决...
  19. 社会学转计算机博士,科学网—记我国社会计算学科第一位博士 - 王帅的博文
  20. mqtt连接百度天工物接入平台

热门文章

  1. Unity 游戏黑暗之光笔记第五章 背包系统的实现
  2. 关于的FPV救援机器人的演讲。
  3. 图片懒加载的原理和实现
  4. C语言获取窗口dc,C语言新案例-捕获电脑桌面并打印
  5. nacos1.4.1启动报错acos is starting with cluster
  6. 甲醛(Formaldehyde)
  7. MySQL主从恢复数据
  8. 上网/游戏/看剧太慢了:瞧瞧是不是运营商干的
  9. 漫谈广告机制设计 | 从维纳斯的七个香吻说起
  10. 裸奔系列之博科SAN交换机(1)---SAN交换机产品介绍