forked from openstenoproject/plover
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
doc: Move remainder of plugin dev doc to separate pages
- Loading branch information
Showing
6 changed files
with
340 additions
and
303 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
Dictionaries | ||
============ | ||
|
||
To define a dictionary format with the file extension ``.abc``, add this name | ||
(without the ``.``) as an entry point: | ||
|
||
.. code-block:: ini | ||
[options.entry_points] | ||
plover.dictionary = | ||
abc = plover_my_plugin.dictionary:ExampleDictionary | ||
Dictionary plugins are implemented as **classes** inheriting from | ||
:class:`StenoDictionary<plover.steno_dictionary.StenoDictionary>`. Override the | ||
``_load`` and ``_save`` methods *at least* to provide functionality to read and | ||
write your desired dictionary format. | ||
|
||
.. highlight:: python | ||
|
||
:: | ||
|
||
# plover_my_plugin/dictionary.py | ||
|
||
from plover.steno_dictionary import StenoDictionary | ||
|
||
class ExampleDictionary(StenoDictionary): | ||
|
||
def _load(self, filename): | ||
# If you are not maintaining your own state format, self.update is usually | ||
# called here to add strokes / definitions to the dictionary state. | ||
pass | ||
|
||
def _save(self, filename): | ||
pass | ||
|
||
Some dictionary formats, such as Python dictionaries, may require implementing | ||
other parts of the class as well. See the documentation for | ||
:class:`StenoDictionary<plover.steno_dictionary.StenoDictionary>` for more | ||
information. | ||
|
||
Note that setting ``readonly`` to ``True`` on your dictionary class will make | ||
it so the user is not able to modify a dictionary of that type in the UI. | ||
|
||
.. TODO: | ||
- dictionary loading/saving code | ||
- programmatic dictionary formats |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
Extensions | ||
========== | ||
|
||
Extension plugins are implemented as **classes**. The initializer should take | ||
only a :class:`StenoEngine<plover.engine.StenoEngine>` as a parameter. | ||
|
||
.. code-block:: ini | ||
[options.entry_points] | ||
plover.extension = | ||
example_extension = plover_my_plugin.extension:Extension | ||
.. highlight:: python | ||
|
||
:: | ||
|
||
# plover_my_plugin/extension.py | ||
|
||
class Extension: | ||
def __init__(self, engine): | ||
# Called once to initialize an instance which lives until Plover exits. | ||
pass | ||
|
||
def start(self): | ||
# Called to start the extension or when the user enables the extension. | ||
# It can be used to start a new thread for example. | ||
pass | ||
|
||
def stop(self): | ||
# Called when Plover exits or the user disables the extension. | ||
pass | ||
|
||
.. TODO: | ||
- demonstrate hooks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
GUI Tools | ||
========= | ||
|
||
Plugins containing GUI tools will also require modifying the ``setup.py`` | ||
as follows: | ||
|
||
.. highlight:: python | ||
|
||
:: | ||
|
||
from setuptools import setup | ||
from plover_build_utils.setup import BuildPy, BuildUi | ||
|
||
BuildPy.build_dependencies.append("build_ui") | ||
BuildUi.hooks = ["plover_build_utils.pyqt:fix_icons"] | ||
CMDCLASS = { | ||
"build_py": BuildPy, | ||
"build_ui": BuildUi, | ||
} | ||
|
||
setup(cmdclass=CMDCLASS) | ||
|
||
By making these changes, you get commands to generate Python files from your | ||
Qt Designer UI and resource files: | ||
|
||
.. code-block:: none | ||
python3 setup.py build_py build_ui | ||
In addition, create a file named ``MANIFEST.in`` in your plugin directory as | ||
follows. Change the paths as needed, but make sure to only include the Qt | ||
Designer ``.ui`` files and resources, and not the generated Python files. | ||
|
||
.. code-block:: none | ||
exclude plover_my_plugin/tool/*_rc.py | ||
exclude plover_my_plugin/tool/*_ui.py | ||
include plover_my_plugin/tool/*.ui | ||
recursive-include plover_my_plugin/tool/resources * | ||
.. code-block:: ini | ||
[options.entry_points] | ||
plover.gui.qt.tool = | ||
example_tool = plover_my_plugin.tool:Main | ||
GUI tools are implemented as Qt widget **classes** inheriting from | ||
:class:`Tool<plover.gui_qt.tool.Tool>`: | ||
|
||
:: | ||
|
||
# plover_my_plugin/tool.py | ||
|
||
from plover.gui_qt.tool import Tool | ||
|
||
# You will also want to import / inherit for your Python class generated by | ||
# your .ui file if you are using Qt Designer for creating your UI rather | ||
# than only from code | ||
class Main(Tool): | ||
TITLE = 'Example Tool' | ||
ICON = '' | ||
ROLE = 'example_tool' | ||
|
||
def __init__(self, engine): | ||
super().__init__(engine) | ||
# If you are inheriting from your .ui generated class, also call | ||
# self.setupUi(self) before any additional setup code | ||
|
||
Keep in mind that when you need to make changes to the UI, you will need to | ||
generate new Python files. | ||
|
||
See the documentation on :class:`Tool<plover.gui_qt.tool.Tool>` for more | ||
information. | ||
|
||
.. TODO: | ||
- Qt signal hooks | ||
- creating UIs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
Machines | ||
======== | ||
|
||
To define a new machine called ``Example Machine``, add the name as an entry | ||
point to your ``setup.py``: | ||
|
||
.. code-block:: ini | ||
[options.entry_points] | ||
plover.machine = | ||
Example Machine = plover_my_plugin.machine:ExampleMachine | ||
Machines are implemented as **classes** that inherit from one of a few machine | ||
classes. The example shown uses the | ||
:class:`ThreadedStenotypeBase<plover.machine.base.ThreadedStenotypeBase>` class | ||
as it is the most common use case, but you can build machine plugins off of the | ||
:class:`StenotypeBase<plover.machine.base.StenotypeBase>`, | ||
:class:`SerialStenotypeBase<plover.machine.base.SerialStenotypeBase>`, or other | ||
classes depending on your needs. | ||
|
||
.. highlight:: python | ||
|
||
:: | ||
|
||
# plover_my_plugin/machine.py | ||
|
||
from plover.machine.base import ThreadedStenotypeBase | ||
|
||
class ExampleMachine(ThreadedStenotypeBase): | ||
KEYS_LAYOUT: str = '0 1 2 3 4 5 6 7 8 9 10' | ||
def __init__(self, params): | ||
super().__init__() | ||
self._params = params | ||
|
||
def run(self): | ||
self._ready() | ||
while not self.finished.wait(1): | ||
self._notify(self.keymap.keys_to_actions(['1'])) | ||
|
||
def start_capture(self): | ||
super().start_capture() | ||
|
||
def stop_capture(self): | ||
super().stop_capture() | ||
|
||
@classmethod | ||
def get_option_info(cls): | ||
pass | ||
|
||
The ``_notify`` method should be called whenever a stroke is received. It takes | ||
a set of key names in the current system (it's possible to convert from machine | ||
key names to system key names (actions) with ``self.keymap.keys_to_actions`` | ||
function) and then tells the steno engine the key input that just occurred. | ||
|
||
There are 3 ways to configure the keymap: | ||
|
||
* Add an entry for the machine in a system plugin's default bindings | ||
definition (``KEYMAPS`` variable) | ||
* The user can manually set the keymap in the Machine section in the | ||
configuration, along with any other additional configuration if a | ||
machine_option plugin is available for the machine type | ||
* Define a class variable ``KEYMAP_MACHINE_TYPE``, which means that the | ||
default configuration is the same as the default configuration of the | ||
specified machine. | ||
|
||
See :doc:`api/machine` for more information. | ||
|
||
Machine Options | ||
--------------- | ||
|
||
If your machine requires additional configuration options, add a machine | ||
options entry point: | ||
|
||
.. code-block:: ini | ||
[options.entry_points] | ||
plover.gui_qt.machine_options = | ||
plover_my_plugin.machine:ExampleMachine = plover_my_plugin.machine:ExampleMachineOption | ||
Machine options plugins are implemented as Qt widget **classes**: | ||
|
||
:: | ||
|
||
# plover_my_plugin/machine.py | ||
|
||
from PyQt5.QtWidgets import QWidget | ||
|
||
class ExampleMachineOption(QWidget): | ||
def setValue(self, value): | ||
pass | ||
|
||
The process for developing these is similar to that for :doc:`gui_tools`. | ||
See :ref:`qt_machine_options` for more information. | ||
|
||
.. TODO: | ||
- serial machine API | ||
- implementing protocols | ||
- Qt UI for machine options |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
Systems | ||
======= | ||
|
||
To define a new system called ``Example System``, add it as an entry point: | ||
|
||
.. code-block:: ini | ||
[options.entry_points] | ||
plover.system = | ||
Example System = plover_my_plugin.system | ||
If you have any dictionaries, also add the following line to your | ||
``MANIFEST.in``, to ensure that the dictionaries are copied when you distribute | ||
the plugin: | ||
|
||
.. code-block:: none | ||
include plover_my_plugin/dictionaries/* | ||
System plugins are implemented as **modules** with all of the necessary fields | ||
to create a custom key layout. | ||
|
||
.. highlight:: python | ||
|
||
:: | ||
|
||
# plover_my_plugin/system.py | ||
|
||
# The keys in your system, defined in steno order | ||
KEYS: Tuple[str, ...] | ||
# Keys that serve as an implicit hyphen between the two sides of a stroke | ||
IMPLICIT_HYPHEN_KEYS: Tuple[str, ...] | ||
|
||
# Singular keys that are defined with suffix strokes in the dictionary | ||
# to allow for folding them into a stroke without an explicit definition | ||
SUFFIX_KEYS: Tuple[str, ...] | ||
|
||
# The key that serves as the "number key" like # in English | ||
NUMBER_KEY: Optional[str] | ||
# A mapping of keys to number aliases, e.g. {"S-": "1-"} means "#S-" can be | ||
# written as "1-" | ||
NUMBERS: Dict[str, str] | ||
|
||
# The stroke to undo the last stroke | ||
UNDO_STROKE_STENO: str | ||
|
||
# A list of rules mapping regex inputs to outputs for orthography. | ||
ORTHOGRAPHY_RULES: List[Tuple[str, str]] | ||
# Aliases for similar or interchangeable suffixes, e.g. "able" and "ible" | ||
ORTHOGRAPHY_RULES_ALIASES: Dict[str, str] | ||
# Name of a file containing words that can be used to resolve ambiguity | ||
# when applying suffixes. | ||
ORTHOGRAPHY_WORDLIST: Optional[str] | ||
|
||
# Default key mappins for machine plugins to system keys. | ||
KEYMAPS: Dict[str, Dict[str, Union[str, Tuple[str, ...]]]] | ||
|
||
# Root location for default dictionaries | ||
DICTIONARIES_ROOT: str | ||
# File names of default dictionaries | ||
DEFAULT_DICTIONARIES: Tuple[str, ...] | ||
|
||
Note that there are a lot of possible fields in a system plugin. You must set | ||
them all to something but you don't necessarily have to set them to something | ||
*meaningful* (i.e. some can be empty), so they can be pretty straightforward. | ||
|
||
Since it is a Python file rather than purely declarative you can run code for | ||
logic as needed, but Plover will try to directly access all of these fields, | ||
which does not leave much room for that. However, it does mean that if for | ||
example you wanted to make a slight modification on the standard English system | ||
to add a key, you could import it and set your system's fields to its fields | ||
as desired with changes to ``KEYS`` only; or, you could make a base system | ||
class that you import and expand with slightly different values in the various | ||
fields for multiple system plugins like Michela does for Italian. | ||
|
||
See the documentation for :mod:`plover.system` for information on all the fields. | ||
|
||
.. TODO: | ||
- more details on individual system fields |
Oops, something went wrong.