plover 5.1.0__py3-none-any.whl → 5.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plover/__init__.py +5 -3
- plover/config.py +58 -14
- plover/dictionary/loading_manager.py +1 -1
- plover/engine.py +205 -37
- plover/formatting.py +5 -2
- plover/gui_qt/about_dialog_ui.py +1 -1
- plover/gui_qt/add_translation_dialog_ui.py +1 -1
- plover/gui_qt/add_translation_widget_ui.py +1 -1
- plover/gui_qt/appearance.py +49 -0
- plover/gui_qt/config_file_widget_ui.py +1 -1
- plover/gui_qt/config_keyboard_widget_ui.py +1 -1
- plover/gui_qt/config_plover_hid_widget_ui.py +1 -1
- plover/gui_qt/config_serial_widget_ui.py +2 -11
- plover/gui_qt/config_window.py +139 -33
- plover/gui_qt/config_window_ui.py +2 -2
- plover/gui_qt/console_widget.py +1 -1
- plover/gui_qt/console_widget_ui.py +1 -1
- plover/gui_qt/dictionaries_widget_ui.py +1 -1
- plover/gui_qt/dictionary_editor_ui.py +1 -1
- plover/gui_qt/lookup_dialog_ui.py +1 -1
- plover/gui_qt/machine_options.py +1 -19
- plover/gui_qt/main_window.py +13 -1
- plover/gui_qt/main_window_ui.py +15 -8
- plover/gui_qt/paper_tape_ui.py +1 -1
- plover/gui_qt/plugins_manager.py +9 -4
- plover/gui_qt/plugins_manager_ui.py +2 -2
- plover/gui_qt/resources_rc.py +29 -29
- plover/gui_qt/run_dialog_ui.py +1 -1
- plover/gui_qt/suggestions_dialog_ui.py +1 -1
- plover/gui_qt/trayicon.py +0 -2
- plover/gui_qt/utils.py +0 -1
- plover/i18n.py +1 -1
- plover/key_combo.py +3 -1
- plover/log.py +2 -2
- plover/machine/base.py +12 -2
- plover/machine/keyboard_capture/__init__.py +33 -10
- plover/machine/keymap.py +86 -10
- plover/machine/plover_hid.py +46 -25
- plover/machine/procat.py +0 -3
- plover/machine/stentura.py +5 -5
- plover/messages/es/LC_MESSAGES/plover.mo +0 -0
- plover/messages/es/LC_MESSAGES/plover.po +2 -2
- plover/messages/fr/LC_MESSAGES/plover.mo +0 -0
- plover/messages/fr/LC_MESSAGES/plover.po +2 -2
- plover/messages/it/LC_MESSAGES/plover.mo +0 -0
- plover/messages/it/LC_MESSAGES/plover.po +2 -2
- plover/messages/nl/LC_MESSAGES/plover.mo +0 -0
- plover/messages/nl/LC_MESSAGES/plover.po +2 -2
- plover/messages/plover.pot +1 -1
- plover/messages/zh_tw/LC_MESSAGES/plover.mo +0 -0
- plover/messages/zh_tw/LC_MESSAGES/plover.po +2 -2
- plover/orthography.py +2 -1
- plover/oslayer/controller.py +1 -1
- plover/oslayer/linux/keyboardcontrol.py +4 -2
- plover/oslayer/linux/keyboardcontrol_uinput.py +107 -343
- plover/oslayer/linux/keyboardcontrol_x11.py +22 -13
- plover/oslayer/linux/keyboardlayout_wayland.py +403 -0
- plover/oslayer/linux/log.py +3 -1
- plover/oslayer/linux/wayland_connection.py +293 -0
- plover/oslayer/osx/keyboardlayout.py +1 -1
- plover/plugins_manager/registry.py +4 -3
- plover/registry.py +1 -1
- plover/scripts/main.py +6 -3
- plover/system/__init__.py +7 -7
- {plover-5.1.0.dist-info → plover-5.2.1.dist-info}/METADATA +5 -4
- {plover-5.1.0.dist-info → plover-5.2.1.dist-info}/RECORD +76 -74
- {plover-5.1.0.dist-info → plover-5.2.1.dist-info}/WHEEL +1 -1
- plover_build_utils/check_requirements.py +0 -3
- plover_build_utils/functions.sh +0 -11
- plover_build_utils/testing/__init__.py +9 -0
- plover_build_utils/testing/blackbox.py +3 -1
- plover_build_utils/testing/steno_dictionary.py +2 -2
- plover_build_utils/deps.sh +0 -2
- {plover-5.1.0.dist-info → plover-5.2.1.dist-info}/entry_points.txt +0 -0
- {plover-5.1.0.dist-info → plover-5.2.1.dist-info}/licenses/LICENSE.txt +0 -0
- {plover-5.1.0.dist-info → plover-5.2.1.dist-info}/top_level.txt +0 -0
- {plover-5.1.0.dist-info → plover-5.2.1.dist-info}/zip-safe +0 -0
plover/__init__.py
CHANGED
|
@@ -11,9 +11,11 @@ else:
|
|
|
11
11
|
# exec from `setup.py`, package data
|
|
12
12
|
# may not be available, and we don't
|
|
13
13
|
# want to translate anyway.
|
|
14
|
-
_
|
|
14
|
+
def _(s):
|
|
15
|
+
return s
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
|
|
18
|
+
__version__ = "5.2.1"
|
|
17
19
|
__copyright__ = "(C) Open Steno Project"
|
|
18
20
|
__url__ = "http://www.openstenoproject.org/"
|
|
19
21
|
__download_url__ = "http://www.openstenoproject.org/plover"
|
|
@@ -24,7 +26,7 @@ Developers:
|
|
|
24
26
|
|
|
25
27
|
Joshua Lifton
|
|
26
28
|
Hesky Fisher
|
|
27
|
-
|
|
29
|
+
Thea Morin
|
|
28
30
|
Benoit Pierre
|
|
29
31
|
Sammi Ta
|
|
30
32
|
Martin Koerner
|
plover/config.py
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Copyright (c) 2010-2011 Joshua Harlan Lifton.
|
|
2
2
|
# See LICENSE.txt for details.
|
|
3
3
|
|
|
4
|
-
"""
|
|
4
|
+
"""This modules handles reading and writing Plover's configuration files, as well
|
|
5
|
+
as updating the configuration on-the-fly while Plover is running."""
|
|
5
6
|
|
|
6
7
|
from collections import ChainMap, namedtuple, OrderedDict
|
|
7
8
|
import configparser
|
|
8
9
|
import json
|
|
9
10
|
import re
|
|
11
|
+
from typing import Any, Dict
|
|
10
12
|
|
|
11
13
|
from plover.exception import InvalidConfigurationError
|
|
12
14
|
from plover.machine.keymap import Keymap
|
|
@@ -17,6 +19,7 @@ from plover import log
|
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
# General configuration sections, options and defaults.
|
|
22
|
+
APPEARANCE_CONFIG_SECTION = "Appearance"
|
|
20
23
|
MACHINE_CONFIG_SECTION = "Machine Configuration"
|
|
21
24
|
|
|
22
25
|
LEGACY_DICTIONARY_CONFIG_SECTION = "Dictionary Configuration"
|
|
@@ -36,14 +39,23 @@ SYSTEM_KEYMAP_OPTION = "keymap[%s]"
|
|
|
36
39
|
|
|
37
40
|
|
|
38
41
|
class DictionaryConfig(namedtuple("DictionaryConfig", "path enabled")):
|
|
42
|
+
"""Represents the configuration for one dictionary.
|
|
43
|
+
|
|
44
|
+
Attributes:
|
|
45
|
+
path (str): The fully qualified path to the dictionary file.
|
|
46
|
+
enabled (bool): Whether the dictionary is enabled.
|
|
47
|
+
"""
|
|
48
|
+
|
|
39
49
|
def __new__(cls, path, enabled=True):
|
|
40
50
|
return super().__new__(cls, expand_path(path), enabled)
|
|
41
51
|
|
|
42
52
|
@property
|
|
43
|
-
def short_path(self):
|
|
53
|
+
def short_path(self) -> str:
|
|
54
|
+
"""The shortened path to the dictionary file. This is automatically calculated from :attr:`path`."""
|
|
44
55
|
return shorten_path(self.path)
|
|
45
56
|
|
|
46
|
-
def to_dict(self):
|
|
57
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
58
|
+
"""Returns the ``dict`` representation of the dictionary configuration."""
|
|
47
59
|
# Note: do not use _asdict because of
|
|
48
60
|
# https://bugs.python.org/issue24931
|
|
49
61
|
return {
|
|
@@ -51,11 +63,13 @@ class DictionaryConfig(namedtuple("DictionaryConfig", "path enabled")):
|
|
|
51
63
|
"enabled": self.enabled,
|
|
52
64
|
}
|
|
53
65
|
|
|
54
|
-
def replace(self, **kwargs):
|
|
66
|
+
def replace(self, **kwargs) -> "DictionaryConfig":
|
|
67
|
+
"""Replaces the values of :attr:`path` and :attr:`enabled` with those in ``kwargs``."""
|
|
55
68
|
return self._replace(**kwargs)
|
|
56
69
|
|
|
57
70
|
@staticmethod
|
|
58
|
-
def from_dict(d):
|
|
71
|
+
def from_dict(d: Dict[str, Any]) -> "DictionaryConfig":
|
|
72
|
+
"""Returns a :class:`DictionaryConfig` constructed from its ``dict`` representation."""
|
|
59
73
|
return DictionaryConfig(**d)
|
|
60
74
|
|
|
61
75
|
def __repr__(self):
|
|
@@ -73,6 +87,11 @@ ConfigOption = namedtuple(
|
|
|
73
87
|
|
|
74
88
|
|
|
75
89
|
class InvalidConfigOption(ValueError):
|
|
90
|
+
"""An exception raised when a configuration option has been set to an invalid
|
|
91
|
+
value, such as one of the wrong type. ``fixed_value`` is the value that
|
|
92
|
+
Plover is falling back on if ``raw_value`` can't be parsed correctly.
|
|
93
|
+
"""
|
|
94
|
+
|
|
76
95
|
def __init__(self, raw_value, fixed_value, message=None):
|
|
77
96
|
super().__init__(raw_value)
|
|
78
97
|
self.raw_value = raw_value
|
|
@@ -368,14 +387,22 @@ def dictionaries_option():
|
|
|
368
387
|
|
|
369
388
|
|
|
370
389
|
class Config:
|
|
371
|
-
|
|
390
|
+
"""An object containing the entire Plover configuration. The config object
|
|
391
|
+
maintains a cache for any changes that are made while Plover is running.
|
|
392
|
+
"""
|
|
393
|
+
|
|
394
|
+
def __init__(self, path=None) -> None:
|
|
372
395
|
self._config = None
|
|
373
396
|
self._cache = {}
|
|
374
397
|
# A convenient place for other code to store a file name.
|
|
375
398
|
self.path = path
|
|
376
399
|
self.clear()
|
|
377
400
|
|
|
378
|
-
def load(self):
|
|
401
|
+
def load(self) -> None:
|
|
402
|
+
"""Reads and parses the configuration from the configuration file. Raises an
|
|
403
|
+
:exc:`InvalidConfigurationError<plover.exception.InvalidConfigurationError>`
|
|
404
|
+
if the configuration could not be parsed correctly.
|
|
405
|
+
"""
|
|
379
406
|
self.clear()
|
|
380
407
|
with open(self.path, encoding="utf-8") as fp:
|
|
381
408
|
try:
|
|
@@ -383,11 +410,13 @@ class Config:
|
|
|
383
410
|
except configparser.Error as e:
|
|
384
411
|
raise InvalidConfigurationError(str(e))
|
|
385
412
|
|
|
386
|
-
def clear(self):
|
|
413
|
+
def clear(self) -> None:
|
|
414
|
+
"""Clears the configuration and returns to the base state."""
|
|
387
415
|
self._config = configparser.RawConfigParser()
|
|
388
416
|
self._cache.clear()
|
|
389
417
|
|
|
390
|
-
def save(self):
|
|
418
|
+
def save(self) -> None:
|
|
419
|
+
"""Writes the current state of the configuration to the configuration file."""
|
|
391
420
|
with resource_update(self.path) as temp_path:
|
|
392
421
|
with open(temp_path, mode="w", encoding="utf-8") as fp:
|
|
393
422
|
self._config.write(fp)
|
|
@@ -427,7 +456,7 @@ class Config:
|
|
|
427
456
|
),
|
|
428
457
|
choice_option(
|
|
429
458
|
"keyboard_layout",
|
|
430
|
-
("qwerty", "qwertz", "colemak", "colemak-dh", "dvorak"),
|
|
459
|
+
("qwerty", "qwertz", "colemak", "colemak-dh", "dvorak", "wayland-auto"),
|
|
431
460
|
OUTPUT_CONFIG_SECTION,
|
|
432
461
|
),
|
|
433
462
|
# Logging.
|
|
@@ -439,6 +468,13 @@ class Config:
|
|
|
439
468
|
),
|
|
440
469
|
boolean_option("enable_stroke_logging", False, LOGGING_CONFIG_SECTION),
|
|
441
470
|
boolean_option("enable_translation_logging", False, LOGGING_CONFIG_SECTION),
|
|
471
|
+
# Appearance.
|
|
472
|
+
choice_option(
|
|
473
|
+
"appearance_mode",
|
|
474
|
+
("system", "light", "dark"),
|
|
475
|
+
APPEARANCE_CONFIG_SECTION,
|
|
476
|
+
"mode",
|
|
477
|
+
),
|
|
442
478
|
# GUI.
|
|
443
479
|
boolean_option("start_minimized", False, "Startup", "Start Minimized"),
|
|
444
480
|
boolean_option("show_stroke_display", False, "Stroke Display", "show"),
|
|
@@ -471,7 +507,10 @@ class Config:
|
|
|
471
507
|
key = opt.full_key(self, key)
|
|
472
508
|
return key, opt
|
|
473
509
|
|
|
474
|
-
def __getitem__(self, key):
|
|
510
|
+
def __getitem__(self, key: str) -> Any:
|
|
511
|
+
"""Returns the value of the specified ``key`` in the cache, or in the
|
|
512
|
+
full configuration if not available.
|
|
513
|
+
"""
|
|
475
514
|
key, opt = self._lookup(key)
|
|
476
515
|
if key in self._cache:
|
|
477
516
|
return self._cache[key]
|
|
@@ -485,16 +524,21 @@ class Config:
|
|
|
485
524
|
self._cache[key] = value
|
|
486
525
|
return value
|
|
487
526
|
|
|
488
|
-
def __setitem__(self, key, value):
|
|
527
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
528
|
+
"""Sets the property ``key`` in the configuration to the specified value."""
|
|
489
529
|
key, opt = self._lookup(key)
|
|
490
530
|
value = opt.validate(self._config, key, value)
|
|
491
531
|
opt.setter(self, key, value)
|
|
492
532
|
self._cache[key] = value
|
|
493
533
|
|
|
494
|
-
def as_dict(self):
|
|
534
|
+
def as_dict(self) -> Dict[str, Any]:
|
|
535
|
+
"""Returns the ``dict`` representation of the current state of the
|
|
536
|
+
configuration.
|
|
537
|
+
"""
|
|
495
538
|
return {opt.name: self[opt.name] for opt in self._OPTIONS.values()}
|
|
496
539
|
|
|
497
|
-
def update(self, **kwargs):
|
|
540
|
+
def update(self, **kwargs) -> None:
|
|
541
|
+
"""Update the cache to reflect the contents of the full configuration."""
|
|
498
542
|
new_settings = []
|
|
499
543
|
new_config = ChainMap({}, self)
|
|
500
544
|
for opt in self._OPTIONS.values():
|
plover/engine.py
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
"""The steno engine is the core of Plover; it handles communication between the
|
|
2
|
+
machine and the translation and formatting subsystems, and manages configuration
|
|
3
|
+
and dictionaries.
|
|
4
|
+
"""
|
|
5
|
+
|
|
1
6
|
from collections import namedtuple, OrderedDict
|
|
2
7
|
from functools import wraps
|
|
3
8
|
from queue import Queue
|
|
@@ -5,6 +10,7 @@ import functools
|
|
|
5
10
|
import os
|
|
6
11
|
import shutil
|
|
7
12
|
import threading
|
|
13
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
8
14
|
|
|
9
15
|
from plover import log, system
|
|
10
16
|
from plover.dictionary.loading_manager import DictionaryLoadingManager
|
|
@@ -22,14 +28,42 @@ StartingStrokeState = namedtuple(
|
|
|
22
28
|
"StartingStrokeState", "attach capitalize space_char", defaults=(False, False, " ")
|
|
23
29
|
)
|
|
24
30
|
|
|
31
|
+
StartingStrokeState.__doc__ = """An object representing the starting state of the formatter before any
|
|
32
|
+
strokes are input.
|
|
33
|
+
|
|
34
|
+
Attributes:
|
|
35
|
+
attach (bool): Whether to delete the space before the translation when the
|
|
36
|
+
initial stroke is translated.
|
|
37
|
+
capitalize (bool): Whether to capitalize the translation when the initial
|
|
38
|
+
stroke is translated.
|
|
39
|
+
"""
|
|
25
40
|
|
|
26
41
|
MachineParams = namedtuple("MachineParams", "type options keymap")
|
|
27
42
|
|
|
43
|
+
MachineParams.__doc__ = """An object representing the current state of the machine.
|
|
44
|
+
|
|
45
|
+
Attributes:
|
|
46
|
+
type (str): The name of the machine. This is the same as the name of the plugin
|
|
47
|
+
that provides the machine's functionality. ``Keyboard`` by default.
|
|
48
|
+
options (Dict[str, Any]): A dictionary of machine specific options. See
|
|
49
|
+
:mod:`plover.config` for more information.
|
|
50
|
+
keymap (plover.machine.keymap.Keymap): A
|
|
51
|
+
:class:`Keymap<plover.machine.keymap.Keymap>` mapping the current
|
|
52
|
+
system to this machine.
|
|
53
|
+
"""
|
|
54
|
+
|
|
28
55
|
|
|
29
56
|
class ErroredDictionary(StenoDictionary):
|
|
30
|
-
"""
|
|
57
|
+
"""A placeholder class for a dictionary that failed to load.
|
|
58
|
+
|
|
59
|
+
This is a subclass of :class:`StenoDictionary<plover.steno_dictionary.StenoDictionary>`.
|
|
31
60
|
|
|
32
|
-
|
|
61
|
+
Attributes:
|
|
62
|
+
path (str): The path to the dictionary file.
|
|
63
|
+
exception (Any): The exception that caused the dictionary loading to fail.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(self, path: str, exception: Any):
|
|
33
67
|
super().__init__()
|
|
34
68
|
self.enabled = False
|
|
35
69
|
self.readonly = True
|
|
@@ -76,7 +110,36 @@ def with_lock(func):
|
|
|
76
110
|
|
|
77
111
|
|
|
78
112
|
class StenoEngine:
|
|
79
|
-
|
|
113
|
+
"""
|
|
114
|
+
Attributes:
|
|
115
|
+
config (Dict[str, Any]): A dictionary containing configuration options.
|
|
116
|
+
controller (plover.oslayer.controller.Controller): An instance of
|
|
117
|
+
:class:`Controller<plover.oslayer.controller.Controller>` for managing
|
|
118
|
+
commands sent to this Plover instance. This is provided during startup.
|
|
119
|
+
keyboard_emulation (plover.oslayer.keyboardcontrol.KeyboardEmulation): An
|
|
120
|
+
instance of
|
|
121
|
+
:class:`KeyboardEmulation<plover.oslayer.keyboardcontrol.KeyboardEmulation>`
|
|
122
|
+
provided during startup.
|
|
123
|
+
HOOKS (List[str]): A list of all the possible engine hooks. See
|
|
124
|
+
:ref:`engine-hooks` below for a list of valid hooks.
|
|
125
|
+
machine_state (str): The connection state of the current machine. One of
|
|
126
|
+
``stopped``, ``initializing``, ``connected`` or ``disconnected``.
|
|
127
|
+
output (bool): ``True`` if steno output is enabled, ``False`` otherwise.
|
|
128
|
+
_config (plover.config.Config): A :class:`Config<plover.config.Config>` object
|
|
129
|
+
containing the engine's configuration.
|
|
130
|
+
translator_state (plover.translation._State): A
|
|
131
|
+
:class:`_State<plover.translation._State>` object containing the current
|
|
132
|
+
state of the translator.
|
|
133
|
+
starting_stroke_state (StartingStrokeState): A :class:`StartingStrokeState`
|
|
134
|
+
representing the initial state of the formatter.
|
|
135
|
+
dictionaries (plover.steno_dictionary.StenoDictionaryCollection): A
|
|
136
|
+
:class:`StenoDictionaryCollection<plover.steno_dictionary.StenoDictionaryCollection>`
|
|
137
|
+
of all the dictionaries Plover has loaded for the current system. This
|
|
138
|
+
includes disabled dictionaries and dictionaries that failed to load.
|
|
139
|
+
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
HOOKS: List[str] = """
|
|
80
143
|
stroked
|
|
81
144
|
translated
|
|
82
145
|
machine_state_changed
|
|
@@ -95,7 +158,7 @@ class StenoEngine:
|
|
|
95
158
|
quit
|
|
96
159
|
""".split()
|
|
97
160
|
|
|
98
|
-
def __init__(self, config, controller, keyboard_emulation):
|
|
161
|
+
def __init__(self, config: Any, controller: Any, keyboard_emulation: Any):
|
|
99
162
|
self._config = config
|
|
100
163
|
self._controller = controller
|
|
101
164
|
self._is_running = False
|
|
@@ -134,7 +197,14 @@ class StenoEngine:
|
|
|
134
197
|
def __exit__(self, exc_type, exc_value, traceback):
|
|
135
198
|
self._lock.__exit__(exc_type, exc_value, traceback)
|
|
136
199
|
|
|
137
|
-
def _in_engine_thread(self):
|
|
200
|
+
def _in_engine_thread(self) -> bool:
|
|
201
|
+
"""Returns whether we are currently in the same thread that the engine
|
|
202
|
+
is running on.
|
|
203
|
+
|
|
204
|
+
This is useful because event listeners for machines and others are run
|
|
205
|
+
on separate threads, and we want to be able to run engine events on the
|
|
206
|
+
same thread as the main engine.
|
|
207
|
+
"""
|
|
138
208
|
raise NotImplementedError()
|
|
139
209
|
|
|
140
210
|
def _same_thread_hook(self, func, *args, **kwargs):
|
|
@@ -143,7 +213,8 @@ class StenoEngine:
|
|
|
143
213
|
else:
|
|
144
214
|
self._queue.put((func, args, kwargs))
|
|
145
215
|
|
|
146
|
-
def run(self):
|
|
216
|
+
def run(self) -> None:
|
|
217
|
+
"""Starts the steno engine, translating any strokes that are input."""
|
|
147
218
|
while True:
|
|
148
219
|
func, args, kwargs = self._queue.get()
|
|
149
220
|
try:
|
|
@@ -423,26 +494,48 @@ class StenoEngine:
|
|
|
423
494
|
self._keyboard_emulation.send_key_combination(c)
|
|
424
495
|
self._trigger_hook("send_key_combination", c)
|
|
425
496
|
|
|
426
|
-
def _send_engine_command(self, command):
|
|
497
|
+
def _send_engine_command(self, command: str) -> None:
|
|
498
|
+
"""Runs the specified Plover command, which can be either a built-in
|
|
499
|
+
command like ``set_config`` or one from an external plugin.
|
|
500
|
+
|
|
501
|
+
``command`` is a string containing the command and its argument (if any),
|
|
502
|
+
separated by a colon. For example, ``lookup`` sends the ``lookup`` command
|
|
503
|
+
(the same as stroking ``{PLOVER:LOOKUP}``), and ``run_shell:foo`` sends the
|
|
504
|
+
``run_shell`` command with the argument ``foo``.
|
|
505
|
+
"""
|
|
427
506
|
suppress = not self._is_running
|
|
428
507
|
suppress &= self._consume_engine_command(command)
|
|
429
508
|
if suppress:
|
|
430
509
|
self._machine.suppress_last_stroke(self._keyboard_emulation.send_backspaces)
|
|
431
510
|
|
|
432
511
|
def toggle_output(self):
|
|
512
|
+
"""Toggles steno mode.
|
|
513
|
+
|
|
514
|
+
See :attr:`output` to get the current state, or
|
|
515
|
+
:meth:`set_output` to set the state to a specific value.
|
|
516
|
+
"""
|
|
433
517
|
self._same_thread_hook(self._toggle_output)
|
|
434
518
|
|
|
435
|
-
def set_output(self, enabled):
|
|
519
|
+
def set_output(self, enabled: bool) -> None:
|
|
520
|
+
"""Enables or disables steno mode.
|
|
521
|
+
|
|
522
|
+
Set ``enabled`` to ``True`` to enable steno mode, or ``False`` to disable it.
|
|
523
|
+
"""
|
|
436
524
|
self._same_thread_hook(self._set_output, enabled)
|
|
437
525
|
|
|
438
526
|
@property
|
|
439
527
|
@with_lock
|
|
440
|
-
def machine_state(self):
|
|
528
|
+
def machine_state(self) -> Optional[str]:
|
|
529
|
+
"""The connection state of the current machine.
|
|
530
|
+
|
|
531
|
+
One of ``stopped``, ``initializing``, ``connected`` or ``disconnected``.
|
|
532
|
+
"""
|
|
441
533
|
return self._machine_state
|
|
442
534
|
|
|
443
535
|
@property
|
|
444
536
|
@with_lock
|
|
445
|
-
def output(self):
|
|
537
|
+
def output(self) -> bool:
|
|
538
|
+
"""``True`` if steno output is enabled, ``False`` otherwise."""
|
|
446
539
|
return self._is_running
|
|
447
540
|
|
|
448
541
|
@output.setter
|
|
@@ -451,7 +544,8 @@ class StenoEngine:
|
|
|
451
544
|
|
|
452
545
|
@property
|
|
453
546
|
@with_lock
|
|
454
|
-
def config(self):
|
|
547
|
+
def config(self) -> Dict[str, Any]:
|
|
548
|
+
"""A dictionary containing configuration options."""
|
|
455
549
|
return self._config.as_dict()
|
|
456
550
|
|
|
457
551
|
@config.setter
|
|
@@ -459,16 +553,24 @@ class StenoEngine:
|
|
|
459
553
|
self._same_thread_hook(self._update, config_update=update)
|
|
460
554
|
|
|
461
555
|
@with_lock
|
|
462
|
-
def __getitem__(self, setting):
|
|
556
|
+
def __getitem__(self, setting: str) -> Any:
|
|
557
|
+
"""Returns the value of the configuration property ``setting``."""
|
|
463
558
|
return self._config[setting]
|
|
464
559
|
|
|
465
|
-
def __setitem__(self, setting, value):
|
|
560
|
+
def __setitem__(self, setting: str, value: Any) -> None:
|
|
561
|
+
"""Sets the configuration property ``setting`` to ``value``."""
|
|
466
562
|
self.config = {setting: value}
|
|
467
563
|
|
|
468
|
-
def reset_machine(self):
|
|
564
|
+
def reset_machine(self) -> None:
|
|
565
|
+
"""Resets the machine state and Plover's connection with the machine, if
|
|
566
|
+
necessary, and loads all the configuration and dictionaries.
|
|
567
|
+
"""
|
|
469
568
|
self._same_thread_hook(self._update, reset_machine=True)
|
|
470
569
|
|
|
471
|
-
def load_config(self):
|
|
570
|
+
def load_config(self) -> bool:
|
|
571
|
+
"""Loads the Plover configuration file and returns ``True`` if it was
|
|
572
|
+
loaded successfully, ``False`` if not.
|
|
573
|
+
"""
|
|
472
574
|
try:
|
|
473
575
|
self._config.load()
|
|
474
576
|
except Exception:
|
|
@@ -479,62 +581,92 @@ class StenoEngine:
|
|
|
479
581
|
return False
|
|
480
582
|
return True
|
|
481
583
|
|
|
482
|
-
def start(self):
|
|
584
|
+
def start(self) -> None:
|
|
585
|
+
"""Starts the steno engine."""
|
|
483
586
|
self._same_thread_hook(self._start)
|
|
484
587
|
|
|
485
|
-
def quit(self, code=0):
|
|
588
|
+
def quit(self, code: int = 0) -> None:
|
|
589
|
+
"""Quits the steno engine, ensuring that all pending tasks are completed
|
|
590
|
+
before exiting.
|
|
591
|
+
"""
|
|
486
592
|
# We need to go through the queue, even when already called
|
|
487
593
|
# from the engine thread so _quit's return code does break
|
|
488
594
|
# the thread out of its main loop.
|
|
489
595
|
self._queue.put((self._quit, (code,), {}))
|
|
490
596
|
|
|
491
|
-
def restart(self):
|
|
597
|
+
def restart(self) -> None:
|
|
598
|
+
"""Quits and restarts the steno engine, ensuring that all pending tasks
|
|
599
|
+
are completed.
|
|
600
|
+
"""
|
|
492
601
|
self.quit(-1)
|
|
493
602
|
|
|
494
|
-
def join(self):
|
|
603
|
+
def join(self) -> int:
|
|
604
|
+
"""Joins any sub-threads if necessary and returns an exit code."""
|
|
495
605
|
return self.code
|
|
496
606
|
|
|
497
607
|
@with_lock
|
|
498
|
-
def lookup(self, translation):
|
|
608
|
+
def lookup(self, translation: Tuple[str, ...]) -> str:
|
|
609
|
+
"""Returns the first translation for the steno outline ``translation`` using
|
|
610
|
+
all the filters.
|
|
611
|
+
"""
|
|
499
612
|
return self._dictionaries.lookup(translation)
|
|
500
613
|
|
|
501
614
|
@with_lock
|
|
502
|
-
def raw_lookup(self, translation):
|
|
615
|
+
def raw_lookup(self, translation: Tuple[str, ...]) -> str:
|
|
616
|
+
"""Like :meth:`lookup`, but without any of the filters."""
|
|
503
617
|
return self._dictionaries.raw_lookup(translation)
|
|
504
618
|
|
|
505
619
|
@with_lock
|
|
506
|
-
def lookup_from_all(self, translation):
|
|
620
|
+
def lookup_from_all(self, translation: Tuple[str, ...]):
|
|
621
|
+
"""Returns all translations for the steno outline ``translation`` using
|
|
622
|
+
all the filters.
|
|
623
|
+
"""
|
|
507
624
|
return self._dictionaries.lookup_from_all(translation)
|
|
508
625
|
|
|
509
626
|
@with_lock
|
|
510
|
-
def raw_lookup_from_all(self, translation):
|
|
627
|
+
def raw_lookup_from_all(self, translation: Tuple[str, ...]):
|
|
628
|
+
"""Like :meth:`lookup_from_all`, but without any of the filters."""
|
|
511
629
|
return self._dictionaries.raw_lookup_from_all(translation)
|
|
512
630
|
|
|
513
631
|
@with_lock
|
|
514
|
-
def reverse_lookup(self, translation):
|
|
515
|
-
|
|
516
|
-
return
|
|
632
|
+
def reverse_lookup(self, translation: str):
|
|
633
|
+
"""Returns the list of steno outlines that translate to ``translation``."""
|
|
634
|
+
return self._dictionaries.reverse_lookup(translation)
|
|
517
635
|
|
|
518
636
|
@with_lock
|
|
519
|
-
def casereverse_lookup(self, translation):
|
|
520
|
-
|
|
521
|
-
return
|
|
637
|
+
def casereverse_lookup(self, translation: str):
|
|
638
|
+
"""Like :meth:`reverse_lookup`, but performs a case-insensitive lookup."""
|
|
639
|
+
return self._dictionaries.casereverse_lookup(translation)
|
|
522
640
|
|
|
523
641
|
@with_lock
|
|
524
|
-
def add_dictionary_filter(
|
|
642
|
+
def add_dictionary_filter(
|
|
643
|
+
self, dictionary_filter: Callable[[Tuple[str, ...], str], bool]
|
|
644
|
+
) -> None:
|
|
645
|
+
"""Adds ``dictionary_filter`` to the list of dictionary filters.
|
|
646
|
+
|
|
647
|
+
See :attr:`StenoDictionaryCollection.filters<plover.steno_dictionary.StenoDictionaryCollection.filters>`
|
|
648
|
+
for more information.
|
|
649
|
+
"""
|
|
525
650
|
self._dictionaries.add_filter(dictionary_filter)
|
|
526
651
|
|
|
527
652
|
@with_lock
|
|
528
|
-
def remove_dictionary_filter(
|
|
653
|
+
def remove_dictionary_filter(
|
|
654
|
+
self, dictionary_filter: Callable[[Tuple[str, ...], str], bool]
|
|
655
|
+
) -> None:
|
|
656
|
+
"""Removes ``dictionary_filter`` from the list of dictionary filters."""
|
|
529
657
|
self._dictionaries.remove_filter(dictionary_filter)
|
|
530
658
|
|
|
531
659
|
@with_lock
|
|
532
|
-
def get_suggestions(self, translation):
|
|
660
|
+
def get_suggestions(self, translation: str):
|
|
661
|
+
"""Returns a list of suggestions for the specified ``translation``."""
|
|
533
662
|
return Suggestions(self._dictionaries).find(translation)
|
|
534
663
|
|
|
535
664
|
@property
|
|
536
665
|
@with_lock
|
|
537
666
|
def translator_state(self):
|
|
667
|
+
"""A :class:`_State<plover.translation._State>` object containing the
|
|
668
|
+
current state of the translator.
|
|
669
|
+
"""
|
|
538
670
|
return self._translator.get_state()
|
|
539
671
|
|
|
540
672
|
@translator_state.setter
|
|
@@ -543,7 +675,13 @@ class StenoEngine:
|
|
|
543
675
|
self._translator.set_state(state)
|
|
544
676
|
|
|
545
677
|
@with_lock
|
|
546
|
-
def clear_translator_state(self, undo=False):
|
|
678
|
+
def clear_translator_state(self, undo: bool = False) -> None:
|
|
679
|
+
"""Resets the translator to an empty state, as if Plover had just started up,
|
|
680
|
+
clearing the entire translation stack.
|
|
681
|
+
|
|
682
|
+
If ``undo`` is ``True``, this also reverts all previous translations on the
|
|
683
|
+
stack (which could include a lot of backspaces).
|
|
684
|
+
"""
|
|
547
685
|
if undo:
|
|
548
686
|
state = self._translator.get_state()
|
|
549
687
|
if state.translations:
|
|
@@ -552,7 +690,10 @@ class StenoEngine:
|
|
|
552
690
|
|
|
553
691
|
@property
|
|
554
692
|
@with_lock
|
|
555
|
-
def starting_stroke_state(self):
|
|
693
|
+
def starting_stroke_state(self) -> StartingStrokeState:
|
|
694
|
+
"""A :class:`StartingStrokeState` representing the initial state of the
|
|
695
|
+
formatter.
|
|
696
|
+
"""
|
|
556
697
|
return StartingStrokeState(
|
|
557
698
|
self._formatter.start_attached,
|
|
558
699
|
self._formatter.start_capitalized,
|
|
@@ -567,7 +708,16 @@ class StenoEngine:
|
|
|
567
708
|
self._formatter.space_char = state.space_char
|
|
568
709
|
|
|
569
710
|
@with_lock
|
|
570
|
-
def add_translation(
|
|
711
|
+
def add_translation(
|
|
712
|
+
self,
|
|
713
|
+
strokes: Tuple[str, ...],
|
|
714
|
+
translation: str,
|
|
715
|
+
dictionary_path: Optional[str] = None,
|
|
716
|
+
) -> None:
|
|
717
|
+
"""Adds a steno entry mapping the steno outline ``strokes`` to
|
|
718
|
+
``translation`` in the dictionary at ``dictionary_path``, if specified,
|
|
719
|
+
or the first writable dictionary.
|
|
720
|
+
"""
|
|
571
721
|
if dictionary_path is None:
|
|
572
722
|
dictionary_path = self._dictionaries.first_writable().path
|
|
573
723
|
self._dictionaries.set(strokes, translation, path=dictionary_path)
|
|
@@ -576,6 +726,12 @@ class StenoEngine:
|
|
|
576
726
|
@property
|
|
577
727
|
@with_lock
|
|
578
728
|
def dictionaries(self):
|
|
729
|
+
"""A
|
|
730
|
+
:class:`StenoDictionaryCollection<plover.steno_dictionary.StenoDictionaryCollection>`
|
|
731
|
+
of all the dictionaries Plover has loaded for the current system.
|
|
732
|
+
|
|
733
|
+
This includes disabled dictionaries and dictionaries that failed to load.
|
|
734
|
+
"""
|
|
579
735
|
return self._dictionaries
|
|
580
736
|
|
|
581
737
|
# Hooks.
|
|
@@ -588,9 +744,21 @@ class StenoEngine:
|
|
|
588
744
|
log.error("hook %r callback %r failed", hook, callback, exc_info=True)
|
|
589
745
|
|
|
590
746
|
@with_lock
|
|
591
|
-
def hook_connect(self, hook, callback):
|
|
747
|
+
def hook_connect(self, hook: str, callback: Callable[..., Any]) -> None:
|
|
748
|
+
"""Adds ``callback`` to the list of handlers that are called when the ``hook``
|
|
749
|
+
hook gets triggered. Raises a ``KeyError`` if ``hook`` is not in
|
|
750
|
+
:data:`HOOKS`.
|
|
751
|
+
|
|
752
|
+
The expected signature of the callback is depends on the hook; see
|
|
753
|
+
:ref:`engine-hooks` for more information.
|
|
754
|
+
"""
|
|
592
755
|
self._hooks[hook].append(callback)
|
|
593
756
|
|
|
594
757
|
@with_lock
|
|
595
|
-
def hook_disconnect(self, hook, callback):
|
|
758
|
+
def hook_disconnect(self, hook: str, callback: Callable[..., Any]) -> None:
|
|
759
|
+
"""Removes ``callback`` from the list of handlers that are called when
|
|
760
|
+
the ``hook`` hook is triggered. Raises a ``KeyError`` if ``hook`` is not in
|
|
761
|
+
:data:`HOOKS`, and a ``ValueError`` if ``callback`` was never added as
|
|
762
|
+
a handler in the first place.
|
|
763
|
+
"""
|
|
596
764
|
self._hooks[hook].remove(callback)
|
plover/formatting.py
CHANGED
|
@@ -370,7 +370,10 @@ class Formatter:
|
|
|
370
370
|
|
|
371
371
|
def set_output(self, output):
|
|
372
372
|
"""Set the output class."""
|
|
373
|
-
|
|
373
|
+
|
|
374
|
+
def noop(x):
|
|
375
|
+
return None
|
|
376
|
+
|
|
374
377
|
output_type = self.output_type
|
|
375
378
|
fields = output_type._fields
|
|
376
379
|
self._output = output_type(*[getattr(output, f, noop) for f in fields])
|
|
@@ -921,7 +924,7 @@ def apply_case(text, case):
|
|
|
921
924
|
|
|
922
925
|
def apply_mode(text, case, space_char, begin, last_action):
|
|
923
926
|
# Should title case be applied to the beginning of the next string?
|
|
924
|
-
lower_title_case = begin and
|
|
927
|
+
lower_title_case = begin and last_action.case not in (
|
|
925
928
|
Case.CAP_FIRST_WORD,
|
|
926
929
|
Case.UPPER_FIRST_WORD,
|
|
927
930
|
)
|
plover/gui_qt/about_dialog_ui.py
CHANGED
|
@@ -4,7 +4,7 @@ _ = __import__(__package__.split(".", 1)[0])._
|
|
|
4
4
|
################################################################################
|
|
5
5
|
## Form generated from reading UI file 'about_dialog.ui'
|
|
6
6
|
##
|
|
7
|
-
## Created by: Qt User Interface Compiler version 6.10.
|
|
7
|
+
## Created by: Qt User Interface Compiler version 6.10.2
|
|
8
8
|
##
|
|
9
9
|
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
|
10
10
|
################################################################################
|
|
@@ -4,7 +4,7 @@ _ = __import__(__package__.split(".", 1)[0])._
|
|
|
4
4
|
################################################################################
|
|
5
5
|
## Form generated from reading UI file 'add_translation_dialog.ui'
|
|
6
6
|
##
|
|
7
|
-
## Created by: Qt User Interface Compiler version 6.10.
|
|
7
|
+
## Created by: Qt User Interface Compiler version 6.10.2
|
|
8
8
|
##
|
|
9
9
|
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
|
10
10
|
################################################################################
|
|
@@ -4,7 +4,7 @@ _ = __import__(__package__.split(".", 1)[0])._
|
|
|
4
4
|
################################################################################
|
|
5
5
|
## Form generated from reading UI file 'add_translation_widget.ui'
|
|
6
6
|
##
|
|
7
|
-
## Created by: Qt User Interface Compiler version 6.10.
|
|
7
|
+
## Created by: Qt User Interface Compiler version 6.10.2
|
|
8
8
|
##
|
|
9
9
|
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
|
10
10
|
################################################################################
|