4

Rupert Swarbrick came up with the following three functions to print an Emacs buffer to pdf in which lines are wrapped (this is not normally the case when using ps-print* functions).

The problem is this function is that to achieve this line wrapping, a copy of the current buffer has to be made. This effectively breaks the capability of ps-print-buffer-with-faces to display a correct header on top of each page in the resulting PDF file.

As part of his solution, Rupert Swarbrick wrote a function that preserves this information. The resulting header, however, is always HeaderLinesLeft

Who can spot the mistake?

(defun harden-newlines ()
  (interactive)
  "Make all the newlines in the buffer hard."
  (save-excursion
    (goto-char (point-min))
    (while (search-forward "\n" nil t)
      (backward-char)
      (put-text-property (point) (1+ (point)) 'hard t)
      (forward-char))))

(defun spool-buffer-given-name (name)
  (load "ps-print")
  (let ((tmp ps-left-header))
    (unwind-protect
        (progn
          (setq ps-left-header
                (list (lambda () name) 'ps-header-dirpart))
          (ps-spool-buffer-with-faces))
      (setf ps-left-header tmp))))

(defun print-to-pdf ()
  "Print the current file to /tmp/print.pdf"
  (interactive)
  (let ((wbuf (generate-new-buffer "*Wrapped*"))
        (sbuf (current-buffer)))
    (jit-lock-fontify-now)
    (save-current-buffer
      (set-buffer wbuf)
      (insert-buffer sbuf)
      (setq fill-column 95)
      (longlines-mode t)
      (harden-newlines)
      (message (buffer-name sbuf))
      (spool-buffer-given-name (buffer-name sbuf))
      (kill-buffer wbuf)
      (switch-to-buffer "*PostScript*")
      (write-file "/tmp/print.ps")
      (kill-buffer (current-buffer)))
    (call-process "ps2pdf14" nil nil nil
                  "/tmp/print.ps" "/tmp/print.pdf")
    (delete-file "/tmp/print.ps")
    (message "PDF saved to /tmp/print.pdf")))
Werner
  • 261
  • 2
  • 8

1 Answers1

2

Try this:

(defun spool-buffer-given-name (name)
  (let ((ps-left-header (list (format "(%s)" name))))
    (ps-spool-buffer-with-faces)))

See documentation for variable ps-left-header, which is what clued me in to the above.

This is a neat capability; I'll definitely use it instead of ps-print. It would be good to make it act more like C-u M-x ps-print-buffer-with-faces; two missing features are directory name in the header, and prompting the user for a filename. Neither is too difficult.

Rory Yorke
  • 2,166
  • 13
  • 13
  • Hi Rory. Thanks for your reply. Do I replace `spool-buffer-given-name` entirely or do I need to alter it? – Werner Dec 20 '11 at 13:21
  • Hi Werner. You can just replace it with mine; it's equivalent. The effect of unwind-protect/setf is more easily achieved (in this case, anyway) with let. I'm not sure why the lambda was necessary. As disclaimer, this version (combined with the code you posted) works fine on my Emacs 23.1.1 on Ubuntu 10.04. – Rory Yorke Dec 21 '11 at 19:50
  • I just wanted to create a comment with two related posts: The initial code by Rupert Swarbrick: http://stackoverflow.com/questions/7362625/word-wrap-for-emacs-print-buffer-to-pdf And, the second follow-up: http://stackoverflow.com/questions/16779882/save-buffer-as-a-pdf-with-ns-write-file-using-panel-or-similar-option I still need to implement opening the panel, but it almost does what I'm looking for. – lawlist May 28 '13 at 15:17