diff --git a/kalamine/cli.py b/kalamine/cli.py index 60d29cb..8822341 100644 --- a/kalamine/cli.py +++ b/kalamine/cli.py @@ -1,16 +1,14 @@ #!/usr/bin/env python3 import json -import pkgutil from contextlib import contextmanager from importlib import metadata from pathlib import Path from typing import Iterator, List, Literal, Union import click -import tomli -from .help import TOML_FOOTER, TOML_HEADER, inline_guide, user_guide +from .help import user_guide, create_layout from .layout import KeyboardLayout, load_layout from .server import keyboard_server @@ -174,38 +172,7 @@ def make( @click.option("--1dk/--no-1dk", "odk", default=False, help="Set a custom dead key.") def create(output_file: Path, geometry: str, altgr: bool, odk: bool) -> None: """Create a new TOML layout description.""" - - def get_layout(name: str) -> KeyboardLayout: - """Return a layout of type NAME with constrained geometry.""" - descriptor = pkgutil.get_data(__package__, f"../layouts/{name}.toml") - layout = KeyboardLayout(tomli.loads(descriptor.decode("utf-8"))) # type: ignore - layout.geometry = geometry - return layout - - def keymap(layout_name, layout_layer, layer_name=""): - """Return a multiline keymap ASCII art for the specified layout.""" - layer = "\n" - layer += f"\n{layer_name or layout_layer} = '''" - layer += "\n" - layer += "\n".join(getattr(get_layout(layout_name), layout_layer)) - layer += "\n'''" - return layer - - content = f'{TOML_HEADER}"{geometry.upper()}"' - if odk: - content += keymap("intl", "base") - if altgr: - content += keymap("prog", "altgr") - content += "\n" - content += TOML_FOOTER - elif altgr: - content += keymap("prog", "full") - else: - content += keymap("ansi", "base") - - # append user guide sections - with open(output_file, "w", encoding="utf-8", newline="\n") as file: - file.write(content + inline_guide()) + create_layout(output_file, geometry, altgr, odk) click.echo(f"... {output_file}") diff --git a/kalamine/data/layout.yaml b/kalamine/data/layout.yaml new file mode 100644 index 0000000..3c6f98e --- /dev/null +++ b/kalamine/data/layout.yaml @@ -0,0 +1,62 @@ +name: custom +name8: custom +locale: us +variant: custom +author: nobody +description: QWERTY, custom variant +url: https://OneDeadKey.github.com/kalamine/ +version: 0.0.1 + +alpha: | + ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━━┓ + │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + ┃ ┃ + │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = ┃ ⌫ ┃ + ┢━━━━━┷━━┱──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┺━━┯━━━━━━━┩ + ┃ ┃ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ { │ } │ | │ + ┃ ↹ ┃ │ │ │ │ │ │ │ │ │ │ [ │ ] │ \ │ + ┣━━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┲━━━━┷━━━━━━━┪ + ┃ ┃ A │ S │ D │ F │ G │ H │ J │ K │ L │ : │ " ┃ ┃ + ┃ ⇬ ┃ │ │ │ │ │ │ │ │ │ ; │ ' ┃ ⏎ ┃ + ┣━━━━━━━━━┻━━┱──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┲━━┻━━━━━━━━━━━━┫ + ┃ ┃ Z │ X │ C │ V │ B │ N │ M │ < │ > │ ? ┃ ┃ + ┃ ⇧ ┃ │ │ │ │ │ │ │ , │ . │ / ┃ ⇧ ┃ + ┣━━━━━━━┳━━━━┻━━┳━━┷━━━━┱┴─────┴─────┴─────┴─────┴─────┴─┲━━━┷━━━┳━┷━━━━━╋━━━━━━━┳━━━━━━━┫ + ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ + ┃ Ctrl ┃ super ┃ Alt ┃ ␣ ┃ Alt ┃ super ┃ menu ┃ Ctrl ┃ + ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┻━━━━━━━┛ + +1dk: | + ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━━┓ + │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + ┃ ┃ + │ ` │ 1 │ 2 « │ 3 » │ 4 │ 5 € │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = ┃ ⌫ ┃ + ┢━━━━━┷━━┱──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┺━━┯━━━━━━━┩ + ┃ ┃ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ { │ } │ | │ + ┃ ↹ ┃ │ │ é │ │ │ ý │ ú │ í │ ó │ │ [ │ ] │ \ │ + ┣━━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┲━━━━┷━━━━━━━┪ + ┃ ┃ A │ S │ D │ F │ G │ H │ J │ K │ L │ : │*¨ ┃ ┃ + ┃ ⇬ ┃ á │ │ │ │ │ │ │ │ │ ; │** ' ┃ ⏎ ┃ + ┣━━━━━━━━━┻━━┱──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┲━━┻━━━━━━━━━━━━┫ + ┃ ┃ Z │ X │ C │ V │ B │ N │ M │ < • │ > │ ? ┃ ┃ + ┃ ⇧ ┃ │ │ ç │ │ │ │ µ │ , · │ . … │ / ┃ ⇧ ┃ + ┣━━━━━━━┳━━━━┻━━┳━━┷━━━━┱┴─────┴─────┴─────┴─────┴─────┴─┲━━━┷━━━┳━┷━━━━━╋━━━━━━━┳━━━━━━━┫ + ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ + ┃ Ctrl ┃ super ┃ Alt ┃ ␣ ┃ Alt ┃ super ┃ menu ┃ Ctrl ┃ + ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┻━━━━━━━┛ + +altgr: | + ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━━┓ + │ *~ │ │ │ │ │ │ │ │ │ │ │ │ ┃ ┃ + │ *` │ │ │ │ │ │ *^ │ │ │ │ │ │ ┃ ⌫ ┃ + ┢━━━━━┷━━┱──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┺━━┯━━━━━━━┩ + ┃ ┃ │ │ │ │ │ │ │ │ │ │ │ │ │ + ┃ ↹ ┃ @ │ < │ > │ $ │ % │ ^ │ & │ * │ ' │ ` │ │ │ │ + ┣━━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┲━━━━┷━━━━━━━┪ + ┃ ┃ │ │ │ │ │ │ │ │ │ │ *¨ ┃ ┃ + ┃ ⇬ ┃ { │ ( │ ) │ } │ = │ \ │ + │ - │ / │ " │ *' ┃ ⏎ ┃ + ┣━━━━━━━━━┻━━┱──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┲━━┻━━━━━━━━━━━━┫ + ┃ ┃ │ │ │ │ │ │ │ │ │ ┃ ┃ + ┃ ⇧ ┃ ~ │ [ │ ] │ _ │ # │ | │ ! │ ; │ : │ ? ┃ ⇧ ┃ + ┣━━━━━━━┳━━━━┻━━┳━━┷━━━━┱┴─────┴─────┴─────┴─────┴─────┴─┲━━━┷━━━┳━┷━━━━━╋━━━━━━━┳━━━━━━━┫ + ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ + ┃ Ctrl ┃ super ┃ Alt ┃ ␣ ┃ AltGr ┃ super ┃ menu ┃ Ctrl ┃ + ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┻━━━━━━━┛ diff --git a/kalamine/help.py b/kalamine/help.py index ed8316b..96aaafa 100644 --- a/kalamine/help.py +++ b/kalamine/help.py @@ -1,8 +1,15 @@ +import pkgutil +from pathlib import Path from typing import List +import yaml + +from .layout import KeyboardLayout from .utils import load_data -SEPARATOR = "--------------------------------------------------------------------------------" +SEPARATOR = ( + "--------------------------------------------------------------------------------" +) MARKDOWN_HEADER = """Defining a Keyboard Layout ================================================================================ @@ -10,26 +17,7 @@ Kalamine keyboard layouts are defined with TOML files including this kind of ASCII-art layer templates: -``` -full = ''' -┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━━┓ -│ ~*~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + ┃ ┃ -│ `*` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6*^ │ 7 │ 8 │ 9 │ 0 │ - │ = ┃ ⌫ ┃ -┢━━━━━┷━━┱──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┺━━┯━━━━━━━┩ -┃ ┃ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ { │ } │ | │ -┃ ↹ ┃ @ │ < │ > │ $ │ % │ ^ │ & │ * │ ' │ ` │ [ │ ] │ \\ │ -┣━━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┲━━━━┷━━━━━━━┪ -┃ ┃ A │ S │ D │ F │ G │ H │ J │ K │ L │ : │ "*¨ ┃ ┃ -┃ ⇬ ┃ { │ ( │ ) │ } │ = │ \\ │ + │ - │ / │ ; " │ '*´ ┃ ⏎ ┃ -┣━━━━━━━━━┻━━┱──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┬──┴──┲━━┻━━━━━━━━━━━━┫ -┃ ┃ Z │ X │ C │ V │ B │ N │ M │ < │ > │ ? ┃ ┃ -┃ ⇧ ┃ ~ │ [ │ ] │ _ │ # │ | │ ! │ , ; │ . : │ / ? ┃ ⇧ ┃ -┣━━━━━━━┳━━━━┻━━┳━━┷━━━━┱┴─────┴─────┴─────┴─────┴─────┴─┲━━━┷━━━┳━┷━━━━━╋━━━━━━━┳━━━━━━━┫ -┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ -┃ Ctrl ┃ super ┃ Alt ┃ ␣ ┃ AltGr ┃ super ┃ menu ┃ Ctrl ┃ -┗━━━━━━━┻━━━━━━━┻━━━━━━━┹────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┻━━━━━━━┛ -''' -``` +```KALAMINE_LAYOUT``` """ TOML_HEADER = """# kalamine keyboard layout descriptor @@ -78,15 +66,71 @@ def core_guide() -> List[str]: return sections +def draw_layout(geometry: str = "ISO", altgr: bool = False, odk: bool = False) -> str: + """Draw a ASCII art description of a default layout.""" + + pkg_file = pkgutil.get_data(__package__, "data/layout.yaml") + if pkg_file is None: + return "" + + # load the descriptor bug only keep the leyers we need + descriptor = yaml.safe_load(pkg_file.decode("utf-8")) + if not altgr: + del descriptor["altgr"] + if not odk: + del descriptor["1dk"] + descriptor["base"] = descriptor.pop("alpha") + else: + del descriptor["alpha"] + descriptor["base"] = descriptor.pop("1dk") + descriptor["geometry"] = geometry.upper() + + # make a lyaout, just to get the ASCII arts + layout = KeyboardLayout(descriptor) + layout.geometry = geometry + + def keymap(layer_name: str) -> str: + layer = "\n".join(getattr(layout, layer_name)) + return f"\n{layer_name} = '''\n{layer}\n'''\n" + + content = "" + if odk: + content += keymap("base") + if altgr: + content += keymap("altgr") + elif altgr: + content += keymap("full") + else: + content += keymap("base") + + return content + + +### +# Public API +## + + def user_guide() -> str: - return MARKDOWN_HEADER + "\n".join(core_guide()) + """Create a user guide with a sample layout description.""" + + header = MARKDOWN_HEADER.replace( + "KALAMINE_LAYOUT", draw_layout(geometry="ANSI", altgr="true") + ) + return header + "\n" + "\n".join(core_guide()) + +def create_layout(output_file: Path, geometry: str, altgr: bool, odk: bool) -> None: + """Create a new TOML layout description.""" -def inline_guide() -> str: - content: str = "" + content = f'{TOML_HEADER}"{geometry.upper()}"\n' + content += draw_layout(geometry, altgr, odk) + if odk: + content += TOML_FOOTER for topic in core_guide(): content += f"\n\n\n# {SEPARATOR}" content += "\n# ".join(topic.rstrip().split("\n")) - return content.replace(" \n", "\n") + with open(output_file, "w", encoding="utf-8", newline="\n") as file: + file.write(content.replace(" \n", "\n")) diff --git a/layouts/ansi.toml b/layouts/ansi.toml index b9cbb3a..8bf36ab 100644 --- a/layouts/ansi.toml +++ b/layouts/ansi.toml @@ -3,7 +3,7 @@ name8 = "q-ansi" locale = "us" variant = "ansi" description = "standard QWERTY-US layout" -url = "http://OneDeadKey.github.com/kalamine/" +url = "https://OneDeadKey.github.com/kalamine/" version = "1.0.0" geometry = "ANSI" diff --git a/layouts/intl.toml b/layouts/intl.toml index d98b125..953b1de 100644 --- a/layouts/intl.toml +++ b/layouts/intl.toml @@ -3,7 +3,7 @@ name8 = "q-intl" locale = "us" variant = "intl" description = "QWERTY layout, international variant" -url = "http://OneDeadKey.github.com/kalamine/" +url = "https://OneDeadKey.github.com/kalamine/" version = "1.0.0" geometry = "ISO" diff --git a/layouts/prog.toml b/layouts/prog.toml index 99cac96..a2005b7 100644 --- a/layouts/prog.toml +++ b/layouts/prog.toml @@ -3,7 +3,7 @@ name8 = "q-prog" variant = "prog" locale = "us" description = "QWERTY-intl layout, developer variant" -url = "http://OneDeadKey.github.com/kalamine/" +url = "https://OneDeadKey.github.com/kalamine/" version = "0.6.0" geometry = "ANSI" diff --git a/pyproject.toml b/pyproject.toml index 4426682..efde121 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,10 +2,6 @@ requires = ["hatchling"] build-backend = "hatchling.build" -# XXX distributing this "layouts" directory is a terrible idea -[tool.hatch.build.targets.sdist] -include = [ "/kalamine", "/layouts" ] - [project] name = "kalamine" version = "0.28"