Commit fb088e1f authored by Moritz Lipp's avatar Moritz Lipp

Merge branch 'feature/sphinx' into develop

parents 66bdac61 224d8e92
......@@ -13,9 +13,12 @@ zathura.pc
gcov/
*.swp
version.h
doc/
./doc/_build
*.tmp
zathura.1
zathurarc.5
.version-checks/
dbus-interface-definitions.c
.ycm_extra_conf.py
.ropeproject
compile_commands.json
......@@ -99,7 +99,6 @@ clean:
${PROJECT}-debug \
.depend \
${PROJECT}.pc \
doc \
version.h \
version.h.tmp \
dbus-interface-definitions.c \
......@@ -111,6 +110,7 @@ ifneq "$(wildcard ${RSTTOMAN})" ""
endif
$(QUIET)$(MAKE) -C tests clean
$(QUIET)$(MAKE) -C po clean
$(QUIET)$(MAKE) -C doc clean
${PROJECT}-debug: ${DOBJECTS}
$(ECHO) CC -o $@
......@@ -142,12 +142,26 @@ dist: clean build-manpages
$(QUIET)mkdir -p ${PROJECT}-${VERSION}
$(QUIET)mkdir -p ${PROJECT}-${VERSION}/tests
$(QUIET)mkdir -p ${PROJECT}-${VERSION}/po
$(QUIET)cp LICENSE Makefile config.mk common.mk README AUTHORS Doxyfile \
$(QUIET)mkdir -p ${PROJECT}-${VERSION}/doc
$(QUIET)cp LICENSE Makefile config.mk common.mk README AUTHORS \
${PROJECT}.1.rst ${PROJECT}rc.5.rst ${OSOURCE} ${HEADER} ${PROJECT}.pc.in \
${PROJECT}.desktop version.h.in \
${PROJECT}.1 ${PROJECT}rc.5 \
${PROJECT}-${VERSION}
$(QUIET)cp -r data ${PROJECT}-${VERSION}
$(QUIET)cp -r \
doc/Makefile \
doc/Doxyfile \
doc/config.mk \
doc/conf.py \
doc/*.rst \
doc/requirements.txt \
doc/api \
doc/configuration \
doc/installation \
doc/man \
doc/usage \
${PROJECT}-${VERSION}/doc
$(QUIET)cp tests/Makefile tests/config.mk tests/*.c \
${PROJECT}-${VERSION}/tests
$(QUIET)cp po/Makefile po/*.po ${PROJECT}-${VERSION}/po
......@@ -156,7 +170,7 @@ dist: clean build-manpages
$(QUIET)rm -rf ${PROJECT}-${VERSION}
doc:
$(QUIET)doxygen Doxyfile
$(QUIET)make -C doc
gcov: clean
$(QUIET)CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage" LDFLAGS="${LDFLAGS} -fprofile-arcs" ${MAKE} $(PROJECT)
......@@ -170,29 +184,17 @@ po:
update-po:
$(QUIET)${MAKE} -C po update-po
ifneq "$(wildcard ${RSTTOMAN})" ""
%.1 %.5: config.mk
$(QUIET)sed "s/VERSION/${VERSION}/g" < $@.rst > $@.tmp
$(QUIET)${RSTTOMAN} $@.tmp > $@.out.tmp
$(QUIET)mv $@.out.tmp $@
$(QUIET)rm $@.tmp
${PROJECT}.1: ${PROJECT}.1.rst
${PROJECT}rc.5: ${PROJECT}rc.5.rst
build-manpages: ${PROJECT}.1 ${PROJECT}rc.5
else
build-manpages:
endif
$(QUIET)${MAKE} -C doc man
install-manpages: build-manpages
$(ECHO) installing manual pages
$(QUIET)mkdir -m 755 -p ${DESTDIR}${MANPREFIX}/man1 ${DESTDIR}${MANPREFIX}/man5
ifneq "$(wildcard ${PROJECT}.1)" ""
$(QUIET)install -m 644 ${PROJECT}.1 ${DESTDIR}${MANPREFIX}/man1
ifneq "$(wildcard ./doc/_build/man/${PROJECT}.1)" ""
$(QUIET)install -m 644 ./doc/_build/man/${PROJECT}.1 ${DESTDIR}${MANPREFIX}/man1
endif
ifneq "$(wildcard ${PROJECT}rc.5)" ""
$(QUIET)install -m 644 ${PROJECT}rc.5 ${DESTDIR}${MANPREFIX}/man5
ifneq "$(wildcard ./doc/_build/man/${PROJECT}rc.5)" ""
$(QUIET)install -m 644 ./doc/_build/man/${PROJECT}rc.5 ${DESTDIR}${MANPREFIX}/man5
endif
install-headers: ${PROJECT}.pc
......
......@@ -31,6 +31,9 @@ WITH_MAGIC=0.
If you pass these flags as a command line argument to make, you have to ensure
to pass the same flags when executing the install target.
If you want to build zathuras documentation, please install all python
dependencies from the ./doc/requirements.txt file.
Installation
------------
To build and install zathura:
......
......@@ -48,9 +48,6 @@ PLUGINDIR ?= ${LIBDIR}/zathura
# locale directory
LOCALEDIR ?= ${PREFIX}/share/locale
# rst2man
RSTTOMAN ?= /usr/bin/rst2man
# libs
GTK_INC ?= $(shell pkg-config --cflags gtk+-3.0)
GTK_LIB ?= $(shell pkg-config --libs gtk+-3.0)
......
......@@ -2,7 +2,7 @@
# General information
PROJECT_NAME = zathura
OUTPUT_DIRECTORY = ./doc/
OUTPUT_DIRECTORY = ./_build/doxygen/
OUTPUT_LANGUAGE = English
TAB_SIZE = 2
EXTRACT_ALL = YES
......@@ -16,15 +16,15 @@ WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
# Input files
INPUT =
EXCLUDE = ./tests
INPUT = ../
EXCLUDE = ./tests ./doc
FILE_PATTERNS = *.h *.c
RECURSIVE = YES
# Output files
GENERATE_HTML = YES
GENERATE_HTML = NO
GENERATE_LATEX = NO
GENERATE_RTF = NO
GENERATE_XML = NO
GENERATE_XML = YES
SOURCE_BROWSER = YES
# See LICENSE file for license and copyright information
#
include ../config.mk
include ../common.mk
include config.mk
ifeq ($(shell which $(SPHINX_BIN) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINX_BIN)' command was not found.)
endif
all: html man
init:
$(QUIET)mkdir -p $(SPHINX_BUILDDIR)/
clean:
$(QUIET)rm -rf $(SPHINX_BUILDDIR)/
html: doxygen
$(QUIET)$(SPHINX_BIN) -b html $(SPHINX_OPTS) $(SPHINX_BUILDDIR)/html
man: doxygen
$(QUIET)$(SPHINX_BIN) -b man $(SPHINX_OPTS) $(SPHINX_BUILDDIR)/man
doxygen: init
$(QUIET)$(DOXYGEN_BIN) Doxyfile
.PHONY: clean html man
API and Development
===================
This guide should give a short introduction in the way zathura's plugin
system works and how you can write your own plugin and let zathura use
it.
zathura's plugin system is quite simple. At startup zathura searches
through a specified directory for shared objects and tries to load them
as plugins. Each plugin has to register itself by a name, its version, a
special function as well as its supported mimetypes to zathura. After
the registration of the plugin zathura will automatically use it to open
files with the previous defined mimetypes. That's it.
.. toctree::
:maxdepth: 2
:hidden:
plugin
Example - A minimalistic PDF plugin
===================================
In this section we are going to develop a simplified version of the
`zathura-pdf-poppler <../zathura-pdf-poppler>`_ plugin. For the sake of
simplicity we are not discussing the build process of the plugin because
we would recommend you to adapt our Makefiles from existing plugins. In
addition we avoid most of the error handling that should be implemented.
Prerequisites
~~~~~~~~~~~~~
In order to use the following described functions and macros you have to
include the *plugin-api.h* header file:
::
#include <zathura/plugin-api.h>
This automatically loads other header files for the
*zathura\_document\_t*, *zathura\_page\_t* as well as all the other
types that are necessary automatically.
Register the plugin
~~~~~~~~~~~~~~~~~~~
As previously described each plugin has to register itself to zathura so
that it can be used properly. Therefore we have introduced a macro
called *ZATHURA\_PLUGIN\_REGISTER* which expects several parameters:
- Plugin name *The name of the plugin*
- Major version *The plugins major version*
- Minor version *The plugins minor version*
- Revision *The plugins revision*
- Open function *The open function*
- Mimetypes *A character array of supported mime types*
In our case we are going to register our plugin "my plugin" with its
version 1.0.1, the register function *register\_functions* and the list
of supported mimetypes.
::
ZATHURA_PLUGIN_REGISTER(
"plugin-tutorial",
0, 1, 0,
register_functions,
ZATHURA_PLUGIN_MIMETYPES({
"application/pdf"
})
)
This macro will automatically generate among others a function called
*plugin\_register* which is used to register the plugin to zathura when
it has been loaded.
Register the plugin functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In our macro we have defined that the function *register\_functions* is
used to install our functions which will implement a certain
functionality in the struct:
::
void
register_functions(zathura_plugin_functions_t* functions)
{
functions->document_open = plugin_document_open;
functions->document_free = plugin_document_free;
functions->page_init = plugin_page_init;
functions->page_clear = plugin_page_clear;
functions->page_render_cairo = plugin_page_render_cairo;
}
We are now going to give a short overview about the used functions in
the above code snippet. For a complete documentation you should checkout
the documentation of `zathura\_document\_functions\_t <../../doxygen>`_.
A document instance consists out of a *zathura\_document\_t* document
object that contains information about the document itself and a defined
number of *zathura\_page\_t* page objects. There are several functions
defined for those two types and they have to be implemented by the
plugin. For our simple plugin which will only be capable of rendering a
page we will need one function that is capable of opening the PDF
document and setting up all necessary objects for further usage and one
function which will clean up all the allocated objects afterwards. In
addition we need two of those functions for page objects as well and one
function that will actually implement the rendering process.
Open and closing a document
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The first thing we have to do when opening a document is to initialize
all necessary objects and values that we are going to need for the
future use of the plugin. Therefore we have to implement our
*pdf\_document\_open* function:
::
zathura_error_t
plugin_document_open(zathura_document_t* document)
{
/* get path and password */
const char* path = zathura_document_get_path(document);
const char* password = zathura_document_get_password(document);
/* create document data */
char* uri = g_filename_to_uri(path, NULL, NULL);
PopplerDocument* poppler_document = poppler_document_new_from_file(uri, password, NULL);
g_free(uri);
if (poppler_document == NULL) {
return ZATHURA_ERROR_UNKNOWN;
}
/* save poppler document for further usage */
zathura_document_set_data(document, poppler_document);
/* get number of pages */
unsigned int number_of_pages = poppler_document_get_n_pages(poppler_document);
zathura_document_set_number_of_pages(document, number_of_pages);
return ZATHURA_ERROR_OK;
}
To open the document we retrieve the *path* and the optional *password*
of the document to create an instance of *PopplerDocument* which
represents a document in the poppler library. If this fails for any
reason (e.g.: the path does not exist, the user provided the incorrect
password) we tell zathura that this function failed for an unknown
reason. If we are lucky we continue and save the created
*poppler\_document* object in the custom data field of the document so
that we can access it later on. After that we determine the number of
pages that the document contains so that zathura can initialize every
single page.
Since we have allocated the *poppler\_document* object we have to make
sure that its resources will be freed when it is no longer needed. This
happens in our *pdf\_document\_free* function:
::
zathura_error_t
plugin_document_free(zathura_document_t* document, PopplerDocument* poppler_document)
{
g_object_unref(poppler_document);
return ZATHURA_ERROR_OK;
}
Page initialization
~~~~~~~~~~~~~~~~~~~
Each page has to be initialized so that zathura knows about its
dimension. In addition this stage is used to store additional data in
the page that will be used for further use with it. Therefore we are
implementing *pdf\_page\_init* which will save the width and the height
of the page in the given structure:
::
zathura_error_t
plugin_page_init(zathura_page_t* page)
{
unsigned int page_index = zathura_page_get_index(page);
zathura_document_t* document = zathura_page_get_document(page);
PopplerDocument* poppler_document = zathura_document_get_data(document);
/* create poppler page */
PopplerPage* poppler_page = poppler_document_get_page(poppler_document, page_index);
zathura_page_set_data(page, poppler_page);
/* get page dimensions */
double width, height;
poppler_page_get_size(poppler_page, &width, &height);
zathura_page_set_width(page, width);
zathura_page_set_height(page, height);
return ZATHURA_ERROR_OK;
}
And we have to make sure that all requested resources are freed in the
end:
::
zathura_error_t
plugin_page_clear(zathura_page_t* page, PopplerPage* poppler_page)
{
g_object_unref(poppler_page);
return ZATHURA_ERROR_OK;
}
Render a page
~~~~~~~~~~~~~
After we have setup the document and the page objects we are ready to
implement the render function which finally will be able to draw our
page on a widget so that it can be viewed with zathura. This function
has two additional parameters to the already known *zathura\_page\_t*
object: One of them is a *cairo\_t* object which will be used to render
the page, the other one is a flag called *printing* which determines if
the rendered page should be rendered for the print process of zathura.
For instance if this flag is set to true you should not render any
rectangles around links in the document because they are totally
worthless on paper:
::
zathura_error_t
pdf_page_render_cairo(zathura_page_t* page, cairo_t* cairo, bool printing)
{
if (printing == false) {
poppler_page_render(poppler_page, cairo);
} else {
poppler_page_render_for_printing(poppler_page, cairo);
}
return ZATHURA_ERROR_OK;
}
In this case the *pdf\_page\_render\_cairo* function is very simplistic
since all the work is done by the *poppler* library. In your case you
might have to do some magic here to draw the page to the cairo object.
Make sure to check out the source code of our plugins.
Installation of the plugin
~~~~~~~~~~~~~~~~~~~~~~~~~~
As we suggested earlier the easiest way to build and install the plugin
is to duplicate the *Makefile* (as long with its *common.mk* and
*config.mk* files of one of our plugins. It already contains all
necessary targets for building, installing and debugging the plugin.
Otherwise you could build the above plugin with the following command:
::
$ gcc -std=c99 -shared -fPIC -pedantic -Wall `pkg-config --cflags --libs poppler-glib zathura` \
-o pdf.so pdf.c
After that you have to copy the *pdf.so* file into the directory where
zathura looks for plugins (this is by default: */usr/lib/zathura*).
Plugin system
=============
zathura's plugin system is quite simple. At startup zathura searches
through a specified directory for shared objects and tries to load them
as plugins. Each plugin has to register itself by a name, its version, a
special function as well as its supported mimetypes to zathura. After
the registration of the plugin zathura will automatically use it to open
files with the previous defined mimetypes. That's it.
Each plugin has to implement a basic set of functionality so that it can
be used in a meaningful way with zathura. For instance it would not make
any sense if the plugin was not able to render any page at all. On the
contrary the export of images out of the document might not be
considered as that important.
We have predefined a certain set of functionality that a plugin can have
and that can be used by zathura if it has been implemented by the
plugin. When a plugin is loaded, zathura calls a certain function that
the plugin **must implemented** in order to work correctly. This
function gets a data structure which has to be filled with function
pointers by the plugin, which are then used by the main application.
.. toctree::
plugin-development
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# See LICENSE file for license and copyright information
import sphinx_rtd_theme
# -- General configuration ------------------------------------------------
extensions = [
'sphinx.ext.todo',
'breathe'
]
source_suffix = '.rst'
master_doc = 'index'
templates_path = ['_templates']
exclude_patterns = ['_build']
pygments_style = 'sphinx'
# -- Project configuration ------------------------------------------------
project = 'zathura'
copyright = '2014, pwmt.org'
version = '0.2.7'
release = '0.2.7'
# -- Options for HTML output ----------------------------------------------
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
html_static_path = ['_static']
htmlhelp_basename = 'zathuradoc'
# -- Options for manual page output ---------------------------------------
man_pages = [
('man/zathura.1', 'zathura', 'a document viewer', ['pwmt.org'], 1),
('man/zathurarc.5', 'zathurarc', 'a document viewer', ['pwmt.org'], 5)
]
# -- Options for breathe ---------------------------------------
breathe_projects = { "zathura": "_build/doxygen/xml" }
breathe_default_project = "zathura"
breathe_build_directory = "_build"
breathe_projects_source = {
"zathura": "../"
}
breathe_domain_by_extension = {
"h" : "c",
"c" : "c"
}
# See LICENSE file for license and copyright information
SPHINX_BIN = sphinx-build
SPHINX_BUILDDIR = _build
SPHINX_OPTS = -d $(SPHINX_BUILDDIR)/doctrees .
DOXYGEN_BIN = doxygen
Configuration
=============
.. toctree::
:maxdepth: 1
set
map
options
The customization of zathura is be managed via a configuration file
called *zathurarc*. By default zathura will evaluate the following
files:
- */etc/zathurarc*
- *$XDG\_CONFIG\_HOME/zathura/zathurarc* (default:
~/.config/zathura/zathurarc)
The *zathurarc* file is a simple plain text file that can be populated
with various commands to change the behaviour and the look of zathura
which we are going to describe in the following subsections. Each line
(besides empty lines and comments (which start with a prepended *#*) is
evaluated on its own, so it is not possible to write multiple commands
in one single line.
map - Mapping a shortcut
========================
It is possible to map or remap new key bindings to shortcut functions
which allows a high level of customization. The *:map* command can also
be used in the *zathurarc* file to make those changes permanent:
::
map [mode] <binding> <shortcut function> <argument>
Mode
----
The *map* command expects several arguments where only the *binding* as
well as the *shortcut-function* argument is required. Since zathura uses
several modes it is possible to map bindings only for a specific mode by
passing the *mode* argument which can take one of the following values:
- normal (default)
- visual
- insert
- fullscreen
- index
The brackets around the value are mandatory.
Single key binding
~~~~~~~~~~~~~~~~~~
The (possible) second argument defines the used key binding that should
be mapped to the shortcut function and is structured like the following.
On the one hand it is possible to just assign single letters, numbers or
signs to it:
::
map a shortcut_function
map b shortcut_function
map c shortcut_function
map 1 shortcut_function
map 2 shortcut_function
map 3 shortcut_function
map ! shortcut_function
map ? shortcut_function
Using modifiers
---------------
It is also possible to use modifiers like the *Control* or *Alt* button
on the keyboard. It is possible to use the following modifiers:
- A - *Alt*
- C - *Control*
- S - *Shift*
Now it is required to define the *binding* with the following structure:
::
map <A-a> shortcut_function
map <C-a> shortcut_function
Special keys
------------
zathura allows it also to assign keys like the space bar or the tab
button which also have to be written in between angle brackets. The
following special keys are currently available:
+--------------+--------------------+
| Identifier | Description |
+==============+====================+
| BackSpace | *Back space* |
+--------------+--------------------+
| CapsLock | *Caps lock* |
+--------------+--------------------+
| Esc | *Escape* |
+--------------+--------------------+
| Down | *Arrow down* |
+--------------+--------------------+
| Up | *Arrow up* |
+--------------+--------------------+
| Left | *Arrow left* |
+--------------+--------------------+
| Right | *Arrow right* |
+--------------+--------------------+
| F1 | *F1* |
+--------------+--------------------+
| F2 | *F2* |
+--------------+--------------------+
| F3 | *F3* |
+--------------+--------------------+
| F4 | *F4* |
+--------------+--------------------+
| F5 | *F5* |
+--------------+--------------------+
| F6 | *F6* |
+--------------+--------------------+
| F7 | *F7* |
+--------------+--------------------+
| F8 | *F8* |
+--------------+--------------------+
| F9 | *F9* |
+--------------+--------------------+
| F10 | *F10* |
+--------------+--------------------+
| F11 | *F11* |
+--------------+--------------------+
| F12 | *F12* |
+--------------+--------------------+
| PageDown | *Page Down* |
+--------------+--------------------+
| PageUp | *Page Up* |
+--------------+--------------------+
| Return | *Return* |
+--------------+--------------------+
| Space | *Space* |
+--------------+--------------------+
| Super | *Windows button* |
+--------------+--------------------+
| Tab | *Tab* |
+--------------+--------------------+
Of course it is possible to combine those special keys with a modifier.
The usage of those keys should be explained by the following examples:
::
map <Space> shortcut_function
map <C-Space> shortcut_function
Mouse buttons
-------------
It is also possible to map mouse buttons to shortcuts by using the
following special keys:
+--------------+--------------------+
| Identifier | Description |
+==============+====================+
| Button1 | *Mouse button 1* |
+--------------+--------------------+
| Button2 | *Mouse button 2* |
+--------------+--------------------+
| Button3 | *Mouse button 3* |
+--------------+--------------------+
| Button4 | *Mouse button 4* |
+--------------+--------------------+
| Button5 | *Mouse button 5* |
+--------------+--------------------+
They can also be combined with modifiers:
::
map <Button1> shortcut_function
map <C-Button1> shortcut_function
Buffer commands
---------------
If a mapping does not match one of the previous definition but is still
a valid mapping it will be mapped as a buffer command:
::
map abc quit
map test quit
Shortcut functions
------------------
The following shortcut functions can be mapped:
+----------------------+----------------------------------------+
| Function | Description |
+======================+========================================+
| abort | *Switch back to normal mode* |
+----------------------+----------------------------------------+
| adjust\_window | *Adjust page width* |
+----------------------+----------------------------------------+
| change\_mode | *Change current mode* |
+----------------------+----------------------------------------+
| follow | *Follow a link* |
+----------------------+----------------------------------------+
| focus\_inputbar | *Focus inputbar* |
+----------------------+----------------------------------------+
| goto | *Go to a certain page* |
+----------------------+----------------------------------------+
| index\_navigate | *Navigate through the index* |
+----------------------+----------------------------------------+
| navigate | *Navigate to the next/previous page* |
+----------------------+----------------------------------------+
| quit | *Quit zathura* |
+----------------------+----------------------------------------+
| recolor | *Recolor the pages* |
+----------------------+----------------------------------------+
| reload | *Reload the document* |
+----------------------+----------------------------------------+
| rotate | *Rotate the page* |
+----------------------+----------------------------------------+
| scroll | *Scroll* |
+----------------------+----------------------------------------+