/doc-tools

Universal document viewing and editing tools for Emacs

Primary LanguageEmacs LispGNU General Public License v3.0GPL-3.0

Doc Tools for Emacs

Introduction

This package provides a universal document reader for Emacs, combined with a set of tools for editing documents. It is centered around the doc-scroll ‘display engine’ (if I am allowed to use such fancy term). The doc-scroll display engine provides continuous scroll, and multiple column functionality, as displayed below:

doc-tools-demo.gif

In the above demo, we first show the continuous scroll and multi-column functionality. The number of columns can be easily selected by using a numerical prefix. Subsequently, we show the thumbnail side-bar functionality. As shown, the number of columns in the side-bar is variable also via a numerical prefix.

The goal of this package is to be, mostly, an improvement on the other packages (see Improvements over other packages below), while, similar to doc-view, integrating all document viewing/editing into a single coherent, easier to understand and maintain, library.

This package mainly targets the GNU/linux platform, but it can probably made to work perfectly fine on other (non-)free platforms also.

Important

Currently, this package caches all page images somewhere in the /tmp directory. Therefore (although it is a nice default anyway), the images are set to a limited size (memory use increases exponentially with image size). Most/all computers probably have enough memory space (about 50-300 MB per book), however you can check the memory size of the books pages folder using doc-scroll-cache-folder-size (the recommended way is to call it via doc-scroll-info by pressing i from the book buffer).

Join / Donate

The code in this package is very accessible for beginning emacs-lisp hackers. If you’d like to practice some elisp, while contributing to a package then check out the TODO list below. Of course you are always welcome to contact me (e.g. on github or per email).

If this package helps you with your paid (or optionally your unpaid) work (or if you just like to support/popularize Emacs by supporting to make it more attractive and more useful for more people), then please help me with my work also. Creating this package takes a huge amount of time (for coding, but especially for investigating). However, I am in a situation that I have very little spare time, and even less money. Despite the deep wisdom in the saying: ’Let not the fruits of action be your motive’, we do need some fruit to stay alive. Therefore, I would be very happy either with your contributions to the code, or otherwise, if you can afford it, with your financial support. Without donations, I am simply unable to work on the package, while small donations let me add nice features (so you could see your donation as a donation to Emacs and the community).

Why this package?

Although having columns might not be a huge improvement, I find Emacs and its users valuable enough to add this feature to its document reader. Additionally, although it might not be essential for many users, I guess for some users it would be great to have support for line annotations in Emacs.

So why not just extending pdf-tools or doc-view.

I have first tried to implement this improved ‘display engine’ (if I am allowed to use that fancy term) into PDF-tools. However, because of PDF-tools being explicitly designed for having a single page per view, this was taking too much time (it was quite a lot more difficult than implementing support for image-roll, which was already hard enough). Of course, I would like to make the ‘display-engine’ available for reading djvu also.

So then, why not extend doc-view? Doc-view also is not designed to support continuous scrolling. Additionally, for some reason, scrolling in doc-view is very slow/laggy (I have tried to use it with image-roll before, but that was an annoying experience). It also does not support isearch nor annotations (both requiring the possibility of highlighting). Additionally, I prefer to have a more modular design, i.e. having the display engine as a separate package, for which simply backends can be added. These backends typically make use of document inspection/editing libraries, which can again be implemented in different packages (see doc-tools-djvu, doc-tools-poppler, doc-tools-mupdf, doc-tools-pymupdf, doc-tools-epdf (to be added)). These are just document manipulation libraries, that could be used by other packages also (this modular organization may change, but currently this is how it is organized).

So in the end it is just much easier to start from scratch, taking into account all new features while designing the package and optionally port features from the other packages (possibly also from djvu.el) into this package.

doc-scroll

Simplified code

The doc-scroll display engine is an improved an simplified version of the image-roll display engine. Instead of the cumbersome code for the display logic in image-roll, it simply uses the sophisticated overlay searching functionality that is built-in in Emacs (see the initial comment in doc-scroll.el).

Versatile rendering via SVG

The doc-scroll display engine supports displaying the page images as SVG, enabling rendering of annotations in djvu documents (similar to djvu3.el), and the possibility to draw over pages (similar to sketch-mode and el-easydraw).

Improvements over other packages

pdf-tools

Currently, the most powerful (depending on its definition) document viewer for Emacs is pdf-tools. This package improves on it in a few ways:

  • support multiple backends (like djvu, pymupdf)
  • continuous scrolling, and supports viewing and scrolling 2 or more pages side-by-side where the view can be changed by simply using a numeric prefix
  • more annotation features, like line, arrow, and free text annotations (although currently only some type of annotations implemented, but adding support for more types is relatively easy).
  • a togglable thumbs side bar where the number of columns can easily be set using a numeric prefix
  • swiper/consult-line support, where individual candidates (i.e. the ‘searched regions’) can stretch over multiple lines or even full pages. (currently only implemented for djvu)
  • support for all document formats that are supported by mupdf (e.g. epub) (requires the mupdf backend)
  • much simpler code and therefore much more hackable than pdf-tools
  • modular design so that other packages can use ‘individual’ packages without installing all of doc-tools.
  • available via ELPA

image-roll

The image-roll package adds support for continuous scrolling to PDF-tools. This package improves on image-roll in various ways

  • page side-by-side reading (see parent section)
  • thumbs side-bar

more technically

  • greatly simplifies the code by using overlays-in to determine the displayed overlays
  • replace macro’s with generalized variables (i.e. prevent void function errors)

doc-view

  • no waiting for all pages to be converted (on each ‘zoom adjustment’)
  • isearch support
  • imenu support
  • fast scrolling
  • all points mentioned in previous section

djvu.el

  • display annotations support
  • annotate directly in ‘image-mode’ using the mouse
  • all points mentioned in previous sections

Design choices

Page data

  • Caching Currently the package uses the simplest approach for caching the images, all page images simply get written to the /tmp directory. Because the memory required for the images scales exponentially with their size, the package limits the width of the images by default (see doc-scroll-overlay-width variable). Instead of recreating all pages after adjusting the ‘zoom’
  • Columns Displaying columns could have been implemented by fully refilling the buffer, and ‘redistribute’ the overly placeholders (e.g. using single spaces). However, using such implementation would not allow for showing different numbers of columns in different windows. This package implements the columns by using placeholders with a length that is a multiple of the possible number of columns (e.g. 1 x 2 x 3 x 4 x 5 = 120, i.e. the default value). In this way, the overlays can be moved to obtain a different number of columns (1 column uses 120 characters per overlay, 2 columns 60 etc.)

Implemented features

djvu

  • [X] imenu (provides TOC via imenu-list)
  • [X] select/yank text
  • [X] search forward
  • [X] add highlight annotation
  • [ ] save file (partially implemented, i.e. the file gets saved, but the buffer does not yet get restored so that the file has to be killed and found again).

pdf

  • [X] search forward
  • [X] imenu (provides TOC via imenu-list)

Installation

As this package is a work in development, and has not been published on any Emacs archive, the package has to be installed manually. For that:

First clone this package to some directory.

djvu

Make sure that you have djvulibre installed (e.g. for Fedora use sudo dnf install djvulibre). Then download the doc-tools-djvu package from here. Finally, open doc-backend-djvu.el, adjust the paths on top of the file and evaluate the buffer/load the file.

mupdf

Make sure that you have mupdf and poppler-urils installed (e.g. for Fedora use sudo dnf install mupdf poppler-utils, for Ubuntu also mupdf-utils is required). Then download the doc-tools-mupdf package from here. Finally, open doc-backend-mupdf.el, adjust the paths on top of the file and evaluate the buffer/load the file.

pymupdf (recommended)

The following installation instructions are not tested. Please let me know if anything is missing.

Usage

Use n c to switch to display pages side-by-side (where n stands for a number that also determines the number of columns). Use n t to show the thumbs side-bar (n works same as with c). When showing more then about 5 columns, then using the t options is preferred (works more smoothly).

Do M-x imenu-list to show outline (requires imenu-list).

Do M-x doc-scroll-info to obtain all kinds of info about/data from a document.

Do M-x doc-scroll-search (optionally followed by M-x doc-scroll-search-previous/next to search incrementally.

Do M-x doc-scroll-set-pdf/djvu-mode to select which package to use for opening documents (e.g. quickly switch to opening with PDF-tools).

Add annotation range function to pymupdf backend

To create some ‘markup’ annotation, one typically starts with some ‘start’ and ‘end’ coordinates. From those coordinates, the exact region(s) for the highlights should be determined, i.e. extracted from the ‘structured text contents’. As the data structure of structured text in djvu documents is easier to work with, than the data structure from pdf documents, the pymupdf backend can pass the structured text in ‘djvu’ format (Do M-x doc-scroll-info -> doc-pymupdf-info -> doc-pymupdf-page-structured-text -> insert page numbers -> djvu).