HOW I DEVELOP PLUGINS FOR KOREADER
Sure, you could get rich and flame out building FarmVille
clones for Tim Cook and Larry Page. Or you could live a
hermit's life and build silly little plugins for your e-ink
powered device, like an app to or or . But how would you
accomplish all that, being a hermit and all that?
Well... Maybe you've heard of ? Oh. You haven't... Well let
me tell you that KOReader is only the best aftermarket
document viewer for Kobos, Kindles, PocketBooks and Android
(imagine that, fortune strikes after all). KOReader has been
around just shy of a decade (though I only found out about
its glory two years ago). It boasts a plenty of features to
put your first-party e-reading software to shame.
In this rambling, I'll cover my workflow for writing,
building, and testing code with the KOReader emulator, as
well as my workflow for testing on my e-reader, a Kobo Libra
H2O. It's not really a tutorial per se (I'll admit the title
misleads on this revelation). More like an overly pedantic
explanation of my workflow.
What I don't cover is how I write Lua or how a person can
use KOReader's to build their iPhone-killer plugins. To
grasp the lunar language I recommend sifting through . To
understand KOReader's front-end modules I'd suggest reading
through the , which is a pretty simple plugin and covers
most of the conventions you'll need to know.
Development Environment and Tools
------------------------------------------------------------
What's a guy need to get going? Just a small satchel of
dependencies: , , , and . Oh, and the . That last dep might
be a bit tricky to install.
If you're reading this rambling like a "how-to" and are
having trouble getting your environment setup, reach out the
for help. Feel free to ping me @roygbyte, or cast your voice
into the void. You'll get help, for sure.
Project Structure
------------------------------------------------------------
Some people work on their plugins straight out of the
`koreader/plugins' folder. This is a fairly straight-forward
process and will work if you don't want a separate
repository for your plugin.
My preferred structure is to dedicate a folder on my machine
to KOReader development. Inside that folder I include the
project base, as well as the plugins I'm working. For me,
this folder looks like:
,----
| /_KOReader
| /koreader
| /crossword.koplugin
| /weather.koplugin
| /contrib
`----
Concerning the above: `koreader' is the ,
`crossword.koplugin' and `weather.koplugin' are my two
plugins, and `contrib' is KOReader's plugin repository (It's
actually not relevant for this rambling, but I'm including
it as a "shout-out" and encouragement to my dear reader to
check it out, where you'll find some KOReader treasures.)
I like this setup because it lets me keep the KOReader
project files separate from my plugin development. I can
have separate Git repositories for both and not worry about
one fan's shit hitting another and causing a real foobar. I
use a system link to stitch it all together:
,----
| /_KOReader
| /koreader
| /plugins
| crossword.koplugin -> [...]/_KOReader/crossword.koplugin
| /crossword.koplugin
`----
The one thing to note is that the system link has to be
*absolute*. I learned this the "hard" way, with KOReader
fritzing out over relative paths. What a mess that
was... Anyways! In the snippet above, I've truncated it, but
the full thing reads
`/home/scarlett/Development/_KOReader/crossword.koplugin'.
Maybe you'd like to try something similar? Well, to create a
soft-link navigate to your `=/koreader/plugins='
folder. From this directory, execute the following command
(but, like, change the directories to match your file
system):
,----
| # FYI: First argument is the target (i.e.: destination folder).
| # Second argument is the link name and location.
| ln -s /home/scarlett/Development/_KOReader/crossword.koplugin crossword.koplugin
`----
If you're copying along, you'll want to confirm the link was
successful. Either try and travel through it with `cd' or
list the directory contents with `ls'. Running the emulator
and then seeing if you plugin exists can also confirm
success (or failure!)
,----
| # A happy link will show the link name and the target.
| ls -la koreader/plugins
| # Or launch the emulator from `koreader`.
| ./kodev run
`----
Development workflow
------------------------------------------------------------
For my actual development (i.e.: coding, linting, debugging,
testing) process, I'm no outlier of genius. As I learned
from the wise words of in art school, always start with
pseudo-code. After that's done, I slowly turn it over into
code-code. Before running the emulator and testing the
results, I will check the files over for correct syntax
using `luacheck', like so:
,----
| luacheck crossword.koplugin/*
`----
(As I'm writing this, I see that Luacheck can be integrated directly into
Emacs through the [FlyCheck]()
extension. I am absolutely going to be installing this extension next
time I work on my plugin!)
After linting/syntax analysing, I run the emulator (`./kodev
run') and proceed to test the plugin by hand. Then it's a
simple matter of rinsing and repeating those steps over and
over again.
When it comes time to test the plugin on my e-reader, I use
`scp' to transfer the files. First, I enable the wifi
connection on KOReader. Then I launch KOReader's SSH daemon
(Settings > Network > SSH server), set the port to 22 and
"login without password". Then I run `scp' with the
following arguments (note: you'll have to change the local
address to whatever your device indicates):
,----
| scp -r --exclude='.*' crossword.koplugin/*
| root@192.168.2.16:/mnt/onboard/.adds/koreader/plugins/crossword.koplugin/
`----
Looking at that snippet now, I can't remember if it works
out-of-the-box. I think I had to make `crossword.koplugin'
on my Kobo before I could upload to it. And I don't think
`scp' even accepts an exclude argument? And probably I
should be using `rsync' anyways? Gosh, there's so much to
learn. And on that note I better go... bye!