org-mode写文档

Table of Contents

1 介绍

I really do not like Microsoft Word!

1.1 Org Mode

一个快速高效的纯文本系统。我所有笔记,TODO,当前的blog以及研究生毕业 论文全都是用它写的。

优点:

  1. 纯文本。
  2. 开源。
  3. 高效。

1.2 LaTeX

LaTeX是一个高质量的排版系统。它是为科学和技术文档来设计的。它是通讯 和科学领域的事实标准。关键是,它还免费。我的简历是直接用它来排版的。

2 Org Mode直接导出pdf

Org Mode支持各种各样的导出。本文只介绍Org Mode直接导出pdf文档相关内 容。

简单来说,想要把Org Mode写的纯文本文件转为pdf文件进行发布,需要先导 出为LaTeX的源文件,然后再通过LaTeX提供的工具来“编译”为pdf。

+--------------------------+
| Org Mode Plain Text File |
+--------------------------+
           |
           | export
           v
+--------------------------+
|  LaTeX Source File       |
+--------------------------+
           |
           | compile
           v
+--------------------------+
|   Final pdf file         |
+--------------------------+

2.1 配置texlive环境

可以到 这里 去下载新的最新的texlive的iso文件。

下载完成后,使用下面命令把iso挂载到目录:

sudo mount -o loop texlive.iso /tmp/texlive/

进入对应目录执行install开头的脚本即可。

安装完成后,会有提示需要设置几个环境变量:

Welcome to TeX Live!

See /usr/local/texlive/2018/index.html for links to documentation.
The TeX Live web site (http://tug.org/texlive/) contains any updates and
corrections. TeX Live is a joint project of the TeX user groups around the
world; please consider supporting it by joining the group best for you. The
list of groups is available on the web at http://tug.org/usergroups.html.

Add /usr/local/texlive/2018/texmf-dist/doc/man to MANPATH.
Add /usr/local/texlive/2018/texmf-dist/doc/info to INFOPATH.
Most importantly, add /usr/local/texlive/2018/bin/x86_64-linux
to your PATH for current and future sessions.

在.bashrc这些地方搞定就可以了, 注意 ,这几个变量是必须要设置的, 不然可能编译都通不过。

# for texlive
export PATH=/usr/local/texlive/2018/bin/x86_64-linux:$PATH
export MANPATH=/usr/local/texlive/2018/texmf-dist/doc/man:$MANPATH
export INFOPATH=/usr/local/texlive/2018/texmf-dist/doc/info:$INFOPATH

然后就可以使用 xelatex 来把tex的源文件编译为pdf文件啦。

2.1.1 字体

以前texlive默认选择的是windows上的字体。在linux上我有时直接把 windows上的字体拷过来当成盗版来用。有时是去配置texlive使用当前系统 有的字体。

新款的texlive(我当前使用的是2018)是支持ubuntu和mac了。看起来,直 接使用 !fontsec=ubuntu! 选项就可以了。比如这样:

\documentclass[11pt,fontset=ubuntu]{ctexart}

这个选项其实就是在选择 /usr/local/texlive/2018/texmf-dist/tex/latex/ctex/fontset/ 目录中 的哪个文件。我看里面的代码,其实它就是设置中文字体为文泉一系的字体 了。

如果ubuntu上没有安装文泉字体,编译还是会报错。这时候不如就手动设置 中文字体,可以参考下面的latex代码:

\documentclass{article}

\usepackage{xeCJK}

% 下面这些字体一定要是系统有的
\setCJKmainfont[BoldFont={SimHei},ItalicFont={STKaiti}]{SimSun}
\setCJKsansfont{SimHei}
\setCJKmonofont{STFangsong}
\setCJKfamilyfont{zhsong}{SimSun}
\setCJKfamilyfont{zhhei}{SimHei}
\setCJKfamilyfont{zhkai}{STKaiti}
\setCJKfamilyfont{zhfs}{STFangsong}

% 重新定义一些中文拼音命令方便使用
\newcommand*{\songti}{\CJKfamily{zhsong}} % 宋体
\newcommand*{\heiti}{\CJKfamily{zhhei}}   % 黑体
\newcommand*{\kaishu}{\CJKfamily{zhkai}}  % 楷书
\newcommand*{\fangsong}{\CJKfamily{zhfs}} % 仿宋
\newcommand*{\lishu}{\CJKfamily{zhli}}    % 隶书
\newcommand*{\youyuan}{\CJKfamily{zhyou}} % 幼圆

\begin{document}

你好,TeX Live 2009!

\lishu{这是隶书}

\fangsong{这是仿宋}

\songti{这是宋体}

\heiti{这是黑体}

\kaishu{这是楷书}

\youyuan{这是幼圆}

\end{document}

2.2 查询latex的package

可以使用 texdoc 命令来查询。

texdoc spverbatim

2.3 自定义生成pdf的格式

2.3.1 org文档转pdf文件格式

原生的org生成的tex源文件都是使用 article 这个class。作为中文用户, 需要设置org在导出的时候使用 ctexart ,还可以根据自己需要定制一下。 设轩 org-latex-classes 这个变量就可以了。

(add-to-list 'org-latex-classes '("ctexart" "\\documentclass[11pt]{ctexart}
[NO-DEFAULT-PACKAGES]
\\usepackage[utf8]{inputenc}
\\usepackage[T1]{fontenc}
\\usepackage{fixltx2e}
\\usepackage{graphicx}
\\usepackage{longtable}
\\usepackage{float}
\\usepackage{wrapfig}
\\usepackage{rotating}
\\usepackage[normalem]{ulem}
\\usepackage{amsmath}
\\usepackage{textcomp}
\\usepackage{marvosym}
\\usepackage{wasysym}
\\usepackage{listings}
\\usepackage{amssymb}
\\usepackage{booktabs}
\\usepackage[colorlinks,linkcolor=black,anchorcolor=red,citecolor=black]{hyperref}
\\tolerance=1000

% 设置源码格式
\\lstset{framexleftmargin=5mm, frame=shadowbox, rulesepcolor=\\color{blue}}
\\lstset{basicstyle=\\tiny}
\\lstset{postbreak=\\space, breakindent=5pt, breaklines}

% 设置verbatim的字体大小
\\makeatletter
\\def\\verbatim{\\tiny\\@verbatim \\frenchspacing\\@vobeyspaces \\@xverbatim}
\\makeatother
"
                                  ("\\section{%s}" . "\\section*{%s}")
                                  ("\\subsection{%s}" . "\\subsection*{%s}")
                                  ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
                                  ("\\paragraph{%s}" . "\\paragraph*{%s}")
                                  ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))

;;; 设置默认的class为ctexart
(setq org-latex-default-class "ctexart")

设置好后,所有通过org文件导出的tex源文件的开头部分就是我们设置的内 容了。

这样就可以从org文件直接导出到pdf文件。后面如果需要修改导出的pdf的默 认章节格式时,可以直接修改一下上面的变量即可。

还可以设置多个class,然后在单个org文件中指定使用:

#+LATEX_CLASS: article

这样设置后,该文件导出还是按 article 的设置来。

2.3.2 结合body only进一步定制pdf文件格式

有时针对一个类型的文档,可能需要进一步的定制,可能到了需要修改latex 源码的时候,有两种办法。

2.3.2.1 需要修改文章头页眉页脚等

org在导出时,有一个 body-only 的选项,打开后(在 C-c C-e 后默 认是使用 C-b 来切换),只有内容才会导出。

有了这个功能,可以把tex源文件的头部分开,需要修改格式的tex源码都在 这个文件进行,然后 \include{body} 就可以了。

假设org文件名为 body.org ,我开启 body-only 后,导出到 body.tex 文件中。

写一个 head.tex 大概像这样:

\documentclass[11pt]{ctexart}

%% 这里面可以随意地修改格式

\maketitle

\clearpage

\tableofcontents

%% 这个直接把内容包进来就好
\include{body}

\end{document}

最后直接编译 head.tex 就可以了。

2.3.2.2 需要在文档中直接插入latex源码

直接使用 +BEGIN_LATEX 这个的block插入就可以了。

2.3.3 org文档中需要写latex源码做为示例

此时直接使用 example 的block还不行,需要给这个block加上一个latex 的属性。比如这样:

#+ATTR_LATEX: :environment verbatim
#+BEGIN_EXAMPLE
\documentclass{article}

hi

\end{document}
#+END_EXAMPLE

这样导出的tex文件会被一个 verbatim 包住。

2.3.4 org的block中的行太长

默认的block导出来对应的tex都是 verbatim 。verbatim对太长的行不会 自动折行。这样如果我写了很长的行在block里面。导出的pdf就超长了。

解决的方法有几种:

  1. 不要在block中写太长的行。废话。
  2. 设置默认verbatim的字体,缩小它的字体。这种方法可以解决一些情况。 但还是治标不治本。我在导出的tex前后加入了下面这段:

    % 设置verbatim的字体大小
    \\makeatletter
    \\def\\verbatim{\\tiny\\@verbatim \\frenchspacing\\@vobeyspaces \\@xverbatim}
    \\makeatother
    

    这样verbatim都是使用tiny的字体了。

  3. 使用 spverbatim 包。这个包可以自动给超长的行添加换行。在头部 加上 \usepackge{spverbatim} 后。 注意 ,我测试出来的话,当 前只在org的example这个block支持 :environment 这个选项。直接接 照这样写就可以了:

    #+ATTR_LATEX: :environment spverbatim
    #+BEGIN_EXAMPLE
    This is a very long line.
    #+END_EXAMPLE
    

    这样这个block导出就会被 spverbatim 包住,而不是默认的 verbatim 了。

2.3.5 标题和目录分页显示

在org文件中加入这样神奇的一行就可以了:

#+LATEX_HEADER: \makeatletter \def\@maketitle{\null \begin{center} {\vskip 5em \Huge \@title} \vskip 30em {\LARGE \@author} \vskip 3em {\LARGE \@date} \end{center} \newpage} \makeatother

这个我参考的是 这里

要在org-mode导出时让标题页和目录页分页显示,得修改\maketitle命令,查阅
有两种方法,一种直接修改,见链接
http://tex.stackexchange.com/questions/216098/redefine-maketitle 6 ,
另一种是用titling包去修改,我自己在org-mode加入一下代码,标题页和目录
页就可以分开了,具体样式可以自己去修改

2.3.6 自定义源码的格式

源码默认的block默认导出还是 verbatim 此时还管设置什么 options 都是不支持的。可以修改为 listings 或者 minted

这样修改就是listings了:

;; 设置org-mode的源代码block默认导出的latex的environment为listtings
(setq org-latex-listings 'listings)
(add-to-list 'org-latex-packages-alist '("" "listings"))

这样设置为 minted

;; 设置org-mode的源代码block默认导出的latex的environment为minted
(setq org-latex-listings 'minted
      org-latex-packages-alist '(("" "minted"))
      )

这两个都是支持直接在org中设置options:

     #+ATTR_LATEX: :options commentstyle=\bfseries
     #+BEGIN_SRC emacs-lisp
       (defun Fib (n)
         (if (< n 2) n (+ (Fib (- n 1)) (Fib (- n 2)))))
     #+END_SRC

设置源代码导出为这两个环境后,需要给编译的命令加上 -shell-escape 选项。 比如我这样设置编译命令:

(setq org-latex-pdf-process
      '(
        "xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"
        "xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"
        "xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"
        "rm -fr %b.out %b.log %b.tex auto"
        ))

2.3.7 全局定义example block导出的environment

参考info,可以给 org-export-filter-TYPE-block-functions 挂钩子。 会把所有block的text都传给它。这里我直接在钩子函数里面把 {verbatim} 替换成了 mylongverbatim 。当然, mylongverbatim 是我自定义好的。

;; 添加这个filter把默认example导出的environment从verbatim换成我自定
;; 议的 mylongverbatim
(defun my-latex-filter-example-myverbatim (text backend info)
  "user my customized verbatim."
  (when (org-export-derived-backend-p backend 'latex)
    (replace-regexp-in-string "{verbatim}" "{mylongverbatim}" text)))
(add-to-list 'org-export-filter-example-block-functions
             'my-latex-filter-example-myverbatim)

2.3.8 org导出标题的级别

默认是3级,可以修改变量 org-export-headline-levels

也可以直接在org文件中设置,这样就可以设置为4级:

#+options: H:4

2.3.9 不要title页

下面这样就可以搞定:

#+title:
#+OPTIONS: author:nil date:nil

2.3.10 TODO mylongverbatim现在使用的是listings,换行后不爽,看下能不能使用 spverbatim 。后者我加不上frame加框

3 Org Mode导出为html再打印成pdf

3.1 最简单的做法

org-mode转html是最简单的。html可以直接打印为pdf。在chrome中,一般可 以设置不需要打印页眉页脚。

如果有很长的行,还可以通过在打印时缩放来缩小后打印。

3.2 为pdf加书签(bookmarks)

最后一个问题就是打印出来的pdf没有书签。就是左侧边栏的东西。我在 这里 找到了方法。

可惜的是 ,我按照此方法加入加入中文书签会显示乱码。

写一个文件叫 index.info

[/Page 1 /Title (January) /OUT pdfmark
[/Page 2 /Title (February) /OUT pdfmark
[/Page 3 /Title (March) /OUT pdfmark
[/Page 4 /Title (April) /OUT pdfmark
[/Page 5 /Title (May) /OUT pdfmark
[/Page 6 /Title (June) /OUT pdfmark
[/Page 7 /Title (July) /OUT pdfmark

然后使用下面的命令来把input.pdf转为output.pdf,出来的output.pdf就是有书签的了

$ gs -sDEVICE=pdfwrite -q -dBATCH -dNOPAUSE -sOutputFile=output.pdf -dPDFSETTINGS=/prepress index.info -f input.pdf

这样修改 index.info 就可以加入嵌入的书签:

[/Count 3 /Page 4 /Title (Introduction) /OUT pdfmark
[/Page 4 /Title (Features) /OUT pdfmark
[/Page 6 /Title (Mailing lists and IRC channel) /OUT pdfmark
[/Page 6 /Title (Virus submitting) /OUT pdfmark
[/Count 2 /Page 6 /Title (Base package) /OUT pdfmark
[/Count 2 /Page 6 /Title (Supported platforms) /OUT pdfmark
[/Page 6 /Title (UNIX) /OUT pdfmark
[/Page 7 /Title (Windows) /OUT pdfmark
[/Page 7 /Title (Binary packages) /OUT pdfmark
[/Count 7 /Page 7 /Title (Installation) /OUT pdfmark
[/Page 7 /Title (Requirements) /OUT pdfmark
[/Page 8 /Title (Installing on shell account) /OUT pdfmark
[/Page 8 /Title (Adding new system user and group) /OUT pdfmark
[/Page 9 /Title (Compilation of base package) /OUT pdfmark
[/Page 9 /Title (Compilation with clamav-milter enabled) /OUT pdfmark
[/Page 9 /Title (Running unit tests) /OUT pdfmark
[/Page 10 /Title (Reporting a unit test failure bug) /OUT pdfmark

原文纯文本如下:


How to add bookmarks to a PDF document on Linux
Posted on April 11, 2016 by Dan Nanni   2 Comments

Question: I would like to add bookmarks to a PDF file, so that the
bookmarks appear in the left hand side bookmarks panel. Is there a
command-line approach to create bookmarks and embed bookmark links in
a PDF file on Linux?

In a PDF document, bookmarks can be added as a navigational tool to
allow readers to locate and quickly move to particular sections in the
document by clicking on bookmark links. If a PDF file is a very log
document with hundreds of pages, adding properly organized bookmarks
can be essential to guide users to browse the document effectively.

PDF bookmarks can be implemented with the pdfmark operator, which is
part of a PostScript language extension. Among other things, pdfmark
can be used to add a hotlink to a small piece of text in a PDF, which
is pretty much a bookmark function.

pdfmark can be embedded into a PDF file with Ghostscript. Here is how
to add PDF bookmarks from the command line with Ghostscript on Linux.
Add Bookmarks in a PDF file with Ghostscript

To add PDF bookmarks, first create an index file (index.info) in the format of:

[/Page 1 /Title (January) /OUT pdfmark
[/Page 2 /Title (February) /OUT pdfmark
[/Page 3 /Title (March) /OUT pdfmark
[/Page 4 /Title (April) /OUT pdfmark
[/Page 5 /Title (May) /OUT pdfmark
[/Page 6 /Title (June) /OUT pdfmark
[/Page 7 /Title (July) /OUT pdfmark

"/Page" indicates the page number to the bookmark jumps to, and
"/Title" represents the name of the bookmark.

Once you created index.info, use the following command to add the
bookmarks in the PDF file input.pdf. output.pdf will have the
bookmarks embedded.

$ gs -sDEVICE=pdfwrite -q -dBATCH -dNOPAUSE -sOutputFile=output.pdf -dPDFSETTINGS=/prepress index.info -f input.pdf

For example, given the input PDF file:

The output PDF file will look like:

Add Nested Bookmarks in a PDF file with Ghostscript

If you have a structured PDF document with chapters, sections,
subsections, etc., you may want to add "nested" bookmarks in the PDF
file. In that case, use "/Count N" attribute with pdfmark to represent
nested levels. The argument 'N' corresponds to the number of
immediately subordinate bookmarks. For example, if the first chapter
has three sections, you can can add "/Count 3" in that chapter's
bookmark, and if a given section has two subsections, include "/Count
2" in the section's bookmark.

Let's create nested bookmarks for the following document.

The created index file looks like the following.

[/Count 3 /Page 4 /Title (Introduction) /OUT pdfmark
[/Page 4 /Title (Features) /OUT pdfmark
[/Page 6 /Title (Mailing lists and IRC channel) /OUT pdfmark
[/Page 6 /Title (Virus submitting) /OUT pdfmark
[/Count 2 /Page 6 /Title (Base package) /OUT pdfmark
[/Count 2 /Page 6 /Title (Supported platforms) /OUT pdfmark
[/Page 6 /Title (UNIX) /OUT pdfmark
[/Page 7 /Title (Windows) /OUT pdfmark
[/Page 7 /Title (Binary packages) /OUT pdfmark
[/Count 7 /Page 7 /Title (Installation) /OUT pdfmark
[/Page 7 /Title (Requirements) /OUT pdfmark
[/Page 8 /Title (Installing on shell account) /OUT pdfmark
[/Page 8 /Title (Adding new system user and group) /OUT pdfmark
[/Page 9 /Title (Compilation of base package) /OUT pdfmark
[/Page 9 /Title (Compilation with clamav-milter enabled) /OUT pdfmark
[/Page 9 /Title (Running unit tests) /OUT pdfmark
[/Page 10 /Title (Reporting a unit test failure bug) /OUT pdfmark

Use the same command as above to add nested bookmarks in the input PDF
file.

$ gs -sDEVICE=pdfwrite -q -dBATCH -dNOPAUSE -sOutputFile=output.pdf -dPDFSETTINGS=/prepress index.info -f input.pdf

The output PDF file with nested bookmarks will look like the
following.

All nested bookmarks are expanded by default. If you want nested
bookmarks to be collapsed initially, use "[/Count -N]" format (i.e.,
add '-' sign in front of the number).

With that, the output will look like the following.

You will need to click on each closed bookmark to expand it.

Author: Peng Xie

Created: 2018-10-20 Sat 10:35