如何从 Linux 手册页创建 pdf 以保留样式?

如何从 Linux 手册页创建 pdf 以保留样式?

我想使用 LaTeX 制作一本关于 C 函数的 Linux 手册页的 pdf 书。

例如man malloc如下所示 -

man ls 输出 我希望我的 pdf 书有这种风格。具体颜色不作要求,但颜色必须与终端颜色匹配。

答案1

如果您不知道,man页面已经用比 TeX 更古老的排版系统编写。这就是 *roff 家族:在历史的不同时期,相关程序曾使用过RUNOFFrunoffroffnrofftroff、等名称。如果您使用的是类 Unix 系统(您问的是手册页,所以猜得不错),您可能已经ditroff在系统上安装了,可能使用和等名称。groffgrofftroffnroff

事实上,man页面是用宏包对于 *roff 排字机。如果您输入man -d malloc,您将获得一些调试信息:在我的计算机上,最后一行显示它将运行什么命令,以(排版和)显示malloc手册页:

cd '/usr/share/man' && (echo ".ll 18.3i"; echo ".nr LL 18.3i"; /bin/cat '/usr/share/man/man3/malloc.3') | /usr/bin/tbl | /usr/bin/groff -Wall -mtty-char -Tascii -mandoc -c | (/usr/bin/less -is || true)

这表明文件/usr/share/man/man3/malloc.3首先经过tbl预处理器(处理表格),然后格式化以groff显示在屏幕上。“输入”/usr/share/man/man3/malloc.3文件本身有这样的指令:

The
.Fn malloc
function allocates
.Fa size
bytes of memory and returns a pointer to the allocated memory.

这类似于(在某些假设的 LaTeX 包中)编写类似以下内容的内容

The \functionname{malloc} function allocates \functionarg{size} bytes of memory and returns a pointer to the allocated memory.

这是由预处理器“排版”的,以(这些和*roff 宏/usr/bin/groff -Wall -mtty-char -Tascii -mandoc -c的定义,以及函数名称应以粗体排版和参数应加下划线的事实,位于与手册页相关的宏包中)结尾,这就是为什么它最终在屏幕上以适当的粗体和下划线显示:.Fn.Fa

来自 malloc 手册页的行


所以:如果您想要生成 PDF,则只需更改输出格式即可。您可以通过多种方式执行此操作(不幸的是,输出结果存在一些差异,因此您可能需要尝试每种方式并​​选择最喜欢的一种):

man -t malloc > malloc.ps
ps2pdf malloc.ps

或者(是的,除了 TeX 之外还有其他程序可以生成 DVI 文件!)

groff -T dvi -m mandoc '/usr/share/man/man3/malloc.3' > malloc.dvi
dvipdfmx malloc.dvi

或者:

groff -T ps -m mandoc '/usr/share/man/man3/malloc.3' > malloc.ps
ps2pdf malloc.ps

或者在 Linux 上,你可能需要:

zcat '/usr/share/man/man3/malloc.3.gz' | tbl | groff -T ps -m mandoc > malloc.ps
ps2pdf malloc.ps

或者使用不同的转换器将 PS 转换为 PDF 或将 DVI 转换为 PDF。然后,您可以将 PDF 直接包含在 LaTeX 文档中;您可以在此网站上搜索多种方法。如果您不喜欢页边距、行长等,您可以通过多种方式将它们指定给 groff

另一种方法是使用mandoc程序,它可以理解 man 文件的源格式:

zcat '/usr/share/man/man3/malloc.3.gz' | mandoc -T pdf > malloc.pdf

或者

zcat '/usr/share/man/man3/malloc.3.gz' | mandoc -T html > malloc.html
# convert from html to pdf or to latex in your preferred way

请注意,转换html为 LaTeX 提供了多种可能性。例如,您可以使用pandoc。这里有一个与屏幕截图中显示的某些方面相匹配的示例:

  • 所有粗体文本显示为红色(就像您的终端显然显示的那样)
  • 背景不是白色
  • 使用下划线代替斜体(您的终端之所以这样做,是因为它没有斜体字体;您可以考虑是否要在 PDF 中匹配斜体:下划线通常被认为是糟糕的排版)

创建mancolours.tex包含:

\usepackage{pagecolor}

% Set background colour (of the page)
\definecolor{weirdbgcolor}{HTML}{FCF4F0}
\pagecolor{weirdbgcolor}

% Make bold text appear in a particular colour
\definecolor{boldcolor}{HTML}{6E0002}
\let\realtextbf=\textbf
\renewcommand{\textbf}[1]{\textcolor{boldcolor}{\realtextbf{#1}}}

% Use underlines instead of emphasis (ugh)
\renewcommand{\emph}[1]{\underline{#1}}

% % Use fixed-width font by default
% \renewcommand*\familydefault{\ttdefault}

进而:

zcat '/usr/share/man/man3/malloc.3.gz' | mandoc -T html > malloc.html
pandoc -s -o malloc.tex --include-in-header=mancolours.tex malloc.html
pdflatex malloc.tex

这会产生如下内容:

与截图非常吻合


最后,如果这些都不令人满意,您可以查看手册页的源代码并编写自己的工具,将 *roff 宏转换为您想要的任何等效 LaTeX 宏。这样的工具并不多,所以这应该是合理可行的。(网上有一些脚本,人们编写了类似的翻译器,但我尝试了几个,效果都不太好。所以最好自己写一个。)如果您觉得更容易,您也可以考虑对mandoc -Thtml或 的输出进行操作。mandoc -Ttree


另一个选择,如果您想要精确匹配格式化的终端输出,则将其连同格式一起转储到文件中。当您运行 时man malloc,调用的分页程序很可能是这样的less。如果您转储到文件显示的所有内容,并在合适的编辑器中打开文件,您将看到终端如何执行此操作:

 The m^Hma^Hal^Hll^Hlo^Hoc^Hc() function allocates _^Hs_^Hi_^Hz_^He bytes of memory and…

(文件中的实际字符是字节 8,我已将其更改为^H上面的两个字符,以便您可以看到它)。因此:要使字符变为粗体,它会先打印字符,然后打印^H,然后再打印字符。要使某个字符加下划线,它会先打印_,然后打印^H字符。(如果您想象这^H就像向后移动,并且在字符本身上叠印字符会使其变为粗体,那么这些就说得通了——这实际上是历史上某个时候的工作方式。)最重要的是,您的终端首选项会应用到如何显示这些粗体和下划线字符。

现在,您有了这个文件,就可以提取其中的格式,将其转换为适合 LaTeX 的格式。例如,使用以下 Python 脚本,我将它们分别转换为\bold{...}\underline{...}man malloc恰好不包含反斜杠,但如果包含,您可能也想替换它们):

import re
import sys

def parseFormatting(text):
    """Detects 'bold' and 'underlined' characters in the output to a terminal."""
    chars = [(c, '') for c in text]
    while True:  # Detect bold characters
        m = re.search('(.)\x08\\1', ''.join(c[0] for c in chars))
        if not m: break
        s = m.start()
        chars[s : s + 3] = [(chars[s + 2][0], 'bold')]
    while True:  # Detect underlined characters
        m = re.search('_\x08.', ''.join(c[0] for c in chars))
        if not m: break
        s = m.start()
        chars[s : s + 3] = [(chars[s + 2][0], 'underline')]
    i = 0
    while i < len(chars):  # Collapse runs of identical formatting (for efficiency later)
        j = i
        while j < len(chars) and chars[j][1] == chars[i][1]: j += 1
        chars[i : j] = [(''.join(chars[k][0] for k in range(i, j)), chars[i][1])]
        i += 1
    return chars

def parseFileReplaceFormatting(filename):
    text = open(filename, 'rb').read().decode('utf-8').split('\n')
    newtext = ''
    for line in text:
        for c in parseFormatting(line):
            if c[1] == '':
                newtext += c[0]
            elif c[1] == 'bold':
                newtext += '\\bold{%s}' % c[0]
            elif c[1] == 'underline':
                newtext += '\\underline{%s}' % c[0]
            else: assert False, ('Unknown formatting', c[1], 'for', c[0])
        newtext += '\n'
    return newtext

if __name__ == '__main__':
    infilename = sys.argv[1]
    outfilename = sys.argv[2]
    updated = parseFileReplaceFormatting(infilename)
    with open(outfilename, 'wb') as f:
        f.write(updated.encode('utf-8'))

因此运行上述脚本后,如下所示:

python malloc.man.less malloc.man.less.py2

你可以\input用 TeX 处理 ( ) 生成的文件。如果你愿意,你甚至可以保留换行符以及终端所做的任何粗略的连字符和对齐!(当然,这样做会失去 TeX 优美的换行算法的所有好处,但你可以精确匹配终端输出。)你只需确保页面和终端的宽度大致兼容:

\documentclass{article}

\usepackage[paperwidth=11in, textwidth=10in, textheight=4in, paperheight=5in]{geometry}

\usepackage{fontspec}
\setmainfont{Consolas}

\usepackage{xcolor}
% Set background colour (of the page)
\definecolor{weirdbgcolor}{HTML}{FCF4F0}
\usepackage[pagecolor=weirdbgcolor]{pagecolor}
% Make bold text appear in a particular colour
\definecolor{boldcolor}{HTML}{6E0002}
\newcommand{\bold}[1]{\textcolor{boldcolor}{\textbf{#1}}}

\begin{document}
% Foreground colour
\definecolor{fgcolor}{HTML}{A57716}
\color{fgcolor}

\def\nextline{\null\par} % \null so that a blank line in input (two consecutive newlines) becomes an empty paragraph.
{\catcode`\^^M=\active \def^^M{\nextline} \catcode`#=12 \catcode`_=12 \catcode32=12\relax\input{malloc.man.less.py2}}

\end{document}

上述 TeX 文档生成的输出第 1 页

(您可以从底部的黑色页码看出上述输出是由 TeX 生成的!)

答案2

也许加起来man2html可能pandoc是一个简单的良好开始:

$ zcat '/usr/share/man/man3/malloc.3.gz' | man2html > malloc.html
$ pandoc -s -f html -t latex  malloc.html -o malloc.tex

但如果你不需要修改 LaTeX 源,你可以直接导出为 PDF:

$ pandoc -f html -t latex malloc.html -o malloc.pdf

姆韦

然后,用一个新的序言(并删除一些第一行):

姆韦

\documentclass[10pt]{hitec}
\usepackage[tmargin=.5in]{geometry}
\usepackage[english]{babel}
\settextfraction {1}
\setlength\leftmarginwidth{4em}
\setlength\textwidth{.84\paperwidth}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[colorlinks]{hyperref}
\usepackage{longtable,booktabs}
\usepackage{parskip}
\setlength{\parskip}{6pt plus 2pt minus 1pt}
\setlength{\emergencystretch}{3em}  % prevent overfull lines
\setcounter{secnumdepth}{0}
\usepackage{xcolor}
\definecolor{texto}{HTML}{801c35}
\definecolor{fondo}{HTML}{FDF6F3}
\definecolor{textob}{HTML}{BB8B04}
\pagecolor{fondo}\color{textob}
\let\oldbfseries\bfseries
\def\bfseries{\color{texto}\oldbfseries}
\def\textbf#1{\textcolor{texto}{\oldbfseries #1}}
\pagestyle{empty}
\title{Man page of MALLOC}

\begin{document}

\section{MALLOC}\label{malloc}
\subsection{NAME}\label{name}

malloc, free, calloc, realloc - allocate and free dynamic memory

... % remaining text is not changed 

\end{document}

答案3

男人-w男人 返回存储命令手册页的文件路径男人

在我的机器上, 男人-w男人返回 /usr/share/man/fr/man1/man.1.gz

因此您可以轻松地将此命令与其他命令组合

man -l -Tdvi $(man -w man) > man.dvi && dvipdf man.dvi && rm -f man.dvi && xpdf man.pdf

解释:1.man -l -Tdvi $(man -w man) > man.dvi 让 man 告诉 groof 生成 man 手册页的 dvi 文件

2.dvipdf 手册.dvi 我们告诉 dvipdf 为 man.dvi 文件创建 man.pdf

  1. rm -f man.dvi 我们删除临时的 man.dvi 文件

  2. xpdf 手册.pdf 我们使用 xpdf 来显示文件。我在这里使用它是因为我想大多数系统都会默认使用它。

你可以在 kde 系统上使用 okular 奥克拉人.pdf

相关内容