Idiomdrottning’s homepage

Reading books via PDF on desktop

Even though I don’t use Firefox normally, I’ve been using it to read EPUB books because I like how it’s three columns. What I don’t like is how those columns get completely mabla at the end of each chapter.

So instead I set up this li’l shell script to read the EPUBs via Pandoc using a custom template for the ConTeXt PDF engine.

You can git clone https://idiomdrottning.org/visp for a repository of all the code from this article.

ellenread.context

Here is the template, it belongs in ~/.pandoc/templates/ellenread.context so pandoc can find it.

It’s made for a 1600×1200 screen and gives me three columns and tiny letters.

That 1600x1200 is currently hardcoded (as width=423.33333mm,height=317.5mm), I measured it out in Inkscape. It’s not just for the aspect ratio, it also affects the font size relative to your screen, which is why it’s good to get it right if you are modifying this script.

It looks like this.

% interface output=luatex
\setuppagenumbering[location=]
\language [sv]
\mainlanguage [sv]
\setuplanguage[sv][leftquote=›,rightquote=‹,leftquotation=»,rightquotation=«]
\definefontfamily [praise][serif][junicode]
\setupalign[justified,hanging,hz]
\setupbodyfont [praise]
$if(number-sections)$
$else$
\setuphead[chapter, section, subsection, subsubsection, subsubsubsection, subsubsubsubsection][number=no]
$endif$
\definefallbackfamily [jeans] [ss] [DejaVu Sans] [range=miscellaneoussymbols]
\definefontfamily [jeans] [ss] [FuturaLT]
\setuphead[chapter][style={\switchtobodyfont[jeans]}]
\setuphead[subject][style={\switchtobodyfont[jeans]\tfc\bold}]
\setuphead[subsubject][style={\switchtobodyfont[jeans]\tfb}]
\setuphead[section][style={\switchtobodyfont[jeans]\tfc\bold}]
\setuphead[subsection][style={\switchtobodyfont[jeans]\tfb}]
\setupindenting[yes,small]
\hyphenation{hall-en}
\definepapersize[ellen][width=423.33333mm,height=317.5mm]
\setuppapersize[ellen]
\setuplayout[
        backspace=14mm,
        width=middle,
	cutspace=14mm,
        topspace=14mm,
	bottomspace=14mm,
        height=middle,
        header=0mm,
        footer=0mm,
        margin=0mm
]
\starttext
\startcolumns[n=3]
$body$
\stopcolumns
\stoptext

visp

I made this shell script, visp to try to play nicely with Calibre. It depends on pandoc, sqlite3, calibredb and context to be in your path. And mupdf-gl but you can change that to any PDF viever.

It takes one argument, a epub file. It can be any random epub file, like "/tmp/0123456789.epub" that you’ve gotten from a publisher, or whatever.

It checks to see if that book is already in Calibre. If it is, it is gonna read Calibre’s version instead. If it’s not, it adds it to calibre and then reads Calibres version. This is nice because I can just be “sloppy” and open EPUBs from the download directory or whereever I find them and visp will organize them for me without clobbering any organization it, or I, have already done.

Then, it checks to see if there is already a PDF-version of that book in Calibre, either a publisher-supplied version or one that this script has made. If not, it calls pandoc with ConTeXt to make a new one with the ellenread template above.

Then finally it calls mupdf to open the document it found or made.

#!/usr/bin/zsh

function multigrep () {
    if  [[ $# -ge 3 ]]; then
	grep -i "$1" =(multigrep "${@[2,-1]}")
    else
	grep -i "$@"
    fi
}

echo "$1"|grep -q .epub$ && {
    calibre_output="$(calibredb add "$1" 2>&1)"
    book_id="$(echo "$calibre_output"|cut -d\  -f 4)"
    echo $book_id|grep -q '^[0-9][0-9]*$' || book_id=$(calibredb -w 1000 list -s "title:$(echo "$calibre_output"|sed -n '2s/^  //p')"|sed -n '1s/ .*//p')
} || book_id=$(multigrep $* =(calibredb -w 1000 list) |cut -d\  -f1)

calibre_path=~/Calibre\ Library/"$(sqlite3 ~/Calibre\ Library/metadata.db "select path from books where id like $book_id")"

find "$calibre_path" |grep -q .pdf$ || {
    pandoc -t context --pdf-engine=context --template ellenread -s -o /tmp/my-visp-${book_id}.pdf "$(find "$calibre_path" |grep .epub$)"
    calibredb add_format $book_id /tmp/my-visp-${book_id}.pdf
    rm /tmp/my-visp-${book_id}.pdf
}

mupdf-gl "$(find "$calibre_path" |grep .pdf$)"

Usage

Yeah, I know that that’s a lot to setup but from then on, just visp blablabla.epub and up pops PDF on my screen.

Or if you are searching for files already in Calibre, just visp bla bla bla for the same thing, you don’t have to supply a filename, just any search terms.

Bonus feature! epubid

I also extracted just the first few lines of that script into epubid, that just takes an epub, adds it to Calibre if it’s not in there but returns the local Calibre book id either way.

Getting the book id from Calibre can be useful for when calling calibredb for various other things, like add_format.

Example usage:

calibredb add_format $(epubid The_Fantastic_Novel.epub) The_Fantastic_Novel.mobi
calibredb add_format $(epubid The_Fantastic_Novel.epub) The_Fantastic_Novel.pdf`

when you want to add The_Fantastic_Novel.epub, The_Fantastic_Novel.mobi and The_Fantastic_Novel.pdf to Calibre all in one go and they’re all in your current shell dir.

Remember that add_format can overwrite your Calibre’s database, which is good when you want to overwrite the visp-generated PDF with a publisher-supplied one, but bad because it can accidentally clobber. That’s why visp tries to take such good care to see that there’s not already a PDF in there.

Future features?