Converting Plaintext to PDF

txt2pdf is a tool to convert a plaintext file to PDF. By default, it uses Courier 10 point font, which can fit about 78 characters across a line and 56 lines on a page. The command works by:

  • paginating the input using the pr command. This also inserts the file’s creation timestamp, the filename, and the page number in the header
  • expanding tabs to spaces (width 8)
  • appending the .br troff directive to each newline with sed1
  • converting to troff and then postscript and then pdf using troff | grops | ps2pdf

You can find the txt2pdf command at github.com/ughe/txt2pdf. Here is the full command:

#!/usr/bin/env bash
# Converts plaintext to PDF. Courier 10 point font. 78 cols x 56 rows
set -o pipefail
if [ $# -lt 1 ]; then
  >&2 echo "usage: $0 [-p12] [-n] [-2] abc.txt > abc.pdf"; exit 1; fi
PS=10 # Default font size
if echo "$@" | grep -q -- '^ *-p[0-9][0-9]* '; then # -p12 must be 1st
  PS=`echo "$@" | sed -nr 's/^ *-p([0-9]+) .*/\1/gp'`; shift; fi
# Format: 1) font size $PS 2) .br every newline 3) delete last line
FMT='1s/^/.ps '${PS}'\n/;s/$/\n.br/g;s/\\/\\\\/g;$ d'
pr "${@}" | expand | sed "$FMT" | troff -Tps -fC | grops | ps2pdf - -

We can use txt2pdf to convert itself to PDF using the following invocation:

./txt2pdf -n -h "txt2pdf" ./txt2pdf > txt2pdf.pdf

And here is the resulting txt2pdf.pdf that was outputted:

Additional Examples

In addition to converting itself, txt2pdf has three more examples in the repository:

  1. Comparing C and Rust “hello world” assembly output on x86-64 (intel)
  2. Generating a table of arithmetic problems (multiplication) and answers
  3. Printing out poems in 12 point font with line numbers (“Kubla Khan” and “Ulysses”)2

We will discuss the C vs. Rust example, which prints the assembly output of their respective hello world programs side by side. The lines are truncated after about 30 characters, which makes assembly a good example since often source code or poems are longer than 30 characters wide.

Here are the hello world files for C and Rust3:

  • hello_c.c
    #include <stdio.h>
    int main(int argc, char* argv[]) {
      printf("hello, world\n");
      return 0;
    }
    
  • hello_rs.rs
    fn main() {
        print!("hello, world\n");
    }
    

After compiling (with -O3) to assembly using the Makefile here, we run txt2pdf with the -m flag and both *.S assembly files. C is on the left and Rust is on the right. Here is the output:

Compiler Versions

See the Makefile used in examples/hello for the full methodology. Here are the versions used:

$ gcc --version
Apple clang version 13.1.6 (clang-1316.0.21.2)
Target: x86_64-apple-darwin21.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

$ rustc --version
rustc 1.56.1

Conclusion

txt2pdf is a handy tool for converting plaintext to PDF without installing more powerful commands.

  1. Simplification. We also: 1) insert the font size .ps directive at the start of the file; 2) Escape all backslashes by replacing them with two backslashes; and 3) Remove the last line (which is always empty and was introduced by pr

  2. Public domain poems sourced from Project Gutenberg 

  3. Note: the actual hello_rs.rs file has more variations attempting to generate fewer asm lines.