Skip to content

Commit

Permalink
Add support for commands in platform-specific translations
Browse files Browse the repository at this point in the history
  • Loading branch information
paulfioravanti committed Aug 9, 2024
1 parent bfcff6f commit aea17d7
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 34 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,17 @@ Specify only a default fallback for other platforms (pointless, but supported):
"KP*EU": "{:PLATFORM:OTHER:#CONTROL(C)}"
```

Note that the translation values are not limited to keyboard shortcuts, but can
contain any text to be output:
Note that the translation values are not limited to keyboard shortcuts, and can
contain [commands][] to run:

```json
"TO*LG": "{:PLATFORM:WINDOWS:PLOVER:TOGGLE_DICT:+win_dict.py:MAC::COMMAND:TOGGLE_DICT:+mac_dict.py}"
```

> Both command prefixes of `{PLOVER:<command>}` and `{:COMMAND:<command>}` are
> supported.
Naturally, plain text output is also supported:

```json
"H-L": "{:PLATFORM:WINDOWS:Hello:MAC:Hi:LINUX:Good day:OTHER:Whassup}"
Expand Down Expand Up @@ -190,6 +199,7 @@ plover --script plover_plugins uninstall plover-platform-specific-translation

[Build Status image]: https://github.com/paulfioravanti/plover-platform-specific-translation/actions/workflows/ci.yml/badge.svg
[Build Status url]: https://github.com/paulfioravanti/plover-platform-specific-translation/actions/workflows/ci.yml
[commands]: https://plover.readthedocs.io/en/latest/plugin-dev/commands.html
[Coverage.py]: https://github.com/nedbat/coveragepy
[extension]: https://plover.readthedocs.io/en/latest/plugin-dev/extensions.html
[git]: https://git-scm.com/
Expand Down
4 changes: 3 additions & 1 deletion plover_platform_specific_translation/extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@ def _platform_specific_translation(

action = ctx.new_action()

if platform_translation_type == "combo":
if platform_translation_type == translation.COMBO:
action.combo = platform_translation
elif platform_translation_type == translation.COMMAND:
action.command = platform_translation
else:
action.text = platform_translation

Expand Down
4 changes: 3 additions & 1 deletion plover_platform_specific_translation/translation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
A package dealing with:
- resolving the correct translation from a platform-specific outline value
"""
from .resolver import resolve
from .resolver import COMBO, COMMAND, resolve

__all__ = [
"COMBO",
"COMMAND",
"resolve"
]
25 changes: 20 additions & 5 deletions plover_platform_specific_translation/translation/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,20 @@
from typing import Pattern, Tuple


_ARGUMENT_DIVIDER = ":"
COMBO = "combo"
COMMAND = "command"
_TEXT = "text"

_ARGUMENT_DIVIDER: Pattern[str] = re.compile(
"(?:(?<=MAC)|(?<=WINDOWS)|(?<=LINUX|OTHER)):"
"|:(?:(?=MAC)|(?=WINDOWS)|(?=LINUX|OTHER))",
re.IGNORECASE
)
_COMBO_TYPE: Pattern[str] = re.compile(r"#(.*)")
_COMMAND_TYPE: Pattern[str] = re.compile(
r"(?:PLOVER|:COMMAND):(.*)",
re.IGNORECASE
)

def resolve(platform: str, outline_translation: str) -> Tuple[str, str]:
"""
Expand All @@ -25,13 +37,16 @@ def resolve(platform: str, outline_translation: str) -> Tuple[str, str]:
f"No translation provided for platform: {platform}"
) from exc

if combo_translation := _COMBO_TYPE.match(translation):
return ("combo", combo_translation.group(1))
if combo_translation := re.match(_COMBO_TYPE, translation):
return (COMBO, combo_translation.group(1))

if command_translation := re.match(_COMMAND_TYPE, translation):
return (COMMAND, command_translation.group(1))

return ("text", translation)
return (_TEXT, translation)

def _parse_outline_translation(outline_translation: str) -> dict[str, str]:
it = iter(outline_translation.split(_ARGUMENT_DIVIDER))
it = iter(re.split(_ARGUMENT_DIVIDER, outline_translation))
return {
platform.upper(): translation
for platform, translation
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ long_description = file: README.md
long_description_content_type = text/markdown
name = plover_platform_specific_translation
url = https://github.com/paulfioravanti/plover-platform-specific-translation
version = 0.1.1
version = 0.2.0

[options]
install_requires =
Expand Down
4 changes: 4 additions & 0 deletions test/config/files/valid_platform_translations.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
"platform_specific_translations": {
"WINDOWS::COMMAND:TOGGLE_DICT:-some_dict.py:MAC::COMMAND:APPLESCRIPT:/path/to/script.scpt:LINUX:PLOVER:TOGGLE_DICT:+some_dict.py:OTHER::COMMAND:TOGGLE_DICT:~some_dict.py": [
"command",
"APPLESCRIPT:/path/to/script.scpt"
],
"WINDOWS:#CONTROL(C):MAC:#SUPER(C):LINUX:#CONTROL(C):OTHER:#CONTROL(C)": [
"combo",
"SUPER(C)"
Expand Down
123 changes: 99 additions & 24 deletions test/translation/test_translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# Fixtures

@pytest.fixture
def all_platforms():
def all_platforms_text():
return (
"WINDOWS:Windows value"
":MAC:Mac value"
Expand All @@ -15,60 +15,135 @@ def all_platforms():
)

@pytest.fixture
def some_platforms_with_fallback():
def all_platforms_combo():
return (
"WINDOWS:#CONTROL(C)"
":MAC:#SUPER(C)"
":LINUX:#SHIFT(CONTROL(C))"
":OTHER:#ALT(CONTROL(C))"
)

@pytest.fixture
def all_platforms_command():
return (
"WINDOWS::COMMAND:SOLO_DICT:-commands.md"
":MAC::COMMAND:APPLESCRIPT:/path/to/script.scpt"
":LINUX:PLOVER:TOGGLE_DICT:+some_dict.py"
":OTHER::COMMAND:TOGGLE_DICT:~some_dict.py"
)

@pytest.fixture
def some_platforms_with_fallback_text():
return "MAC:Mac value:OTHER:Default value"

@pytest.fixture
def some_platforms_without_fallback():
def some_platforms_without_fallback_text():
return "WINDOWS:Windows value:MAC:Mac value"

@pytest.fixture
def fallback_platform_only():
def fallback_platform_only_text():
return "OTHER:Default value"

# Tests

def test_platform_given_in_non_uppercase():
outline_translation = "Windows:#CONTROL(C)"
platform_translation = translation.resolve("WINDOWS", outline_translation)
assert platform_translation == ("combo", "CONTROL(C)")

def test_all_platforms_translation_with_windows(all_platforms):
def test_all_platforms_text_translation_with_windows(all_platforms_text):
assert (
translation.resolve("WINDOWS", all_platforms)
translation.resolve("WINDOWS", all_platforms_text)
== ("text", "Windows value")
)

def test_all_platforms_translation_with_mac(all_platforms):
assert translation.resolve("MAC", all_platforms) == ("text", "Mac value")
def test_all_platforms_text_translation_with_mac(all_platforms_text):
assert (
translation.resolve("MAC", all_platforms_text)
== ("text", "Mac value")
)

def test_all_platforms_text_translation_with_linux(all_platforms_text):
assert (
translation.resolve("LINUX", all_platforms_text)
== ("text", "Linux value")
)

def test_all_platforms_text_translation_with_default(all_platforms_text):
assert (
translation.resolve("OTHER", all_platforms_text)
== ("text", "Default value")
)

def test_all_platforms_translation_with_linux(all_platforms):
def test_all_platforms_combo_translation_with_windows(all_platforms_combo):
assert (
translation.resolve("LINUX", all_platforms) == ("text", "Linux value")
translation.resolve("WINDOWS", all_platforms_combo)
== ("combo", "CONTROL(C)")
)

def test_all_platforms_translation_with_default(all_platforms):
def test_all_platforms_combo_translation_with_mac(all_platforms_combo):
assert (
translation.resolve("OTHER", all_platforms) == ("text", "Default value")
translation.resolve("MAC", all_platforms_combo)
== ("combo", "SUPER(C)")
)

def test_some_platforms_translation_with_fallback(some_platforms_with_fallback):
def test_all_platforms_combo_translation_with_linux(all_platforms_combo):
assert (
translation.resolve("WINDOWS", some_platforms_with_fallback)
translation.resolve("LINUX", all_platforms_combo)
== ("combo", "SHIFT(CONTROL(C))")
)

def test_all_platforms_combo_translation_with_default(all_platforms_combo):
assert (
translation.resolve("OTHER", all_platforms_combo)
== ("combo", "ALT(CONTROL(C))")
)

def test_all_platforms_command_translation_with_windows(all_platforms_command):
assert (
translation.resolve("WINDOWS", all_platforms_command)
== ("command", "SOLO_DICT:-commands.md")
)

def test_all_platforms_command_translation_with_mac(all_platforms_command):
assert (
translation.resolve("MAC", all_platforms_command)
== ("command", "APPLESCRIPT:/path/to/script.scpt")
)

def test_all_platforms_command_translation_with_linux(all_platforms_command):
assert (
translation.resolve("LINUX", all_platforms_command)
== ("command", "TOGGLE_DICT:+some_dict.py")
)

def test_all_platforms_command_translation_with_default(all_platforms_command):
assert (
translation.resolve("OTHER", all_platforms_command)
== ("command", "TOGGLE_DICT:~some_dict.py")
)

def test_some_platforms_text_translation_with_fallback(
some_platforms_with_fallback_text
):
assert (
translation.resolve("WINDOWS", some_platforms_with_fallback_text)
== ("text", "Default value")
)

def test_some_platforms_translation_without_fallback(
some_platforms_without_fallback
def test_some_platforms_text_translation_without_fallback(
some_platforms_without_fallback_text
):
with pytest.raises(
ValueError,
match="No translation provided for platform: LINUX"
):
translation.resolve("LINUX", some_platforms_without_fallback)
translation.resolve("LINUX", some_platforms_without_fallback_text)

def test_only_fallback_platform_translation_given(fallback_platform_only):
def test_only_fallback_platform_text_translation_given(
fallback_platform_only_text
):
assert (
translation.resolve("WINDOWS", fallback_platform_only)
translation.resolve("WINDOWS", fallback_platform_only_text)
== ("text", "Default value")
)

def test_platform_text_translation_given_in_non_uppercase():
outline_translation = "Windows:Windows value"
platform_translation = translation.resolve("WINDOWS", outline_translation)
assert platform_translation == ("text", "Windows value")

0 comments on commit aea17d7

Please sign in to comment.