orgtre / qpdf.el

A transient Emacs wrapper for qpdf
5 stars 2 forks source link
emacs emacs-packages pdf qpdf

** Installation

qpdf.el is a [[https://github.com/magit/transient][transient]] [[https://www.gnu.org/savannah-checkouts/gnu/emacs/emacs.html][Emacs]] wrapper for [[https://github.com/qpdf/qpdf][qpdf]].

To use it you hence need Emacs, transient, and qpdf. Transient may be installed from [[https://elpa.gnu.org/packages/transient.html][ELPA]] or its Github repo, but you likely already have it as it comes as a [[https://magit.vc][Magit]] dependency. Linux and Windows binaries for qpdf are available [[https://github.com/qpdf/qpdf/releases][here]]; a homebrew formula for macOS is [[https://formulae.brew.sh/formula/qpdf][here]].

To install qpdf.el itself and set it up with [[https://github.com/radian-software/straight.el][straight.el]] the following can be used:

+begin_src elisp

(use-package qpdf.el :straight (:host github :repo "orgtre/qpdf.el") :commands qpdf)

+end_src

** Features

qpdf.el provides the Emacs command =qpdf=, which brings up a transient menu through which arguments in a call to the powerful qpdf shell command can be quickly specified.

Examples of what is possible:

See the [[https://qpdf.readthedocs.io/en/stable/cli.html][qpdf documentation]], which can be shown by using the =qpdf-docs= command, for a list of all available arguments and syntax details.

When the command =qpdf= is invoked from a buffer in =doc-view-mode= or [[https://github.com/vedang/pdf-tools][pdf-tools]]' =pdf-view-mode=, the default infile is set to the current file, the default outfile is set based on the current file, presets for pages are shown based on the current page, and the outfile is opened in Emacs.

** Customization

Flexible customization options exist – see the source code or customization group qpdf.el. For example, to change key bindings and control which commands are shown in the =qpdf= transient, =qpdf-prefix-groups= can be edited.

It is also possible to make use of transients built-in customization methods. When the =qpdf= transient is active, ~C-x l~ (=transient-set-level=) can be used to set the level of each argument/command. By default only those with level 4 or larger are shown. See [[https://magit.vc/manual/transient/Enabling-and-Disabling-Suffixes.html][this section]] of the transient manual.

Transient also provides several functions to [[https://magit.vc/manual/transient/Modifying-Existing-Transients.html][modify existing transients non-interactively]]. For example, =(transient-insert-suffix 'qpdf "c" '("l" "" "--linearize"))= inserts the =--linearize= argument before the =--custom= argument, while the following inserts a group of "Transformation" options after the second group in the =qpdf= transient and hides this group unless ~t~ is pressed:

+begin_src elisp

(transient-append-suffix 'qpdf '(1) ["Transformation" :hide (lambda () (not (eq (car transient--redisplay-key) ?t))) ("t l" "" "--linearize") ("t r" "" "--remove-unreferenced-resources")])

+end_src

The command =qpdf= passes the arguments it receives through the transient menu on to the command =qpdf-run=. By passing suitable arguments directly to =qpdf-run=, even more convenient custom commands to for example delete the current page, rotate the current page, en/decrypt a file, etc. can quickly be created. See the docstring of =qpdf-run=. An example is:

+begin_src elisp

(defun qpdf-delete-current-page () "Delete the current page of pdf file." (interactive) (unless (or (equal major-mode 'doc-view-mode) (equal major-mode 'pdf-view-mode)) (error "Buffer should visit a pdf file in doc-view-mode or pdf-view-mode.")) (qpdf-run (list (concat "--pages=" (qpdf--read-pages-with-presets nil nil nil 'except-current)) (concat "--infile=" (buffer-file-name)) "--replace-input")))

+end_src