diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 68bfe0c..88a2b70 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -51,13 +51,13 @@ jobs: run: cargo clippy -- -D warnings && cargo fmt -- --check # 6. 構建 (Build) - # --dist dist/typewriter: 將產物放在子目錄,為了適配 rime.io/typewriter/ 結構 + # --dist dist/typewriter: 将產物放在子目錄,為了適配 rime.io/typewriter/ 結構 # --public-url "/typewriter/": 確保資源引用路徑正確 - name: Build with Trunk run: ./trunk build --release --dist dist/typewriter --public-url "/typewriter/" # 7. 配置 Cloudflare 重定向 - # 讓訪問 rime.io (根路徑) 的用戶自動跳轉到 rime.io/typewriter/ + # 讓訪問 rime.io (根路徑) 的用戶自動跳转到 rime.io/typewriter/ - name: Create _redirects for Cloudflare run: echo "/ /typewriter 301" > dist/_redirects diff --git a/.gitignore b/.gitignore index ea8c4bf..d59da3c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ +.vscode/ +dist/ /target diff --git a/Cargo.lock b/Cargo.lock index fc295fc..a4b48ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ "event-listener", "event-listener-strategy", @@ -136,15 +136,15 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "camino" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" [[package]] name = "cc" @@ -177,9 +177,9 @@ dependencies = [ [[package]] name = "codee" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774365d8238a8dbd57c3047f865187fe6417e765d9955ba8e99e794678a41a0e" +checksum = "a9dbbdc4b4d349732bc6690de10a9de952bd39ba6a065c586e26600b6b0b91f5" dependencies = [ "serde", "serde_json", @@ -203,9 +203,9 @@ dependencies = [ [[package]] name = "config" -version = "0.15.18" +version = "0.15.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e549344080374f9b32ed41bf3b6b57885ff6a289367b3dbc10eea8acc1918" +checksum = "b30fa8254caad766fc03cb0ccae691e14bf3bd72bfff27f72802ce729551b3d6" dependencies = [ "convert_case 0.6.0", "pathdiff", @@ -226,9 +226,9 @@ dependencies = [ [[package]] name = "const-str" -version = "0.6.4" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451d0640545a0553814b4c646eb549343561618838e9b42495f466131fe3ad49" +checksum = "b0664d2867b4a32697dfe655557f5c3b187e9b605b38612a748e5ec99811d160" [[package]] name = "const_format" @@ -308,14 +308,26 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", ] +[[package]] +name = "custom_attribute_macro" +version = "0.0.1" +dependencies = [ + "chrono", + "parse_cargo_toml", + "proc-macro2", + "quote", + "semver", + "syn", +] + [[package]] name = "darling" version = "0.20.11" @@ -586,9 +598,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.9" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -695,12 +707,11 @@ dependencies = [ [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -790,9 +801,9 @@ checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ "icu_collections", "icu_locale_core", @@ -804,9 +815,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" @@ -877,15 +888,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "js-sys" -version = "0.3.82" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -922,9 +933,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "leptos" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b78b04cc52d6f6372e546afcd8ed98ee29ea1a9221b19befb8f9961e47b8307c" +checksum = "87c98f6d751e524ff425ad9d63d53e120ed68311ffbc22bbd9c0b3c4005a421e" dependencies = [ "any_spawner", "cfg-if", @@ -952,8 +963,8 @@ dependencies = [ "tachys", "thiserror 2.0.17", "throw_error", - "typed-builder", - "typed-builder-macro", + "typed-builder 0.22.0", + "typed-builder-macro 0.22.0", "wasm-bindgen", "wasm-bindgen-futures", "wasm_split_helpers", @@ -962,9 +973,9 @@ dependencies = [ [[package]] name = "leptos-use" -version = "0.16.3" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce2162c453100c7d6bc0b6f188ef1df582e35c2458caf6cb69fcddc87619c0db" +checksum = "3a59caa13dbc0f4d71bf3d610884953273c52a0bbe995b35d36cdb1c8f91142f" dependencies = [ "cfg-if", "chrono", @@ -987,15 +998,15 @@ dependencies = [ [[package]] name = "leptos_config" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240b4cb96284256a44872563cf029f24d6fe14bc341dcf0f4164e077cb5a1471" +checksum = "071fc40aeb9fcab885965bad1887990477253ad51f926cd19068f45a44c59e89" dependencies = [ "config", "regex", "serde", "thiserror 2.0.17", - "typed-builder", + "typed-builder 0.21.2", ] [[package]] @@ -1033,9 +1044,9 @@ dependencies = [ [[package]] name = "leptos_macro" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2009e2cc8ac3aa3e417c51d2a2b951c34dfea51f25935717b564c347fb20cb3f" +checksum = "9d199fafe14b7925fd392764fdd851215909604955acfda7c0263b8722d57c23" dependencies = [ "attribute-derive", "cfg-if", @@ -1056,9 +1067,9 @@ dependencies = [ [[package]] name = "leptos_server" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38acbf32649a4b127c8d4ccaed8fb388e19a746430a0ea8f8160e51e28c36e2d" +checksum = "dbf1045af93050bf3388d1c138426393fc131f6d9e46a65519da884c033ed730" dependencies = [ "any_spawner", "base64", @@ -1224,6 +1235,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "parse_cargo_toml" +version = "0.0.1" +dependencies = [ + "chrono", + "semver", + "toml", +] + [[package]] name = "paste" version = "1.0.15" @@ -1393,9 +1413,9 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "reactive_graph" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77cbe7c61b939523104883fd00d431f6c681c7005fd350f01a9ff2fc96509399" +checksum = "4043190442021086719fb9183daacb050f44d4ed8d3a1c8534e366d45dd95c29" dependencies = [ "any_spawner", "async-lock", @@ -1404,6 +1424,7 @@ dependencies = [ "hydration_context", "indexmap", "or_poisoned", + "paste", "pin-project-lite", "rustc-hash", "rustc_version", @@ -1518,12 +1539,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - [[package]] name = "same-file" version = "1.0.6" @@ -1586,15 +1601,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -1619,9 +1634,9 @@ dependencies = [ [[package]] name = "server_fn" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc30228718f62d80a376964baf990edbcb5e97688fdc71183a8ef3d44cb6c89" +checksum = "353d02fa2886cd8dae0b8da0965289fa8f2ecc7df633d1ce965f62fdf9644d29" dependencies = [ "base64", "bytes", @@ -1700,9 +1715,9 @@ checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "slotmap" -version = "1.0.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" dependencies = [ "version_check", ] @@ -1782,9 +1797,9 @@ dependencies = [ [[package]] name = "tachys" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f88be37609c1891b748ed1feb9b08b0e772156a80d586b38726253f80859134d" +checksum = "f2b2db11e455f7e84e2cc3e76f8a3f3843f7956096265d5ecff781eabe235077" dependencies = [ "any_spawner", "async-trait", @@ -1911,10 +1926,12 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" dependencies = [ + "indexmap", "serde_core", "serde_spanned", "toml_datetime", "toml_parser", + "toml_writer", "winnow", ] @@ -1936,13 +1953,28 @@ dependencies = [ "winnow", ] +[[package]] +name = "toml_writer" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" + [[package]] name = "typed-builder" version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fef81aec2ca29576f9f6ae8755108640d0a86dd3161b2e8bca6cfa554e98f77d" dependencies = [ - "typed-builder-macro", + "typed-builder-macro 0.21.2", +] + +[[package]] +name = "typed-builder" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "398a3a3c918c96de527dc11e6e846cd549d4508030b8a33e1da12789c856b81a" +dependencies = [ + "typed-builder-macro 0.22.0", ] [[package]] @@ -1956,6 +1988,17 @@ dependencies = [ "syn", ] +[[package]] +name = "typed-builder-macro" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e48cea23f68d1f78eb7bc092881b6bb88d3d6b5b7e6234f6f9c911da1ffb221" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "typenum" version = "1.19.0" @@ -1967,11 +2010,13 @@ name = "typewriter" version = "0.1.0" dependencies = [ "console_error_panic_hook", + "custom_attribute_macro", "lazy-regex", "lazy_static", "leptos", "leptos-use", "maybe-owned", + "parse_cargo_toml", "strum", ] @@ -2025,9 +2070,9 @@ dependencies = [ [[package]] name = "utf8-width" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" +checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" [[package]] name = "utf8_iter" @@ -2037,9 +2082,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.18.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" dependencies = [ "getrandom", "js-sys", @@ -2073,9 +2118,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", @@ -2086,9 +2131,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.55" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "js-sys", @@ -2099,9 +2144,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2109,9 +2154,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ "bumpalo", "proc-macro2", @@ -2122,9 +2167,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.105" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] @@ -2166,9 +2211,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.82" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", @@ -2361,3 +2406,9 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zmij" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3280a1b827474fcd5dbef4b35a674deb52ba5c312363aef9135317df179d81b" diff --git a/Cargo.toml b/Cargo.toml index 2c806ed..e4a21a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,18 +1,27 @@ +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + [package] name = "typewriter" -version = "0.1.0" edition = "2021" +version = "0.1.0" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[package.metadata] +update_date = "2025-12-31" + +[workspace] +members = ["tool/*"] [dependencies] -console_error_panic_hook = "0.1.7" -lazy-regex = "3.4.1" -lazy_static = "1.5.0" +custom_attribute_macro = { path = "tool/custom_attribute_macro" } +parse_cargo_toml = { path = "tool/parse_cargo_toml" } + +console_error_panic_hook = "0.1" +lazy-regex = "3.4" +lazy_static = "1.5" leptos = { version = "0.8", features = ["csr", "nightly"] } -leptos-use = "0.16" -maybe-owned = "0.3.4" -strum = { version = "0.27.1", features = ["derive"] } +leptos-use = "0.17" +maybe-owned = "0.3" +strum = { version = "0.27", features = ["derive"] } [profile.release] codegen-units = 1 diff --git a/README.md b/README.md index 05ceb06..24bfe9a 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# RIME 打字機 +# RIME 打字机 -宮保拼音打字練習 +宫保拼音打字练习 -內置開發版 Rime 輸入法微觀引擎 +内置开发版 Rime 输入法微观引擎 ## 用法 -``` sh +```sh trunk serve --open ``` diff --git a/src/.vscode/settings.json b/src/.vscode/settings.json new file mode 100644 index 0000000..bd8188c --- /dev/null +++ b/src/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "files.encoding": "utf8", + "files.eol": "\n", + "editor.rulers": [ + 40, + 80, + 120 + ] +} \ No newline at end of file diff --git a/src/action.rs b/src/action.rs index cdc1370..07351ea 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,16 +1,16 @@ #![allow(dead_code)] -pub trait 動作: Fn() + Copy + 'static {} -impl 動作 for T where T: Fn() + Copy + 'static {} +pub trait 动作: Fn() + Copy + 'static {} +impl 动作 for T where T: Fn() + Copy + 'static {} pub struct 未有(); -pub type 成功失敗 = Result<(), 未有>; +pub type 成功失败 = Result<(), 未有>; -pub trait 動作得一結果: Fn() -> R + Copy + 'static {} -impl 動作得一結果 for T where T: Fn() -> R + Copy + 'static {} +pub trait 动作得一结果: Fn() -> R + Copy + 'static {} +impl 动作得一结果 for T where T: Fn() -> R + Copy + 'static {} -pub trait 動作給一參數

: Fn(P) + Copy + 'static {} -impl 動作給一參數

for T where T: Fn(P) + Copy + 'static {} +pub trait 动作给一参数

: Fn(P) + Copy + 'static {} +impl 动作给一参数

for T where T: Fn(P) + Copy + 'static {} -pub trait 動作給一參數得一結果: Fn(P) -> R + Copy + 'static {} -impl 動作給一參數得一結果 for T where T: Fn(P) -> R + Copy + 'static {} +pub trait 动作给一参数得一结果: Fn(P) -> R + Copy + 'static {} +impl 动作给一参数得一结果 for T where T: Fn(P) -> R + Copy + 'static {} diff --git a/src/app.rs b/src/app.rs index f82a2bd..0f7237c 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,288 +1,265 @@ use leptos::prelude::*; -use crate::definition::{觸鍵方式, 鍵組}; -use crate::engine::{微觀引擎, 微觀引擎輸出信號}; +use crate::definition::{ 击键方式, 键组 }; +use crate::engine::{ 微观引擎, 微观引擎输出信号 }; use crate::gear::{ - assignment::{作業, 作業機關輸出信號}, - caption::{字幕機關輸出信號, 字幕表示}, - chord::{並擊機關輸出信號, 並擊狀態}, - key_press::連擊機關輸出信號, - layout::{ - 功能鍵::{回車鍵, 製表鍵, 退出鍵, 退格鍵}, - 配列機關輸出信號, - }, - mode::{工作模式, 工作模式機關輸出信號}, - theory::輸入方案機關輸出信號, + assignment::{ 作业模式输出信号, 作业 }, + caption::{ 字幕机关输出信号, 字幕表示 }, + chord::{ 并击模式输出信号, 并击状态 }, + key_press::连击模式输出信号, + layout::{ 功能键::{ 制表键, 回车键, 退出键, 退格键 }, 键盘配列输出信号 }, + mode::{ 工作模式, 工作模式输出信号 }, + theory::输入方案输出信号, }; use crate::key_code::KeyCode; use crate::view::{ caption::Rime字幕屏, - exercise_menu::Rime練習題選單, - input_code::{ - Rime反查輸入欄, Rime編碼回顯區, Rime編碼欄, 回顯區佈局, 編碼欄顯示選項 - }, - keyboard::{Rime鍵圖, Rime鍵盤圖, 鍵面動態着色法}, - layout_menu::Rime配列選單, - status_bar::Rime狀態欄, - theory_menu::Rime方案選單, + exercise_menu::Rime练习题选单, + input_code::{ Rime反查输入栏, Rime编码回显区, Rime编码栏, 回显区布局, 编码栏显示选项 }, + keyboard::{ Rime键图, Rime键盘图, 键面动态着色法 }, + layout_menu::Rime配列选单, + status_bar::Rime状态栏, + theory_menu::Rime方案选单, }; #[derive(Clone, Copy)] -struct 並擊對標動態 { - 目標並擊: Signal>, - 實況並擊: Signal<並擊狀態>, +struct 并击对标动态 { + 目标并击: Signal>, + 实况并击: Signal<并击状态>, } -impl 鍵面動態着色法 for 並擊對標動態 { - fn 鍵位提示(&self, 鍵: KeyCode) -> bool { - self.目標並擊 +impl 键面动态着色法 for 并击对标动态 { + fn 键位提示(&self, 键: KeyCode) -> bool { + self.目标并击 .read() .as_ref() - .is_some_and(|並擊| 並擊.0.contains(&鍵)) + .is_some_and(|并击| 并击.0.contains(&键)) } - fn 是否落鍵(&self, 鍵: KeyCode) -> bool { - self.實況並擊.read().實時落鍵.0.contains(&鍵) + fn 是否落键(&self, 键: KeyCode) -> bool { + self.实况并击.read().实时击键.0.contains(&键) } - fn 是否擊中(&self, 鍵: KeyCode) -> bool { - self.實況並擊.read().累計擊鍵.0.contains(&鍵) + fn 是否击中(&self, 键: KeyCode) -> bool { + self.实况并击.read().累计击键.0.contains(&键) } } #[derive(Clone, Copy)] -struct 功能鍵開關狀態 { - 現行工作模式: ReadSignal<工作模式>, +struct 功能键开关状态 { + 现行工作模式: ReadSignal<工作模式>, } -impl 鍵面動態着色法 for 功能鍵開關狀態 { - fn 鍵位提示(&self, _鍵: KeyCode) -> bool { +impl 键面动态着色法 for 功能键开关状态 { + fn 键位提示(&self, _键: KeyCode) -> bool { false } - fn 是否落鍵(&self, 鍵: KeyCode) -> bool { - match 鍵 { - KeyCode::Enter => self.現行工作模式.get() == 工作模式::輸入反查碼, - KeyCode::Escape => self.現行工作模式.get() == 工作模式::選取練習題, - KeyCode::Grave => self.現行工作模式.get() == 工作模式::選擇輸入方案, + fn 是否落键(&self, 键: KeyCode) -> bool { + match 键 { + KeyCode::Enter => self.现行工作模式.get() == 工作模式::输入反查码, + KeyCode::Escape => self.现行工作模式.get() == 工作模式::选取练习题, + KeyCode::Grave => self.现行工作模式.get() == 工作模式::选择输入方案, _ => false, } } - fn 是否擊中(&self, _鍵: KeyCode) -> bool { + fn 是否击中(&self, _键: KeyCode) -> bool { false } } #[component] -pub fn Rime打字機應用() -> impl IntoView { - let 微觀引擎輸出信號 { - 方案, - 模式, - 配列, - 作業, - 字幕, - 連擊, - 並擊, - } = 微觀引擎(); - let 輸入方案機關輸出信號 { - 現行方案, - 選用方案, - 方案定義, - 指法, - .. - } = 方案; - let 配列機關輸出信號 { - 已選配列, 選用配列 - } = 配列; - let 工作模式機關輸出信號 { - 現行工作模式, - 開啓反查輸入, - 開啓練習題選單, - 關閉輸入欄, - 開啓方案選單, - 開啓配列選單, +pub fn Rime打字机应用() -> impl IntoView { + let 微观引擎输出信号 { 方案, 模式, 键盘配列, 作业, 字幕, 连击, 并击 } = 微观引擎(); + let 输入方案输出信号 { 当前方案, 选用方案, 方案定义, 指法, .. } = 方案; + let 键盘配列输出信号 { 已选配列, 选用配列 } = 键盘配列; + let 工作模式输出信号 { + 现行工作模式, + 开启反查输入, + 开启练习题选单, + 关闭输入栏, + 开启方案选单, + 开启配列选单, .. } = 模式; - let 作業機關輸出信號 { - 當前作業, - 佈置作業, - 目標輸入碼片段, - .. - } = 作業; - let 字幕機關輸出信號 { 段落表示, .. } = 字幕; - let 連擊機關輸出信號 { - 連擊輸入碼, - 實況字根碼, - .. - } = 連擊; - let 並擊機關輸出信號 { - 並擊狀態流, - 反查鍵位, - 反查所得並擊碼, - 實況並擊碼, - 並擊所得拼音, - 並擊完成, - 並擊成功, + let 作业模式输出信号 { 当前作业, 布置作业, 目标输入码片段, .. } = 作业; + let 字幕机关输出信号 { 段落表示, .. } = 字幕; + let 连击模式输出信号 { 连击输入码, 实况字根码, .. } = 连击; + let 并击模式输出信号 { + 并击状态流, + 反查键位, + 反查所得并击码, + 实际并击码, + 并击所得拼音, + 并击完成, + 并击成功, .. - } = 並擊; + } = 并击; - let 是否顯示光標 = Signal::derive(move || matches!(指法(), 觸鍵方式::連擊)); - let 有無輸入碼 = Signal::derive(move || match 指法() { - 觸鍵方式::連擊 => !實況字根碼.read().is_empty(), - 觸鍵方式::並擊 => !實況並擊碼.read().is_empty(), + let 是否显示光标 = Signal::derive(move || matches!(指法(), 击键方式::连击)); + let 有无输入码 = Signal::derive(move || { + match 指法() { + 击键方式::连击 => !实况字根码.read().is_empty(), + 击键方式::并击 => !实际并击码.read().is_empty(), + } }); - let 顯示選項 = Signal::derive(move || { - if 反查鍵位.read().is_some() { - 編碼欄顯示選項::顯示反查 - } else if 有無輸入碼() { - 編碼欄顯示選項::顯示實況 + let 显示选项 = Signal::derive(move || { + if 反查键位.read().is_some() { + 编码栏显示选项::显示反查 + } else if 有无输入码() { + 编码栏显示选项::显示实况 } else { - 編碼欄顯示選項::無顯示 + 编码栏显示选项::无显示 } }); - let 完成一詞 = move || { - 段落表示 - .read() + let 完成一词 = move || { + 段落表示.read() .as_ref() - .is_some_and(|字幕表示 { 指標文字, .. }| ["", " "].contains(&指標文字.as_str())) + .is_some_and(|字幕表示 { 指标文字, .. }| ["", " "].contains(&指标文字.as_str())) }; - let 輸入正確 = Signal::derive(move || match 指法() { - 觸鍵方式::連擊 => 完成一詞(), - 觸鍵方式::並擊 => 並擊完成() && 並擊成功(), + let 输入正确 = Signal::derive(move || { + match 指法() { + 击键方式::连击 => 完成一词(), + 击键方式::并击 => 并击完成() && 并击成功(), + } }); - let 點擊編碼欄動作 = move || { - if 現行工作模式() == 工作模式::錄入 { - if 當前作業.read().是否練習題() { - 開啓練習題選單(); + let 点击编码栏动作 = move || { + if 现行工作模式() == 工作模式::录入 { + if 当前作业.read().是否练习题() { + 开启练习题选单(); } else { - 開啓反查輸入(); + 开启反查输入(); } } }; - let 編碼回顯區佈局 = Signal::derive(move || match 指法() { - 觸鍵方式::連擊 => 回顯區佈局::單欄, - 觸鍵方式::並擊 => 回顯區佈局::左右對照, + let 编码回显区布局 = Signal::derive(move || { + match 指法() { + 击键方式::连击 => 回显区布局::单栏, + 击键方式::并击 => 回显区布局::左右对照, + } }); - let 回顯輸入碼 = Signal::derive(move || match 指法() { - 觸鍵方式::連擊 => { - let 輸入碼 = 連擊輸入碼.read().join(""); - match 輸入碼.as_str() { - "" | "␣" => 輸入碼, - _ => 輸入碼 + "‸", + let 回显输入码 = Signal::derive(move || { + match 指法() { + 击键方式::连击 => { + let 输入码 = 连击输入码.read().join(""); + match 输入码.as_str() { + "" | "␣" => 输入码, + _ => 输入码 + "‸", + } } + 击键方式::并击 => 反查所得并击码().unwrap_or_else(实际并击码), } - 觸鍵方式::並擊 => 反查所得並擊碼().unwrap_or_else(實況並擊碼), }); - let 回顯轉寫碼 = Signal::derive(move || match 指法() { - 觸鍵方式::連擊 => None, - 觸鍵方式::並擊 => { - 目標輸入碼片段() - .and_then(|輸入碼| 輸入碼.轉寫碼原文) - .or_else(並擊所得拼音) - // 加尖括弧表示拉丁文轉寫 - .map(|轉寫| format!("⟨{轉寫}⟩")) + let 回显转写码 = Signal::derive(move || { + match 指法() { + 击键方式::连击 => None, + 击键方式::并击 => { + 目标输入码片段() + .and_then(|输入码| 输入码.转写码原文) + .or_else(并击所得拼音) + // 加尖括弧表示拉丁文转写 + .map(|转写| format!("⟨{转写}⟩")) + } } }); - let 反查碼 = Signal::derive(move || { - 當前作業 - .read() - .自訂反查碼 - .clone() - .or_else(|| 當前作業.read().目標輸入碼().map(str::to_owned)) + let 反查码 = Signal::derive(move || { + 当前作业.read() + .自定义反查码.clone() + .or_else(|| 当前作业.read().目标输入码().map(str::to_owned)) }); - let 反查碼變更動作 = move |反查碼: String| { - 佈置作業(作業::自訂(現行方案(), 反查碼)); + let 反查码变更动作 = move |反查码: String| { + 布置作业(作业::自定义(当前方案(), 反查码)); }; - let 當選題號 = Signal::derive(move || 當前作業.read().題號); - let 選中題號動作 = move |題號| { - 佈置作業(作業::練習題(現行方案(), 題號)); - 關閉輸入欄(); + let 当前题号 = Signal::derive(move || 当前作业.read().题号); + let 选中题号动作 = move |题号| { + 布置作业(作业::练习题(当前方案(), 题号)); + 关闭输入栏(); }; - let 選中方案動作 = move |選中項| { - 選用方案(選中項); - 關閉輸入欄(); + let 选中方案动作 = move |选中项| { + 选用方案(选中项); + 关闭输入栏(); }; - let 選用配列動作 = move |選中項| { - 選用配列(選中項); - 關閉輸入欄(); + let 选用配列动作 = move |选中项| { + 选用配列(选中项); + 关闭输入栏(); }; - let 方案配套練習題 = Signal::derive(move || 現行方案.get().配套練習題().unwrap_or(&[])); - let 方案指定佈局 = Signal::derive(move || *方案定義.read().佈局); - let 方案指定盤面 = Signal::derive(move || 方案指定佈局().默認盤面); + let 方案配套练习题 = Signal::derive(move || 当前方案.get().配套练习题().unwrap_or(&[])); + let 方案指定布局 = Signal::derive(move || *方案定义.read().布局); + let 方案指定盘面 = Signal::derive(move || 方案指定布局().默认盘面); - let 標註功能鍵 = |功能鍵| Signal::derive(move || 功能鍵); + let 标注功能键 = |功能键| Signal::derive(move || 功能键); - let 並擊動態 = 並擊對標動態 { - 目標並擊: 反查鍵位, - 實況並擊: 並擊狀態流.into(), + let 并击动态 = 并击对标动态 { + 目标并击: 反查键位, + 实况并击: 并击状态流.into(), }; - let 開關狀態 = 功能鍵開關狀態 { 現行工作模式 }; + let 开关状态 = 功能键开关状态 { 现行工作模式 }; view! { - +

-
- +
+
-
- +
+
- { - move || match 現行工作模式() { - 工作模式::錄入 => view! { - + move || match 现行工作模式() { + 工作模式::录入 => view! { + }.into_any(), - 工作模式::輸入反查碼 => view! { - view! { + }.into_any(), - 工作模式::選取練習題 => view! { - view! { + }.into_any(), - 工作模式::選擇輸入方案 => view! { - view! { + }.into_any(), - 工作模式::選擇配列 => view! { - view! { + }.into_any(), } } - -
- + +
+
-
- +
+
- + - } } diff --git a/src/definition.rs b/src/definition.rs index c202b64..1a6e0de 100644 --- a/src/definition.rs +++ b/src/definition.rs @@ -2,121 +2,141 @@ use lazy_regex::Regex; use std::borrow::Cow; use std::collections::BTreeSet; -use crate::gear::layout::鍵盤佈局; +use crate::gear::layout::键盘布局; use crate::key_code::KeyCode; -use crate::spelling_algebra::{拼寫運算, 施展拼寫運算}; +use crate::spelling_algebra::{ 拼写运算, 施展拼写运算 }; -pub struct 鍵位定義<'a> { - pub 輸入碼: &'a str, - pub 鍵碼: KeyCode, +pub struct 键位映射定义<'a> { + pub 输入码: &'a str, + pub 键码: KeyCode, } #[derive(Clone, Copy)] -pub struct 輸入方案定義<'a> { - pub 名稱: &'a str, - pub 佈局: &'a 鍵盤佈局, - pub 指法: 觸鍵方式, - pub 字根表: &'a [鍵位定義<'a>], - pub 轉寫法: 轉寫法定義<'a>, +pub struct 输入方案定义<'a> { + pub 名称: &'a str, + pub 布局: &'a 键盘布局, + pub 指法: 击键方式, + pub 键位映射: &'a [键位映射定义<'a>], + pub 转写: 转写定义<'a>, } -#[derive(Clone, Copy, PartialEq)] -pub enum 觸鍵方式 { - 連擊, - 並擊, +#[derive(Clone, Copy, Default, PartialEq)] +pub enum 击键方式 { + #[default] + 连击, + 并击, } #[derive(Clone, Copy)] -pub struct 轉寫法定義<'a> { - /// 將按鍵序列轉換成慣用的表示形式,如字母與附標符號合字 - pub 輸入碼表示: &'a [拼寫運算<'a>], - /// 將輸入碼的表示形式轉換成按鍵序列 - pub 輸入碼鍵位: &'a [拼寫運算<'a>], - /// 將輸入碼轉寫成符合詞典規範的編碼 - pub 拼式轉寫規則: &'a [拼寫運算<'a>], - /// 將詞典碼拆分爲按鍵序列 - pub 字根拆分規則: &'a [拼寫運算<'a>], - /// 定義若干識別有效詞典碼的規則。若未定義任何規則,則不做驗證 - pub 拼式驗證規則: &'a [&'a Regex], +pub struct 转写定义<'a> { + /// 将按键序列转换成惯用的表示形式,如字母与附标符号合字 + pub 编码预览: &'a [拼写运算<'a>], + /// 将输入码的表示形式转换成按键序列 + pub 键位提示: &'a [拼写运算<'a>], + /// 将输入码转写成符合词典规范的编码 + pub 输入棱镜: &'a [拼写运算<'a>], + /// 将词典码拆分为按键序列 + pub 词库棱镜: &'a [拼写运算<'a>], + /// 定义若干识别有效词典码的规则。若未定义任何规则,则不做验证 + pub 拼式验证规则: &'a [&'a Regex], } -pub trait 判定鍵位 { - fn 有無鍵位(&self) -> bool; - fn 包含鍵位(&self, 鍵碼: &KeyCode) -> bool; +pub trait 判定键位 { + fn 有无键位(&self) -> bool; + fn 包含键位(&self, 键码: &KeyCode) -> bool; } #[derive(Clone, Debug, PartialEq)] -pub struct 鍵組(pub BTreeSet); +pub struct 键组(pub BTreeSet); -impl 鍵組 { +impl 键组 { pub fn new() -> Self { - 鍵組(BTreeSet::new()) + 键组(BTreeSet::new()) } } -impl 判定鍵位 for &鍵組 { - fn 有無鍵位(&self) -> bool { +impl 判定键位 for &键组 { + fn 有无键位(&self) -> bool { !self.0.is_empty() } - fn 包含鍵位(&self, 鍵碼: &KeyCode) -> bool { - self.0.contains(鍵碼) + fn 包含键位(&self, 键码: &KeyCode) -> bool { + self.0.contains(键码) } } -impl 判定鍵位 for KeyCode { - fn 有無鍵位(&self) -> bool { +impl 判定键位 for KeyCode { + fn 有无键位(&self) -> bool { *self != KeyCode::No } - fn 包含鍵位(&self, 鍵碼: &KeyCode) -> bool { - self == 鍵碼 + fn 包含键位(&self, 键码: &KeyCode) -> bool { + self == 键码 } } -impl 輸入方案定義<'_> { - pub fn 尋得字根(&self, 字根: &str) -> Option<&鍵位定義<'_>> { - self.字根表.iter().find(|鍵| 鍵.輸入碼 == 字根) +impl 输入方案定义<'_> { + pub fn 寻得字根(&self, 字根: &str) -> Option<&键位映射定义<'_>> { + self.键位映射.iter().find(|键| 键.输入码 == 字根) } - pub fn 讀出鍵位(&self, 字根碼: &str) -> 鍵組 { - let 鍵碼序列 = 施展拼寫運算(字根碼, self.轉寫法.輸入碼鍵位) + pub fn 读出键位(&self, 字根码: &str) -> 键组 { + let 键码序列 = 施展拼写运算(字根码, self.转写.键位提示) .map(Cow::Owned) - .unwrap_or(Cow::Borrowed(字根碼)); - 鍵組( - self.字根表 + .unwrap_or(Cow::Borrowed(字根码)); + 键组( + self.键位映射 .iter() - .filter(|鍵| 鍵碼序列.contains(鍵.輸入碼)) - .map(|鍵| 鍵.鍵碼) - .collect(), + .filter(|键| 键码序列.contains(键.输入码)) + .map(|键| 键.键码) + .collect() ) } - pub fn 寫成字根碼(&self, 鍵位: impl 判定鍵位) -> String { - if !鍵位.有無鍵位() { + pub fn 写成字根码(&self, 键位: impl 判定键位) -> String { + if !键位.有无键位() { String::new() } else { - let 字根碼 = self - .字根表 + let 字根码 = self.键位映射 .iter() - .filter(|鍵| 鍵位.包含鍵位(&鍵.鍵碼)) - .map(|鍵| 鍵.輸入碼) + .filter(|键| 键位.包含键位(&键.键码)) + .map(|键| 键.输入码) .collect::(); - 施展拼寫運算(&字根碼, self.轉寫法.輸入碼表示).unwrap_or(字根碼) + 施展拼写运算(&字根码, self.转写.编码预览).unwrap_or(字根码) } } } -impl 轉寫法定義<'_> { - pub fn 字根碼轉寫爲拼式(&self, 字根碼: &str) -> Option { - 施展拼寫運算(字根碼, self.拼式轉寫規則) +impl 转写定义<'_> { + pub fn 字根码转写为拼式(&self, 字根码: &str) -> Option { + 施展拼写运算(字根码, self.输入棱镜) } - pub fn 拼式拆分爲字根碼(&self, 轉寫碼: &str) -> Option { - 施展拼寫運算(轉寫碼, self.字根拆分規則) + pub fn 拼式拆分为字根码(&self, 转写码: &str) -> Option { + 施展拼写运算(转写码, self.词库棱镜) } - pub fn 驗證拼式(&self, 待驗證拼式: &str) -> bool { - self.拼式驗證規則.iter().any(|r| r.is_match(待驗證拼式)) + pub fn 验证拼式(&self, 待验证拼式: &str) -> bool { + self.拼式验证规则.iter().any(|r| r.is_match(待验证拼式)) } } + +#[macro_export] +macro_rules! 默认映射 { + ($字母:ident) => { + 键位映射定义 { + 输入码: stringify!($字母), + 键码: KeyCode::$字母, + } + }; +} + +#[macro_export] +macro_rules! 键位映射 { + ($输入码:ident => $键码:path) => { + 键位映射定义 { + 输入码: stringify!($输入码), + 键码: $键码, + } + }; +} diff --git a/src/drill/alphabet.rs b/src/drill/alphabet.rs index 9592edb..d52205c 100644 --- a/src/drill/alphabet.rs +++ b/src/drill/alphabet.rs @@ -1,27 +1,27 @@ -use super::練習題; +use super::练习题; use crate::gear::caption::{ - 字幕格式::{段落, 詞句}, - 字幕步進::逐字, + 字幕格式::{段落, 词句}, + 字幕步进::逐字, }; -pub const 字母鍵盤練習題: &[練習題] = &[ - 練習題 { - 標題: "字母表", - 編碼: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", - 字幕: 詞句("ABCD EFGH IJKL MNOPQ RSTU VWXYZ"), +pub const 字母键盘练习题: &[练习题] = &[ + 练习题 { + 标题: "字母表", + 编码: "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + 字幕: 词句("ABCD EFGH IJKL MNOPQ RSTU VWXYZ"), }, - 練習題 { - 標題: "QWERTY 鍵盤", - 編碼: "QWERTYUIOPASDFGHJKLZXCVBNM", - 字幕: 詞句( + 练习题 { + 标题: "QWERTY 鍵盤", + 编码: "QWERTYUIOPASDFGHJKLZXCVBNM", + 字幕: 词句( "QWERT YUIOP \ ASDFG HJKL \ ZXCVB NM", ), }, - 練習題 { - 標題: "洋文金句", - 編碼: "HELLO␣WORLD + 练习题 { + 标题: "洋文金句", + 编码: "HELLO␣WORLD THE␣QUICK␣BROWN␣FOX␣JUMPS␣OVER␣THE␣LAZY␣DOG", 字幕: 段落( 逐字, diff --git a/src/drill/ancient_chinese.rs b/src/drill/ancient_chinese.rs index 1b1ba9e..8d07579 100644 --- a/src/drill/ancient_chinese.rs +++ b/src/drill/ancient_chinese.rs @@ -1,9 +1,10 @@ -use super::練習題; -use crate::gear::caption::字幕格式::詞句; +use super::练习题; +use crate::gear::caption::字幕格式::词句; -pub const 上古漢語練習題: &[練習題] = &[練習題 { - 標題: "隰有萇楚 上古漢語 鄭張尚芳擬音", - 編碼: "[邪緝]= [匣之]=<ɢʷɯʔ> [定陽]= [初魚]= \ +pub const 上古汉语练习题: &[练习题] = &[ + 练习题 { + 标题: "隰有萇楚 上古汉语 鄭張尚芳擬音", + 编码: "[邪緝]= [匣之]=<ɢʷɯʔ> [定陽]= [初魚]= \ [影歌]= [泥歌]= [羣之]=<ɡɯ> [章支]= \ [影宵]= [章之]= [影藥]= [影藥]= \ [疑豹]=<ŋraːwɢs> [精之]=<ʔslɯʔ> [章之]= [明魚]= [端支]=<ʔle> \ @@ -17,16 +18,18 @@ pub const 上古漢語練習題: &[練習題] = &[練習題 { [影歌]= [泥歌]= [羣之]=<ɡɯ> [船質]=<ɦliɡ> \ [影宵]= [章之]= [影藥]= [影藥]= \ [疑豹]=<ŋraːwɢs> [精之]=<ʔslɯʔ> [章之]= [明魚]= [書質]=", - 字幕: 詞句( - "隰有萇楚 猗儺其枝 夭之沃沃 樂子之無知 \ + 字幕: 词句( + "隰有萇楚 猗儺其枝 夭之沃沃 樂子之無知 \ 隰有萇楚 猗儺其華 夭之沃沃 樂子之無家 \ - 隰有萇楚 猗儺其實 夭之沃沃 樂子之無室", - ), -}]; + 隰有萇楚 猗儺其實 夭之沃沃 樂子之無室" + ), + }, +]; -pub const 早期中古漢語練習題: &[練習題] = &[練習題 { - 標題: "隰有萇楚 早期中古漢語 《切韻》音系", - 編碼: "[邪深入]= [云流上]=<ɣiu²> [澄宕]=<ɖiaŋ> [初遇上]= \ +pub const 早期中古汉语练习题: &[练习题] = &[ + 练习题 { + 标题: "隰有萇楚 早期中古汉语 《切韻》音系", + 编码: "[邪深入]= [云流上]=<ɣiu²> [澄宕]=<ɖiaŋ> [初遇上]= \ [影止]=<ʔɹie> [泥果]= [羣止]=<ɡiə> [章止]= \ [影效]=<ʔɹiau> [章止]= [影通入]=<ʔuk> [影通入]=<ʔuk> \ [疑效去]=<ŋrau³> [精止上]= [章止]= [明遇]= [知止]=<ʈɹie> \ @@ -40,16 +43,18 @@ pub const 早期中古漢語練習題: &[練習題] = &[練習題 { [影止]=<ʔɹie> [泥果]= [羣止]=<ɡiə> [船臻入]=<ʑit> \ [影效]=<ʔɹiau> [章止]=<ʨiə> [影通入]=<ʔuk> [影通入]=<ʔuk> \ [疑效去]=<ŋɹau³> [精止上]= [章止]= [明遇]= [書臻入]=<ɕit>", - 字幕: 詞句( - "隰有萇楚 猗儺其枝 夭之沃沃 樂子之無知 \ + 字幕: 词句( + "隰有萇楚 猗儺其枝 夭之沃沃 樂子之無知 \ 隰有萇楚 猗儺其華 夭之沃沃 樂子之無家 \ - 隰有萇楚 猗儺其實 夭之沃沃 樂子之無室", - ), -}]; + 隰有萇楚 猗儺其實 夭之沃沃 樂子之無室" + ), + }, +]; -pub const 晚期中古漢語練習題: &[練習題] = &[練習題 { - 標題: "隰有萇楚 晚期中古漢語 北宋官話", - 編碼: "[邪深入]= [影流上]= [牀宕]= [穿遇上]= \ +pub const 晚期中古汉语练习题: &[练习题] = &[ + 练习题 { + 标题: "隰有萇楚 晚期中古汉语 北宋官話", + 编码: "[邪深入]= [影流上]= [牀宕]= [穿遇上]= \ [影止]= [泥果]= [羣止]= [照止]= \ [影效]= [照止]= [影通入]= [影通入]= \ [疑效去]=<ŋiau⁴> [精止上]= [照止]= [明遇]= [照止]= \ @@ -63,16 +68,18 @@ pub const 晚期中古漢語練習題: &[練習題] = &[練習題 { [影止]= [泥果]= [羣止]= [禪臻入]=<ʂit²> \ [影效]= [照止]= [影通入]= [影通入]= \ [疑效去]=<ŋiau⁴> [精止上]= [照止]= [明遇]= [審臻入]=<ʂit>", - 字幕: 詞句( - "隰有萇楚 猗儺其枝 夭之沃沃 樂子之無知 \ + 字幕: 词句( + "隰有萇楚 猗儺其枝 夭之沃沃 樂子之無知 \ 隰有萇楚 猗儺其華 夭之沃沃 樂子之無家 \ - 隰有萇楚 猗儺其實 夭之沃沃 樂子之無室", - ), -}]; + 隰有萇楚 猗儺其實 夭之沃沃 樂子之無室" + ), + }, +]; -pub const 近古漢語練習題: &[練習題] = &[練習題 { - 標題: "隰有萇楚 近古漢語 《中原音韻》音系", - 編碼: "[心齊]= [影尤]= [穿江]= [穿魚]= \ +pub const 近古汉语练习题: &[练习题] = &[ + 练习题 { + 标题: "隰有萇楚 近古汉语 《中原音韻》音系", + 编码: "[心齊]= [影尤]= [穿江]= [穿魚]= \ [影齊]= [泥歌]= [溪齊]= [照支]= \ [影蕭]= [照支]= [影魚]= [影魚]= \ [影蕭]= [精支]= [照支]= [微魚]=<ʋu²> [照齊]= \ @@ -86,16 +93,18 @@ pub const 近古漢語練習題: &[練習題] = &[練習題 { [影齊]= [泥歌]= [溪齊]= [審齊]=<ʂi²> \ [影蕭]= [照支]= [影魚]= [影魚]= \ [影蕭]= [精支]= [照支]= [微魚]=<ʋu²> [審齊]=<ʂi³>", - 字幕: 詞句( - "隰有萇楚 猗儺其枝 夭之沃沃 樂子之無知 \ + 字幕: 词句( + "隰有萇楚 猗儺其枝 夭之沃沃 樂子之無知 \ 隰有萇楚 猗儺其華 夭之沃沃 樂子之無家 \ - 隰有萇楚 猗儺其實 夭之沃沃 樂子之無室", - ), -}]; + 隰有萇楚 猗儺其實 夭之沃沃 樂子之無室" + ), + }, +]; -pub const 現代漢語練習題: &[練習題] = &[練習題 { - 標題: "隰有萇楚 現代漢語 普通話", - 編碼: "[曉齊]=<ɕi²> [影侯齊]= [穿唐]= [穿模]= \ +pub const 现代汉语练习题: &[练习题] = &[ + 练习题 { + 标题: "隰有萇楚 现代汉语 普通話", + 编码: "[曉齊]=<ɕi²> [影侯齊]= [穿唐]= [穿模]= \ [影齊]= [泥波合]= [溪齊]= [照支]= \ [影豪齊]= [照支]= [影波合]= [影波合]= \ [影豪齊]= [精支]= [照支]= [影模]= [照支]= \ @@ -109,9 +118,10 @@ pub const 現代漢語練習題: &[練習題] = &[練習題 { [影齊]= [泥波合]= [溪齊]= [審支]=<ʂʅ²> \ [影豪齊]= [照支]= [影波合]= [影波合]= \ [影豪齊]= [精支]= [照支]= [影模]= [審支]=<ʂʅ⁴>", - 字幕: 詞句( - "隰有萇楚 猗儺其枝 夭之沃沃 樂子之無知 \ + 字幕: 词句( + "隰有萇楚 猗儺其枝 夭之沃沃 樂子之無知 \ 隰有萇楚 猗儺其華 夭之沃沃 樂子之無家 \ - 隰有萇楚 猗儺其實 夭之沃沃 樂子之無室", - ), -}]; + 隰有萇楚 猗儺其實 夭之沃沃 樂子之無室" + ), + }, +]; diff --git a/src/drill/cantonese.rs b/src/drill/cantonese.rs index eed16ee..89bb975 100644 --- a/src/drill/cantonese.rs +++ b/src/drill/cantonese.rs @@ -1,9 +1,10 @@ -use super::練習題; -use crate::gear::caption::字幕格式::詞句; +use super::练习题; +use crate::gear::caption::字幕格式::词句; -pub const 粵語練習題: &[練習題] = &[練習題 { - 標題: "林峯-出鞘", - 編碼: "[清東]= [以先]= [心威]= [見翻]= \ +pub const 粤语练习题: &[练习题] = &[ + 练习题 { + 标题: "林峯-出鞘", + 编码: "[清東]= [以先]= [心威]= [見翻]= \ [明高]= [滂畢]= [曉高]= [幫英]= [曉幾]= \ [以畢]= [非發]= [精朝]= \ [非篤]= [以諸]= [見英]= [透先]= [端幾]= \ @@ -66,8 +67,8 @@ pub const 粵語練習題: &[練習題] = &[練習題 { [幫畢]= [以賓]= [心遮]= [曉幾]= \ [曉東]= [我翻]= [見修]= [明東]= [非家]= [幫畢]= [精津]= \ [見兼]= [精栽]= [非幾]=", - 字幕: 詞句( - "重現世間無匹好兵器 一發招 覆雨驚天地 \ + 字幕: 词句( + "重現世間無匹好兵器 一發招 覆雨驚天地 \ 情和義 不忍捨棄 浮雲共暴雨洶湧 變幻起 \ 縱是渴望逍遙走我路 拋去稀世的劍譜 \ 要逐我夢竟令天震怒 代價太高 \ @@ -82,13 +83,15 @@ pub const 粵語練習題: &[練習題] = &[練習題 { 重現世間無匹好兵器 一發招 覆雨驚天地 \ 情和義 不忍捨棄 仇人爲甚變知己 \ 重現世間無匹好兵器 一發招 覆雨驚天地 \ - 情和義 不忍捨棄 紅顏舊夢化不盡劍在飛", - ), -}]; + 情和義 不忍捨棄 紅顏舊夢化不盡劍在飛" + ), + }, +]; -pub const 宮保粵拼練習題: &[練習題] = &[練習題 { - 標題: "林峯-出鞘", - 編碼: "cung jin sai gaan mou pat hou bing hei \ +pub const 宫保粤拼练习题: &[练习题] = &[ + 练习题 { + 标题: "林峯-出鞘", + 编码: "cung jin sai gaan mou pat hou bing hei \ jat faat ziu \ fuk jyu ging tin dei \ cing wo ji \ @@ -136,8 +139,8 @@ pub const 宮保粵拼練習題: &[練習題] = &[練習題 { cing wo ji \ bat jan se hei \ hung ngaan gau mung faa bat zeon gim zoi fei", - 字幕: 詞句( - "重現世間無匹好兵器 一發招 覆雨驚天地 \ + 字幕: 词句( + "重現世間無匹好兵器 一發招 覆雨驚天地 \ 情和義 不忍捨棄 浮雲共暴雨洶湧 變幻起 \ 縱是渴望逍遙走我路 拋去稀世的劍譜 \ 要逐我夢竟令天震怒 代價太高 \ @@ -152,6 +155,7 @@ pub const 宮保粵拼練習題: &[練習題] = &[練習題 { 重現世間無匹好兵器 一發招 覆雨驚天地 \ 情和義 不忍捨棄 仇人爲甚變知己 \ 重現世間無匹好兵器 一發招 覆雨驚天地 \ - 情和義 不忍捨棄 紅顏舊夢化不盡劍在飛", - ), -}]; + 情和義 不忍捨棄 紅顏舊夢化不盡劍在飛" + ), + }, +]; diff --git a/src/drill/combo_pinyin.rs b/src/drill/combo_pinyin.rs index 88484f6..a6850bc 100644 --- a/src/drill/combo_pinyin.rs +++ b/src/drill/combo_pinyin.rs @@ -1,27 +1,24 @@ -use super::練習題; -use crate::gear::caption::{ - 字幕格式::{段落, 詞句}, - 字幕步進::逐詞, -}; +use super::练习题; +use crate::gear::caption::{ 字幕格式::{ 段落, 词句 }, 字幕步进::逐词 }; -pub const 宮保拼音練習題: &[練習題] = &[ - 練習題 { - 標題: "中州韻輸入法引擎", - 編碼: "zhong zhou yun shu ru fa yin qing \ +pub const 宫保拼音练习题: &[练习题] = &[ + 练习题 { + 标题: "中州韻輸入法引擎", + 编码: "zhong zhou yun shu ru fa yin qing \ si xiang yong jian pan biao da ye xing", - 字幕: 詞句("中州韻輸入法引擎 思想用鍵盤表達也行"), + 字幕: 词句("中州韻輸入法引擎 思想用鍵盤表達也行"), }, - 練習題 { - 標題: "東風破早梅", - 編碼: "dong feng po zao mei \ + 练习题 { + 标题: "東風破早梅", + 编码: "dong feng po zao mei \ xiang nuan yi zhi kai \ bing xue wu ren jian \ chun cong tian shang lai", - 字幕: 詞句("東風破早梅 向暖一枝開 冰雪無人見 春從天上來"), + 字幕: 词句("東風破早梅 向暖一枝開 冰雪無人見 春從天上來"), }, - 練習題 { - 標題: "聲母韻母練習", - 編碼: "b p m f d t n l \ + 练习题 { + 标题: "聲母韻母練習", + 编码: "b p m f d t n l \ g k h j q x \ zh ch sh r z c s \ i u ü \ @@ -29,33 +26,37 @@ pub const 宮保拼音練習題: &[練習題] = &[ ai uai ei uei ao iao ou iou \ an ian uan üan en in uen ün \ ang iang uang eng ing ueng ong iong", - 字幕: 段落(逐詞, - "b p m f d t n l + 字幕: 段落( + 逐词, + "b p m f d t n l g k h j q x zh ch sh r z c s i u ü a ia ua o uo e ie üe er ai uai ei uei ao iao ou iou an ian uan üan en in uen ün - ang iang uang eng ing ueng ong iong"), + ang iang uang eng ing ueng ong iong" + ), }, - 練習題 { - 標題: "音節練習", - 編碼: "bu pu fu me \ + 练习题 { + 标题: "音節練習", + 编码: "bu pu fu me \ de te le ne \ ge ke he \ zhi chi shi ri zi ci si \ er AE=<'a> A=<␣>", - 字幕: 段落(逐詞, - "bu pu fu me + 字幕: 段落( + 逐词, + "bu pu fu me de te le ne ge ke he zhi chi shi ri zi ci si - er 'a ␣"), + er 'a ␣" + ), }, - 練習題 { - 標題: "單字練習", - 編碼: "yi er san si wu liu qi ba jiu shi \ + 练习题 { + 标题: "單字練習", + 编码: "yi er san si wu liu qi ba jiu shi \ ren kou shou shang zhong xia ri yue shui huo shan shi tian tu \ mu he mi zhu dao gong che zhou qian hou zuo you er mu she ya \ tou zu zuo li zou chi cun yuan jiao fen \ @@ -63,29 +64,33 @@ pub const 宮保拼音練習題: &[練習題] = &[ niao chong yu zhua zi wei ba kai men guan chu ru lai qu \ fang xiang dong nan xi bei bai tian hei ye yun dian feng yu \ fu qin mu er nü ba ma", - 字幕: 詞句("一二三四五 六七八九十 \ + 字幕: 词句( + "一二三四五 六七八九十 \ 人口手 上中下 日月水火 山石田土 \ 木禾米竹 刀弓車舟 前後左右 耳目舌牙 \ 頭足坐立走 尺寸元角分 \ 大小多少斤兩 馬牛羊毛皮 \ 鳥蟲魚爪子尾巴 開門關出入來去 \ 方向東南西北 白天黑夜雲電風雨 \ - 父親母兒女爸媽"), + 父親母兒女爸媽" + ), }, - 練習題 { - 標題: "綜合練習一", - 編碼: "yang'wang'xing'kong yan'jiu'jue'ding \ + 练习题 { + 标题: "綜合練習一", + 编码: "yang'wang'xing'kong yan'jiu'jue'ding \ zi'ran'xuan'ze che'di'jue'lie \ bu'duan'fa'zhan ren'min'qun'zhong \ zhu'yi'an'quan huan'yuan'fan'ying \ sheng'ming'cai'chan shao'xiao'jun'xian \ yuan'lai'ru'ci hou'yan'wu'chi", - 字幕: 詞句("仰望星空 研究決定 自然選擇 徹底決裂 不斷發展 人民羣衆 \ - 注意安全 還原反應 生命財產 少校軍銜 原來如此 厚顏無恥"), + 字幕: 词句( + "仰望星空 研究決定 自然選擇 徹底決裂 不斷發展 人民羣衆 \ + 注意安全 還原反應 生命財產 少校軍銜 原來如此 厚顏無恥" + ), }, - 練習題 { - 標題: "綜合練習二", - 編碼: "wan'sui jie'jue guo'cheng quan'xuan tiao'jian yuan'yin sheng'chan'xian \ + 练习题 { + 标题: "綜合練習二", + 编码: "wan'sui jie'jue guo'cheng quan'xuan tiao'jian yuan'yin sheng'chan'xian \ tu'di nu'li he'ge qi'ji tu'chu tu'shu wan'quan yuan'yan wan'yan yan'yuan \ zhi'chi fu'chi fu'zhi fu'shi si'shi shi'si si'shi'si \ wu'yi yi'wu yu'yi yi'yu wu'yu yu'wu wu'wu yi'yi yu'yu \ @@ -94,7 +99,8 @@ pub const 宮保拼音練習題: &[練習題] = &[ tang'lang yuan'yang yong'yuan yong'you yuan'you yuan'wen wei'wen wen'zhang wen'dang \ lun'wen nian'lun yan'lun duan'dian duan'lian zhuan'huan chuan'huan lun'huan \ guan'jun guan'li'yuan chuan'yuan zhan'zhuan shan'chuan zhan'chuan", - 字幕: 詞句("萬歲 解決 過程 全選 條件 原因 生產綫 \ + 字幕: 词句( + "萬歲 解決 過程 全選 條件 原因 生產綫 \ 土地 努力 合格 奇跡 突出 圖書 完全 怨言 晚宴 演員 \ 支持 扶持 複製 服飾 四十 十四 四十四 \ 無疑 義務 雨衣 易於 無語 雨霧 無誤 意義 遇雨 \ @@ -102,11 +108,12 @@ pub const 宮保拼音練習題: &[練習題] = &[ 方丈 長廊 商行 滄桑 喪葬 幫忙 浪蕩 嚷嚷 \ 螳螂 鴛鴦 永遠 擁有 原有 原文 慰問 文章 文檔 \ 論文 年輪 言論 斷電 鍛鍊 轉換 傳喚 輪換 \ - 冠軍 管理員 船員 輾轉 山川 戰船"), + 冠軍 管理員 船員 輾轉 山川 戰船" + ), }, - 練習題 { - 標題: "綜合練習三", - 編碼: "jing'xing gong'jing jiong'jing hong'xing jing'kong kong'jing qiong'kong qiong'kun \ + 练习题 { + 标题: "綜合練習三", + 编码: "jing'xing gong'jing jiong'jing hong'xing jing'kong kong'jing qiong'kong qiong'kun \ wang'jing guang'jing kuang'jing kuang'wang qiang'guang qiang'jiang qiang'xiang \ yang'xiang yang'qiang xiang'xiang bei'jing bei'ying bei'qing fei'xing \ bei'fang bei'yang bei'fei fei'fan fei'chang fei'fu hui'fei hui'yi xue'hui \ @@ -115,7 +122,8 @@ pub const 宮保拼音練習題: &[練習題] = &[ qu'ju qu'qu qu'yu qi'yi gu'wu gu'yi ji'yi ju'yu yu'ju yu'ji \ shuo'guo zhong'guo zui'duo huo'zhe ge'jiu'ge'wei yue'lai'yue \ wei'shen'me zen'me'yang ke'bu'ke'yi you'mei'you", - 字幕: 詞句("驚醒 恭敬 窘境 紅杏 驚恐 孔徑 穹空 窮困 \ + 字幕: 词句( + "驚醒 恭敬 窘境 紅杏 驚恐 孔徑 穹空 窮困 \ 網警 光景 礦井 狂妄 強光 強將 強項 \ 洋相 洋槍 想象 北京 背影 悲情 飛行 \ 北方 北洋 北非 非凡 非常 肺腑 會飛 會議 學會 \ @@ -123,20 +131,23 @@ pub const 宮保拼音練習題: &[練習題] = &[ 惡意 訛誤 俄語 飢餓 企鵝 襲擊 稀奇 七夕 習武 思緒 次序 自詡 \ 屈居 區區 區域 起義 鼓舞 故意 記憶 局域 語句 預計 \ 說過 中國 最多 或者 各就各位 越來越 \ - 爲什麼 怎麼樣 可不可以 有沒有"), + 爲什麼 怎麼樣 可不可以 有沒有" + ), }, - 練習題 { - 標題: "縮略碼示例", - 編碼: "SHG= SHGUA= ZUAO= \ + 练习题 { + 标题: "縮略碼示例", + 编码: "SHG= SHGUA= ZUAO= \ FBUR= ZFB= BUA= SHGU= SGIAN= \ xian wen SHB= zai wen FBUR=", - 字幕: 詞句("[什麼] [輸入法] [最好] \ + 字幕: 词句( + "[什麼] [輸入法] [最好] \ [爲什麼] [沒有] [辦法] [輸入] [時間] \ - 先問[是不是] 再問[爲什麼]"), + 先問[是不是] 再問[爲什麼]" + ), }, - 練習題 { - 標題: "宮保拼音並擊術", - 編碼: "gong bao pin yin bing ji shu \ + 练习题 { + 标题: "宮保拼音並擊術", + 编码: "gong bao pin yin bing ji shu \ zie zou ming kuai you zhi guan \ yi ji yi ge zhong wen zi \ neng fen ping qiao yu zian tuan \ @@ -144,14 +155,16 @@ pub const 宮保拼音練習題: &[練習題] = &[ liu jian wu chong cii zhi chan \ su ji cian zong gui jian yi \ yin yun wan bian lie qin pan", - 字幕: 詞句("宮保拼音並擊術 節奏明快又直觀 \ + 字幕: 词句( + "宮保拼音並擊術 節奏明快又直觀 \ 一擊一個中文字 能分平翹與尖團 \ 標準設備廣兼容 六鍵無衝七指禪 \ - 速記千宗歸簡易 音韻萬變列琴盤"), + 速記千宗歸簡易 音韻萬變列琴盤" + ), }, - 練習題 { - 標題: "倉頡轉世賦", - 編碼: "cang jie gong zhuan shi \ + 练习题 { + 标题: "倉頡轉世賦", + 编码: "cang jie gong zhuan shi \ qiao ziang chu he yin \ zhong zhou yun qi yan shi fan pin \ da dao zhi jian yi xuan ao gao shen \ @@ -164,16 +177,18 @@ pub const 宮保拼音練習題: &[練習題] = &[ nan yu jiang ming liao sin li zhen hua \ ji cing bian ma yong cian wan ci qiao da \ xue hui si siang zai jian pan shang biao da", - 字幕: 詞句("蒼頡公轉世 巧匠出河陰 中州韻豈言是凡品 \ + 字幕: 词句( + "蒼頡公轉世 巧匠出河陰 中州韻豈言是凡品 \ 大道至簡亦玄奧高深 運用妙法存乎一心 \ 縱情漁獵字海詞林 會不會某天穿越古今 \ 口中言語是華夏正音 我怎肯將主流放任 \ 苦執一念終不得瀟灑 難於講明了心裏真話 \ - 寄情編碼用千萬次敲打 學會思想在鍵盤上表達"), + 寄情編碼用千萬次敲打 學會思想在鍵盤上表達" + ), }, - 練習題 { - 標題: "中州韻", - 編碼: "hui hao ji jian shu tu tong gui \ + 练习题 { + 标题: "中州韻", + 编码: "hui hao ji jian shu tu tong gui \ wen zi zing miao ji qiao sheng hui \ shu fa cheng shi bu dao chen gui \ jin yin gu yun yan yi lui tui \ @@ -181,14 +196,16 @@ pub const 宮保拼音練習題: &[練習題] = &[ die dai han shu da zao shen qi \ dai ma bu ji zhi ling sii li \ kai bi yuan xi si liu yong ji", - 字幕: 詞句("揮毫擊鍵 殊途同歸 文字精妙 機巧生輝 \ + 字幕: 词句( + "揮毫擊鍵 殊途同歸 文字精妙 機巧生輝 \ 書法程式 不蹈陳規 今音古韻 演繹類推 \ 寄思中土 心懷主義 迭代寒暑 打造神器 \ - 代碼不羈 指令犀利 開彼源兮 斯流永繼"), + 代碼不羈 指令犀利 開彼源兮 斯流永繼" + ), }, - 練習題 { - 標題: "鼠鬚管", - 編碼: "zhuo jun yi jing zhou yu zhen zhi ziao \ + 练习题 { + 标题: "鼠鬚管", + 编码: "zhuo jun yi jing zhou yu zhen zhi ziao \ zeng jun yi süan cheng shu sü zhi guan \ ziu ru chang hong yin cang hai \ bi ruo zün ma chi ping ban \ @@ -202,12 +219,14 @@ pub const 宮保拼音練習題: &[練習題] = &[ wei wu sui wei cing bu cian \ sin shi zui mo shi yi hui \ bie hou ji wo wu ci yuan", - 字幕: 詞句("酌君以荊州魚枕之蕉 贈君以宣城䑕須之管 \ + 字幕: 词句( + "酌君以荊州魚枕之蕉 贈君以宣城䑕須之管 \ 酒如長虹飲滄海 筆若駿馬馳平坂 \ 愛君尚少力方豪 嗟我久衰歡漸鮮 \ 文章驚世知名早 意氣論交相得晚 \ 魚枕蕉 一舉十分當覆盞 \ 䑕須管 為物雖㣲情不淺 \ - 新詩醉墨時一揮 別後寄我無辭逺"), + 新詩醉墨時一揮 別後寄我無辭逺" + ), }, ]; diff --git a/src/drill/double_pinyin_fly.rs b/src/drill/double_pinyin_fly.rs new file mode 100644 index 0000000..41a0089 --- /dev/null +++ b/src/drill/double_pinyin_fly.rs @@ -0,0 +1,79 @@ +use super::练习题; +use crate::gear::caption::{ + 字幕格式::{段落, 词句}, + 字幕步进::逐字, +}; + +pub const 小鹤双拼练习题: &[练习题] = &[ + 练习题 { + 标题: "聪明的输入法懂我心意", + 编码: "cong ming de shu ru fa dong wo xin yi", + 字幕: 词句("聪明的输入法懂我心意"), + }, + 练习题 { + 标题: "出师表", + 编码: "xian di chuang ye wei ban er zhong dao beng cu \ + jin tian xia san fen yi zhou pi bi ci cheng wei ji cun wang zhi qiu ye \ + ran shi wei zhi chen bu xie yu nei zhong zhi zhi shi wang shen yu wai zhe \ + gai zhui xian di zhi yu yu bao zhi yu xia ye \ + cheng yi kai sheng ting yi guang xian di yi de hui hong zhi shi chen \ + bu yi wang zi fei bo yin yu shi yi yi sai zhong jian zhi lu ye \ + gong zhong fu zhong ju wei yi ti zang fa zang fou bu yi yi tong \ + shi you zuo jian ji ling zhong zhe xing zhong yan you si ji qi xing lun qi xing shang \ + zuo zhong bu xing bu zhi yi zhi zhong jian zhi que lou you suo guang yi \ + shi shi shi chu zhi chen xing xing su su bu chi yu dang shi zhe \ + jie liang zhong zhi chen ye yuan bi xia qin zhi xin zhi ze han shi zhi long ke ji ri er dai ye \ + chen ben bu yi gong geng yu nan yang \ + gou quan xing ming yu luan shi bu qiu wen da zhu hou \ + xian di bu yi chen bei biie wang zi qu qu zhi \ + san gu chen yu cao lu zhi zhong zi chen yi dang shi zhi shi \ + you shi gan ji sui xu xian di qu chi hou jin zhen fu dao yuan \ + hou zhi jun ju er dao ling bing zhan wei jue xian ming bu xiao \ + jin tian xia ding yi yi zhou pi bi ci cheng wei ji cun wang zhi qiu ye \ + ran shi wei zhi chen bu xie yu nei zhong zhi zhi shi wang shen yu wai zhe \ + gai zhui xian di zhi yu yu bao zhi yu xia ye \ + cheng yi kai sheng ting yi guang xian di yi de hui hong zhi shi chen \ + bu yi wang zi fei bo yin yu shi yi yi sai zhong jian zhi lu ye \ + gong zhong fu zhong ju wei yi ti zang fa zang fou bu yi yi tong \ + shi you zuo jian ji ling zhong zhe xing zhong yan you si ji qi xing lun qi xing shang \ + zuo zhong bu xing bu zhi yi zhi zhong jian zhi que lou you suo guang yi \ + shi shi shi chu zhi chen xing xing su su bu chi yu dang shi zhe \ + jie liang zhong zhi chen ye yuan bi xia qin zhi xin zhi ze han shi zhi long ke ji ri er dai ye \ + chen ben bu yi gong geng yu nan yang \ + gou quan xing ming yu luan shi bu qiu wen da zhu hou \ + xian di bu yi chen bei biie wang zi qu qu zhi \ + san gu chen yu cao lu zhi zhong zi chen yi dang shi zhi shi \ + you shi gan ji sui xu xian di qu chi hou jin zhen fu dao yuan \ + hou zhi jun ju er dao ling bing zhan wei jue xian ming bu xiao \ + jin dang yuan li zhi bing fa zui qiang chu ming bu xiao er ren yong zhi \ + shi wei zhi chen qu ci zhi chen ye zhi bi xia shen zhi yi \ + yi zhi ming chui zhuo que shi bu xiao ze ming zhi chen zhi zui ye \ + qin bi xia tuo chen yi tao zei xing fu xiao xiao zhi guo yi zhao ping ming \ + chen bu sheng shou en gan ji jin dang yuan li lin biao ti ling bu zhi suo yan", + 字幕: 段落(逐字, "先帝创业未半而中道崩殂 今天下三分 益州疲弊 此诚危急存亡之秋也 + 然侍卫之臣不懈于内 忠志之士忘身于外者 盖追先帝之遇欲报之于陛下也 + 诚宜开张圣听 以光先帝遗德 恢弘志士之气 不宜妄自菲薄 引喻失义 以塞忠谏之路也 + 宫中府中俱为一体 陟罚臧否不宜异同 + 若有作奸犯科及为忠善者 宜付有司论其刑赏 以昭陛下平明之治 + 不宜偏私 使内外异法也 + 侍中侍郎郭攸之费祎董允等 此皆良实 志虑忠纯 是以先帝简拔以遗陛下 + 愚以为宫中之事 事无大小 悉以咨之 然后施行 必能裨补阙漏 有所广益也 + 将军向宠 性行淑均 晓畅军事 试用之于昔日 先帝称之曰能 是以众议举宠为督 + 愚以为营中之事 悉以咨之 必能使行阵和穆 优劣得所也 + 亲贤臣 远小人 此先汉所以兴隆也 亲小人 远贤臣 此后汉所以倾颓也 + 先帝在时 每与臣论此事 未尝不叹息痛恨于桓灵也 + 侍中尚书长史参军 此悉贞亮死节之臣也 愿陛下亲之信之 则汉室之隆可计日而待也 + 臣本布衣 躬耕于南阳 苟全性命于乱世 不求闻达于诸侯 + 先帝不以臣卑鄙 猥自枉屈 三顾臣于草庐之中 咨臣以当世之事 + 由是感激 遂许先帝以驱驰 后值倾覆 受任于败军之际 奉命于危难之间 + 尔来二十有一年矣 + 先帝知臣谨慎 故临崩寄臣以大事也 + 受命以来 夙夜忧叹 恐付托不效 以伤先帝之明 故五月渡泸 深入不毛 + 今南方已定 兵甲已足 当奖率三军 北定中原 庶竭驽钝 攘除奸凶 兴复汉室 还于旧都 + 此臣所以报先帝而忠陛下之职分也 至于斟酌损益 进尽忠言 则攸之祎允之任也 + 愿陛下托臣以讨贼兴复之效 不效则治臣之罪 以告先帝之灵 + 若无兴德之言 则责攸之祎允等之慢 以彰其咎 + 陛下亦宜自谋 以咨诹善道 察纳雅言 深追先帝遗诏 + 臣不胜受恩感激 今当远离 临表涕零 不知所言") + } +]; diff --git a/src/drill/mod.rs b/src/drill/mod.rs index 456be05..7838187 100644 --- a/src/drill/mod.rs +++ b/src/drill/mod.rs @@ -2,42 +2,45 @@ mod alphabet; mod ancient_chinese; mod cantonese; mod combo_pinyin; +mod double_pinyin_fly; -use alphabet::字母鍵盤練習題; +use alphabet::字母键盘练习题; use ancient_chinese::{ - 上古漢語練習題, 早期中古漢語練習題, 晚期中古漢語練習題, 現代漢語練習題, 近古漢語練習題, + 上古汉语练习题, + 早期中古汉语练习题, + 晚期中古汉语练习题, + 现代汉语练习题, + 近古汉语练习题, }; -use cantonese::{宮保粵拼練習題, 粵語練習題}; -use combo_pinyin::宮保拼音練習題; +use cantonese::{ 宫保粤拼练习题, 粤语练习题 }; +use combo_pinyin::宫保拼音练习题; +use double_pinyin_fly::小鹤双拼练习题; -use crate::gear::{caption::字幕格式, theory::方案選項}; +use crate::gear::{ caption::字幕格式, theory::方案选项 }; -pub struct 練習題<'a> { - pub 標題: &'a str, - pub 編碼: &'a str, +pub struct 练习题<'a> { + pub 标题: &'a str, + pub 编码: &'a str, pub 字幕: 字幕格式<'a>, } -const 各方案練習題組: &[(方案選項, &[練習題])] = &[ - (方案選項::拉丁字母, 字母鍵盤練習題), - (方案選項::宮保拼音, 宮保拼音練習題), - (方案選項::上古漢語, 上古漢語練習題), - (方案選項::早期中古漢語, 早期中古漢語練習題), - (方案選項::晚期中古漢語, 晚期中古漢語練習題), - (方案選項::近古漢語, 近古漢語練習題), - (方案選項::現代漢語, 現代漢語練習題), - (方案選項::粵語, 粵語練習題), - (方案選項::宮保粵拼, 宮保粵拼練習題), +const 各方案练习题组: &[(方案选项, &[练习题])] = &[ + (方案选项::拉丁字母, 字母键盘练习题), + (方案选项::宫保拼音, 宫保拼音练习题), + (方案选项::上古汉语, 上古汉语练习题), + (方案选项::早期中古汉语, 早期中古汉语练习题), + (方案选项::晚期中古汉语, 晚期中古汉语练习题), + (方案选项::近古汉语, 近古汉语练习题), + (方案选项::现代汉语, 现代汉语练习题), + (方案选项::粤语, 粤语练习题), + (方案选项::宫保粤拼, 宫保粤拼练习题), + (方案选项::小鹤双拼, 小鹤双拼练习题), ]; -impl 方案選項 { - pub fn 配套練習題(&self) -> Option<&'static [練習題<'static>]> { - 各方案練習題組.iter().find_map(|&(方案, 練習題)| { - if 方案 == *self { - Some(練習題) - } else { - None - } +impl 方案选项 { + pub fn 配套练习题(&self) -> Option<&'static [练习题<'static>]> { + 各方案练习题组.iter().find_map(|&(方案, 练习题)| { + if 方案 == *self { Some(练习题) } else { None } }) } } diff --git a/src/engine.rs b/src/engine.rs index c776b34..7edd98c 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1,277 +1,270 @@ use leptos::logging::log; use leptos::prelude::*; -use crate::action::動作; -use crate::definition::觸鍵方式; +use crate::action::动作; +use crate::definition::击键方式; use crate::gear::{ - assignment::{作業, 作業機關, 作業機關輸出信號, 步進法}, - caption::{字幕機關, 字幕機關輸出信號, 字幕段落}, - chord::{並擊機關, 並擊機關輸出信號}, - input::{焦點事件處理機關, 觸鍵消息, 輸入事件處理機關}, - key_press::{連擊機關, 連擊機關輸出信號}, - layout::{配列機關, 配列機關輸出信號}, - mode::{工作模式, 工作模式機關, 工作模式機關輸出信號}, - theory::{輸入方案機關, 輸入方案機關輸出信號}, + assignment::{ 作业模式输出信号, 作业, 作业模式, 步进设置 }, + caption::{ 字幕机关, 字幕机关输出信号, 字幕段落 }, + chord::{ 并击模式, 并击模式输出信号 }, + input::{ 焦点事件处理机关, 击键消息, 输入事件处理机关 }, + key_press::{ 连击模式输出信号, 连击机关 }, + layout::{ 配列机关, 键盘配列输出信号 }, + mode::{ 工作模式, 工作模式机关, 工作模式输出信号 }, + theory::{ 输入方案, 输入方案输出信号 }, }; use crate::key_code::KeyCode; #[derive(Clone)] -pub struct 微觀引擎輸出信號 { - pub 方案: 輸入方案機關輸出信號, - pub 模式: 工作模式機關輸出信號, - pub 配列: 配列機關輸出信號, - pub 作業: 作業機關輸出信號, - pub 字幕: 字幕機關輸出信號, - pub 連擊: 連擊機關輸出信號, - pub 並擊: 並擊機關輸出信號, +pub struct 微观引擎输出信号 { + pub 方案: 输入方案输出信号, + pub 模式: 工作模式输出信号, + pub 键盘配列: 键盘配列输出信号, + pub 作业: 作业模式输出信号, + pub 字幕: 字幕机关输出信号, + pub 连击: 连击模式输出信号, + pub 并击: 并击模式输出信号, } -pub fn 微觀引擎() -> 微觀引擎輸出信號 { - let 方案 = 輸入方案機關(); - let 配列 = 配列機關(&方案); - let 作業 = 作業機關(&方案); - let 字幕 = 字幕機關(&方案, &作業); - let 連擊 = 連擊機關(&方案, &作業); - let 並擊 = 並擊機關(&方案, &作業); +pub fn 微观引擎() -> 微观引擎输出信号 { + let 方案 = 输入方案(); + let 键盘配列 = 配列机关(&方案); + let 作业 = 作业模式(&方案); + let 字幕 = 字幕机关(&方案, &作业); + let 连击 = 连击机关(&方案, &作业); + let 并击 = 并击模式(&方案, &作业); - let 輸入方案機關輸出信號 { - 現行方案, 指法, - .. - } = 方案; - let 作業機關輸出信號 { - 佈置作業, - 作業進度, - 重置作業進度, - 作業進度完成, - 作業推進, - 作業回退, - 有無作業, + let 输入方案输出信号 { 当前方案, 指法, .. } = 方案; + let 作业模式输出信号 { + 布置作业, + 作业进度, + 重置作业进度, + 作业完成, + 作业推进, + 作业回退, + 有无作业, .. - } = 作業; - let 字幕機關輸出信號 { - 分段字幕, - 當前段落, - 前序段落, + } = 作业; + let 字幕机关输出信号 { 分段字幕, 当前段落, 前序段落, .. } = 字幕; + let 连击模式输出信号 { + 连击状态变更, + 连击比对成功, + 清空连击输入码, + 回退连击输入码, + 编辑连击输入码, .. - } = 字幕; - let 連擊機關輸出信號 { - 連擊狀態變更, - 連擊比對成功, - 清空連擊輸入碼, - 回退連擊輸入碼, - 編輯連擊輸入碼, - .. - } = 連擊; - let 並擊機關輸出信號 { - 並擊狀態變更, - 重置並擊狀態, - 並擊完成, - 並擊成功, - .. - } = 並擊; + } = 连击; + let 并击模式输出信号 { 并击状态变更, 重置并击状态, 并击完成, 并击成功, .. } = 并击; - let 輸入 = 輸入動作機關(&方案, &連擊, &並擊); + let 输入 = 输入动作机关(&方案, &连击, &并击); - let 模式 = 工作模式機關(&方案, &作業, &輸入); + let 模式 = 工作模式机关(&方案, &作业, &输入); - let 輸入動作 { 重置輸入狀態 } = 輸入; + let 输入动作 { 重置输入状态 } = 输入; - let 工作模式機關輸出信號 { - 現行工作模式, - 開啓反查輸入, - 開啓練習題選單, - 開啓方案選單, - 開啓配列選單, - 關閉輸入欄, + let 工作模式输出信号 { + 现行工作模式, + 开启反查输入, + 开启练习题选单, + 开启方案选单, + 开启配列选单, + 关闭输入栏, .. } = 模式; let _ = Effect::watch( - 現行工作模式, - move |新, 舊, _| { - log!("工作模式: {:?} -> {:?}", 舊, 新); + 现行工作模式, + move |新, 旧, _| { + log!("工作模式: {:?} -> {:?}", 旧, 新); }, - false, + false ); - 焦點事件處理機關(重置並擊狀態); + 焦点事件处理机关(重置并击状态); - let 處理功能鍵 = move |觸鍵消息 { 鍵碼, 檔位 }| match 鍵碼 { - KeyCode::Escape => { - match 現行工作模式() { - 工作模式::錄入 => { - if 作業進度() != 0 { - 重置作業進度(); - 重置輸入狀態(); - } else { - 開啓練習題選單(); + let 处理功能键 = move |击键消息 { 键码, 档位 }| { + match 键码 { + KeyCode::Escape => { + match 现行工作模式() { + 工作模式::录入 => { + if 作业进度() != 0 { + 重置作业进度(); + 重置输入状态(); + } else { + 开启练习题选单(); + } } + _ => 关闭输入栏(), } - _ => 關閉輸入欄(), + true } - true - } - KeyCode::Tab => { - match 現行工作模式() { - 工作模式::錄入 => { - let 跳轉結果 = if 檔位.shift { - let 目標 = 前序段落() - .or_else(|| 分段字幕.with(|衆段落| 衆段落.last().cloned())) - .map(|字幕段落(起, _, _)| 起); - 作業回退(步進法 { - 目標, 迴轉: true - }) - } else { - let 目標 = 當前段落().map(|字幕段落(_, 止, _)| 止); - 作業推進(步進法 { - 目標, 迴轉: true - }) - }; - if 跳轉結果.is_ok() { - 重置輸入狀態(); + KeyCode::Tab => { + match 现行工作模式() { + 工作模式::录入 => { + let 跳转结果 = if 档位.shift { + let 目标 = 前序段落() + .or_else(|| 分段字幕.with(|众段落| 众段落.last().cloned())) + .map(|字幕段落(起, _, _)| 起); + 作业回退(步进设置 { + 目标, + 循环: true, + }) + } else { + let 目标 = 当前段落().map(|字幕段落(_, 止, _)| 止); + 作业推进(步进设置 { + 目标, + 循环: true, + }) + }; + if 跳转结果.is_ok() { + 重置输入状态(); + } + } + 工作模式::选取练习题 => { + 开启方案选单(); + } + 工作模式::选择输入方案 => { + 开启配列选单(); + } + 工作模式::选择配列 => { + 开启练习题选单(); + } + _ => { + 关闭输入栏(); } } - 工作模式::選取練習題 => { - 開啓方案選單(); - } - 工作模式::選擇輸入方案 => { - 開啓配列選單(); - } - 工作模式::選擇配列 => { - 開啓練習題選單(); - } - _ => { - 關閉輸入欄(); - } + true } - true - } - KeyCode::Backspace => { - if 現行工作模式() == 工作模式::錄入 { - match 指法() { - 觸鍵方式::連擊 => { - if 有無作業() { - let _不看結果 = 作業回退(步進法::default()); + KeyCode::Backspace => { + if 现行工作模式() == 工作模式::录入 { + match 指法() { + 击键方式::连击 => { + if 有无作业() { + let _不看结果 = 作业回退(步进设置::default()); + } + 回退连击输入码(); } - 回退連擊輸入碼(); - } - 觸鍵方式::並擊 => { - if 並擊完成() || 作業回退(步進法::default()).is_ok() { - 重置並擊狀態(); + 击键方式::并击 => { + if 并击完成() || 作业回退(步进设置::default()).is_ok() { + 重置并击状态(); + } } } + return true; } - return true; + false } - false - } - KeyCode::Enter => { - if 現行工作模式() == 工作模式::錄入 { - 開啓反查輸入(); - } else { - 關閉輸入欄(); + KeyCode::Enter => { + if 现行工作模式() == 工作模式::录入 { + 开启反查输入(); + } else { + 关闭输入栏(); + } + true } - true - } - KeyCode::Grave => { - match 現行工作模式() { - 工作模式::選擇輸入方案 => 關閉輸入欄(), - _ => 開啓方案選單(), + KeyCode::Grave => { + match 现行工作模式() { + 工作模式::选择输入方案 => 关闭输入栏(), + _ => 开启方案选单(), + } + true } - true + _ => false, } - _ => false, }; - let 擊中目標 = move || match 指法() { - 觸鍵方式::連擊 => 連擊比對成功(), - 觸鍵方式::並擊 => 並擊完成() && 並擊成功(), + let 击中目标 = move || { + match 指法() { + 击键方式::连击 => 连击比对成功(), + 击键方式::并击 => 并击完成() && 并击成功(), + } }; - let 批閱作業 = move || { - // 擊中目標輸入碼後反查下一個輸入碼 - let 分段落則迴轉 = 步進法 { - 目標: None, - 迴轉: 分段字幕.read().len() > 1, + let 批阅作业 = move || { + // 击中目标输入码后反查下一个输入码 + let 分段落则回转 = 步进设置 { + 目标: None, + 循环: 分段字幕.read().len() > 1, }; - 擊中目標() && 作業推進(分段落則迴轉).is_ok() + 击中目标() && 作业推进(分段落则回转).is_ok() }; let 另起一段 = move || { - 當前段落 - .read() + 当前段落.read() .as_ref() - .is_some_and(|字幕段落(段落起始, _, _)| 作業進度.read() == *段落起始) + .is_some_and(|字幕段落(段落起始, _, _)| 作业进度.read() == *段落起始) }; - let 既然落鍵 = move |鍵碼| { - // 繼續擊鍵時消除已完成的反查作業 - if 作業進度完成() { - 佈置作業(作業::自習(現行方案())); + let 既然落键 = move |键码| { + // 继续击键时消除已完成的反查作业 + if 作业完成() { + 布置作业(作业::自习(当前方案())); } - if 現行工作模式() == 工作模式::錄入 { - 並擊狀態變更.write().落鍵(鍵碼); - if 指法() == 觸鍵方式::連擊 { - 連擊狀態變更.write().擊發(鍵碼); - 編輯連擊輸入碼(鍵碼); - if 批閱作業() && 另起一段() { - 清空連擊輸入碼(); + if 现行工作模式() == 工作模式::录入 { + 并击状态变更.write().落键(键码); + if 指法() == 击键方式::连击 { + 连击状态变更.write().击发(键码); + 编辑连击输入码(键码); + if 批阅作业() && 另起一段() { + 清空连击输入码(); } } } }; - let 既然抬鍵 = move |鍵碼| { - if 現行工作模式() == 工作模式::錄入 { - 並擊狀態變更.write().抬鍵(鍵碼); + let 既然擡键 = move |键码| { + if 现行工作模式() == 工作模式::录入 { + 并击状态变更.write().抬键(键码); } match 指法() { - 觸鍵方式::連擊 => { - // 顯示並擊動態, 抬鍵後清除並擊結果 - if 並擊完成() { - 重置並擊狀態(); + 击键方式::连击 => { + // 显示并击动态, 擡键后清除并击结果 + if 并击完成() { + 重置并击状态(); } } - 觸鍵方式::並擊 => { - // 推進到下一題時, 清除上一題的並擊結果 - // 但在最後一題完成後停下顯示結果 - if 批閱作業() && !作業進度完成() { - 重置並擊狀態(); + 击键方式::并击 => { + // 推进到下一题时, 清除上一题的并击结果 + // 但在最后一题完成后停下显示结果 + if 批阅作业() && !作业完成() { + 重置并击状态(); } } } }; - 輸入事件處理機關(處理功能鍵, 既然落鍵, 既然抬鍵); + 输入事件处理机关(处理功能键, 既然落键, 既然擡键); - 微觀引擎輸出信號 { + 微观引擎输出信号 { 方案, 模式, - 配列, - 作業, + 键盘配列, + 作业, 字幕, - 連擊, - 並擊, + 连击, + 并击, } } -pub type 輸入重置動作 = impl 動作; +pub type 输入重置动作 = impl 动作; #[derive(Clone)] -pub struct 輸入動作 { - pub 重置輸入狀態: 輸入重置動作, +pub struct 输入动作 { + pub 重置输入状态: 输入重置动作, } -#[define_opaque(輸入重置動作)] -fn 輸入動作機關( - 方案: &輸入方案機關輸出信號, - 連擊: &連擊機關輸出信號, - 並擊: &並擊機關輸出信號, -) -> 輸入動作 { +#[define_opaque(输入重置动作)] +fn 输入动作机关( + 方案: &输入方案输出信号, + 连击: &连击模式输出信号, + 并击: &并击模式输出信号 +) -> 输入动作 { let 指法 = 方案.指法; - let 清空連擊輸入碼 = 連擊.清空連擊輸入碼; - let 重置並擊狀態 = 並擊.重置並擊狀態; + let 清空连击输入码 = 连击.清空连击输入码; + let 重置并击状态 = 并击.重置并击状态; - let 重置輸入狀態 = move || match 指法() { - 觸鍵方式::連擊 => 清空連擊輸入碼(), - 觸鍵方式::並擊 => 重置並擊狀態(), + let 重置输入状态 = move || { + match 指法() { + 击键方式::连击 => 清空连击输入码(), + 击键方式::并击 => 重置并击状态(), + } }; - 輸入動作 { 重置輸入狀態 } + 输入动作 { 重置输入状态 } } diff --git a/src/gear/assignment.rs b/src/gear/assignment.rs index e670983..0fd7e62 100644 --- a/src/gear/assignment.rs +++ b/src/gear/assignment.rs @@ -4,280 +4,272 @@ use leptos::prelude::*; use std::cmp::min; use crate::action::*; -use crate::definition::{觸鍵方式, 輸入方案定義, 轉寫法定義}; -use crate::gear::{ - caption::字幕格式, - theory::{方案選項, 輸入方案機關輸出信號}, -}; -use crate::spelling_algebra::施展拼寫運算; +use crate::definition::{ 击键方式, 转写定义, 输入方案定义 }; +use crate::gear::{ caption::字幕格式, theory::{ 方案选项, 输入方案输出信号 } }; +use crate::spelling_algebra::施展拼写运算; #[derive(Clone, PartialEq)] -pub struct 作業 { - pub 科目: 方案選項, - pub 題號: Option, - pub 自訂反查碼: Option, +pub struct 作业 { + pub 科目: 方案选项, + pub 题号: Option, + pub 自定义反查码: Option, } -impl 作業 { - pub fn 練習題(科目: 方案選項, 題號: usize) -> Self { +impl 作业 { + pub fn 练习题(科目: 方案选项, 题号: usize) -> Self { Self { 科目, - 題號: Some(題號), - 自訂反查碼: None, + 题号: Some(题号), + 自定义反查码: None, } } - pub fn 自訂(科目: 方案選項, 反查碼: String) -> Self { + pub fn 自定义(科目: 方案选项, 反查码: String) -> Self { Self { 科目, - 題號: None, - 自訂反查碼: Some(反查碼), + 题号: None, + 自定义反查码: Some(反查码), } } - pub fn 自習(科目: 方案選項) -> Self { + pub fn 自习(科目: 方案选项) -> Self { Self { 科目, - 題號: None, - 自訂反查碼: None, + 题号: None, + 自定义反查码: None, } } - fn 自訂編碼(&self) -> Option<&str> { - self.自訂反查碼.as_ref().and_then(|反查碼| { - 反查碼 - .split_once("//") - .map(|(編碼, _字幕)| 編碼.trim()) - .or(Some(反查碼.as_str())) + fn 自定义编码(&self) -> Option<&str> { + self.自定义反查码.as_ref().and_then(|反查码| { + 反查码.split_once("//") + .map(|(编码, _字幕)| 编码.trim()) + .or(Some(反查码.as_str())) }) } - fn 自訂字幕(&self) -> Option<&str> { - self.自訂反查碼 + fn 自定义字幕(&self) -> Option<&str> { + self.自定义反查码 .as_ref() - .and_then(|反查碼| 反查碼.split_once("//").map(|(_編碼, 字幕)| 字幕.trim())) + .and_then(|反查码| 反查码.split_once("//").map(|(_编码, 字幕)| 字幕.trim())) } - pub fn 目標輸入碼(&self) -> Option<&str> { + pub fn 目标输入码(&self) -> Option<&str> { self.科目 - .配套練習題() - .and_then(|練習題| self.題號.and_then(|題號| 練習題.get(題號))) - .map(|題| 題.編碼) - .or(self.自訂編碼()) + .配套练习题() + .and_then(|练习题| self.题号.and_then(|题号| 练习题.get(题号))) + .map(|题目| 题目.编码) + .or(self.自定义编码()) } pub fn 字幕(&self) -> 字幕格式<'_> { self.科目 - .配套練習題() - .and_then(|練習題| self.題號.and_then(|題號| 練習題.get(題號))) - .map(|題| 題.字幕.clone()) - .or_else(|| self.自訂字幕().map(字幕格式::自訂)) - .unwrap_or(字幕格式::自動生成) + .配套练习题() + .and_then(|练习题| self.题号.and_then(|题号| 练习题.get(题号))) + .map(|题目| 题目.字幕.clone()) + .or_else(|| self.自定义字幕().map(字幕格式::自定义)) + .unwrap_or(字幕格式::自动生成) } - pub fn 是否練習題(&self) -> bool { - self.題號.is_some() + pub fn 是否练习题(&self) -> bool { + self.题号.is_some() } } #[derive(Clone, Debug, PartialEq)] -pub struct 對照輸入碼 { - pub 字根碼原文: Option, - pub 轉寫碼原文: Option, +pub struct 对照输入码 { + pub 字根码原文: Option, + pub 转写码原文: Option, } -impl 對照輸入碼 { - pub fn 反查字根碼<'a>(&'a self, 轉寫法: &轉寫法定義<'a>) -> Option { - self.字根碼原文.to_owned().or_else(|| { - self.轉寫碼原文 +impl 对照输入码 { + pub fn 反查字根码<'a>(&'a self, 转写: &转写定义<'a>) -> Option { + self.字根码原文.to_owned().or_else(|| { + self.转写码原文 .as_deref() - .filter(|轉寫碼| 轉寫法.驗證拼式(轉寫碼)) - .and_then(|轉寫碼| 轉寫法.拼式拆分爲字根碼(轉寫碼)) - .and_then(|字根碼| 施展拼寫運算(&字根碼, 轉寫法.輸入碼表示).or(Some(字根碼))) + .filter(|转写码| 转写.验证拼式(转写码)) + .and_then(|转写码| 转写.拼式拆分为字根码(转写码)) + .and_then(|字根码| 施展拼写运算(&字根码, 转写.编码预览).or(Some(字根码))) }) } - /// 用於顯示的輸入碼. 優先顯示轉寫碼. - pub fn 顯示輸入碼(&self) -> Option<&str> { - self.轉寫碼原文.as_deref().or(self.字根碼原文.as_deref()) + /// 用于显示的输入码. 优先显示转写码. + pub fn 显示输入码(&self) -> Option<&str> { + self.转写码原文.as_deref().or(self.字根码原文.as_deref()) } } #[derive(Clone, Copy, Default)] -pub struct 步進法 { - pub 目標: Option, - pub 迴轉: bool, +pub struct 步进设置 { + pub 目标: Option, + pub 循环: bool, } -pub type 重置作業進度動作 = impl 動作; -pub type 作業推進動作 = impl 動作給一參數得一結果<步進法>; -pub type 作業回退動作 = impl 動作給一參數得一結果<步進法>; +pub type 重置作业进度动作 = impl 动作; +pub type 作业推进动作 = impl 动作给一参数得一结果<步进设置>; +pub type 作业回退动作 = impl 动作给一参数得一结果<步进设置>; #[derive(Clone)] -pub struct 作業機關輸出信號 { - pub 當前作業: ReadSignal<作業>, - pub 佈置作業: WriteSignal<作業>, - pub 作業進度: ReadSignal, - pub 重置作業進度: 重置作業進度動作, - pub 目標輸入碼序列: Memo>, - pub 目標輸入碼片段: Memo>, - pub 作業推進: 作業推進動作, - pub 作業回退: 作業回退動作, - pub 有無作業: Signal, - pub 作業進度完成: Signal, +pub struct 作业模式输出信号 { + pub 当前作业: ReadSignal<作业>, + pub 布置作业: WriteSignal<作业>, + pub 作业进度: ReadSignal, + pub 重置作业进度: 重置作业进度动作, + pub 目标输入码序列: Memo>, + pub 目标输入码片段: Memo>, + pub 作业推进: 作业推进动作, + pub 作业回退: 作业回退动作, + pub 有无作业: Signal, + pub 作业完成: Signal, } -#[define_opaque(重置作業進度動作, 作業推進動作, 作業回退動作)] -pub fn 作業機關(方案: &輸入方案機關輸出信號) -> 作業機關輸出信號 { - let 現行方案 = 方案.現行方案; - let 方案定義 = 方案.方案定義; - let 初始方案 = 現行方案.get_untracked(); - let (當前作業, 佈置作業) = signal(作業::練習題(初始方案, 0)); +#[define_opaque(重置作业进度动作, 作业推进动作, 作业回退动作)] +pub fn 作业模式(方案: &输入方案输出信号) -> 作业模式输出信号 { + let 当前方案 = 方案.当前方案; + let 方案定义 = 方案.方案定义; + let 初始方案 = 当前方案.get_untracked(); + let (当前作业, 布置作业) = signal(作业::练习题(初始方案, 0)); let _ = Effect::watch( - 現行方案, + 当前方案, move |&方案, _, _| { - 佈置作業(作業::練習題(方案, 0)); + 布置作业(作业::练习题(方案, 0)); }, - false, + false ); - let (作業進度, 更新作業進度) = signal(0); + let (作业进度, 更新作业进度) = signal(0); - let 重置作業進度 = move || { - 更新作業進度(0); + let 重置作业进度 = move || { + 更新作业进度(0); }; - let 目標輸入碼序列 = Memo::new(move |_| { - 當前作業 - .read() - .目標輸入碼() - .map(|輸入碼| 解析輸入碼序列(輸入碼, &方案定義.read())) + let 目标输入码序列 = Memo::new(move |_| { + 当前作业.read() + .目标输入码() + .map(|输入码| 解析输入码序列(输入码, &方案定义.read())) .unwrap_or(Box::new([])) }); let _ = Effect::watch( - 目標輸入碼序列, - move |目標輸入碼序列, _, _| { - log!("更新了目標輸入碼: {}", 目標輸入碼序列.len()); - 重置作業進度(); + 目标输入码序列, + move |目标输入码序列, _, _| { + log!("更新了目标输入码: {}", 目标输入码序列.len()); + 重置作业进度(); }, - false, + false ); - let 目標輸入碼片段 = Memo::new(move |_| { - 目標輸入碼序列.with(|輸入碼| { - if 輸入碼.is_empty() { + let 目标输入码片段 = Memo::new(move |_| { + 目标输入码序列.with(|输入码| { + if 输入码.is_empty() { None } else { - 輸入碼.get(min(作業進度(), 輸入碼.len() - 1)).cloned() + 输入码.get(min(作业进度(), 输入码.len() - 1)).cloned() } }) }); - let 作業推進 = move |步進: 步進法| { - let 當前進度 = 作業進度(); - let 全文長度 = 目標輸入碼序列.read().len(); - let 目標進度 = 步進.目標.unwrap_or(當前進度 + 1); - if 步進.迴轉 && 目標進度 >= 全文長度 { - 重置作業進度(); + let 作业推进 = move |步进: 步进设置| { + let 当前进度 = 作业进度(); + let 全文长度 = 目标输入码序列.read().len(); + let 目标进度 = 步进.目标.unwrap_or(当前进度 + 1); + if 步进.循环 && 目标进度 >= 全文长度 { + 重置作业进度(); Ok(()) - } - // 非迴轉態可推進至全文結束位置 - else if 目標進度 <= 全文長度 { - 更新作業進度(目標進度); + } else if + // 非循环状态可推进至全文结束位置 + 目标进度 <= 全文长度 + { + 更新作业进度(目标进度); Ok(()) } else { Err(未有()) } }; - let 作業回退 = move |步進: 步進法| { - let 當前進度 = 作業進度(); - let 全文長度 = 目標輸入碼序列.read().len(); - match 步進.目標 { - Some(目標進度) if 步進.迴轉 || 當前進度 > 目標進度 => { - 更新作業進度(目標進度); + let 作业回退 = move |步进: 步进设置| { + let 当前进度 = 作业进度(); + let 全文长度 = 目标输入码序列.read().len(); + match 步进.目标 { + Some(目标进度) if 步进.循环 || 当前进度 > 目标进度 => { + 更新作业进度(目标进度); Ok(()) } - None if 步進.迴轉 && 當前進度 == 0 && 全文長度 > 0 => { - 更新作業進度(全文長度 - 1); + None if 步进.循环 && 当前进度 == 0 && 全文长度 > 0 => { + 更新作业进度(全文长度 - 1); Ok(()) } - None if 當前進度 > 0 => { - 更新作業進度(當前進度 - 1); + None if 当前进度 > 0 => { + 更新作业进度(当前进度 - 1); Ok(()) } _ => Err(未有()), } }; - let 有無作業 = Signal::derive(move || 當前作業.read().目標輸入碼().is_some()); + let 有无作业 = Signal::derive(move || 当前作业.read().目标输入码().is_some()); - let 輸入碼總數 = move || 目標輸入碼序列.read().len(); + let 输入码总数 = move || 目标输入码序列.read().len(); - let 作業進度完成 = Signal::derive(move || 有無作業() && 作業進度() == 輸入碼總數()); + let 作业完成 = Signal::derive(move || 有无作业() && 作业进度() == 输入码总数()); - 作業機關輸出信號 { - 當前作業, - 佈置作業, - 作業進度, - 重置作業進度, - 目標輸入碼序列, - 目標輸入碼片段, - 作業推進, - 作業回退, - 有無作業, - 作業進度完成, + 作业模式输出信号 { + 当前作业, + 布置作业, + 作业进度, + 重置作业进度, + 目标输入码序列, + 目标输入码片段, + 作业推进, + 作业回退, + 有无作业, + 作业完成, } } -fn 解析輸入碼序列( - 輸入碼序列: &str, 方案: &輸入方案定義 -) -> Box<[對照輸入碼]> { +fn 解析输入码序列(输入码序列: &str, 方案: &输入方案定义) -> Box<[对照输入码]> { match 方案.指法 { - 觸鍵方式::連擊 => 解析連擊輸入碼序列(輸入碼序列, 方案), - 觸鍵方式::並擊 => 解析並擊輸入碼序列(輸入碼序列), + 击键方式::连击 => 解析连击输入码序列(输入码序列, 方案), + 击键方式::并击 => 解析并击输入码序列(输入码序列), } } -fn 解析連擊輸入碼序列( - 輸入碼序列: &str, 方案: &輸入方案定義 -) -> Box<[對照輸入碼]> { - 輸入碼序列 +fn 解析连击输入码序列(输入码序列: &str, 方案: &输入方案定义) -> Box<[对照输入码]> { + 输入码序列 .lines() .map(str::trim) .flat_map(|片段| 片段.chars()) .map(|字符| { - let 輸入碼原文 = 字符.to_string(); - if 方案.尋得字根(&輸入碼原文).is_some() { - 對照輸入碼 { - 字根碼原文: Some(輸入碼原文), - 轉寫碼原文: None, + let 输入码原文 = 字符.to_string(); + if 方案.寻得字根(&输入码原文).is_some() { + 对照输入码 { + 字根码原文: Some(输入码原文), + 转写码原文: None, } } else { - 對照輸入碼 { - 字根碼原文: None, - 轉寫碼原文: Some(輸入碼原文), + 对照输入码 { + 字根码原文: None, + 转写码原文: Some(输入码原文), } } }) .collect() } -/// 將並擊輸入碼序列解析爲輸入碼片段. +/// 将并击输入码序列解析为输入码片段. /// -/// 輸入碼通常是拼音音節的序列, 音節之間用空白或隔音符號 `'` 分開. -/// 特殊形式的拼音寫在尖括號中, 如: `<'a>`。 +/// 输入码通常是拼音音节的序列, 音节之间用空白或隔音符号 `'` 分开. +/// 特殊形式的拼音写在尖括号中, 如: `<'a>`。 /// -/// 輸入碼片段也可以是以下形式: +/// 输入码片段也可以是以下形式: /// -/// - 用大寫字母連書並擊碼, 如 `ZFURO` -/// - 寫明並擊碼和對應的拼音, 如 `SHGUA=shu'ru'fa` -/// - 寫明並擊碼並將對應的拼音寫在尖括號中, 如 `SHGUA=` -/// - 非大寫字母的並擊碼,寫在方括號中,如 `[端定]=<泥>` -fn 解析並擊輸入碼序列(輸入碼序列: &str) -> Box<[對照輸入碼]> { - let 輸入碼片段模式 = regex!( +/// - 用大写字母连书并击码, 如 `ZFURO` +/// - 写明并击码和对应的拼音, 如 `SHGUA=shu'ru'fa` +/// - 写明并击码并将对应的拼音写在尖括号中, 如 `SHGUA=` +/// - 非大写字母的并击码,写在方括号中,如 `[端定]=<泥>` +fn 解析并击输入码序列(输入码序列: &str) -> Box<[对照输入码]> { + let 输入码片段模式 = regex!( r"(?x) (?: (?P \p{Uppercase}+ ) | @@ -290,22 +282,22 @@ fn 解析並擊輸入碼序列(輸入碼序列: &str) -> Box<[對照輸入碼]> <(?P [^<>]* )> " ); - 輸入碼片段模式 - .captures_iter(輸入碼序列) + 输入码片段模式 + .captures_iter(输入码序列) .map(|片段| { - let 並擊碼原文 = 片段 + let 并击码原文 = 片段 .name("chord") .or_else(|| 片段.name("non_ascii_chord")) .map(|m| m.as_str().to_owned()); - let 轉寫碼原文 = 片段 + let 转写码原文 = 片段 .name("code") .or_else(|| 片段.name("quoted_code")) .or_else(|| 片段.name("eq_code")) .or_else(|| 片段.name("eq_quoted_code")) .map(|m| m.as_str().to_owned()); - 對照輸入碼 { - 字根碼原文: 並擊碼原文, - 轉寫碼原文, + 对照输入码 { + 字根码原文: 并击码原文, + 转写码原文, } }) .collect() diff --git a/src/gear/caption.rs b/src/gear/caption.rs index 48bf2e4..f2a2e9e 100644 --- a/src/gear/caption.rs +++ b/src/gear/caption.rs @@ -1,65 +1,62 @@ use leptos::prelude::*; use std::borrow::Cow; -use crate::definition::觸鍵方式; -use crate::gear::{ - assignment::{作業機關輸出信號, 對照輸入碼}, - theory::輸入方案機關輸出信號, -}; +use crate::definition::击键方式; +use crate::gear::{ assignment::{ 作业模式输出信号, 对照输入码 }, theory::输入方案输出信号 }; #[derive(Clone, Copy, PartialEq)] -pub enum 字幕步進 { +pub enum 字幕步进 { 逐字, - 逐詞, + 逐词, } -impl From<觸鍵方式> for 字幕步進 { - fn from(source: 觸鍵方式) -> Self { +impl From<击键方式> for 字幕步进 { + fn from(source: 击键方式) -> Self { match source { - 觸鍵方式::連擊 => 字幕步進::逐字, - 觸鍵方式::並擊 => 字幕步進::逐詞, + 击键方式::连击 => 字幕步进::逐字, + 击键方式::并击 => 字幕步进::逐词, } } } #[derive(Clone)] pub enum 字幕格式<'a> { - 自動生成, - 自訂(&'a str), - 詞句(&'static str), - 段落(字幕步進, &'static str), + 自动生成, + 自定义(&'a str), + 词句(&'static str), + 段落(字幕步进, &'static str), } -struct 字幕指標<'a> { +struct 字幕指标<'a> { 字幕: &'a str, - 指標: usize, + 指标: usize, } -impl<'a> From<&'a str> for 字幕指標<'a> { +impl<'a> From<&'a str> for 字幕指标<'a> { fn from(字幕: &'a str) -> Self { - Self { 字幕, 指標: 0 } + Self { 字幕, 指标: 0 } } } /// 迭代字幕中的文字. -/// 傳入的字幕應當是從空白處切分出的一段. -/// 通常一音對一字. 例外情況用文字組標記 `[]` 括住與一個音節對應的一組文字. -/// 文字組不能包含空白字符及左右方括號. -impl Iterator for 字幕指標<'_> { +/// 传入的字幕应当是从空白处切分出的一段. +/// 通常一音对一字. 例外情况用文字组标记 `[]` 括住与一个音节对应的一组文字. +/// 文字组不能包含空白字符及左右方括号. +impl Iterator for 字幕指标<'_> { type Item = String; fn next(&mut self) -> Option { - let mut 剩餘文字 = self.字幕.chars().skip(self.指標); - match 剩餘文字.next() { + let mut 剩余文字 = self.字幕.chars().skip(self.指标); + match 剩余文字.next() { Some('[') => { - // 將文字組標記 [] 中的文字串視作一個文字 - let 文字組 = 剩餘文字.take_while(|字| *字 != ']'); - self.指標 += 文字組.clone().count() + 2; - Some(文字組.collect()) + // 将文字组标记 [] 中的文字串视作一个文字 + let 文字组 = 剩余文字.take_while(|字| *字 != ']'); + self.指标 += 文字组.clone().count() + 2; + Some(文字组.collect()) } - Some(單字) => { - self.指標 += 1; - Some(單字.to_string()) + Some(单字) => { + self.指标 += 1; + Some(单字.to_string()) } None => None, } @@ -69,158 +66,152 @@ impl Iterator for 字幕指標<'_> { #[derive(Clone, PartialEq)] pub struct 字幕段落<'a>(pub usize, pub usize, pub Cow<'a, str>); -fn 標註字序<'a>(衆段落: impl Iterator>) -> Box<[字幕段落<'a>]> { +fn 标注字序<'a>(众段落: impl Iterator>) -> Box<[字幕段落<'a>]> { let 未有段落 = Box::new(vec![]); - 衆段落 - .fold((0, 未有段落), |(起, mut 已標註字序的段落), 又一段| { - let 止 = 起 + 字幕指標::from(又一段.as_ref()).count(); - (*已標註字序的段落).push(字幕段落(起, 止, 又一段)); - (止, 已標註字序的段落) - }) - .1 - .into_boxed_slice() + 众段落.fold((0, 未有段落), |(起, mut 已标注字序的段落), 又一段| { + let 止 = 起 + 字幕指标::from(又一段.as_ref()).count(); + (*已标注字序的段落).push(字幕段落(起, 止, 又一段)); + (止, 已标注字序的段落) + }).1.into_boxed_slice() } -fn 所屬段落序號(衆段落: &[字幕段落], 進度: usize) -> usize { - 衆段落.partition_point(|字幕段落(_, 段落結束, _)| *段落結束 <= 進度) +fn 所属段落序号(众段落: &[字幕段落], 进度: usize) -> usize { + 众段落.partition_point(|字幕段落(_, 段落结束, _)| *段落结束 <= 进度) } #[derive(Clone)] pub struct 字幕表示 { pub 已完成: String, - pub 指標文字: String, + pub 指标文字: String, pub 未完成: String, } #[derive(Clone, Copy)] -pub struct 字幕機關輸出信號 { +pub struct 字幕机关输出信号 { pub 分段字幕: Memo]>>, - pub 當前段落: Memo>>, + pub 当前段落: Memo>>, pub 前序段落: Signal>>, pub 段落表示: Signal>, } -pub fn 字幕機關( - 方案: &輸入方案機關輸出信號, - 作業: &作業機關輸出信號, -) -> 字幕機關輸出信號 { +pub fn 字幕机关(方案: &输入方案输出信号, 作业: &作业模式输出信号) -> 字幕机关输出信号 { let 指法 = 方案.指法; - let 當前作業 = 作業.當前作業; - let 作業進度 = 作業.作業進度; - let 目標輸入碼序列 = 作業.目標輸入碼序列; - - let 分段字幕 = Memo::new(move |_| match 當前作業.read().字幕() { - 字幕格式::自動生成 => { - let 步進 = 字幕步進::from(指法()); - 生成字幕(步進, &目標輸入碼序列.read()) - } - 字幕格式::自訂(字幕) => { - 標註字序(字幕.split_whitespace().map(String::from).map(Cow::Owned)) + let 当前作业 = 作业.当前作业; + let 作业进度 = 作业.作业进度; + let 目标输入码序列 = 作业.目标输入码序列; + + let 分段字幕 = Memo::new(move |_| { + match 当前作业.read().字幕() { + 字幕格式::自动生成 => { + let 步进 = 字幕步进::from(指法()); + 生成字幕(步进, &目标输入码序列.read()) + } + 字幕格式::自定义(字幕) => { + 标注字序(字幕.split_whitespace().map(String::from).map(Cow::Owned)) + } + 字幕格式::词句(字幕) => 标注字序(字幕.split_whitespace().map(Cow::Borrowed)), + 字幕格式::段落(字幕步进::逐字, 字幕) => + 标注字序( + 字幕 + .lines() + .map(|每一行| 每一行.split_whitespace().collect::>().join("[ ]")) + .map(Cow::Owned) + ), + 字幕格式::段落(字幕步进::逐词, 字幕) => + 标注字序( + 字幕 + .lines() + .map(|每一行| { + 每一行.split_whitespace() + .flat_map(|每个词| ["[", 每个词, " ]"]) + .collect::() + }) + .map(Cow::Owned) + ), } - 字幕格式::詞句(字幕) => 標註字序(字幕.split_whitespace().map(Cow::Borrowed)), - 字幕格式::段落(字幕步進::逐字, 字幕) => 標註字序( - 字幕 - .lines() - .map(|每一行| 每一行.split_whitespace().collect::>().join("[ ]")) - .map(Cow::Owned), - ), - 字幕格式::段落(字幕步進::逐詞, 字幕) => 標註字序( - 字幕 - .lines() - .map(|每一行| { - 每一行 - .split_whitespace() - .flat_map(|每個詞| ["[", 每個詞, " ]"]) - .collect::() - }) - .map(Cow::Owned), - ), }); - let 當前段落 = Memo::new(move |_| { - 分段字幕.with(|衆段落| { - let 全文進度 = 作業進度(); - let 當前段落號 = 所屬段落序號(衆段落, 全文進度); - 衆段落 - .get(當前段落號) + let 当前段落 = Memo::new(move |_| { + 分段字幕.with(|众段落| { + let 全文进度 = 作业进度(); + let 当前段落号 = 所属段落序号(众段落, 全文进度); + 众段落.get(当前段落号) .or_else(|| { - 衆段落 - .last() - .filter(|字幕段落(_, 全文結束, _)| *全文結束 == 全文進度) + 众段落.last().filter(|字幕段落(_, 全文结束, _)| *全文结束 == 全文进度) }) .cloned() }) }); let 前序段落 = Signal::derive(move || { - 分段字幕.with(|衆段落| { - let 全文進度 = 作業進度(); - let 當前段落號 = 所屬段落序號(衆段落, 全文進度); - if 當前段落號 == 0 { + 分段字幕.with(|众段落| { + let 全文进度 = 作业进度(); + let 当前段落号 = 所属段落序号(众段落, 全文进度); + if 当前段落号 == 0 { None } else { - 衆段落.get(當前段落號 - 1).cloned() + 众段落.get(当前段落号 - 1).cloned() } }) }); let 段落表示 = Signal::derive(move || { - 當前段落().map(|字幕段落(段落起始, _, 段落文字)| { - let 全文進度 = 作業進度(); - let 段落進度 = 全文進度 - 段落起始; - let 已完成 = 字幕指標::from(段落文字.as_ref()) - .take(段落進度) - .collect::(); - let 指標文字 = 字幕指標::from(段落文字.as_ref()) - .skip(段落進度) + 当前段落().map(|字幕段落(段落起始, _, 段落文字)| { + let 全文进度 = 作业进度(); + let 段落进度 = 全文进度 - 段落起始; + let 已完成 = 字幕指标::from(段落文字.as_ref()).take(段落进度).collect::(); + let 指标文字 = 字幕指标 + ::from(段落文字.as_ref()) + .skip(段落进度) .take(1) .collect::(); - let 未完成 = 字幕指標::from(段落文字.as_ref()) - .skip(段落進度 + 1) + let 未完成 = 字幕指标 + ::from(段落文字.as_ref()) + .skip(段落进度 + 1) .collect::(); 字幕表示 { 已完成, - 指標文字, + 指标文字, 未完成, } }) }); - 字幕機關輸出信號 { + 字幕机关输出信号 { 分段字幕, - 當前段落, + 当前段落, 前序段落, 段落表示, } } -fn 生成字幕<'a>( - 步進: 字幕步進, 輸入碼序列: &[對照輸入碼] -) -> Box<[字幕段落<'a>]> { - if 輸入碼序列.is_empty() { +fn 生成字幕<'a>(步进: 字幕步进, 输入码序列: &[对照输入码]) -> Box<[字幕段落<'a>]> { + if 输入码序列.is_empty() { Box::new([]) } else { - Box::new([字幕段落( - 0, - 輸入碼序列.len(), - Cow::Owned( - 輸入碼序列 - .iter() - .flat_map(對照輸入碼::顯示輸入碼) - .map(match 步進 { - 字幕步進::逐字 => 字幕逐字步進, - 字幕步進::逐詞 => 字幕逐詞步進, - }) - .collect::(), + Box::new([ + 字幕段落( + 0, + 输入码序列.len(), + Cow::Owned( + 输入码序列 + .iter() + .flat_map(对照输入码::显示输入码) + .map(match 步进 { + 字幕步进::逐字 => 字幕逐字步进, + 字幕步进::逐词 => 字幕逐词步进, + }) + .collect::() + ) ), - )]) + ]) } } -fn 字幕逐字步進(輸入碼: &str) -> Cow<'_, str> { - Cow::Borrowed(輸入碼) +fn 字幕逐字步进(输入码: &str) -> Cow<'_, str> { + Cow::Borrowed(输入码) } -fn 字幕逐詞步進(輸入碼: &str) -> Cow<'_, str> { - Cow::Owned(format!("[{輸入碼} ]")) +fn 字幕逐词步进(输入码: &str) -> Cow<'_, str> { + Cow::Owned(format!("[{输入码} ]")) } diff --git a/src/gear/chord.rs b/src/gear/chord.rs index 9e13540..5a92380 100644 --- a/src/gear/chord.rs +++ b/src/gear/chord.rs @@ -1,123 +1,119 @@ use leptos::prelude::*; -use crate::action::動作; -use crate::definition::鍵組; -use crate::gear::{assignment::作業機關輸出信號, theory::輸入方案機關輸出信號}; +use crate::action::动作; +use crate::definition::键组; +use crate::gear::{ assignment::作业模式输出信号, theory::输入方案输出信号 }; use crate::key_code::KeyCode; -pub struct 並擊狀態 { - pub 實時落鍵: 鍵組, - pub 累計擊鍵: 鍵組, +pub struct 并击状态 { + pub 实时击键: 键组, + pub 累计击键: 键组, } -impl 並擊狀態 { +impl 并击状态 { pub fn new() -> Self { - 並擊狀態 { - 實時落鍵: 鍵組::new(), - 累計擊鍵: 鍵組::new(), + 并击状态 { + 实时击键: 键组::new(), + 累计击键: 键组::new(), } } - pub fn 落鍵(&mut self, 鍵碼: KeyCode) { - if self.實時落鍵.0.is_empty() { - self.並擊開始(); + pub fn 落键(&mut self, 键码: KeyCode) { + if self.实时击键.0.is_empty() { + self.并击开始(); } - self.實時落鍵.0.insert(鍵碼); - self.累計擊鍵.0.insert(鍵碼); + self.实时击键.0.insert(键码); + self.累计击键.0.insert(键码); } - pub fn 抬鍵(&mut self, 鍵碼: KeyCode) { - self.實時落鍵.0.remove(&鍵碼); - if self.實時落鍵.0.is_empty() { - self.並擊完成(); + pub fn 抬键(&mut self, 键码: KeyCode) { + self.实时击键.0.remove(&键码); + if self.实时击键.0.is_empty() { + self.并击完成(); } } pub fn 重置(&mut self) { - self.實時落鍵.0.clear(); - self.累計擊鍵.0.clear(); + self.实时击键.0.clear(); + self.累计击键.0.clear(); } - pub fn 並擊開始(&mut self) { + pub fn 并击开始(&mut self) { self.重置(); } - pub fn 並擊完成(&mut self) {} + pub fn 并击完成(&mut self) {} } -pub type 並擊重置動作 = impl 動作; +pub type 并击重置动作 = impl 动作; #[derive(Clone)] -pub struct 並擊機關輸出信號 { - pub 並擊狀態流: ReadSignal<並擊狀態>, - pub 並擊狀態變更: WriteSignal<並擊狀態>, - pub 重置並擊狀態: 並擊重置動作, - pub 實況並擊碼: Memo, - pub 並擊所得拼音: Signal>, - pub 反查所得並擊碼: Memo>, - pub 反查鍵位: Signal>, - pub 並擊完成: Signal, - pub 並擊成功: Memo, +pub struct 并击模式输出信号 { + pub 并击状态流: ReadSignal<并击状态>, + pub 并击状态变更: WriteSignal<并击状态>, + pub 重置并击状态: 并击重置动作, + pub 实际并击码: Memo, + pub 并击所得拼音: Signal>, + pub 反查所得并击码: Memo>, + pub 反查键位: Signal>, + pub 并击完成: Signal, + pub 并击成功: Memo, } -#[define_opaque(並擊重置動作)] -pub fn 並擊機關( - 方案: &輸入方案機關輸出信號, - 作業: &作業機關輸出信號, -) -> 並擊機關輸出信號 { - let 方案定義 = 方案.方案定義; - let 目標輸入碼片段 = 作業.目標輸入碼片段; +#[define_opaque(并击重置动作)] +pub fn 并击模式(方案: &输入方案输出信号, 作业: &作业模式输出信号) -> 并击模式输出信号 { + let 方案定义 = 方案.方案定义; + let 目标输入码片段 = 作业.目标输入码片段; - let (並擊狀態流, 並擊狀態變更) = signal(並擊狀態::new()); + let (并击状态流, 并击状态变更) = signal(并击状态::new()); - let 重置並擊狀態 = move || { - 並擊狀態變更.write().重置(); + let 重置并击状态 = move || { + 并击状态变更.write().重置(); }; - let 實況並擊碼 = - Memo::new(move |_| 方案定義.read().寫成字根碼(&並擊狀態流.read().累計擊鍵)); - let 並擊所得拼音 = - Signal::derive(move || 方案定義.read().轉寫法.字根碼轉寫爲拼式(&實況並擊碼())); + let 实际并击码 = Memo::new(move |_| 方案定义.read().写成字根码(&并击状态流.read().累计击键)); + let 并击所得拼音 = Signal::derive(move || 方案定义.read().转写.字根码转写为拼式(&实际并击码())); - let 反查所得並擊碼 = Memo::new(move |_| { - 目標輸入碼片段 + let 反查所得并击码 = Memo::new(move |_| { + 目标输入码片段 .read() .as_ref() - .and_then(|對照碼| 對照碼.反查字根碼(&方案定義.read().轉寫法)) + .and_then(|对照码| 对照码.反查字根码(&方案定义.read().转写)) }); - let 反查鍵位 = Signal::derive(move || { - 反查所得並擊碼 + let 反查键位 = Signal::derive(move || { + 反查所得并击码 .read() .as_deref() - .map(|並擊碼| 方案定義.read().讀出鍵位(並擊碼)) + .map(|并击码| 方案定义.read().读出键位(并击码)) }); - let _並擊開始 = Signal::derive(move || !並擊狀態流.read().實時落鍵.0.is_empty()); + let _并击开始 = Signal::derive(move || !并击状态流.read().实时击键.0.is_empty()); - let 並擊完成 = Signal::derive(move || { - 並擊狀態流.read().實時落鍵.0.is_empty() && !實況並擊碼.read().is_empty() + let 并击完成 = Signal::derive(move || { + 并击状态流.read().实时击键.0.is_empty() && !实际并击码.read().is_empty() }); - let 並擊成功 = Memo::new(move |_| { - // 拼音一致即爲成功,允許並擊碼不同 - 目標輸入碼片段() - .is_some_and(|輸入碼| { - 輸入碼.字根碼原文.is_some_and(|查得| 查得 == 實況並擊碼()) || - 輸入碼.轉寫碼原文.is_some_and(|查得| 並擊所得拼音().is_some_and(|擊得| 查得 == 擊得)) - }) - // 拼音爲非音節形式的聲母、韻母,須比較並擊碼 - || 反查所得並擊碼().is_some_and(|查得| 查得 == 實況並擊碼()) + let 并击成功 = Memo::new(move |_| { + // 拼音一致即为成功,允许并击码不同 + 目标输入码片段().is_some_and(|输入码| { + 输入码.字根码原文.is_some_and(|查得| 查得 == 实际并击码()) || + 输入码.转写码原文.is_some_and(|查得| + 并击所得拼音().is_some_and(|击得| 查得 == 击得) + ) + }) || + // 拼音为非音节形式的声母、韵母,须比较并击码 + 反查所得并击码().is_some_and(|查得| 查得 == 实际并击码()) }); - 並擊機關輸出信號 { - 並擊狀態流, - 並擊狀態變更, - 重置並擊狀態, - 實況並擊碼, - 並擊所得拼音, - 反查所得並擊碼, - 反查鍵位, - 並擊完成, - 並擊成功, + 并击模式输出信号 { + 并击状态流, + 并击状态变更, + 重置并击状态, + 实际并击码, + 并击所得拼音, + 反查所得并击码, + 反查键位, + 并击完成, + 并击成功, } } diff --git a/src/gear/input.rs b/src/gear/input.rs index 736e667..76fc591 100644 --- a/src/gear/input.rs +++ b/src/gear/input.rs @@ -1,58 +1,58 @@ -use leptos::{ev, leptos_dom::helpers::window_event_listener, logging::log, prelude::*}; +use leptos::{ ev, leptos_dom::helpers::window_event_listener, logging::log, prelude::* }; use leptos_use::use_window_focus; -use crate::action::{動作, 動作給一參數, 動作給一參數得一結果}; -use crate::key_code::{KeyCode, 網頁鍵值轉換}; +use crate::action::{ 动作给一参数, 动作给一参数得一结果, 动作 }; +use crate::key_code::{ KeyCode, 网页键值转换 }; -pub fn 焦點事件處理機關(重置並擊狀態: impl 動作) { - let 鍵盤輸入焦點源 = Selector::new(use_window_focus()); +pub fn 焦点事件处理机关(重置并击状态: impl 动作) { + let 键盘输入焦点源 = Selector::new(use_window_focus()); Effect::new(move |_| { - if 鍵盤輸入焦點源.selected(&false) { - 重置並擊狀態(); + if 键盘输入焦点源.selected(&false) { + 重置并击状态(); } }); } #[allow(dead_code)] -pub struct 檔位 { +pub struct 档位 { pub shift: bool, pub ctrl: bool, pub alt: bool, pub meta: bool, } -pub struct 觸鍵消息 { - pub 鍵碼: KeyCode, - pub 檔位: 檔位, +pub struct 击键消息 { + pub 键码: KeyCode, + pub 档位: 档位, } -pub fn 輸入事件處理機關( - 處理功能鍵: impl 動作給一參數得一結果<觸鍵消息, bool>, - 既然落鍵: impl 動作給一參數, - 既然抬鍵: impl 動作給一參數, +pub fn 输入事件处理机关( + 处理功能键: impl 动作给一参数得一结果<击键消息, bool>, + 既然落键: impl 动作给一参数, + 既然擡键: impl 动作给一参数 ) { let keydown_handle = window_event_listener(ev::keydown, move |ev| { - log!("落鍵 key = {}, code = {}", &ev.key(), ev.code()); - let 鍵碼 = 網頁鍵值轉換(&ev.code()); - let 檔位 = 檔位 { + log!("落键 key = {}, code = {}", &ev.key(), ev.code()); + let 键码 = 网页键值转换(&ev.code()); + let 档位 = 档位 { shift: ev.shift_key(), ctrl: ev.ctrl_key(), alt: ev.alt_key(), meta: ev.meta_key(), }; - if 處理功能鍵(觸鍵消息 { 鍵碼, 檔位 }) { + if 处理功能键(击键消息 { 键码, 档位 }) { ev.prevent_default(); } - if 鍵碼 != KeyCode::No { - 既然落鍵(鍵碼); + if 键码 != KeyCode::No { + 既然落键(键码); } }); let keyup_handle = window_event_listener(ev::keyup, move |ev| { - log!("抬鍵 key = {}, code = {}", &ev.key(), &ev.code()); - let 鍵碼 = 網頁鍵值轉換(&ev.code()); - if 鍵碼 != KeyCode::No { - 既然抬鍵(鍵碼); + log!("抬键 key = {}, code = {}", &ev.key(), &ev.code()); + let 键码 = 网页键值转换(&ev.code()); + if 键码 != KeyCode::No { + 既然擡键(键码); } }); diff --git a/src/gear/key_press.rs b/src/gear/key_press.rs index 4454460..21b942f 100644 --- a/src/gear/key_press.rs +++ b/src/gear/key_press.rs @@ -1,99 +1,97 @@ use leptos::logging::log; use leptos::prelude::*; -use crate::action::{動作, 動作給一參數}; -use crate::gear::{assignment::作業機關輸出信號, theory::輸入方案機關輸出信號}; +use crate::action::{ 动作给一参数, 动作 }; +use crate::gear::{ assignment::作业模式输出信号, theory::输入方案输出信号 }; use crate::key_code::KeyCode; #[derive(Clone, Copy, Debug, PartialEq)] -pub struct 連擊狀態 { - pub 鍵碼: KeyCode, - pub 連擊次數: usize, +pub struct 连击状态 { + pub 键码: KeyCode, + pub 连击次数: usize, } -impl Default for 連擊狀態 { +impl Default for 连击状态 { fn default() -> Self { Self { - 鍵碼: KeyCode::No, - 連擊次數: 0, + 键码: KeyCode::No, + 连击次数: 0, } } } -impl 連擊狀態 { - pub fn 擊發(&mut self, 鍵碼: KeyCode) { - if 鍵碼 == self.鍵碼 { - self.連擊次數 += 1; +impl 连击状态 { + pub fn 击发(&mut self, 键码: KeyCode) { + if 键码 == self.键码 { + self.连击次数 += 1; } else { - self.鍵碼 = 鍵碼; - self.連擊次數 = 1; + self.键码 = 键码; + self.连击次数 = 1; } } } -pub type 清空動作 = impl 動作; -pub type 回退動作 = impl 動作; -pub type 擊鍵動作 = impl 動作給一參數; +pub type 清空动作 = impl 动作; +pub type 回退动作 = impl 动作; +pub type 击键动作 = impl 动作给一参数; #[derive(Clone)] -pub struct 連擊機關輸出信號 { - pub 連擊狀態變更: WriteSignal<連擊狀態>, - pub 連擊輸入碼: ReadSignal>, - pub 實況字根碼: Signal, - pub 連擊比對成功: Memo, - pub 清空連擊輸入碼: 清空動作, - pub 回退連擊輸入碼: 回退動作, - pub 編輯連擊輸入碼: 擊鍵動作, +pub struct 连击模式输出信号 { + pub 连击状态变更: WriteSignal<连击状态>, + pub 连击输入码: ReadSignal>, + pub 实况字根码: Signal, + pub 连击比对成功: Memo, + pub 清空连击输入码: 清空动作, + pub 回退连击输入码: 回退动作, + pub 编辑连击输入码: 击键动作, } -#[define_opaque(清空動作, 回退動作, 擊鍵動作)] -pub fn 連擊機關( - 方案: &輸入方案機關輸出信號, - 作業: &作業機關輸出信號, -) -> 連擊機關輸出信號 { - let 方案 = 方案.方案定義; - let 目標輸入碼片段 = 作業.目標輸入碼片段; +#[define_opaque(清空动作, 回退动作, 击键动作)] +pub fn 连击机关(方案: &输入方案输出信号, 作业: &作业模式输出信号) -> 连击模式输出信号 { + let 方案 = 方案.方案定义; + let 目标输入码片段 = 作业.目标输入码片段; - let (連擊狀態流, 連擊狀態變更) = signal(連擊狀態::default()); + let (连击状态流, 连击状态变更) = signal(连击状态::default()); - let 實況字根碼 = Signal::derive(move || 方案.read().寫成字根碼(連擊狀態流.read().鍵碼)); - let 反查所得字根碼 = move || { - 目標輸入碼片段 + let 实况字根码 = Signal::derive(move || 方案.read().写成字根码(连击状态流.read().键码)); + let 反查所得字根码 = move || { + 目标输入码片段 .read() .as_ref() - .and_then(|對照碼| 對照碼.反查字根碼(&方案.read().轉寫法)) + .and_then(|对照码| 对照码.反查字根码(&方案.read().转写)) }; - let 連擊比對成功 = - Memo::new(move |_| 反查所得字根碼().is_some_and(|查得| 查得 == 實況字根碼())); + let 连击比对成功 = Memo::new(move |_| + 反查所得字根码().is_some_and(|查得| 查得 == 实况字根码()) + ); - let (連擊輸入碼, 更新連擊輸入碼) = signal(Vec::::new()); + let (连击输入码, 更新连击输入码) = signal(Vec::::new()); - let 清空連擊輸入碼 = move || { - 更新連擊輸入碼.write().clear(); + let 清空连击输入码 = move || { + 更新连击输入码.write().clear(); }; - let 回退連擊輸入碼 = move || { - 更新連擊輸入碼.write().pop(); + let 回退连击输入码 = move || { + 更新连击输入码.write().pop(); }; - let 編輯連擊輸入碼 = move |鍵碼: KeyCode| { - let 自由輸入 = 目標輸入碼片段.read().is_none(); - let 擊鍵正確 = 連擊比對成功(); - if 自由輸入 || 擊鍵正確 { - match 鍵碼 { + let 编辑连击输入码 = move |键码: KeyCode| { + let 自由输入 = 目标输入码片段.read().is_none(); + let 击键正确 = 连击比对成功(); + if 自由输入 || 击键正确 { + match 键码 { KeyCode::Space => { - let 空格 = 方案.read().寫成字根碼(KeyCode::Space); - 更新連擊輸入碼(vec![空格]); + let 空格 = 方案.read().写成字根码(KeyCode::Space); + 更新连击输入码(vec![空格]); } - 鍵碼 => { - let 字根碼 = 方案.read().寫成字根碼(鍵碼); - if !字根碼.is_empty() { - log!("更新連擊輸入碼 {字根碼}"); - let 空格 = 方案.read().寫成字根碼(KeyCode::Space); - if *連擊輸入碼.read() == [空格] { - 更新連擊輸入碼(vec![字根碼]); + 键码 => { + let 字根码 = 方案.read().写成字根码(键码); + if !字根码.is_empty() { + log!("更新连击输入码 {字根码}"); + let 空格 = 方案.read().写成字根码(KeyCode::Space); + if *连击输入码.read() == [空格] { + 更新连击输入码(vec![字根码]); } else { - 更新連擊輸入碼.write().push(字根碼); + 更新连击输入码.write().push(字根码); } } } @@ -101,13 +99,13 @@ pub fn 連擊機關( } }; - 連擊機關輸出信號 { - 連擊狀態變更, - 連擊輸入碼, - 實況字根碼, - 連擊比對成功, - 清空連擊輸入碼, - 回退連擊輸入碼, - 編輯連擊輸入碼, + 连击模式输出信号 { + 连击状态变更, + 连击输入码, + 实况字根码, + 连击比对成功, + 清空连击输入码, + 回退连击输入码, + 编辑连击输入码, } } diff --git a/src/gear/layout.rs b/src/gear/layout.rs index f5b8ca2..7e061cf 100644 --- a/src/gear/layout.rs +++ b/src/gear/layout.rs @@ -1,51 +1,49 @@ -//! 本節用到的概念 -//! - 配列 :: 描述物理按鍵的數目和空間排佈 -//! - 矩陣 :: 定義按鍵邏輯上的行列座標, 採用 ISO/IEC 9995-1 的鍵位標註法 -//! - 鍵盤佈局 :: 各個盤面及各個位置上的字符定義 -//! - 盤面 :: 也稱層, 定義在盤面選擇碼指定的狀態下各鍵碼映射到哪些字符 -//! - 鍵面刻印 :: 鍵面顯示的文字 +//! 本节用到的概念 +//! - 键盘配列 :: 描述物理按键的数目和空间排布 +//! - 矩阵 :: 定义按键逻辑上的行列座标, 采用 ISO/IEC 9995-1 的键位标注法 +//! - 键盘布局 :: 各个盘面及各个位置上的字符定义 +//! - 盘面 :: 也称层, 定义在盘面选择码指定的状态下各键码映射到哪些字符 +//! - 键面刻印 :: 键面显示的文字 use leptos::prelude::*; -use strum::{Display, EnumIter}; +use strum::{ Display, EnumIter }; -use crate::gear::theory::輸入方案機關輸出信號; +use crate::gear::theory::输入方案输出信号; use crate::key_code::KeyCode; #[derive(Clone, Copy, Default)] -pub struct 盤面選擇碼(pub u64); +pub struct 盘面序号(pub u64); -impl 盤面選擇碼 { - pub fn 是否可選盤面(&self, 盤面號: usize) -> bool { - 盤面號 == 0 || (self.0 & (1 << (盤面號 - 1))) != 0 +impl 盘面序号 { + pub fn 是否可选盘面(&self, 盘面号: usize) -> bool { + (盘面号 == 0) || ((self.0 & (1 << (盘面号 - 1))) != 0) } - pub fn 頂層盤面(&self) -> usize { - (0..64) - .rfind(|&盤面號| self.是否可選盤面(盤面號)) - .unwrap_or_default() + pub fn 顶层盘面(&self) -> usize { + (0..64).rfind(|&盘面号| self.是否可选盘面(盘面号)).unwrap_or_default() } } #[derive(Clone, Copy)] -pub struct 矩陣座標(pub usize, pub usize); +pub struct 矩阵坐标(pub usize, pub usize); -/// 矩陣的行列座標按照 ISO/IEC 9995-1 的鍵位標註法顯示. -/// 空格至數字行從下到上編號爲 A 到 E. -/// 本品只做字母數字區, 因此 A 行列號從 03 開始, 其他各行從 01 開始. -impl std::fmt::Display for 矩陣座標 { +/// 矩阵的行列座标按照 ISO/IEC 9995-1 的键位标注法显示. +/// 空格至数字行从下到上编号为 A 到 E. +/// 本品只做字母数字区, 因此 A 行列号从 03 开始, 其他各行从 01 开始. +impl std::fmt::Display for 矩阵坐标 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { match self.0 { // (0, 0) -> E01 i @ 0..=3 => { - let 行號 = char::from_u32('E' as u32 - i as u32).ok_or(std::fmt::Error {})?; - let 列號 = self.1 + 1; - write!(f, "{行號}{列號}") + let 行号 = char::from_u32(('E' as u32) - (i as u32)).ok_or(std::fmt::Error {})?; + let 列号 = self.1 + 1; + write!(f, "{行号}{列号}") } // (4, 0) -> A03 4 => { - let 行號 = 'A'; - let 列號 = self.1 + 3; - write!(f, "{行號}{列號}") + let 行号 = 'A'; + let 列号 = self.1 + 3; + write!(f, "{行号}{列号}") } _ => Err(std::fmt::Error {}), } @@ -53,7 +51,7 @@ impl std::fmt::Display for 矩陣座標 { } #[derive(Clone, Copy, Default, PartialEq)] -pub struct 刻印說明 { +pub struct 刻印说明 { pub 中: Option<&'static str>, pub 上: Option<&'static str>, pub 下: Option<&'static str>, @@ -61,7 +59,7 @@ pub struct 刻印說明 { pub 右: Option<&'static str>, } -impl 刻印說明 { +impl 刻印说明 { pub const fn 居中(文字: &'static str) -> Self { Self { 中: Some(文字), @@ -74,161 +72,147 @@ impl 刻印說明 { } #[derive(Clone, Copy, PartialEq)] -pub enum 鍵面刻印 { +pub enum 键面刻印 { 透明, - 無刻, - 有刻(刻印說明), + 无刻, + 有刻(刻印说明), } -impl 鍵面刻印 { +impl 键面刻印 { pub fn 居中刻印文字(&self) -> Option<&'static str> { match self { - 鍵面刻印::有刻(刻印說明 { - 中: 有冇刻印, .. - }) => *有冇刻印, + 键面刻印::有刻(刻印说明 { 中: 有冇刻印, .. }) => *有冇刻印, _ => None, } } pub fn 上方刻印文字(&self) -> Option<&'static str> { match self { - 鍵面刻印::有刻(刻印說明 { - 上: 有冇刻印, .. - }) => *有冇刻印, + 键面刻印::有刻(刻印说明 { 上: 有冇刻印, .. }) => *有冇刻印, _ => None, } } pub fn 下方刻印文字(&self) -> Option<&'static str> { match self { - 鍵面刻印::有刻(刻印說明 { - 下: 有冇刻印, .. - }) => *有冇刻印, + 键面刻印::有刻(刻印说明 { 下: 有冇刻印, .. }) => *有冇刻印, _ => None, } } - pub fn 左側刻印文字(&self) -> Option<&'static str> { + pub fn 左侧刻印文字(&self) -> Option<&'static str> { match self { - 鍵面刻印::有刻(刻印說明 { - 左: 有冇刻印, .. - }) => *有冇刻印, + 键面刻印::有刻(刻印说明 { 左: 有冇刻印, .. }) => *有冇刻印, _ => None, } } - pub fn 右側刻印文字(&self) -> Option<&'static str> { + pub fn 右侧刻印文字(&self) -> Option<&'static str> { match self { - 鍵面刻印::有刻(刻印說明 { - 右: 有冇刻印, .. - }) => *有冇刻印, + 键面刻印::有刻(刻印说明 { 右: 有冇刻印, .. }) => *有冇刻印, _ => None, } } } #[derive(Clone, Copy)] -pub struct 鍵面映射 { - pub 鍵碼: KeyCode, - pub 刻印: 鍵面刻印, +pub struct 键面映射 { + pub 键码: KeyCode, + pub 刻印: 键面刻印, } -pub type 鍵盤矩陣<'a> = &'a [&'a [KeyCode]]; -pub type 盤面定義<'a> = &'a [&'a [鍵面刻印]]; +pub type 键盘矩阵<'a> = &'a [&'a [KeyCode]]; +pub type 盘面定义<'a> = &'a [&'a [键面刻印]]; #[derive(Clone, Copy, Default, Display, EnumIter, PartialEq)] -pub enum 配列 { +pub enum 键盘配列 { #[default] - 主鍵盤區, - 字母鍵盤, + 主键盘区, + 字母键盘, 正交直列, - 直列分體, - 正交直列帶數字行, - 直列分體帶數字行, + 直列分体, + 正交直列带数字行, + 直列分体带数字行, } -impl 配列 { - pub fn 橫向交錯(&self) -> bool { - matches!(self, 配列::主鍵盤區 | 配列::字母鍵盤) +impl 键盘配列 { + pub fn 横向交错(&self) -> bool { + matches!(self, 键盘配列::主键盘区 | 键盘配列::字母键盘) } pub fn 直列(&self) -> bool { matches!( self, - 配列::正交直列 - | 配列::直列分體 - | 配列::正交直列帶數字行 - | 配列::直列分體帶數字行 + 键盘配列::正交直列 | + 键盘配列::直列分体 | + 键盘配列::正交直列带数字行 | + 键盘配列::直列分体带数字行 ) } - pub fn 分體(&self) -> bool { - matches!(self, 配列::直列分體 | 配列::直列分體帶數字行) + pub fn 分体(&self) -> bool { + matches!(self, 键盘配列::直列分体 | 键盘配列::直列分体带数字行) } - pub fn 規格(&self) -> usize { + pub fn 规格(&self) -> usize { match self { - 配列::主鍵盤區 => 60, - 配列::字母鍵盤 => 30, - 配列::正交直列 | 配列::直列分體 => 30, - 配列::正交直列帶數字行 | 配列::直列分體帶數字行 => 60, + 键盘配列::主键盘区 => 60, + 键盘配列::字母键盘 => 30, + 键盘配列::正交直列 | 键盘配列::直列分体 => 30, + 键盘配列::正交直列带数字行 | 键盘配列::直列分体带数字行 => 60, } } - pub fn 矩陣(&self) -> 鍵盤矩陣<'static> { + pub fn 矩阵(&self) -> 键盘矩阵<'static> { match self { - 配列::主鍵盤區 => 主鍵盤區矩陣, - 配列::字母鍵盤 => 字母鍵盤矩陣, - 配列::正交直列 => 正交直列矩陣, - 配列::直列分體 => 直列分體矩陣, - 配列::正交直列帶數字行 => 正交直列帶數字行矩陣, - 配列::直列分體帶數字行 => 直列分體帶數字行矩陣, + 键盘配列::主键盘区 => 主键盘区矩阵, + 键盘配列::字母键盘 => 字母键盘矩阵, + 键盘配列::正交直列 => 正交直列矩阵, + 键盘配列::直列分体 => 直列分体矩阵, + 键盘配列::正交直列带数字行 => 正交直列带数字行矩阵, + 键盘配列::直列分体带数字行 => 直列分体带数字行矩阵, } } } #[derive(Clone, Copy)] -pub struct 鍵盤佈局 { - pub 盤面: &'static [盤面定義<'static>], - pub 默認盤面: 盤面選擇碼, - pub 首選配列: 配列, +pub struct 键盘布局 { + pub 盘面: &'static [盘面定义<'static>], + pub 默认盘面: 盘面序号, + pub 默认配列: 键盘配列, } -impl 鍵盤佈局 { - pub fn 選擇盤面( - &self, - 目標盤面: 盤面選擇碼, - 座標: 矩陣座標, - ) -> Option<(usize, 鍵面刻印)> { - self.盤面 +impl 键盘布局 { + pub fn 选择盘面(&self, 目标盘面: 盘面序号, 坐标: 矩阵坐标) -> Option<(usize, 键面刻印)> { + self.盘面 .iter() .enumerate() .rev() - .filter(|&(盤面號, _)| 目標盤面.是否可選盤面(盤面號)) - .find_map(|(盤面號, 此盤面)| { - self.從盤面讀取刻印(此盤面, 座標) - .and_then(|刻印| match 刻印 { - 鍵面刻印::透明 => None, - _ => Some((盤面號, 刻印)), - }) + .filter(|&(盘面号, _)| 目标盘面.是否可选盘面(盘面号)) + .find_map(|(盘面号, 此盘面)| { + self.从盘面读取刻印(此盘面, 坐标).and_then(|刻印| { + match 刻印 { + 键面刻印::透明 => None, + _ => Some((盘面号, 刻印)), + } + }) }) } - fn 從盤面讀取刻印( - &self, - 此盤面: 盤面定義<'static>, - 座標: 矩陣座標, - ) -> Option<鍵面刻印> { - let 矩陣座標(行, 列) = 座標; - 此盤面.get(行).and_then(|此行| 此行.get(列)).copied() + fn 从盘面读取刻印(&self, 此盘面: 盘面定义<'static>, 坐标: 矩阵坐标) -> Option<键面刻印> { + let 矩阵坐标(行, 列) = 坐标; + 此盘面.get(行) + .and_then(|此行| 此行.get(列)) + .copied() } } -macro_rules! 矩陣 { - [ $( [ $( $鍵:ident )* ] $(,)? )* ] => { - &[ $( &[ $( crate::key_code::KeyCode::$鍵, )* ], )* ] +macro_rules! 矩阵 { + [$([$($键:ident)*] $(,)?)*] => { + &[ $( &[ $( crate::key_code::KeyCode::$键, )* ], )* ] }; } -const 主鍵盤區矩陣: 鍵盤矩陣<'static> = 矩陣![ - // ISO/IEC 9995-2 規定字母數字區至少包含 47 個用於輸入字符的鍵位 - // 以下是協調 48 文字鍵盤佈局的一種實現, 不用鍵位 E00 而選用鍵位 C12, E13 +const 主键盘区矩阵: 键盘矩阵<'static> = + 矩阵![ + // ISO/IEC 9995-2 规定字母数字区至少包含 47 个用于输入字符的键位 + // 以下是协调 48 文字键盘布局的一种实现, 不用键位 E00 而选用键位 C12, E13 [Kc1 Kc2 Kc3 Kc4 Kc5 Kc6 Kc7 Kc8 Kc9 Kc0 Minus Equal Grave], // E01 - E13 [Q W E R T Y U I O P LeftBracket RightBracket], // D01 - D12 [A S D F G H J K L Semicolon Quote Backslash], // C01 - C12 @@ -236,7 +220,8 @@ const 主鍵盤區矩陣: 鍵盤矩陣<'static> = 矩陣![ [Space] // A03 ]; -const 字母鍵盤矩陣: 鍵盤矩陣<'static> = 矩陣![ +const 字母键盘矩阵: 键盘矩阵<'static> = + 矩阵![ [], // E01 [Q W E R T Y U I O P], // D01 - D10 [A S D F G H J K L Semicolon], // C01 - C10 @@ -244,7 +229,8 @@ const 字母鍵盤矩陣: 鍵盤矩陣<'static> = 矩陣![ [Space] // A03 ]; -const 正交直列矩陣: 鍵盤矩陣<'static> = 矩陣![ +const 正交直列矩阵: 键盘矩阵<'static> = + 矩阵![ [], // E01 [Q W E R T Y U I O P], // D01 - D10 [A S D F G H J K L Semicolon], // C01 - C10 @@ -252,7 +238,8 @@ const 正交直列矩陣: 鍵盤矩陣<'static> = 矩陣![ [Space] // A03 ]; -const 直列分體矩陣: 鍵盤矩陣<'static> = 矩陣![ +const 直列分体矩阵: 键盘矩阵<'static> = + 矩阵![ [], // E01 [Q W E R T Y U I O P], // D01 - D10 [A S D F G H J K L Semicolon], // C01 - C10 @@ -260,7 +247,8 @@ const 直列分體矩陣: 鍵盤矩陣<'static> = 矩陣![ [No Space Space] // A03 - A05 ]; -const 正交直列帶數字行矩陣: 鍵盤矩陣<'static> = 矩陣![ +const 正交直列带数字行矩阵: 键盘矩阵<'static> = + 矩阵![ [Kc1 Kc2 Kc3 Kc4 Kc5 Kc6 Kc7 Kc8 Kc9 Kc0], // E01 - E10 [Q W E R T Y U I O P], // D01 - D10 [A S D F G H J K L Semicolon], // C01 - C10 @@ -268,7 +256,8 @@ const 正交直列帶數字行矩陣: 鍵盤矩陣<'static> = 矩陣![ [Space] // A03 ]; -const 直列分體帶數字行矩陣: 鍵盤矩陣<'static> = 矩陣![ +const 直列分体带数字行矩阵: 键盘矩阵<'static> = + 矩阵![ [Kc1 Kc2 Kc3 Kc4 Kc5 Kc6 Kc7 Kc8 Kc9 Kc0], // E01 - E10 [Q W E R T Y U I O P], // D01 - D10 [A S D F G H J K L Semicolon], // C01 - C10 @@ -277,41 +266,46 @@ const 直列分體帶數字行矩陣: 鍵盤矩陣<'static> = 矩陣![ ]; #[macro_export] -macro_rules! 盤面 { - [ $( [ $( $鍵:tt )* ] $(,)? )* ] => { - &[ $( &[ $( 鍵面!($鍵), )* ], )* ] +macro_rules! 盘面 { + [ + $( + [$($键:tt)*] + $(,)? + )* + ] => { + &[ $( &[ $( 键面!($键), )* ], )* ] }; } #[macro_export] -macro_rules! 鍵面 { - ( _ ) => { - 鍵面刻印::透明 +macro_rules! 键面 { + (_) => { + 键面刻印::透明 }; - ( 空 ) => { - 鍵面刻印::無刻 + (空) => { + 键面刻印::无刻 }; - ( $字符:literal ) => { - 鍵面刻印::有刻($crate::gear::layout::刻印說明::居中($字符)) + ($字符:literal) => { + 键面刻印::有刻($crate::gear::layout::刻印说明::居中($字符)) }; - ( $字母:ident ) => { - 鍵面刻印::有刻($crate::gear::layout::刻印說明::居中( + ($字母:ident) => { + 键面刻印::有刻($crate::gear::layout::刻印说明::居中( stringify!($字母), )) }; - ( { 中: $居中:tt, 上: $居上:tt, 下: $居下:tt, 左: $居左:tt, 右: $居右:tt } ) => { - 鍵面刻印::有刻($crate::gear::layout::刻印說明 { - 中: $crate::標註!($居中), - 上: $crate::標註!($居上), - 下: $crate::標註!($居下), - 左: $crate::標註!($居左), - 右: $crate::標註!($居右), + ({ 中: $居中:tt, 上: $居上:tt, 下: $居下:tt, 左: $居左:tt, 右: $居右:tt }) => { + 键面刻印::有刻($crate::gear::layout::刻印说明 { + 中: $crate::标注!($居中), + 上: $crate::标注!($居上), + 下: $crate::标注!($居下), + 左: $crate::标注!($居左), + 右: $crate::标注!($居右), }) }; } #[macro_export] -macro_rules! 標註 { +macro_rules! 标注 { (_) => { None }; @@ -323,7 +317,8 @@ macro_rules! 標註 { }; } -pub const 基本盤面: 盤面定義<'static> = 盤面![ +pub const 基本盘面: 盘面定义<'static> = + 盘面![ [ "1" "2" "3" "4" "5" "6" "7" "8" "9" "0" "-" "=" "`" ], // E01 - E13 [ q w e r t y u i o p "[" "]" ], // D01 - D12 [ a s d f g h j k l ";" "'" "\\" ], // C01 - C12 @@ -331,7 +326,8 @@ pub const 基本盤面: 盤面定義<'static> = 盤面![ [ "␣" "␣" "␣" ] // A03 - A05 ]; -pub const 上檔盤面: 盤面定義<'static> = 盤面![ +pub const 上档盘面: 盘面定义<'static> = + 盘面![ [ "!" "@" "#" "$" "%" "^" "&" "*" "(" ")" "_" "+" "~" ], [ Q W E R T Y U I O P "{" "}" ], [ A S D F G H J K L ":" "\"" "|" ], @@ -339,7 +335,8 @@ pub const 上檔盤面: 盤面定義<'static> = 盤面![ [ _ _ _ ] ]; -pub const 大寫字母盤面: 盤面定義<'static> = 盤面![ +pub const 大写字母盘面: 盘面定义<'static> = + 盘面![ [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], [ Q W E R T Y U I O P _ _ ], [ A S D F G H J K L _ _ _ ], @@ -347,55 +344,56 @@ pub const 大寫字母盤面: 盤面定義<'static> = 盤面![ [ "␣" "␣" "␣" ] ]; -pub const 拉丁字母鍵盤佈局: 鍵盤佈局 = 鍵盤佈局 { - 盤面: &[基本盤面, 上檔盤面, 大寫字母盤面], - 默認盤面: 盤面選擇碼(2), - 首選配列: 配列::字母鍵盤, +pub const 拉丁字母键盘布局: 键盘布局 = 键盘布局 { + 盘面: &[基本盘面, 上档盘面, 大写字母盘面], + 默认盘面: 盘面序号(2), + 默认配列: 键盘配列::字母键盘, }; -pub mod 功能鍵 { +pub mod 功能键 { use super::*; - pub const 退出鍵: 鍵面映射 = 鍵面映射 { - 鍵碼: KeyCode::Escape, - 刻印: 鍵面刻印::有刻(刻印說明::居中("退出")), + pub const 退出键: 键面映射 = 键面映射 { + 键码: KeyCode::Escape, + 刻印: 键面刻印::有刻(刻印说明::居中("退出")), }; - pub const 製表鍵: 鍵面映射 = 鍵面映射 { - 鍵碼: KeyCode::Tab, - 刻印: 鍵面刻印::有刻(刻印說明::居中("製表")), + pub const 制表键: 键面映射 = 键面映射 { + 键码: KeyCode::Tab, + 刻印: 键面刻印::有刻(刻印说明::居中("制表")), }; - pub const 退格鍵: 鍵面映射 = 鍵面映射 { - 鍵碼: KeyCode::Backspace, - 刻印: 鍵面刻印::有刻(刻印說明::居中("退格")), + pub const 退格键: 键面映射 = 键面映射 { + 键码: KeyCode::Backspace, + 刻印: 键面刻印::有刻(刻印说明::居中("退格")), }; - pub const 回車鍵: 鍵面映射 = 鍵面映射 { - 鍵碼: KeyCode::Enter, - 刻印: 鍵面刻印::有刻(刻印說明::居中("回車")), + pub const 回车键: 键面映射 = 键面映射 { + 键码: KeyCode::Enter, + 刻印: 键面刻印::有刻(刻印说明::居中("回车")), }; - pub const 衆功能鍵: &[鍵面映射] = &[退出鍵, 製表鍵, 退格鍵, 回車鍵]; + pub const 众功能键: &[键面映射] = &[退出键, 制表键, 退格键, 回车键]; } #[derive(Clone)] -pub struct 配列機關輸出信號 { - pub 已選配列: ReadSignal<配列>, - pub 選用配列: WriteSignal<配列>, +pub struct 键盘配列输出信号 { + pub 已选配列: ReadSignal<键盘配列>, + pub 选用配列: WriteSignal<键盘配列>, } -pub fn 配列機關(方案: &輸入方案機關輸出信號) -> 配列機關輸出信號 { - let 方案定義 = 方案.方案定義; - let 初始方案 = 方案定義.get_untracked(); - let (已選配列, 選用配列) = signal(初始方案.佈局.首選配列); +pub fn 配列机关(方案: &输入方案输出信号) -> 键盘配列输出信号 { + let 方案定义 = 方案.方案定义; + let 初始方案 = 方案定义.get_untracked(); + let (已选配列, 选用配列) = signal(初始方案.布局.默认配列); let _ = Effect::watch( - 方案定義, + 方案定义, move |&方案, _, _| { - 選用配列(方案.佈局.首選配列); + 选用配列(方案.布局.默认配列); }, - false, + false ); - 配列機關輸出信號 { - 已選配列, 選用配列 + 键盘配列输出信号 { + 已选配列, + 选用配列, } } diff --git a/src/gear/mode.rs b/src/gear/mode.rs index 4608722..9bf7cc9 100644 --- a/src/gear/mode.rs +++ b/src/gear/mode.rs @@ -1,89 +1,86 @@ use leptos::prelude::*; use crate::action::*; -use crate::engine::輸入動作; -use crate::gear::{ - assignment::{作業, 作業機關輸出信號}, - theory::輸入方案機關輸出信號, -}; +use crate::engine::输入动作; +use crate::gear::{ assignment::{ 作业模式输出信号, 作业 }, theory::输入方案输出信号 }; #[derive(Clone, Debug, PartialEq)] pub enum 工作模式 { - 錄入, - 輸入反查碼, - 選取練習題, - 選擇輸入方案, - 選擇配列, + 录入, + 输入反查码, + 选取练习题, + 选择输入方案, + 选择配列, } -pub type 開啓反查輸入動作 = impl 動作; -pub type 開啓練習題選單動作 = impl 動作; -pub type 開啓方案選單動作 = impl 動作; -pub type 開啓配列選單動作 = impl 動作; -pub type 關閉輸入欄動作 = impl 動作; +pub type 开启反查输入动作 = impl 动作; +pub type 开启练习题选单动作 = impl 动作; +pub type 开启方案选单动作 = impl 动作; +pub type 开启配列选单动作 = impl 动作; +pub type 关闭输入栏动作 = impl 动作; #[derive(Clone)] -pub struct 工作模式機關輸出信號 { - pub 現行工作模式: ReadSignal<工作模式>, - pub 開啓反查輸入: 開啓反查輸入動作, - pub 開啓練習題選單: 開啓練習題選單動作, - pub 開啓方案選單: 開啓方案選單動作, - pub 開啓配列選單: 開啓配列選單動作, - pub 關閉輸入欄: 關閉輸入欄動作, +pub struct 工作模式输出信号 { + pub 现行工作模式: ReadSignal<工作模式>, + pub 开启反查输入: 开启反查输入动作, + pub 开启练习题选单: 开启练习题选单动作, + pub 开启方案选单: 开启方案选单动作, + pub 开启配列选单: 开启配列选单动作, + pub 关闭输入栏: 关闭输入栏动作, } #[define_opaque( - 開啓反查輸入動作, - 開啓練習題選單動作, - 開啓方案選單動作, - 開啓配列選單動作, - 關閉輸入欄動作 + 开启反查输入动作, + 开启练习题选单动作, + 开启方案选单动作, + 开启配列选单动作, + 关闭输入栏动作 )] -pub fn 工作模式機關( - 方案: &輸入方案機關輸出信號, - 作業: &作業機關輸出信號, - 輸入: &輸入動作, -) -> 工作模式機關輸出信號 { - let 現行方案 = 方案.現行方案; - let 佈置作業 = 作業.佈置作業; - let 重置作業進度 = 作業.重置作業進度; - let 作業進度完成 = 作業.作業進度完成; - let 重置輸入狀態 = 輸入.重置輸入狀態; +pub fn 工作模式机关( + 方案: &输入方案输出信号, + 作业: &作业模式输出信号, + 输入: &输入动作 +) -> 工作模式输出信号 { + let 当前方案 = 方案.当前方案; + let 布置作业 = 作业.布置作业; + let 重置作业进度 = 作业.重置作业进度; + let 作业完成 = 作业.作业完成; + let 重置输入状态 = 输入.重置输入状态; - let (現行工作模式, 設置工作模式) = signal(工作模式::錄入); + let (现行工作模式, 设置工作模式) = signal(工作模式::录入); - let 開啓反查輸入 = move || { - if 作業進度完成() { - 佈置作業(作業::自習(現行方案())); + let 开启反查输入 = move || { + if 作业完成() { + 布置作业(作业::自习(当前方案())); } - 重置輸入狀態(); - 設置工作模式(工作模式::輸入反查碼); + 重置输入状态(); + 设置工作模式(工作模式::输入反查码); }; - let 開啓練習題選單 = move || { - 重置作業進度(); - 重置輸入狀態(); - 設置工作模式(工作模式::選取練習題); + let 开启练习题选单 = move || { + 重置作业进度(); + 重置输入状态(); + 设置工作模式(工作模式::选取练习题); }; - let 開啓方案選單 = move || { - 設置工作模式(工作模式::選擇輸入方案); + let 开启方案选单 = move || { + 设置工作模式(工作模式::选择输入方案); }; - let 開啓配列選單 = move || { - 設置工作模式(工作模式::選擇配列); + let 开启配列选单 = move || { + 设置工作模式(工作模式::选择配列); }; - let 關閉輸入欄 = move || { - 設置工作模式(工作模式::錄入); + let 关闭输入栏 = move || { + 设置工作模式(工作模式::录入); }; - 工作模式機關輸出信號 { - 現行工作模式, - 開啓反查輸入, - 開啓練習題選單, - 開啓方案選單, - 開啓配列選單, - 關閉輸入欄, + 工作模式输出信号 { + 现行工作模式, + 开启反查输入, + 开启练习题选单, + 开启方案选单, + 开启配列选单, + 关闭输入栏, } } diff --git a/src/gear/theory.rs b/src/gear/theory.rs index 4a4dc8a..b12d7f9 100644 --- a/src/gear/theory.rs +++ b/src/gear/theory.rs @@ -1,87 +1,79 @@ use lazy_static::lazy_static; use leptos::prelude::*; -use crate::definition::{觸鍵方式, 輸入方案定義, 轉寫法定義}; -use crate::gear::layout::拉丁字母鍵盤佈局; -use crate::theory::{ - alphabet::拉丁字母輸入方案, cantonese::粵語輸入方案, combo_jyutping::宮保粵拼輸入方案, - combo_pinyin::宮保拼音輸入方案, early_middle_chinese::早期中古漢語輸入方案, - late_middle_chinese::晚期中古漢語輸入方案, modern_chinese::現代漢語輸入方案, - old_chinese::上古漢語輸入方案, old_mandarin::近古漢語輸入方案, -}; +use crate::definition::{ 击键方式, 转写定义, 输入方案定义 }; +use crate::gear::layout::拉丁字母键盘布局; // 默认键盘布局 +use crate::theory::*; // 输入方案 #[derive(Clone, Copy, Default, PartialEq)] -pub enum 方案選項 { +pub enum 方案选项 { #[default] - 宮保拼音, + 宫保拼音, 拉丁字母, - 上古漢語, - 早期中古漢語, - 晚期中古漢語, - 近古漢語, - 現代漢語, - 粵語, - 宮保粵拼, + 上古汉语, + 早期中古汉语, + 晚期中古汉语, + 近古汉语, + 现代汉语, + 粤语, + 宫保粤拼, + 小鹤双拼, } lazy_static! { - pub static ref 方案選單: Vec<(方案選項, 輸入方案定義<'static>)> = vec![ - (方案選項::宮保拼音, 宮保拼音輸入方案()), - (方案選項::拉丁字母, 拉丁字母輸入方案()), - (方案選項::上古漢語, 上古漢語輸入方案()), - (方案選項::早期中古漢語, 早期中古漢語輸入方案()), - (方案選項::晚期中古漢語, 晚期中古漢語輸入方案()), - (方案選項::近古漢語, 近古漢語輸入方案()), - (方案選項::現代漢語, 現代漢語輸入方案()), - (方案選項::粵語, 粵語輸入方案()), - (方案選項::宮保粵拼, 宮保粵拼輸入方案()), + pub static ref 方案列表: Vec<(方案选项, 输入方案定义<'static>)> = vec![ + (方案选项::宫保拼音, combo_pinyin::输入方案()), + (方案选项::拉丁字母, alphabet::输入方案()), + (方案选项::上古汉语, old_chinese::输入方案()), + (方案选项::早期中古汉语, early_middle_chinese::输入方案()), + (方案选项::晚期中古汉语, late_middle_chinese::输入方案()), + (方案选项::近古汉语, old_mandarin::输入方案()), + (方案选项::现代汉语, modern_chinese::输入方案()), + (方案选项::粤语, cantonese::输入方案()), + (方案选项::宫保粤拼, combo_jyutping::输入方案()), + (方案选项::小鹤双拼, double_pinyin_fly::输入方案()) ]; } -const 未定義方案: 輸入方案定義<'static> = 輸入方案定義 { - 名稱: "未定義", - 佈局: &拉丁字母鍵盤佈局, - 指法: 觸鍵方式::連擊, - 字根表: &[], - 轉寫法: 轉寫法定義 { - 輸入碼表示: &[], - 輸入碼鍵位: &[], - 拼式轉寫規則: &[], - 字根拆分規則: &[], - 拼式驗證規則: &[], +const 未定义方案: 输入方案定义<'static> = 输入方案定义 { + 名称: "未定义", + 布局: &拉丁字母键盘布局, + 指法: 击键方式::连击, + 键位映射: &[], + 转写: 转写定义 { + 编码预览: &[], + 键位提示: &[], + 输入棱镜: &[], + 词库棱镜: &[], + 拼式验证规则: &[], }, }; #[derive(Clone, Copy)] -pub struct 輸入方案機關輸出信號 { - pub 現行方案: ReadSignal<方案選項>, - pub 選用方案: WriteSignal<方案選項>, - pub 方案定義: Signal<輸入方案定義<'static>>, - pub 指法: Signal<觸鍵方式>, +pub struct 输入方案输出信号 { + pub 当前方案: ReadSignal<方案选项>, + pub 选用方案: WriteSignal<方案选项>, + pub 方案定义: Signal<输入方案定义<'static>>, + pub 指法: Signal<击键方式>, } -pub fn 輸入方案機關() -> 輸入方案機關輸出信號 { - let (現行方案, 選用方案) = signal(方案選項::default()); +pub fn 输入方案() -> 输入方案输出信号 { + let (当前方案, 选用方案) = signal(方案选项::default()); - let 方案定義 = Signal::derive(move || { - 方案選單 - .iter() - .find_map(|&(方案, 定義)| { - if 方案 == 現行方案() { - Some(定義) - } else { - None - } + let 方案定义 = Signal::derive(move || { + 方案列表.iter() + .find_map(|&(方案, 定义)| { + if 方案 == 当前方案() { Some(定义) } else { None } }) - .unwrap_or(未定義方案) + .unwrap_or(未定义方案) }); - let 指法 = Signal::derive(move || 方案定義.read().指法); + let 指法 = Signal::derive(move || 方案定义.read().指法); - 輸入方案機關輸出信號 { - 現行方案, - 選用方案, - 方案定義, + 输入方案输出信号 { + 当前方案, + 选用方案, + 方案定义, 指法, } } diff --git a/src/key_code.rs b/src/key_code.rs index 1651e7c..565d3d3 100644 --- a/src/key_code.rs +++ b/src/key_code.rs @@ -27,17 +27,17 @@ pub enum KeyCode { /// `f` and `F` F = 0x0009, /// `g` and `G` - G = 0x000A, + G = 0x000a, /// `h` and `H` - H = 0x000B, + H = 0x000b, /// `i` and `I` - I = 0x000C, + I = 0x000c, /// `j` and `J` - J = 0x000D, + J = 0x000d, /// `k` and `K` - K = 0x000E, + K = 0x000e, /// `l` and `L` - L = 0x000F, + L = 0x000f, /// `m` and `M` M = 0x0010, /// `n` and `N` @@ -59,17 +59,17 @@ pub enum KeyCode { /// `v` and `V` V = 0x0019, /// `w` and `W` - W = 0x001A, + W = 0x001a, /// `x` and `X` - X = 0x001B, + X = 0x001b, /// `y` and `Y` - Y = 0x001C, + Y = 0x001c, /// `z` and `Z` - Z = 0x001D, + Z = 0x001d, /// `1` and `!` - Kc1 = 0x001E, + Kc1 = 0x001e, /// `2` and `@` - Kc2 = 0x001F, + Kc2 = 0x001f, /// `3` and `#` Kc3 = 0x0020, /// `4` and `$` @@ -91,17 +91,17 @@ pub enum KeyCode { /// `Esc` Escape = 0x0029, /// `Backspace` - Backspace = 0x002A, + Backspace = 0x002a, /// `Tab` - Tab = 0x002B, + Tab = 0x002b, /// `Space` - Space = 0x002C, + Space = 0x002c, /// `-` and `_` - Minus = 0x002D, + Minus = 0x002d, /// `=` and `+` - Equal = 0x002E, + Equal = 0x002e, /// `[` and `{` - LeftBracket = 0x002F, + LeftBracket = 0x002f, /// `]` and `}` RightBracket = 0x0030, /// `\` and `|` @@ -123,17 +123,17 @@ pub enum KeyCode { /// `CapsLock` CapsLock = 0x0039, /// `F1` - F1 = 0x003A, + F1 = 0x003a, /// `F2` - F2 = 0x003B, + F2 = 0x003b, /// `F3` - F3 = 0x003C, + F3 = 0x003c, /// `F4` - F4 = 0x003D, + F4 = 0x003d, /// `F5` - F5 = 0x003E, + F5 = 0x003e, /// `F6` - F6 = 0x003F, + F6 = 0x003f, /// `F7` F7 = 0x0040, /// `F8` @@ -155,17 +155,17 @@ pub enum KeyCode { /// Insert Insert = 0x0049, /// Home - Home = 0x004A, + Home = 0x004a, /// Page Up - PageUp = 0x004B, + PageUp = 0x004b, /// Delete - Delete = 0x004C, + Delete = 0x004c, /// End - End = 0x004D, + End = 0x004d, /// Page Down - PageDown = 0x004E, + PageDown = 0x004e, /// Right arrow - Right = 0x004F, + Right = 0x004f, /// Left arrow Left = 0x0050, /// Down arrow @@ -187,17 +187,17 @@ pub enum KeyCode { /// `1` on keypad Kp1 = 0x0059, /// `2` on keypad - Kp2 = 0x005A, + Kp2 = 0x005a, /// `3` on keypad - Kp3 = 0x005B, + Kp3 = 0x005b, /// `4` on keypad - Kp4 = 0x005C, + Kp4 = 0x005c, /// `5` on keypad - Kp5 = 0x005D, + Kp5 = 0x005d, /// `6` on keypad - Kp6 = 0x005E, + Kp6 = 0x005e, /// `7` on keypad - Kp7 = 0x005F, + Kp7 = 0x005f, /// `8` on keypad Kp8 = 0x0060, /// `9` on keypad @@ -219,17 +219,17 @@ pub enum KeyCode { /// `F14` F14 = 0x0069, /// `F15` - F15 = 0x006A, + F15 = 0x006a, /// `F16` - F16 = 0x006B, + F16 = 0x006b, /// `F17` - F17 = 0x006C, + F17 = 0x006c, /// `F18` - F18 = 0x006D, + F18 = 0x006d, /// `F19` - F19 = 0x006E, + F19 = 0x006e, /// `F20` - F20 = 0x006F, + F20 = 0x006f, /// `F21` F21 = 0x0070, /// `F22` @@ -244,13 +244,13 @@ pub enum KeyCode { Select = 0x0077, Stop = 0x0078, Again = 0x0079, - Undo = 0x007A, - Cut = 0x007B, - Copy = 0x007C, - Paste = 0x007D, - Find = 0x007E, + Undo = 0x007a, + Cut = 0x007b, + Copy = 0x007c, + Paste = 0x007d, + Find = 0x007e, /// Mute - KbMute = 0x007F, + KbMute = 0x007f, /// Volume Up KbVolumeUp = 0x0080, /// Volume Down @@ -266,12 +266,12 @@ pub enum KeyCode { International1 = 0x0087, International2 = 0x0088, International3 = 0x0089, - International4 = 0x008A, - International5 = 0x008B, - International6 = 0x008C, - International7 = 0x008D, - International8 = 0x008E, - International9 = 0x008F, + International4 = 0x008a, + International5 = 0x008b, + International6 = 0x008c, + International7 = 0x008d, + International8 = 0x008e, + International9 = 0x008f, Language1 = 0x0090, Language2 = 0x0091, Language3 = 0x0092, @@ -282,97 +282,97 @@ pub enum KeyCode { Language8 = 0x0097, Language9 = 0x0098, AlternateErase = 0x0099, - SystemRequest = 0x009A, - Cancel = 0x009B, - Clear = 0x009C, - Prior = 0x009D, - Return = 0x009E, - Separator = 0x009F, - Out = 0x00A0, - Oper = 0x00A1, - ClearAgain = 0x00A2, - Crsel = 0x00A3, - Exsel = 0x00A4, - SystemPower = 0x00A5, - SystemSleep = 0x00A6, - SystemWake = 0x00A7, - AudioMute = 0x00A8, - AudioVolUp = 0x00A9, - AudioVolDown = 0x00AA, - MediaNextTrack = 0x00AB, - MediaPrevTrack = 0x00AC, - MediaStop = 0x00AD, - MediaPlayPause = 0x00AE, - MediaSelect = 0x00AF, - MediaEject = 0x00B0, - Mail = 0x00B1, - Calculator = 0x00B2, - MyComputer = 0x00B3, - WwwSearch = 0x00B4, - WwwHome = 0x00B5, - WwwBack = 0x00B6, - WwwForward = 0x00B7, - WwwStop = 0x00B8, - WwwRefresh = 0x00B9, - WwwFavorites = 0x00BA, - MediaFastForward = 0x00BB, - MediaRewind = 0x00BC, + SystemRequest = 0x009a, + Cancel = 0x009b, + Clear = 0x009c, + Prior = 0x009d, + Return = 0x009e, + Separator = 0x009f, + Out = 0x00a0, + Oper = 0x00a1, + ClearAgain = 0x00a2, + Crsel = 0x00a3, + Exsel = 0x00a4, + SystemPower = 0x00a5, + SystemSleep = 0x00a6, + SystemWake = 0x00a7, + AudioMute = 0x00a8, + AudioVolUp = 0x00a9, + AudioVolDown = 0x00aa, + MediaNextTrack = 0x00ab, + MediaPrevTrack = 0x00ac, + MediaStop = 0x00ad, + MediaPlayPause = 0x00ae, + MediaSelect = 0x00af, + MediaEject = 0x00b0, + Mail = 0x00b1, + Calculator = 0x00b2, + MyComputer = 0x00b3, + WwwSearch = 0x00b4, + WwwHome = 0x00b5, + WwwBack = 0x00b6, + WwwForward = 0x00b7, + WwwStop = 0x00b8, + WwwRefresh = 0x00b9, + WwwFavorites = 0x00ba, + MediaFastForward = 0x00bb, + MediaRewind = 0x00bc, /// Brightness Up - BrightnessUp = 0x00BD, + BrightnessUp = 0x00bd, /// Brightness Down - BrightnessDown = 0x00BE, - ControlPanel = 0x00BF, - Assistant = 0x00C0, - MissionControl = 0x00C1, - Launchpad = 0x00C2, + BrightnessDown = 0x00be, + ControlPanel = 0x00bf, + Assistant = 0x00c0, + MissionControl = 0x00c1, + Launchpad = 0x00c2, /// Mouse Up - MouseUp = 0x00CD, + MouseUp = 0x00cd, /// Mouse Down - MouseDown = 0x00CE, + MouseDown = 0x00ce, /// Mouse Left - MouseLeft = 0x00CF, + MouseLeft = 0x00cf, /// Mouse Right - MouseRight = 0x00D0, + MouseRight = 0x00d0, /// Mouse Button 1(Left) - MouseBtn1 = 0x00D1, + MouseBtn1 = 0x00d1, /// Mouse Button 2(Right) - MouseBtn2 = 0x00D2, + MouseBtn2 = 0x00d2, /// Mouse Button 3(Middle) - MouseBtn3 = 0x00D3, + MouseBtn3 = 0x00d3, /// Mouse Button 4(Back) - MouseBtn4 = 0x00D4, + MouseBtn4 = 0x00d4, /// Mouse Button 5(Forward) - MouseBtn5 = 0x00D5, - MouseBtn6 = 0x00D6, - MouseBtn7 = 0x00D7, - MouseBtn8 = 0x00D8, - MouseWheelUp = 0x00D9, - MouseWheelDown = 0x00DA, - MouseWheelLeft = 0x00DB, - MouseWheelRight = 0x00DC, - MouseAccel0 = 0x00DD, - MouseAccel1 = 0x00DE, - MouseAccel2 = 0x00DF, + MouseBtn5 = 0x00d5, + MouseBtn6 = 0x00d6, + MouseBtn7 = 0x00d7, + MouseBtn8 = 0x00d8, + MouseWheelUp = 0x00d9, + MouseWheelDown = 0x00da, + MouseWheelLeft = 0x00db, + MouseWheelRight = 0x00dc, + MouseAccel0 = 0x00dd, + MouseAccel1 = 0x00de, + MouseAccel2 = 0x00df, /// Left Control - LCtrl = 0x00E0, + LCtrl = 0x00e0, /// Left Shift - LShift = 0x00E1, + LShift = 0x00e1, /// Left Alt - LAlt = 0x00E2, + LAlt = 0x00e2, /// Left GUI - LGui = 0x00E3, + LGui = 0x00e3, /// Right Control - RCtrl = 0x00E4, + RCtrl = 0x00e4, /// Right Shift - RShift = 0x00E5, + RShift = 0x00e5, /// Right Alt - RAlt = 0x00E6, + RAlt = 0x00e6, /// Right GUI - RGui = 0x00E7, + RGui = 0x00e7, } -pub fn 網頁鍵值轉換(鍵值: &str) -> KeyCode { - match 鍵值 { +pub fn 网页键值转换(键值: &str) -> KeyCode { + match 键值 { "KeyA" => KeyCode::A, "KeyB" => KeyCode::B, "KeyC" => KeyCode::C, diff --git a/src/main.rs b/src/main.rs index d358788..cb1ebbb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,20 +4,22 @@ use leptos::prelude::*; -mod action; -mod app; -mod definition; -mod drill; +mod action; // 不清楚 +mod app; // 主程序吧 +mod definition; // 键盘有关的定义 +mod drill; // 练习文章 mod engine; -mod gear; -mod key_code; -mod spelling_algebra; -mod theory; -mod view; +mod gear; // 核心组件 +mod key_code; // 键盘映射 +mod rime2_api; +mod rime2_api_deprecated; +mod spelling_algebra; // 拼写运算 +mod theory; // 输入方案,应该叫schema的 +mod view; // 视图 -use app::Rime打字機應用; +use app::Rime打字机应用; fn main() { console_error_panic_hook::set_once(); - mount_to_body(|| view! { }); + mount_to_body(|| view! { }); } diff --git a/src/rime2_api.rs b/src/rime2_api.rs new file mode 100644 index 0000000..d2f2cc7 --- /dev/null +++ b/src/rime2_api.rs @@ -0,0 +1,64 @@ +use custom_attribute_macro::deprecated_until; +use parse_cargo_toml::get_package_info; +use std::ffi::CString; +use std::os::raw::c_char; +use std::sync::Mutex; + +lazy_static::lazy_static! { + static ref CURRENT_VERSION: Mutex = Mutex::new(String::new()); +} + +/// **Brief** 获取版本信息API +/// +/// **Description** 从Cargo.toml读取版本号和更新日期,返回格式化的版本字符串 +/// +/// **Return** *const c_char C风格的字符串指针,包含版本信息 +/// +/// **Safety** 调用者需要负责释放返回的字符串内存 +#[deprecated_until("0.0.0 2025-12-31")] +#[no_mangle] +pub extern "C" fn Rime2_API_getVersion() -> *const c_char { + match get_package_info() { + Ok((version, date)) => { + let version_str = format!("Ver{}({})", version, date); + let c_string = CString::new(version_str).unwrap(); + let ptr = c_string.into_raw(); + + // 存储到全局变量,确保内存不被释放 + let current_version = CURRENT_VERSION.lock().unwrap(); + // 先释放旧的字符串内存 + if !current_version.is_empty() { + unsafe { + let old_c_string = CString::from_raw(ptr); + drop(old_c_string); + } + } + + ptr + } + Err(e) => { + let error_msg = format!("Error: {}", e); + let c_string = CString::new(error_msg.clone()).unwrap(); + let ptr = c_string.into_raw(); + + let mut current_version = CURRENT_VERSION.lock().unwrap(); + *current_version = error_msg; + + ptr + } + } +} + +/// **Brief** 释放版本字符串内存 +/// +/// **Description** 释放通过rime2_API_getVersion获取的字符串内存 +/// +/// **Param** ptr *const c_char 需要释放的字符串指针 +#[no_mangle] +pub extern "C" fn rime2_API_freeVersionString(ptr: *const c_char) { + if !ptr.is_null() { + unsafe { + let _ = CString::from_raw(ptr as *mut c_char); + } + } +} diff --git a/src/rime2_api_deprecated.rs b/src/rime2_api_deprecated.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/spelling_algebra.rs b/src/spelling_algebra.rs index d159a86..a762aa4 100644 --- a/src/spelling_algebra.rs +++ b/src/spelling_algebra.rs @@ -2,33 +2,45 @@ use lazy_regex::Regex; use maybe_owned::MaybeOwned; use std::collections::HashMap; -pub enum 拼寫運算<'a> { - 變換 { +pub enum 拼写运算<'a> { + 变换 { 模式: MaybeOwned<'a, Regex>, - 替換文字: &'a str, + 替换文字: &'a str, }, - 轉寫 { + 转写 { 字符映射: HashMap, }, 消除 { 模式: MaybeOwned<'a, Regex>, }, + 派生 { + 模式: MaybeOwned<'a, Regex>, + 替换文字: &'a str, + }, + 模糊 { + 模式: MaybeOwned<'a, Regex>, + 替换文字: &'a str, + }, + 缩写 { + 模式: MaybeOwned<'a, Regex>, + 替换文字: &'a str, + }, } #[macro_export] -macro_rules! 變換 { - ($模式:literal, $替換文字:literal) => { - 拼寫運算::變換 { +macro_rules! 变换 { + ($模式:literal, $替换文字:literal) => { + 拼写运算::变换 { 模式: regex!($模式).deref().into(), - 替換文字: $替換文字, + 替换文字: $替换文字, } }; } #[macro_export] -macro_rules! 轉寫 { +macro_rules! 转写 { ($左字表:literal, $右字表:literal) => { - 拼寫運算::轉寫 { + 拼写运算::转写 { 字符映射: std::iter::zip($左字表.chars(), $右字表.chars()).collect(), } }; @@ -37,36 +49,75 @@ macro_rules! 轉寫 { #[macro_export] macro_rules! 消除 { ($模式:literal) => { - 拼寫運算::消除 { + 拼写运算::消除 { + 模式: regex!($模式).deref().into(), + } + }; +} + +#[macro_export] +macro_rules! 派生 { + ($模式:literal, $替换文字:literal) => { + 拼写运算::派生 { 模式: regex!($模式).deref().into(), + 替换文字: $替换文字, } }; } -pub fn 施展拼寫運算(原形: &str, 運算規則: &[拼寫運算]) -> Option { +#[macro_export] +macro_rules! 模糊 { + ($模式:literal, $替换文字:literal) => { + 拼写运算::模糊 { + 模式: regex!($模式).deref().into(), + 替换文字: $替换文字, + } + }; +} + +#[macro_export] +macro_rules! 缩写 { + ($模式:literal, $替换文字:literal) => { + 拼写运算::缩写 { + 模式: regex!($模式).deref().into(), + 替换文字: $替换文字, + } + }; +} + +pub fn 施展拼写运算(原形: &str, 运算规则: &[拼写运算]) -> Option { if 原形.is_empty() { return None; } - let mut 運算結果 = 原形.to_owned(); - for 運算 in 運算規則 { - match 運算 { - 拼寫運算::變換 { - ref 模式, 替換文字 + let mut 运算结果 = 原形.to_owned(); + for 运算 in 运算规则 { + match 运算 { + 拼写运算::变换 { + ref 模式, 替换文字 + } + | 拼写运算::派生 { + ref 模式, 替换文字 + } + | 拼写运算::模糊 { + ref 模式, 替换文字 + } + | 拼写运算::缩写 { + ref 模式, 替换文字 } => { - 運算結果 = 模式.replace_all(&運算結果, *替換文字).to_string(); + 运算结果 = 模式.replace_all(&运算结果, *替换文字).to_string(); } - 拼寫運算::轉寫 { ref 字符映射 } => { - 運算結果 = 運算結果 + 拼写运算::转写 { ref 字符映射 } => { + 运算结果 = 运算结果 .chars() .map(|字符| 字符映射.get(&字符).copied().unwrap_or(字符)) .collect::(); } - 拼寫運算::消除 { ref 模式 } => { - if 模式.is_match(&運算結果) { + 拼写运算::消除 { ref 模式 } => { + if 模式.is_match(&运算结果) { return None; } } }; } - (!運算結果.is_empty()).then_some(運算結果) + (!运算结果.is_empty()).then_some(运算结果) } diff --git a/src/theory/alphabet.rs b/src/theory/alphabet.rs index f35b68b..3e695d9 100644 --- a/src/theory/alphabet.rs +++ b/src/theory/alphabet.rs @@ -1,82 +1,73 @@ -use lazy_regex::{regex, Regex}; +use lazy_regex::{ regex, Regex }; use lazy_static::lazy_static; -use crate::definition::{觸鍵方式, 輸入方案定義, 轉寫法定義, 鍵位定義}; -use crate::gear::layout::拉丁字母鍵盤佈局; +use crate::definition::{ 击键方式, 转写定义, 输入方案定义, 键位映射定义 }; +use crate::gear::layout::拉丁字母键盘布局; use crate::key_code::KeyCode; -use crate::spelling_algebra::拼寫運算; -use crate::轉寫; +use crate::spelling_algebra::拼写运算; +use crate::转写; +use crate::默认映射; -macro_rules! 字母鍵 { - ($字母: ident) => { - 鍵位定義 { - 輸入碼: stringify!($字母), - 鍵碼: KeyCode::$字母, - } - }; -} - -const 字母表: &[鍵位定義] = &[ - 字母鍵!(A), - 字母鍵!(B), - 字母鍵!(C), - 字母鍵!(D), - 字母鍵!(E), - 字母鍵!(F), - 字母鍵!(G), - 字母鍵!(H), - 字母鍵!(I), - 字母鍵!(J), - 字母鍵!(K), - 字母鍵!(L), - 字母鍵!(M), - 字母鍵!(N), - 字母鍵!(O), - 字母鍵!(P), - 字母鍵!(Q), - 字母鍵!(R), - 字母鍵!(S), - 字母鍵!(T), - 字母鍵!(U), - 字母鍵!(V), - 字母鍵!(W), - 字母鍵!(X), - 字母鍵!(Y), - 字母鍵!(Z), - 鍵位定義 { - 輸入碼: "␣", - 鍵碼: KeyCode::Space, +const 字母表: &[键位映射定义] = &[ + 默认映射!(A), + 默认映射!(B), + 默认映射!(C), + 默认映射!(D), + 默认映射!(E), + 默认映射!(F), + 默认映射!(G), + 默认映射!(H), + 默认映射!(I), + 默认映射!(J), + 默认映射!(K), + 默认映射!(L), + 默认映射!(M), + 默认映射!(N), + 默认映射!(O), + 默认映射!(P), + 默认映射!(Q), + 默认映射!(R), + 默认映射!(S), + 默认映射!(T), + 默认映射!(U), + 默认映射!(V), + 默认映射!(W), + 默认映射!(X), + 默认映射!(Y), + 默认映射!(Z), + 键位映射定义 { + 输入码: "␣", + 键码: KeyCode::Space, }, - 鍵位定義 { - 輸入碼: "'", - 鍵碼: KeyCode::Quote, + 键位映射定义 { + 输入码: "'", + 键码: KeyCode::Quote, }, - 鍵位定義 { - 輸入碼: "-", - 鍵碼: KeyCode::Minus, + 键位映射定义 { + 输入码: "-", + 键码: KeyCode::Minus, }, ]; lazy_static! { - static ref 字母轉鍵位: Box<[拼寫運算<'static>]> = Box::new([轉寫!( - "abcdefghijklmnopqrstuvwxyz ", - "ABCDEFGHIJKLMNOPQRSTUVWXYZ␣" - ),]); - static ref 驗證拉丁文: Box<[&'static Regex]> = Box::new([regex!("^([-A-Za-z '])+$").deref(),]); + static ref 字母转键位: Box<[拼写运算<'static>]> = Box::new([ + 转写!("abcdefghijklmnopqrstuvwxyz ", "ABCDEFGHIJKLMNOPQRSTUVWXYZ␣"), + ]); + static ref 貌似拉丁: Box<[&'static Regex]> = Box::new([regex!("^([-A-Za-z '])+$").deref()]); } -pub fn 拉丁字母輸入方案() -> 輸入方案定義<'static> { - 輸入方案定義 { - 名稱: "拉丁字母", - 佈局: &拉丁字母鍵盤佈局, - 指法: 觸鍵方式::連擊, - 字根表: 字母表, - 轉寫法: 轉寫法定義 { - 輸入碼表示: &[], - 輸入碼鍵位: &[], - 拼式轉寫規則: &[], - 字根拆分規則: &字母轉鍵位, - 拼式驗證規則: &驗證拉丁文, +pub fn 输入方案() -> 输入方案定义<'static> { + 输入方案定义 { + 名称: "拉丁字母", + 布局: &拉丁字母键盘布局, + 指法: 击键方式::连击, + 键位映射: 字母表, + 转写: 转写定义 { + 编码预览: &[], + 键位提示: &[], + 输入棱镜: &[], + 词库棱镜: &字母转键位, + 拼式验证规则: &貌似拉丁, }, } } diff --git a/src/theory/cantonese.rs b/src/theory/cantonese.rs index ac9e01b..2714285 100644 --- a/src/theory/cantonese.rs +++ b/src/theory/cantonese.rs @@ -1,188 +1,182 @@ use lazy_regex::regex; use lazy_static::lazy_static; -use crate::definition::{觸鍵方式, 輸入方案定義, 轉寫法定義, 鍵位定義}; -use crate::gear::layout::{ - 上檔盤面, 基本盤面, 大寫字母盤面, 盤面定義, 盤面選擇碼, 配列, 鍵盤佈局, 鍵面刻印, -}; +use crate::definition::{ 击键方式, 转写定义, 输入方案定义, 键位映射定义 }; +use crate::gear::layout::{ 基本盘面, 上档盘面, 大写字母盘面 }; +use crate::gear::layout::{ 键面刻印, 盘面定义, 盘面序号, 键盘布局, 键盘配列 }; use crate::key_code::KeyCode; -use crate::spelling_algebra::拼寫運算; -use crate::{盤面, 變換, 鍵面}; +use crate::spelling_algebra::拼写运算; +use crate::{ 键面, 盘面 }; +use crate::变换; +use crate::键位映射; -macro_rules! 鍵位 { - ($輸入碼: ident => $鍵碼: path) => { - 鍵位定義 { - 輸入碼: stringify!($輸入碼), - 鍵碼: $鍵碼, - } - }; -} +const 粤语拼音盘面: 盘面定义<'static> = + 盘面![ + [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], + [ 空 {中:清, 上:_, 下:_, 左:_, 右:以} {中:来, 上:_, 下:_, 左:以, 右:泥} {中:端, 上:_, 下:_, 左:泥, 右:_} 透 科 {中:孤, 上:_, 下:_, 左:_, 右:高} {中:修, 上:_, 下:_, 左:高, 右:宾} {中:毕, 上:_, 下:_, 左:宾, 右:_} 空 _ _ ], + [ 空 {中:心, 上:_, 下:_, 左:_, 右:云} {中:晓, 上:_, 下:_, 左:云, 右:疑} {中:见, 上:_, 下:_, 左:疑, 右:_} 溪 遮 {中:师, 上:_, 下:_, 左:_, 右:几} {中:威, 上:_, 下:_, 左:几, 右:登} {中:德, 上:_, 下:_, 左:登, 右:_} 空 _ ], + [ 空 {中:精, 上:_, 下:_, 左:_, 右:亚} {中:非, 上:_, 下:_, 左:亚, 右:明} {中:帮, 上:_, 下:_, 左:明, 右:_} 滂 靴 诸 {中:吾, 上:_, 下:_, 左:_, 右:金} {中:急, 上:_, 下:_, 左:金, 右:_} 空 ], + [ 家 _ 家 ] +]; + +const 粤语并击布局: 键盘布局 = 键盘布局 { + 盘面: &[基本盘面, 上档盘面, 大写字母盘面, 粤语拼音盘面], + 默认盘面: 盘面序号(4), + 默认配列: 键盘配列::正交直列, +}; -const 並擊鍵序: &[鍵位定義] = &[ - 鍵位!(心 => KeyCode::S), - 鍵位!(清 => KeyCode::W), - 鍵位!(精 => KeyCode::X), - 鍵位!(曉 => KeyCode::D), - 鍵位!(來 => KeyCode::E), - 鍵位!(非 => KeyCode::C), - 鍵位!(見 => KeyCode::F), - 鍵位!(端 => KeyCode::R), - 鍵位!(幫 => KeyCode::V), - 鍵位!(溪 => KeyCode::G), - 鍵位!(透 => KeyCode::T), - 鍵位!(滂 => KeyCode::B), - 鍵位!(家 => KeyCode::Space), - 鍵位!(遮 => KeyCode::H), - 鍵位!(科 => KeyCode::Y), - 鍵位!(靴 => KeyCode::N), - 鍵位!(師 => KeyCode::J), - 鍵位!(孤 => KeyCode::U), - 鍵位!(諸 => KeyCode::M), - 鍵位!(威 => KeyCode::K), - 鍵位!(修 => KeyCode::I), - 鍵位!(吾 => KeyCode::Comma), - 鍵位!(德 => KeyCode::L), - 鍵位!(畢 => KeyCode::O), - 鍵位!(急 => KeyCode::Dot), +const 并击键位映射: &[键位映射定义] = &[ + 键位映射!(心 => KeyCode::S), + 键位映射!(清 => KeyCode::W), + 键位映射!(精 => KeyCode::X), + 键位映射!(晓 => KeyCode::D), + 键位映射!(来 => KeyCode::E), + 键位映射!(非 => KeyCode::C), + 键位映射!(见 => KeyCode::F), + 键位映射!(端 => KeyCode::R), + 键位映射!(帮 => KeyCode::V), + 键位映射!(溪 => KeyCode::G), + 键位映射!(透 => KeyCode::T), + 键位映射!(滂 => KeyCode::B), + 键位映射!(家 => KeyCode::Space), + 键位映射!(遮 => KeyCode::H), + 键位映射!(科 => KeyCode::Y), + 键位映射!(靴 => KeyCode::N), + 键位映射!(师 => KeyCode::J), + 键位映射!(孤 => KeyCode::U), + 键位映射!(诸 => KeyCode::M), + 键位映射!(威 => KeyCode::K), + 键位映射!(修 => KeyCode::I), + 键位映射!(吾 => KeyCode::Comma), + 键位映射!(德 => KeyCode::L), + 键位映射!(毕 => KeyCode::O), + 键位映射!(急 => KeyCode::Dot), ]; lazy_static! { - static ref 並擊碼表示: Box<[拼寫運算::<'static>]> = Box::new([ - 變換!("非幫", "明"), - 變換!("來端", "泥"), - 變換!("曉見", "我"), - 變換!("心見", "古"), - 變換!("心溪", "困"), - 變換!("心曉", "云"), - 變換!("清來", "以"), - 變換!("精非", "亞"), - 變換!("^([家遮科靴登賓金德畢急威修])", "亞$1"), - 變換!("^([師諸])", "以$1"), - 變換!("^([孤])", "云$1"), - 變換!("修畢", "賓"), - 變換!("威德", "登"), - 變換!("吾急", "金"), - 變換!("師賓", "先"), - 變換!("師畢", "屑"), - 變換!("師威", "幾"), - 變換!("孤登", "東"), - 變換!("孤德", "篤"), - 變換!("師登", "英"), - 變換!("師德", "益"), - 變換!("遮登", "鄭"), - 變換!("遮德", "石"), - 變換!("靴登", "張"), - 變換!("靴德", "着"), - 變換!("科登", "剛"), - 變換!("科德", "角"), - 變換!("師修", "朝"), - 變換!("孤修", "高"), - 變換!("諸賓", "鴛"), - 變換!("諸畢", "乙"), - 變換!("家威", "皆"), - 變換!("家修", "交"), - 變換!("科威", "栽"), - 變換!("師金", "兼"), - 變換!("師急", "劫"), - 變換!("靴賓", "津"), - 變換!("靴畢", "卒"), - 變換!("靴威", "雖"), - 變換!("家金", "緘"), - 變換!("家急", "甲"), - 變換!("家賓", "翻"), - 變換!("家畢", "發"), - 變換!("孤賓", "官"), - 變換!("孤畢", "括"), - 變換!("孤威", "魁"), - 變換!("科賓", "干"), - 變換!("科畢", "割"), - 變換!("科金", "甘"), - 變換!("科急", "蛤"), - 變換!("家登", "彭"), - 變換!("家德", "額"), + static ref 并击码表示: Box<[拼写运算<'static>]> = Box::new([ + 变换!("非帮", "明"), + 变换!("来端", "泥"), + 变换!("晓见", "我"), + 变换!("心见", "古"), + 变换!("心溪", "困"), + 变换!("心晓", "云"), + 变换!("清来", "以"), + 变换!("精非", "亚"), + 变换!("^([家遮科靴登宾金德毕急威修])", "亚$1"), + 变换!("^([师诸])", "以$1"), + 变换!("^([孤])", "云$1"), + 变换!("修毕", "宾"), + 变换!("威德", "登"), + 变换!("吾急", "金"), + 变换!("师宾", "先"), + 变换!("师毕", "屑"), + 变换!("师威", "几"), + 变换!("孤登", "东"), + 变换!("孤德", "笃"), + 变换!("师登", "英"), + 变换!("师德", "益"), + 变换!("遮登", "郑"), + 变换!("遮德", "石"), + 变换!("靴登", "张"), + 变换!("靴德", "着"), + 变换!("科登", "刚"), + 变换!("科德", "角"), + 变换!("师修", "朝"), + 变换!("孤修", "高"), + 变换!("诸宾", "鸳"), + 变换!("诸毕", "乙"), + 变换!("家威", "皆"), + 变换!("家修", "交"), + 变换!("科威", "栽"), + 变换!("师金", "兼"), + 变换!("师急", "劫"), + 变换!("靴宾", "津"), + 变换!("靴毕", "卒"), + 变换!("靴威", "虽"), + 变换!("家金", "缄"), + 变换!("家急", "甲"), + 变换!("家宾", "翻"), + 变换!("家毕", "发"), + 变换!("孤宾", "官"), + 变换!("孤毕", "括"), + 变换!("孤威", "魁"), + 变换!("科宾", "干"), + 变换!("科毕", "割"), + 变换!("科金", "甘"), + 变换!("科急", "蛤"), + 变换!("家登", "彭"), + 变换!("家德", "额"), ]); - static ref 並擊碼鍵位: Box<[拼寫運算<'static>]> = Box::new([ - 變換!("明", "非幫"), - 變換!("泥", "來端"), - 變換!("我", "曉見"), - 變換!("古", "心見"), - 變換!("困", "心溪"), - 變換!("先", "師賓"), - 變換!("屑", "師畢"), - 變換!("幾", "師威"), - 變換!("東", "孤登"), - 變換!("篤", "孤德"), - 變換!("英", "師登"), - 變換!("益", "師德"), - 變換!("鄭", "遮登"), - 變換!("石", "遮德"), - 變換!("張", "靴登"), - 變換!("着", "靴德"), - 變換!("剛", "科登"), - 變換!("角", "科德"), - 變換!("朝", "師修"), - 變換!("高", "孤修"), - 變換!("鴛", "諸賓"), - 變換!("乙", "諸畢"), - 變換!("皆", "家威"), - 變換!("交", "家修"), - 變換!("栽", "科威"), - 變換!("兼", "師金"), - 變換!("劫", "師急"), - 變換!("津", "靴賓"), - 變換!("卒", "靴畢"), - 變換!("雖", "靴威"), - 變換!("緘", "家金"), - 變換!("甲", "家急"), - 變換!("翻", "家賓"), - 變換!("發", "家畢"), - 變換!("官", "孤賓"), - 變換!("括", "孤畢"), - 變換!("魁", "孤威"), - 變換!("干", "科賓"), - 變換!("割", "科畢"), - 變換!("甘", "科金"), - 變換!("蛤", "科急"), - 變換!("彭", "家登"), - 變換!("額", "家德"), - 變換!("亞([遮科靴登賓金德畢急威修])", "$1"), - 變換!("以([師諸])", "$1"), - 變換!("云([孤])", "$1"), - 變換!("亞", "精非"), - 變換!("以", "清來"), - 變換!("云", "心曉"), - 變換!("賓", "修畢"), - 變換!("登", "威德"), - 變換!("金", "吾急"), + + static ref 并击码键位: Box<[拼写运算<'static>]> = Box::new([ + 变换!("明", "非帮"), + 变换!("泥", "来端"), + 变换!("我", "晓见"), + 变换!("古", "心见"), + 变换!("困", "心溪"), + 变换!("先", "师宾"), + 变换!("屑", "师毕"), + 变换!("几", "师威"), + 变换!("东", "孤登"), + 变换!("笃", "孤德"), + 变换!("英", "师登"), + 变换!("益", "师德"), + 变换!("郑", "遮登"), + 变换!("石", "遮德"), + 变换!("张", "靴登"), + 变换!("着", "靴德"), + 变换!("刚", "科登"), + 变换!("角", "科德"), + 变换!("朝", "师修"), + 变换!("高", "孤修"), + 变换!("鸳", "诸宾"), + 变换!("乙", "诸毕"), + 变换!("皆", "家威"), + 变换!("交", "家修"), + 变换!("栽", "科威"), + 变换!("兼", "师金"), + 变换!("劫", "师急"), + 变换!("津", "靴宾"), + 变换!("卒", "靴毕"), + 变换!("虽", "靴威"), + 变换!("缄", "家金"), + 变换!("甲", "家急"), + 变换!("翻", "家宾"), + 变换!("发", "家毕"), + 变换!("官", "孤宾"), + 变换!("括", "孤毕"), + 变换!("魁", "孤威"), + 变换!("干", "科宾"), + 变换!("割", "科毕"), + 变换!("甘", "科金"), + 变换!("蛤", "科急"), + 变换!("彭", "家登"), + 变换!("额", "家德"), + 变换!("亚([遮科靴登宾金德毕急威修])", "$1"), + 变换!("以([师诸])", "$1"), + 变换!("云([孤])", "$1"), + 变换!("亚", "精非"), + 变换!("以", "清来"), + 变换!("云", "心晓"), + 变换!("宾", "修毕"), + 变换!("登", "威德"), + 变换!("金", "吾急"), ]); } -const 粵語拼音盤面: 盤面定義<'static> = 盤面![ - [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], - [ 空 {中:清, 上:_, 下:_, 左:_, 右:以} {中:來, 上:_, 下:_, 左:以, 右:泥} {中:端, 上:_, 下:_, 左:泥, 右:_} 透 科 {中:孤, 上:_, 下:_, 左:_, 右:高} {中:修, 上:_, 下:_, 左:高, 右:賓} {中:畢, 上:_, 下:_, 左:賓, 右:_} 空 _ _ ], - [ 空 {中:心, 上:_, 下:_, 左:_, 右:云} {中:曉, 上:_, 下:_, 左:云, 右:疑} {中:見, 上:_, 下:_, 左:疑, 右:_} 溪 遮 {中:師, 上:_, 下:_, 左:_, 右:幾} {中:威, 上:_, 下:_, 左:幾, 右:登} {中:德, 上:_, 下:_, 左:登, 右:_} 空 _ ], - [ 空 {中:精, 上:_, 下:_, 左:_, 右:亞} {中:非, 上:_, 下:_, 左:亞, 右:明} {中:幫, 上:_, 下:_, 左:明, 右:_} 滂 靴 諸 {中:吾, 上:_, 下:_, 左:_, 右:金} {中:急, 上:_, 下:_, 左:金, 右:_} 空 ], - [ 家 _ 家 ] -]; - -const 粵語並擊佈局: 鍵盤佈局 = 鍵盤佈局 { - 盤面: &[基本盤面, 上檔盤面, 大寫字母盤面, 粵語拼音盤面], - 默認盤面: 盤面選擇碼(4), - 首選配列: 配列::正交直列, -}; - -pub fn 粵語輸入方案() -> 輸入方案定義<'static> { - 輸入方案定義 { - 名稱: "粵語", - 佈局: &粵語並擊佈局, - 指法: 觸鍵方式::並擊, - 字根表: 並擊鍵序, - 轉寫法: 轉寫法定義 { - 輸入碼表示: &並擊碼表示, - 輸入碼鍵位: &並擊碼鍵位, - 拼式轉寫規則: &[], - 字根拆分規則: &[], - 拼式驗證規則: &[], +pub fn 输入方案() -> 输入方案定义<'static> { + 输入方案定义 { + 名称: "粤语", + 布局: &粤语并击布局, + 指法: 击键方式::并击, + 键位映射: 并击键位映射, + 转写: 转写定义 { + 编码预览: &并击码表示, + 键位提示: &并击码键位, + 输入棱镜: &[], + 词库棱镜: &[], + 拼式验证规则: &[], }, } } diff --git a/src/theory/combo_jyutping.rs b/src/theory/combo_jyutping.rs index cc149fa..5e101ae 100644 --- a/src/theory/combo_jyutping.rs +++ b/src/theory/combo_jyutping.rs @@ -1,206 +1,201 @@ -use lazy_regex::{regex, Regex}; +use lazy_regex::{ regex, Regex }; use lazy_static::lazy_static; -use crate::definition::{觸鍵方式, 輸入方案定義, 轉寫法定義, 鍵位定義}; -use crate::gear::layout::{ - 上檔盤面, 基本盤面, 大寫字母盤面, 盤面定義, 盤面選擇碼, 配列, 鍵盤佈局, 鍵面刻印, -}; +use crate::definition::{ 击键方式, 转写定义, 输入方案定义, 键位映射定义 }; +use crate::gear::layout::{ 上档盘面, 基本盘面, 大写字母盘面 }; +use crate::gear::layout::{ 盘面定义, 盘面序号, 键盘布局, 键盘配列, 键面刻印 }; use crate::key_code::KeyCode; -use crate::spelling_algebra::拼寫運算; -use crate::{盤面, 變換, 轉寫, 鍵面}; +use crate::spelling_algebra::拼写运算; +use crate::{ 变换, 转写 }; +use crate::{ 盘面, 键面 }; +use crate::键位映射; -macro_rules! 鍵位 { - ($輸入碼: ident => $鍵碼: path) => { - 鍵位定義 { - 輸入碼: stringify!($輸入碼), - 鍵碼: $鍵碼, - } - }; -} +const 宫保粤拼盘面: 盘面定义<'static> = + 盘面![ + [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], + [ 空 {中:c, 上:_, 下:_, 左:_, 右:j} {中:l, 上:_, 下:_, 左:_, 右:_} {中:d, 上:_, 下:_, 左:n, 右:_} t o {中:u, 上:_, 下:_, 左:_, 右:ou} {中:"˗u", 上:_, 下:_, 左:_, 右:_} {中:"˗t", 上:_, 下:_, 左:"˗n", 右:_} 空 _ _ ], + [ 空 {中:s, 上:_, 下:_, 左:_, 右:w} {中:h, 上:_, 下:_, 左:_, 右:_} {中:g, 上:_, 下:_, 左:ng, 右:_} k e {中:i, 上:_, 下:_, 左:_, 右:ei} {中:"˗i", 上:_, 下:_, 左:_, 右:_} {中:"˗k", 上:_, 下:_, 左:"˗ng", 右:_} 空 _ ], + [ 空 {中:z, 上:_, 下:_, 左:_, 右:"'"} {中:f, 上:_, 下:_, 左:_, 右:_} {中:b, 上:_, 下:_, 左:m, 右:_} p {中:oe, 上:_, 下:eo, 左:_, 右:_} yu {中:"m", 上:_, 下:_, 左:_, 右:_} {中:"˗p", 上:_, 下:_, 左:"˗m", 右:_} 空 ], + [ aa _ aa ] +]; -const 並擊鍵序: &[鍵位定義] = &[ - 鍵位!(S => KeyCode::S), - 鍵位!(C => KeyCode::W), - 鍵位!(Z => KeyCode::X), - 鍵位!(H => KeyCode::D), - 鍵位!(L => KeyCode::E), - 鍵位!(F => KeyCode::C), - 鍵位!(G => KeyCode::F), - 鍵位!(D => KeyCode::R), - 鍵位!(B => KeyCode::V), - 鍵位!(K => KeyCode::G), - 鍵位!(T => KeyCode::T), - 鍵位!(P => KeyCode::B), - 鍵位!(A => KeyCode::Space), - 鍵位!(E => KeyCode::H), - 鍵位!(O => KeyCode::Y), - 鍵位!(V => KeyCode::N), - 鍵位!(I => KeyCode::J), - 鍵位!(U => KeyCode::U), - 鍵位!(Y => KeyCode::M), - 鍵位!(J => KeyCode::K), - 鍵位!(W => KeyCode::I), - 鍵位!(M => KeyCode::Comma), - 鍵位!(Q => KeyCode::L), - 鍵位!(R => KeyCode::O), - 鍵位!(X => KeyCode::Dot), +const 宫保粤拼布局: 键盘布局 = 键盘布局 { + 盘面: &[基本盘面, 上档盘面, 大写字母盘面, 宫保粤拼盘面], + 默认盘面: 盘面序号(4), + 默认配列: 键盘配列::正交直列, +}; + +const 并击键位映射: &[键位映射定义] = &[ + 键位映射!(A => KeyCode::Space), + 键位映射!(B => KeyCode::V), + 键位映射!(C => KeyCode::W), + 键位映射!(D => KeyCode::R), + 键位映射!(E => KeyCode::H), + 键位映射!(F => KeyCode::C), + 键位映射!(G => KeyCode::F), + 键位映射!(H => KeyCode::D), + 键位映射!(I => KeyCode::J), + 键位映射!(J => KeyCode::K), + 键位映射!(K => KeyCode::G), + 键位映射!(L => KeyCode::E), + 键位映射!(M => KeyCode::Comma), + 键位映射!(O => KeyCode::Y), + 键位映射!(P => KeyCode::B), + 键位映射!(Q => KeyCode::L), + 键位映射!(R => KeyCode::O), + 键位映射!(S => KeyCode::S), + 键位映射!(T => KeyCode::T), + 键位映射!(U => KeyCode::U), + 键位映射!(V => KeyCode::N), + 键位映射!(W => KeyCode::I), + 键位映射!(X => KeyCode::Dot), + 键位映射!(Y => KeyCode::M), + 键位映射!(Z => KeyCode::X), ]; lazy_static! { - static ref 並擊轉粵拼: Box<[拼寫運算::<'static>]> = Box::new([ - 變換!("^FBM$", "m"), - 變換!("^HGM$", "ng"), - 變換!("FB", "m"), - 變換!("LD", "n"), - 變換!("HG", "ng"), - 變換!("SG", "gw"), - 變換!("SK", "kw"), - 變換!("SH", "w"), - 變換!("CL", "j"), - 變換!("ZF", ""), - 變換!("AI", "E"), - 變換!("AU", "O"), - 變換!("AY", "V"), - 變換!("A", "aa"), - 變換!("Y", "yu"), - 變換!("V(J|W?R)$", "eo${1}"), - 變換!("V", "oe"), - 變換!("JQ", "-ng"), - 變換!("WR", "-n"), - 變換!("MX", "-m"), - 變換!("Q$", "-k"), - 變換!("R$", "-t"), - 變換!("X$", "-p"), - 變換!("IJ", "ei"), - 變換!("UW", "ou"), - 變換!("J$", "-i"), - 變換!("W$", "-u"), - 轉寫!("SCZHLFGDBKTPEOIUM", "sczhlfgdbktpeoium"), - 變換!("([aeiou])-([iumptk]|ng?)$", "${1}${2}"), - 變換!("-", "a"), - 變換!(" ", ""), - 變換!("^([iy])", "j${1}"), - 變換!("^(u)", "w${1}"), + static ref 并击码表示: Box<[拼写运算<'static>]> = Box::new([ + 变换!("^FBM$", "m"), + 变换!("^HGM$", "ng"), + 变换!("FB", "m"), + 变换!("LD", "n"), + 变换!("HG", "ng"), + 变换!("SG", "gw"), + 变换!("SK", "kw"), + 变换!("SH", "w"), + 变换!("CL", "j"), + 变换!("ZF", ""), + 变换!("AI", "E"), + 变换!("AU", "O"), + 变换!("AY", "V"), + 变换!("A", "aa"), + 变换!("Y", "yu"), + 变换!("V(J|W?R)$", "eo${1}"), + 变换!("V", "oe"), + 变换!("JQ", "-ng"), + 变换!("WR", "-n"), + 变换!("MX", "-m"), + 变换!("Q$", "-k"), + 变换!("R$", "-t"), + 变换!("X$", "-p"), + 变换!("IJ", "ei"), + 变换!("UW", "ou"), + 变换!("J$", "-i"), + 变换!("W$", "-u"), + 转写!("SCZHLFGDBKTPEOIUM", "sczhlfgdbktpeoium"), + 变换!("^([bpmfdtnlgkhzcsjw]|ng|[gk]w*)([-aeiouy])", "${1} ${2}"), ]); - static ref 粵拼轉並擊: Box<[拼寫運算<'static>]> = Box::new([ - 變換!("^m", "FB"), - 變換!("^ng", "HG"), - 變換!("^n", "LD"), - 變換!("^gw", "SG"), - 變換!("^kw", "SK"), - 變換!("^w([^u])", "SH${1}"), - 變換!("^j([^iy])", "CL${1}"), - 變換!("([aeiou])n$", "${1}WR"), - 變換!("([aeoiu])t$", "${1}R"), - 變換!("([aeoiu])ng$", "${1}JQ"), - 變換!("([aeoiu])k$", "${1}Q"), - 變換!("([aeoiu])m$", "${1}MX"), - 變換!("([aeoiu])p$", "${1}X"), - 變換!("ei$", "IJ"), - 變換!("([aou])i$", "${1}J"), - 變換!("ou$", "UW"), - 變換!("([aei])u$", "${1}W"), - 變換!("aa", "A"), - 變換!("oe|eo", "V"), - 變換!("^j([iy])", "${1}"), - 變換!("^w(u)", "${1}"), - 變換!("^j", "CL"), - 變換!("^w", "SH"), - 變換!("yu", "Y"), - 變換!("a", ""), - 轉寫!("sczhlfgdbktpeoiu", "SCZHLFGDBKTPEOIU"), + static ref 并击码键位: Box<[拼写运算<'static>]> = Box::new([ + 变换!("^m", "FB"), + 变换!("^ng", "HG"), + 变换!("^n", "LD"), + 变换!("^gw", "SG"), + 变换!("^kw", "SK"), + 变换!("^w([^u])", "SH${1}"), + 变换!("^j([^iy])", "CL${1}"), + 变换!("-n$", "WR"), + 变换!("-t$", "R"), + 变换!("-ng$", "JQ"), + 变换!("-k$", "Q"), + 变换!("-m$", "MX"), + 变换!("-p$", "X"), + 变换!("ei$", "IJ"), + 变换!("-i$", "J"), + 变换!("ou$", "UW"), + 变换!("-u$", "W"), + 变换!("aa", "A"), + 变换!("oe|eo", "V"), + 变换!("^j([iy])", "${1}"), + 变换!("^w(u)", "${1}"), + 变换!("^j", "CL"), + 变换!("^w", "SH"), + 变换!("yu", "Y"), + 转写!("sczhlfgdbktpeoiu", "SCZHLFGDBKTPEOIU"), ]); - static ref 並擊碼表示: Box<[拼寫運算<'static>]> = Box::new([ - 變換!("^FBM$", "m"), - 變換!("^HGM$", "ng"), - 變換!("FB", "m"), - 變換!("LD", "n"), - 變換!("HG", "ng"), - 變換!("SG", "gw"), - 變換!("SK", "kw"), - 變換!("SH", "w"), - 變換!("CL", "j"), - 變換!("ZF", ""), - 變換!("AI", "E"), - 變換!("AU", "O"), - 變換!("AY", "V"), - 變換!("A", "aa"), - 變換!("Y", "yu"), - 變換!("V(J|W?R)$", "eo${1}"), - 變換!("V", "oe"), - 變換!("JQ", "-ng"), - 變換!("WR", "-n"), - 變換!("MX", "-m"), - 變換!("Q$", "-k"), - 變換!("R$", "-t"), - 變換!("X$", "-p"), - 變換!("IJ", "ei"), - 變換!("UW", "ou"), - 變換!("J$", "-i"), - 變換!("W$", "-u"), - 轉寫!("SCZHLFGDBKTPEOIUM", "sczhlfgdbktpeoium"), - 變換!("^([bpmfdtnlgkhzcsjw]|ng|[gk]w*)([-aeiouy])", "${1} ${2}"), + + static ref 并击转粤拼: Box<[拼写运算<'static>]> = Box::new([ + 变换!("^FBM$", "m"), + 变换!("^HGM$", "ng"), + 变换!("FB", "m"), + 变换!("LD", "n"), + 变换!("HG", "ng"), + 变换!("SG", "gw"), + 变换!("SK", "kw"), + 变换!("SH", "w"), + 变换!("CL", "j"), + 变换!("ZF", ""), + 变换!("AI", "E"), + 变换!("AU", "O"), + 变换!("AY", "V"), + 变换!("A", "aa"), + 变换!("Y", "yu"), + 变换!("V(J|W?R)$", "eo${1}"), + 变换!("V", "oe"), + 变换!("JQ", "-ng"), + 变换!("WR", "-n"), + 变换!("MX", "-m"), + 变换!("Q$", "-k"), + 变换!("R$", "-t"), + 变换!("X$", "-p"), + 变换!("IJ", "ei"), + 变换!("UW", "ou"), + 变换!("J$", "-i"), + 变换!("W$", "-u"), + 转写!("SCZHLFGDBKTPEOIUM", "sczhlfgdbktpeoium"), + 变换!("([aeiou])-([iumptk]|ng?)$", "${1}${2}"), + 变换!("-", "a"), + 变换!(" ", ""), + 变换!("^([iy])", "j${1}"), + 变换!("^(u)", "w${1}"), ]); - static ref 並擊碼鍵位: Box<[拼寫運算<'static>]> = Box::new([ - 變換!("^m", "FB"), - 變換!("^ng", "HG"), - 變換!("^n", "LD"), - 變換!("^gw", "SG"), - 變換!("^kw", "SK"), - 變換!("^w([^u])", "SH${1}"), - 變換!("^j([^iy])", "CL${1}"), - 變換!("-n$", "WR"), - 變換!("-t$", "R"), - 變換!("-ng$", "JQ"), - 變換!("-k$", "Q"), - 變換!("-m$", "MX"), - 變換!("-p$", "X"), - 變換!("ei$", "IJ"), - 變換!("-i$", "J"), - 變換!("ou$", "UW"), - 變換!("-u$", "W"), - 變換!("aa", "A"), - 變換!("oe|eo", "V"), - 變換!("^j([iy])", "${1}"), - 變換!("^w(u)", "${1}"), - 變換!("^j", "CL"), - 變換!("^w", "SH"), - 變換!("yu", "Y"), - 轉寫!("sczhlfgdbktpeoiu", "SCZHLFGDBKTPEOIU"), + static ref 粤拼转并击: Box<[拼写运算<'static>]> = Box::new([ + 变换!("^m", "FB"), + 变换!("^ng", "HG"), + 变换!("^n", "LD"), + 变换!("^gw", "SG"), + 变换!("^kw", "SK"), + 变换!("^w([^u])", "SH${1}"), + 变换!("^j([^iy])", "CL${1}"), + 变换!("([aeiou])n$", "${1}WR"), + 变换!("([aeoiu])t$", "${1}R"), + 变换!("([aeoiu])ng$", "${1}JQ"), + 变换!("([aeoiu])k$", "${1}Q"), + 变换!("([aeoiu])m$", "${1}MX"), + 变换!("([aeoiu])p$", "${1}X"), + 变换!("ei$", "IJ"), + 变换!("([aou])i$", "${1}J"), + 变换!("ou$", "UW"), + 变换!("([aei])u$", "${1}W"), + 变换!("aa", "A"), + 变换!("oe|eo", "V"), + 变换!("^j([iy])", "${1}"), + 变换!("^w(u)", "${1}"), + 变换!("^j", "CL"), + 变换!("^w", "SH"), + 变换!("yu", "Y"), + 变换!("a", ""), + 转写!("sczhlfgdbktpeoiu", "SCZHLFGDBKTPEOIU"), ]); } lazy_static! { - static ref 貌似粵拼: Box<[&'static Regex]> = - Box::new([regex!("^[bpmfdtnlgkhzcsjwaoey][a-z]*$").deref(),]); + static ref 貌似粤拼: Box<[&'static Regex]> = Box::new([ + regex!("^[bpmfdtnlgkhzcsjwaoey][a-z]*$").deref(), + ]); } -const 宮保粵拼盤面: 盤面定義<'static> = 盤面![ - [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], - [ 空 {中:c, 上:_, 下:_, 左:_, 右:j} {中:l, 上:_, 下:_, 左:_, 右:_} {中:d, 上:_, 下:_, 左:n, 右:_} t o {中:u, 上:_, 下:_, 左:_, 右:ou} {中:"˗u", 上:_, 下:_, 左:_, 右:_} {中:"˗t", 上:_, 下:_, 左:"˗n", 右:_} 空 _ _ ], - [ 空 {中:s, 上:_, 下:_, 左:_, 右:w} {中:h, 上:_, 下:_, 左:_, 右:_} {中:g, 上:_, 下:_, 左:ng, 右:_} k e {中:i, 上:_, 下:_, 左:_, 右:ei} {中:"˗i", 上:_, 下:_, 左:_, 右:_} {中:"˗k", 上:_, 下:_, 左:"˗ng", 右:_} 空 _ ], - [ 空 {中:z, 上:_, 下:_, 左:_, 右:"'"} {中:f, 上:_, 下:_, 左:_, 右:_} {中:b, 上:_, 下:_, 左:m, 右:_} p {中:oe, 上:_, 下:eo, 左:_, 右:_} yu {中:"m", 上:_, 下:_, 左:_, 右:_} {中:"˗p", 上:_, 下:_, 左:"˗m", 右:_} 空 ], - [ aa _ aa ] -]; - -const 宮保粵拼佈局: 鍵盤佈局 = 鍵盤佈局 { - 盤面: &[基本盤面, 上檔盤面, 大寫字母盤面, 宮保粵拼盤面], - 默認盤面: 盤面選擇碼(4), - 首選配列: 配列::正交直列, -}; - -pub fn 宮保粵拼輸入方案() -> 輸入方案定義<'static> { - 輸入方案定義 { - 名稱: "宮保粵拼", - 佈局: &宮保粵拼佈局, - 指法: 觸鍵方式::並擊, - 字根表: 並擊鍵序, - 轉寫法: 轉寫法定義 { - 輸入碼表示: &並擊碼表示, - 輸入碼鍵位: &並擊碼鍵位, - 拼式轉寫規則: &並擊轉粵拼, - 字根拆分規則: &粵拼轉並擊, - 拼式驗證規則: &貌似粵拼, +pub fn 输入方案() -> 输入方案定义<'static> { + 输入方案定义 { + 名称: "宫保粤拼", + 布局: &宫保粤拼布局, + 指法: 击键方式::并击, + 键位映射: 并击键位映射, + 转写: 转写定义 { + 编码预览: &并击码表示, + 键位提示: &并击码键位, + 输入棱镜: &并击转粤拼, + 词库棱镜: &粤拼转并击, + 拼式验证规则: &貌似粤拼, }, } } diff --git a/src/theory/combo_pinyin.rs b/src/theory/combo_pinyin.rs index 3fdaabe..fbe3ee6 100644 --- a/src/theory/combo_pinyin.rs +++ b/src/theory/combo_pinyin.rs @@ -1,223 +1,233 @@ -use lazy_regex::{regex, Regex}; +use lazy_regex::{ regex, Regex }; use lazy_static::lazy_static; -use crate::definition::{觸鍵方式, 輸入方案定義, 轉寫法定義, 鍵位定義}; -use crate::gear::layout::{ - 上檔盤面, 基本盤面, 大寫字母盤面, 盤面定義, 盤面選擇碼, 配列, 鍵盤佈局, 鍵面刻印, -}; +use crate::definition::{ 击键方式, 转写定义, 输入方案定义, 键位映射定义 }; +use crate::gear::layout::{ 上档盘面, 基本盘面, 大写字母盘面 }; +use crate::gear::layout::{ 盘面定义, 盘面序号, 键盘布局, 键盘配列, 键面刻印 }; use crate::key_code::KeyCode; -use crate::spelling_algebra::拼寫運算; -use crate::{消除, 盤面, 變換, 轉寫, 鍵面}; +use crate::spelling_algebra::拼写运算; +use crate::{ 变换, 消除, 转写 }; +use crate::{ 盘面, 键面 }; +use crate::键位映射; -macro_rules! 鍵位 { - ($輸入碼: ident => $鍵碼: path) => { - 鍵位定義 { - 輸入碼: stringify!($輸入碼), - 鍵碼: $鍵碼, - } - }; -} +const 宫保拼音盘面: 盘面定义<'static> = + 盘面![ + [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], + [ 空 {中:C, 上:_, 下:_, 左:_, 右:"ĉ"} {中:L, 上:_, 下:_, 左:"ĉ", 右:"n"} {中:D, 上:_, 下:_, 左:"n", 右:_} T 空 U {中:R, 上:"er", 下:_, 左:"-i", 右:"-u"} O 空 _ _ ], + [ 空 {中:S, 上:_, 下:_, 左:_, 右:"ŝ"} {中:H, 上:"x", 下:_, 左:"ŝ", 右:"r"} {中:G, 上:_, 下:_, 左:"r", 右:"j"} {中:K, 上:_, 下:_, 左:_, 右:"q"} 空 I {中:N, 上:_, 下:_, 左:"-n", 右:"-ŋ"} {中:E, 上:_, 下:_, 左:"-ŋ", 右:_} _ _ _ ], + [ 空 {中:Z, 上:_, 下:_, 左:_, 右:"ẑ"} {中:F, 上:_, 下:_, 左:"ẑ", 右:"m"} {中:B, 上:_, 下:_, 左:"m", 右:_} P 空 Ü _ _ _ ], + [ A _ A ] +]; -const 並擊鍵序: &[鍵位定義] = &[ - 鍵位!(S => KeyCode::S), - 鍵位!(C => KeyCode::W), - 鍵位!(Z => KeyCode::X), - 鍵位!(H => KeyCode::D), - 鍵位!(L => KeyCode::E), - 鍵位!(F => KeyCode::C), - 鍵位!(G => KeyCode::F), - 鍵位!(D => KeyCode::R), - 鍵位!(B => KeyCode::V), - 鍵位!(K => KeyCode::G), - 鍵位!(T => KeyCode::T), - 鍵位!(P => KeyCode::B), - 鍵位!(I => KeyCode::J), - 鍵位!(U => KeyCode::U), - 鍵位!(Ü => KeyCode::M), - 鍵位!(A => KeyCode::Space), - 鍵位!(N => KeyCode::K), - 鍵位!(R => KeyCode::I), - 鍵位!(E => KeyCode::L), - 鍵位!(O => KeyCode::O), +const 宫保拼音键盘布局: 键盘布局 = 键盘布局 { + 盘面: &[基本盘面, 上档盘面, 大写字母盘面, 宫保拼音盘面], + 默认盘面: 盘面序号(4), + 默认配列: 键盘配列::正交直列, +}; + +const 并击键位映射: &[键位映射定义] = &[ + 键位映射!(A => KeyCode::Space), + 键位映射!(B => KeyCode::V), + 键位映射!(C => KeyCode::W), + 键位映射!(D => KeyCode::R), + 键位映射!(E => KeyCode::L), + 键位映射!(F => KeyCode::C), + 键位映射!(G => KeyCode::F), + 键位映射!(H => KeyCode::D), + 键位映射!(I => KeyCode::J), + 键位映射!(K => KeyCode::G), + 键位映射!(L => KeyCode::E), + 键位映射!(N => KeyCode::K), + 键位映射!(O => KeyCode::O), + 键位映射!(P => KeyCode::B), + 键位映射!(R => KeyCode::I), + 键位映射!(S => KeyCode::S), + 键位映射!(T => KeyCode::T), + 键位映射!(U => KeyCode::U), + 键位映射!(Z => KeyCode::X), + 键位映射!(Ü => KeyCode::M), ]; lazy_static! { - static ref 並擊轉拼音: Box<[拼寫運算::<'static>]> = Box::new([ - // 空格鍵單擊時產生空白 - 變換!("^A$", "␣"), + static ref 并击转拼音: Box<[拼写运算<'static>]> = Box::new([ + // 空格键单击时产生空白 + 变换!("^A$", "␣"), - // 並擊聲母 - 變換!("^ZF", "zh"), - 變換!("^CL", "ch"), - 變換!("^FB", "m"), - 變換!("^LD", "n"), - 變換!("^HG", "r"), - // 特殊配列鍵盤用 - 變換!("^ZB", "p"), - 變換!("^CD", "t"), - 變換!("^SG", "k"), + // 并击声母 + 变换!("^ZF", "zh"), + 变换!("^CL", "ch"), + 变换!("^FB", "m"), + 变换!("^LD", "n"), + 变换!("^HG", "r"), + // 特殊配列键盘用 + 变换!("^ZB", "p"), + 变换!("^CD", "t"), + 变换!("^SG", "k"), - 轉寫!("BPFDTLGKHZCS", "bpfdtlgkhzcs"), + 转写!("BPFDTLGKHZCS", "bpfdtlgkhzcs"), - // 通摄三等精組、泥來併入一等,須在尖團音規則前變換 - // 濃龍蹤從松 ⟨niong/liong/ziong/ciong/siong -> nong/long/zong/cong/song⟩ - 變換!("^([nlzcs])(IRO|ÜNE)$", "${1}ong"), + // 通摄三等精组、泥来并入一等,须在尖团音规则前变换 + // 浓龙踪从松 ⟨niong/liong/ziong/ciong/siong -> nong/long/zong/cong/song⟩ + 变换!("^([nlzcs])(IRO|ÜNE)$", "${1}ong"), // G,K,H 接 I/Ü 作 ⟨ji/ju, qi/qu, xi/xu⟩ - // 若分尖團,也可用 Z,C,S 與 I/Ü 相拼 - 變換!("^[gz](I|Ü)", "j$1"), - 變換!("^[kc](I|Ü)", "q$1"), - 變換!("^[hs](I|Ü)", "x$1"), + // 若分尖团,也可用 Z,C,S 与 I/Ü 相拼 + 变换!("^[gz](I|Ü)", "j$1"), + 变换!("^[kc](I|Ü)", "q$1"), + 变换!("^[hs](I|Ü)", "x$1"), - // ⟨er⟩自成音節 - 變換!("^R$", "er"), + // ⟨er⟩自成音节 + 变换!("^R$", "er"), // 舌尖元音⟨ï⟩ - 變換!("^([zcsr]h?)R?$", "${1}i"), + 变换!("^([zcsr]h?)R?$", "${1}i"), - 變換!("ANE$", "ang"), - 變換!("UARO$", "uang"), - 變換!("IRO$", "iong"), - 變換!("URO$", "ong"), - 變換!("ÜNE$", "iong"), - 變換!("UNE$", "ong"), - 變換!("INE$", "ing"), - 變換!("NE$", "eng"), + 变换!("ANE$", "ang"), + 变换!("UARO$", "uang"), + 变换!("IRO$", "iong"), + 变换!("URO$", "ong"), + 变换!("ÜNE$", "iong"), + 变换!("UNE$", "ong"), + 变换!("INE$", "ing"), + 变换!("NE$", "eng"), - 變換!("AN$", "an"), - 變換!("ÜN$", "vn"), - 變換!("UN$", "uen"), - 變換!("IN$", "in"), - 變換!("N$", "en"), + 变换!("AN$", "an"), + 变换!("ÜN$", "vn"), + 变换!("UN$", "uen"), + 变换!("IN$", "in"), + 变换!("N$", "en"), - 變換!("IAR$", "iao"), - 變換!("IR$", "iou"), - 變換!("UR$", "uei"), - 變換!("AO$", "ao"), - 變換!("RO$", "ou"), - 變換!("AR$", "ai"), - 變換!("RE?$", "ei"), - 變換!("AE$", "a"), + 变换!("IAR$", "iao"), + 变换!("IR$", "iou"), + 变换!("UR$", "uei"), + 变换!("AO$", "ao"), + 变换!("RO$", "ou"), + 变换!("AR$", "ai"), + 变换!("RE?$", "ei"), + 变换!("AE$", "a"), - 轉寫!("AOEIUÜ", "aoeiuv"), + 转写!("AOEIUÜ", "aoeiuv"), - // 漢語拼音方案的拼寫規則 - 變換!("^i(ng?)$", "yi$1"), - 變換!("^i$", "yi"), - 變換!("^i", "y"), - 變換!("^ong$", "weng"), - 變換!("^u$", "wu"), - 變換!("^u", "w"), - 變換!("^v", "yu"), - 變換!("^([jqx])v", "${1}u"), - // 一些容錯 - 變換!("^([bpmf])uo$", "${1}o"), - 變換!("^([dtngkhzcsr]h?)o$", "${1}uo"), - 變換!("io$", "iao"), - 變換!("^([nl])uei$", "${1}ei"), - 變換!("^([nl])iong$", "${1}ong"), - 變換!("^([zcsr]h?)i([aoe])", "$1$2"), - 變換!("^([zcsr]h?)i(ng?)$", "${1}e$2"), - // 拼寫規則 - 變換!("iou$", "iu"), - 變換!("uei$", "ui"), - 變換!("uen$", "un"), + // 汉语拼音方案的拼写规则 + 变换!("^i(ng?)$", "yi$1"), + 变换!("^i$", "yi"), + 变换!("^i", "y"), + 变换!("^ong$", "weng"), + 变换!("^u$", "wu"), + 变换!("^u", "w"), + 变换!("^v", "yu"), + 变换!("^([jqx])v", "${1}u"), + // 一些容错 + 变换!("^([bpmf])uo$", "${1}o"), + 变换!("^([dtngkhzcsr]h?)o$", "${1}uo"), + 变换!("io$", "iao"), + 变换!("^([nl])uei$", "${1}ei"), + 变换!("^([nl])iong$", "${1}ong"), + 变换!("^([zcsr]h?)i([aoe])", "$1$2"), + 变换!("^([zcsr]h?)i(ng?)$", "${1}e$2"), + // 拼写规则 + 变换!("iou$", "iu"), + 变换!("uei$", "ui"), + 变换!("uen$", "un"), - // 聲母獨用時補足缺省韻母 + // 声母独用时补足缺省韵母 // ⟨bu, pu, fu⟩ - 變換!("^([bpf])$", "${1}u"), + 变换!("^([bpf])$", "${1}u"), // ⟨de, te, ne, le, ge, ke, he⟩ - // 特別地,⟨me⟩ 對應常用字「麼·么」 - 變換!("^([mdtnlgkh])$", "${1}e"), + // 特别地,⟨me⟩ 对应常用字「么·么」 + 变换!("^([mdtnlgkh])$", "${1}e"), - // 檢查拼音音節,通過檢查則追加隔音符號 - 變換!("^([bpm])([iu]|a|i?e|o|[ae]i|i?ao|[oi]u|i?an|[ie]n|[ei]ng|ang|ong)$", "$1$2'"), - 變換!("^([fw])(u|a|o|[ae]i|ao|ou|an|en|eng|ang|ong)$", "$1$2'"), - 變換!("^([dt])([iu]|i?a|i?e|uo|[aeu]i|i?ao|[oi]u|[iu]?an|[ue]n|[ei]ng|ang|ong)$", "$1$2'"), - 變換!("^([nl])([iuv]|i?a|[iv]?e|u?o|[aeu]i|i?ao|[oi]u|[iu]?an|[iue]n|[ei]ng|i?ang|ong)$", "$1$2'"), - 變換!("^([gkh])(u|u?a|e|uo|u?ai|[ue]i|ao|ou|u?an|[ue]n|eng|u?ang|ong)$", "$1$2'"), - 變換!("^([zcs]h?|r)([iu]|u?a|e|uo|u?ai|[ue]i|ao|ou|u?an|[ue]n|eng|u?ang|ong)$", "$1$2'"), - 變換!("^([jqxy])([iu]|i?a|[iu]?e|o|i?ao|[oi]u|[iu]?an|[iu]n|ing|i?ang|i?ong)$", "$1$2'"), - 變換!("^([aeo]|[ae]i|ao|ou|[ae]ng?|er)$", "$1'"), - // 消除不構成合法音節的並擊組合 + // 检查拼音音节,通过检查则追加隔音符号 + 变换!("^([bpm])([iu]|a|i?e|o|[ae]i|i?ao|[oi]u|i?an|[ie]n|[ei]ng|ang|ong)$", "$1$2'"), + 变换!("^([fw])(u|a|o|[ae]i|ao|ou|an|en|eng|ang|ong)$", "$1$2'"), + 变换!("^([dt])([iu]|i?a|i?e|uo|[aeu]i|i?ao|[oi]u|[iu]?an|[ue]n|[ei]ng|ang|ong)$", "$1$2'"), + 变换!( + "^([nl])([iuv]|i?a|[iv]?e|u?o|[aeu]i|i?ao|[oi]u|[iu]?an|[iue]n|[ei]ng|i?ang|ong)$", + "$1$2'" + ), + 变换!("^([gkh])(u|u?a|e|uo|u?ai|[ue]i|ao|ou|u?an|[ue]n|eng|u?ang|ong)$", "$1$2'"), + 变换!("^([zcs]h?|r)([iu]|u?a|e|uo|u?ai|[ue]i|ao|ou|u?an|[ue]n|eng|u?ang|ong)$", "$1$2'"), + 变换!("^([jqxy])([iu]|i?a|[iu]?e|o|i?ao|[oi]u|[iu]?an|[iu]n|ing|i?ang|i?ong)$", "$1$2'"), + 变换!("^([aeo]|[ae]i|ao|ou|[ae]ng?|er)$", "$1'"), + // 消除不构成合法音节的并击组合 消除!("^[A-Za-z]+$"), - 轉寫!("v", "ü"), - // 顯示單個音節不需要加隔音符號 - 變換!("^(.*)'$", "$1"), + 转写!("v", "ü"), + // 显示单个音节不需要加隔音符号 + 变换!("^(.*)'$", "$1"), ]); - static ref 拼音轉並擊: Box<[拼寫運算<'static>]> = Box::new([ - // 缺省韻母 - 變換!("^bu$", "B"), - 變換!("^pu$", "P"), - 變換!("^me$", "FB"), - 變換!("^fu$", "F"), - 變換!("^de$", "D"), - 變換!("^te$", "T"), - 變換!("^ne$", "LD"), - 變換!("^le$", "L"), - 變換!("^ge$", "G"), - 變換!("^ke$", "K"), - 變換!("^he$", "H"), - 變換!("^zhi$", "ZF"), - 變換!("^chi$", "CL"), - 變換!("^shi$", "SH"), - 變換!("^ri$", "HG"), - 變換!("^zi$", "Z"), - 變換!("^ci$", "C"), - 變換!("^si$", "S"), - 變換!("^er$", "R"), - // 韻母的並擊碼 - 變換!("^a$", "AE"), - 變換!("a$", "A"), - 變換!("ao$", "AO"), - 變換!("o$", "O"), - 變換!("y?ue$", "ÜE"), - 變換!("e$", "E"), - 變換!("ai$", "AR"), - 變換!("^wei$|ui$", "UR"), - 變換!("^ei$", "RE"), - 變換!("^([zcsr]h?)ei$", "${1}RE"), - 變換!("ei$", "R"), - 變換!("^you$|iou$|iu$", "IR"), - 變換!("ou$", "RO"), - 變換!("an$", "AN"), - 變換!("^yin$|in$", "IN"), - 變換!("^yun$|ün$|vn$", "ÜN"), - 變換!("^([jqx])un$", "${1}ÜN"), - 變換!("^wen$|uen$|un$", "UN"), - 變換!("en$", "N"), - 變換!("wang$|uang$", "UARO"), - 變換!("ang$", "ANE"), - 變換!("^ying$|ing$", "INE"), - 變換!("^yong$|iong$", "IRO"), - 變換!("^weng$|ueng$|ong$", "URO"), - 變換!("eng$", "NE"), - 變換!("^([jqx])u", "${1}Ü"), - 變換!("^yu|ü|v", "Ü"), - 變換!("^yi?|ii?", "I"), - 變換!("^wu?|u", "U"), - // 聲母的並擊碼 - 變換!("^b", "B"), - 變換!("^p", "P"), - 變換!("^m", "FB"), - 變換!("^f", "F"), - 變換!("^d", "D"), - 變換!("^t", "T"), - 變換!("^n", "LD"), - 變換!("^l", "L"), - 變換!("^j-?$", "GI"), - 變換!("^q-?$", "KI"), - 變換!("^x-?$", "HI"), - 變換!("^[gj]", "G"), - 變換!("^[kq]", "K"), - 變換!("^[hx]", "H"), - 變換!("^zh", "ZF"), - 變換!("^ch", "CL"), - 變換!("^sh", "SH"), - 變換!("^z", "Z"), - 變換!("^c", "C"), - 變換!("^s", "S"), - 變換!("^r", "HG"), + static ref 拼音转并击: Box<[拼写运算<'static>]> = Box::new([ + // 缺省韵母 + 变换!("^bu$", "B"), + 变换!("^pu$", "P"), + 变换!("^me$", "FB"), + 变换!("^fu$", "F"), + 变换!("^de$", "D"), + 变换!("^te$", "T"), + 变换!("^ne$", "LD"), + 变换!("^le$", "L"), + 变换!("^ge$", "G"), + 变换!("^ke$", "K"), + 变换!("^he$", "H"), + 变换!("^zhi$", "ZF"), + 变换!("^chi$", "CL"), + 变换!("^shi$", "SH"), + 变换!("^ri$", "HG"), + 变换!("^zi$", "Z"), + 变换!("^ci$", "C"), + 变换!("^si$", "S"), + 变换!("^er$", "R"), + // 韵母的并击码 + 变换!("^a$", "AE"), + 变换!("a$", "A"), + 变换!("ao$", "AO"), + 变换!("o$", "O"), + 变换!("y?ue$", "ÜE"), + 变换!("e$", "E"), + 变换!("ai$", "AR"), + 变换!("^wei$|ui$", "UR"), + 变换!("^ei$", "RE"), + 变换!("^([zcsr]h?)ei$", "${1}RE"), + 变换!("ei$", "R"), + 变换!("^you$|iou$|iu$", "IR"), + 变换!("ou$", "RO"), + 变换!("an$", "AN"), + 变换!("^yin$|in$", "IN"), + 变换!("^yun$|ün$|vn$", "ÜN"), + 变换!("^([jqx])un$", "${1}ÜN"), + 变换!("^wen$|uen$|un$", "UN"), + 变换!("en$", "N"), + 变换!("wang$|uang$", "UARO"), + 变换!("ang$", "ANE"), + 变换!("^ying$|ing$", "INE"), + 变换!("^yong$|iong$", "IRO"), + 变换!("^weng$|ueng$|ong$", "URO"), + 变换!("eng$", "NE"), + 变换!("^([jqx])u", "${1}Ü"), + 变换!("^yu|ü|v", "Ü"), + 变换!("^yi?|ii?", "I"), + 变换!("^wu?|u", "U"), + // 声母的并击码 + 变换!("^b", "B"), + 变换!("^p", "P"), + 变换!("^m", "FB"), + 变换!("^f", "F"), + 变换!("^d", "D"), + 变换!("^t", "T"), + 变换!("^n", "LD"), + 变换!("^l", "L"), + 变换!("^j-?$", "GI"), + 变换!("^q-?$", "KI"), + 变换!("^x-?$", "HI"), + 变换!("^[gj]", "G"), + 变换!("^[kq]", "K"), + 变换!("^[hx]", "H"), + 变换!("^zh", "ZF"), + 变换!("^ch", "CL"), + 变换!("^sh", "SH"), + 变换!("^z", "Z"), + 变换!("^c", "C"), + 变换!("^s", "S"), + 变换!("^r", "HG"), ]); static ref 貌似拼音: Box<[&'static Regex]> = Box::new([ @@ -230,43 +240,31 @@ lazy_static! { regex!("^([gkh])(u|u?a|e|uo|u?ai|[ue]i|ao|ou|u?an|[ue]n|eng|u?ang|ong)$").deref(), regex!("^([zcs]h?|r)([iu]|u?a|e|uo|u?ai|[ue]i|ao|ou|u?an|[ue]n|eng|u?ang|ong)$").deref(), regex!("^([jqxy])([iu]|i?a|[iu]?e|o|i?ao|[oi]u|[iu]?an|[iu]n|ing|i?ang|i?ong)$").deref(), - // 尖音,演示指法用。其中韻母 i 雙寫 + // 尖音,演示指法用。其中韵母 i 双写 regex!("^([zcs])(ii|[iv]e?|üe?|i?ao|iu|[iv]a?n|üa?n|ia?ng|iong)$").deref(), regex!("^([aeo]|[ae]i|ao|ou|[ae]ng?|er)$").deref(), - // 聲母 + // 声母 regex!("^([bpmfdtnlgkhjqxr]|[zcs]h?)-?$").deref(), - // 非音節形式的韻母 + // 非音节形式的韵母 regex!("^([yw])-?$").deref(), - regex!("^-?([iuv]|[iu]?[ao]|[iuv]?e|üe?|u?[ae]i|ui|i?ao|i?ou|iu|[iuv]?an|üa?n|[iuv]n|u?en|[iu]?ang|ing|u?eng|i?ong)?$").deref(), + regex!( + "^-?([iuv]|[iu]?[ao]|[iuv]?e|üe?|u?[ae]i|ui|i?ao|i?ou|iu|[iuv]?an|üa?n|[iuv]n|u?en|[iu]?ang|ing|u?eng|i?ong)?$" + ).deref(), ]); } -const 宮保拼音盤面: 盤面定義<'static> = 盤面![ - [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], - [ 空 {中:C, 上:_, 下:_, 左:_, 右:"ĉ"} {中:L, 上:_, 下:_, 左:"ĉ", 右:"n"} {中:D, 上:_, 下:_, 左:"n", 右:_} T 空 U {中:R, 上:"er", 下:_, 左:"-i", 右:"-u"} O 空 _ _ ], - [ 空 {中:S, 上:_, 下:_, 左:_, 右:"ŝ"} {中:H, 上:"x", 下:_, 左:"ŝ", 右:"r"} {中:G, 上:_, 下:_, 左:"r", 右:"j"} {中:K, 上:_, 下:_, 左:_, 右:"q"} 空 I {中:N, 上:_, 下:_, 左:"-n", 右:"-ŋ"} {中:E, 上:_, 下:_, 左:"-ŋ", 右:_} _ _ _ ], - [ 空 {中:Z, 上:_, 下:_, 左:_, 右:"ẑ"} {中:F, 上:_, 下:_, 左:"ẑ", 右:"m"} {中:B, 上:_, 下:_, 左:"m", 右:_} P 空 Ü _ _ _ ], - [ A _ A ] -]; - -const 宮保拼音鍵盤佈局: 鍵盤佈局 = 鍵盤佈局 { - 盤面: &[基本盤面, 上檔盤面, 大寫字母盤面, 宮保拼音盤面], - 默認盤面: 盤面選擇碼(4), - 首選配列: 配列::正交直列, -}; - -pub fn 宮保拼音輸入方案() -> 輸入方案定義<'static> { - 輸入方案定義 { - 名稱: "宮保拼音", - 佈局: &宮保拼音鍵盤佈局, - 指法: 觸鍵方式::並擊, - 字根表: 並擊鍵序, - 轉寫法: 轉寫法定義 { - 輸入碼表示: &[], - 輸入碼鍵位: &[], - 拼式轉寫規則: &並擊轉拼音, - 字根拆分規則: &拼音轉並擊, - 拼式驗證規則: &貌似拼音, +pub fn 输入方案() -> 输入方案定义<'static> { + 输入方案定义 { + 名称: "宫保拼音", + 布局: &宫保拼音键盘布局, + 指法: 击键方式::并击, + 键位映射: 并击键位映射, + 转写: 转写定义 { + 编码预览: &[], + 键位提示: &[], + 输入棱镜: &并击转拼音, + 词库棱镜: &拼音转并击, + 拼式验证规则: &貌似拼音, }, } } diff --git a/src/theory/double_pinyin_fly.rs b/src/theory/double_pinyin_fly.rs new file mode 100644 index 0000000..bbf2642 --- /dev/null +++ b/src/theory/double_pinyin_fly.rs @@ -0,0 +1,223 @@ +use lazy_regex::{ regex, Regex }; +use lazy_static::lazy_static; + +use crate::definition::{ 击键方式, 转写定义, 输入方案定义, 键位映射定义 }; +use crate::gear::layout::{ 上档盘面, 基本盘面, 大写字母盘面 }; +use crate::gear::layout::{ 盘面定义, 盘面序号, 键盘布局, 键盘配列, 键面刻印 }; +use crate::key_code::KeyCode; +use crate::spelling_algebra::拼写运算; +use crate::{ 变换, 派生, 消除, 缩写, 转写 }; +use crate::{ 盘面, 键面 }; +use crate::默认映射; + +const 小鹤双拼助记盘面: 盘面定义<'static> = + 盘面![ + [ _ _ _ _ _ _ _ _ _ _ ], + [ {中:Q, 上:_, 下:"iu", 左:_, 右:_} {中:W, 上:_, 下:"ei", 左:_, 右:_} {中:E, 上:_, 下:"e", 左:_, 右:_} {中:R, 上:_, 下:"uan/van", 左:_, 右:_} {中:T, 上:_, 下:"ue/ve", 左:_, 右:_} {中:Y, 上:_, 下:"un/vn", 左:_, 右:_} {中:U, 上:_, 下:"u", 左:_, 右:_} {中:I, 上:_, 下:"i", 左:_, 右:_} {中:O, 上:_, 下:"uo/o", 左:_, 右:_} {中:P, 上:_, 下:"ie", 左:_, 右:_} ], + [ {中:A, 上:_, 下:"a", 左:_, 右:_} {中:S, 上:_, 下:"ong/iong", 左:_, 右:_} {中:D, 上:_, 下:"ai", 左:_, 右:_} {中:F, 上:_, 下:"en", 左:_, 右:_} {中:G, 上:_, 下:"eng", 左:_, 右:_} {中:H, 上:_, 下:"ang", 左:_, 右:_} {中:J, 上:_, 下:"an", 左:_, 右:_} {中:K, 上:_, 下:"uai/ing", 左:_, 右:_} {中:L, 上:_, 下:"uang/iang", 左:_, 右:_} {中:";", 上:":", 下:_, 左:_, 右:_} ], + [ {中:Z, 上:_, 下:"ou", 左:_, 右:_} {中:X, 上:_, 下:"ua/ia", 左:_, 右:_} {中:C, 上:_, 下:"ao", 左:_, 右:_} {中:V, 上:_, 下:"ui/v", 左:_, 右:_} {中:B, 上:_, 下:"in", 左:_, 右:_} {中:N, 上:_, 下:"iao", 左:_, 右:_} {中:M, 上:_, 下:"ian", 左:_, 右:_} {中:",", 上:"<", 下:_, 左:_, 右:_} {中:".", 上:">", 下:_, 左:_, 右:_} {中:"/", 上:"?", 下:_, 左:_, 右:_} ], + [ "␣" _ "␣" ] +]; + +const 小鹤双拼助记键盘布局: 键盘布局 = 键盘布局 { + 盘面: &[基本盘面, 上档盘面, 大写字母盘面, 小鹤双拼助记盘面], + 默认盘面: 盘面序号(4), + 默认配列: 键盘配列::正交直列, +}; + +const 字母表: &[键位映射定义] = &[ + 默认映射!(A), + 默认映射!(B), + 默认映射!(C), + 默认映射!(D), + 默认映射!(E), + 默认映射!(F), + 默认映射!(G), + 默认映射!(H), + 默认映射!(I), + 默认映射!(J), + 默认映射!(K), + 默认映射!(L), + 默认映射!(M), + 默认映射!(N), + 默认映射!(O), + 默认映射!(P), + 默认映射!(Q), + 默认映射!(R), + 默认映射!(S), + 默认映射!(T), + 默认映射!(U), + 默认映射!(V), + 默认映射!(W), + 默认映射!(X), + 默认映射!(Y), + 默认映射!(Z), + 键位映射定义 { + 输入码: "␣", + 键码: KeyCode::Space, + }, + 键位映射定义 { + 输入码: "'", + 键码: KeyCode::Quote, + }, + 键位映射定义 { + 输入码: "-", + 键码: KeyCode::Minus, + }, +]; + +lazy_static! { + static ref 小鹤转全拼: Box<[拼写运算<'static>]> = Box::new([ + 变换!("([BPMFDTNLJQX])N", "${1}iao"), + 变换!("(\\w)G", "${1}eng"), + 变换!("(\\w)Q", "${1}iu"), + + 变换!("(\\w)W", "${1}ei"), + 变换!("([DTNLGKHJQXYVIURZCS])R", "${1}uan"), + 变换!("(\\w)T", "${1}ve"), + 变换!("(\\w)Y", "${1}un"), + 变换!("([DTNLGKHVUIRzcs])O", "${1}uo"), + 变换!("(\\w)P", "{$}ie"), + 变换!("([JQX])S", "${1}iong"), + 变换!("(\\w)S", "${1}ong"), + 变换!("(\\w)D", "${1}ai"), + 变换!("(\\w)F", "${1}en"), + 变换!("(\\w)H", "${1}ang"), + 变换!("(\\w)J", "${1}an"), + 变换!("([GKHVUIRZCS])K", "${1}uai"), + 变换!("(\\w)K", "${1}ing"), + 变换!("([JQXNL])L", "${1}iang"), + 变换!("(\\w)L", "${1}uang"), + 变换!("(\\w)Z", "${1}ou"), + 变换!("([GKHVUIRZCS])X", "${1}ua"), + 变换!("(\\w)X", "${1}ia"), + 变换!("(\\w)C", "${1}ao"), + 变换!("([DTGKHVUIRZCS])V", "${1}ui"), + 变换!("(\\w)B", "${1}in"), + 变换!("(\\w)M", "${1}ian"), + // 变换!("([AOE])\\1(\\w)", "$1$2"), + + 变换!("(^|[ ])V", "${1}zh"), + 变换!("(^|[ ])I", "${1}ch"), + 变换!("(^|[ ])U", "${1}sh"), + + 变换!("([JQXY])V", "${1}u"), + 变换!("([NL])V", "${1}v"), + + 转写!("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), + ]); + static ref 全拼转小鹤: Box<[拼写运算<'static>]> = Box::new([ + 变换!("cong", "CS"), + 变换!("ming", "MK"), + ]); + static ref 键位转字母: Box<[拼写运算<'static>]> = Box::new([ + 变换!("([BPMFDTNLJQX])N", "$1iao"), + 变换!("(\\w)G", "$1eng"), + 变换!("(\\w)Q", "$1iu"), + 变换!("(\\w)W", "$1ei"), + 变换!("([DTNLGKHJQXYVIURZCS])R", "$1uan"), + 变换!("(\\w)T", "$1ve"), + 变换!("(\\w)Y", "$1un"), + 变换!("([DTNLGKHVUIRzcs])o", "$1uo"), + 变换!("(\\w)P", "$1ie"), + 变换!("([JQX])S", "$1iong"), + 变换!("(\\w)S", "$1ong"), + 变换!("(\\w)D", "$1ai"), + 变换!("(\\w)F", "$1en"), + 变换!("(\\w)H", "$1ang"), + 变换!("(\\w)J", "$1an"), + 变换!("([GKHVUIRZCS])K", "$1uai"), + 变换!("(\\w)K", "$1ing"), + 变换!("([JQXNL])L", "$1iang"), + 变换!("(\\w)L", "$1uang"), + 变换!("(\\w)Z", "$1ou"), + 变换!("([GKHVUIRZCS])X", "$1ua"), + 变换!("(\\w)X", "$1ia"), + 变换!("(\\w)C", "$1ao"), + 变换!("([DTGKHVUIRZCS])V", "$1ui"), + 变换!("(\\w)B", "$1in"), + 变换!("(\\w)M", "$1ian"), + // 变换!("([AOE])\\1(\\w)", "$1$2"), + + 变换!("(^|[ ])V", "$1zh"), + 变换!("(^|[ ])I", "$1ch"), + 变换!("(^|[ ])U", "$1sh"), + + 变换!("([JQXY])V", "$1u"), + 变换!("([NL])V", "$1ü"), + ]); + static ref 字母转键位: Box<[拼写运算<'static>]> = Box::new([ + 消除!("^xx$"), + + 派生!("^([jqxy])u$", "$1V"), + 派生!("^([aoe])([ioun])$", "$1$1$2"), + + 变换!("^([aoe])(ng)?$", "$1$1$2"), + + 变换!("iu$", "Q"), + 变换!("(.)ei$", "$1W"), + 变换!("uan$", "R"), + 变换!("[uv]e$", "T"), + 变换!("un$", "Y"), + 变换!("^sh", "U"), + 变换!("^ch", "I"), + 变换!("^zh", "V"), + 变换!("uo$", "O"), + 变换!("ie$", "P"), + 变换!("i?ong$", "S"), + 变换!("ing$|uai$", "K"), + 变换!("(.)ai$", "$1D"), + 变换!("(.)en$", "$1F"), + 变换!("(.)eng$", "$1G"), + 变换!("[iu]ang$", "L"), + 变换!("(.)ang$", "$1H"), + 变换!("ian$", "M"), + 变换!("(.)an$", "$1J"), + 变换!("(.)ou$", "$1Z"), + 变换!("[iu]a$", "X"), + 变换!("iao$", "N"), + 变换!("(.)ao$", "$1C"), + 变换!("ui$", "V"), + 变换!("in$", "B"), + + 转写!("qwrtyuiopsdfghjklzxcvbnm", "QWRTYUIOPSDFGHJKLZXCVBNM"), + 缩写!("^(.).+$", "$1"), + ]); + static ref 貌似拼音: Box<[&'static Regex]> = Box::new([ + regex!("^([bpm])([iu]|a|i?e|o|[ae]i|i?ao|[oi]u|i?an|[ie]n|[ei]ng|ang|ong)$").deref(), + regex!("^([fw])(u|a|o|[ae]i|ao|ou|an|en|eng|ang|ong)$").deref(), + regex!("^([dt])([iu]|i?a|i?e|uo|[aeu]i|i?ao|[oi]u|[iu]?an|[ue]n|[ei]ng|ang|ong)$").deref(), + regex!( + "^([nl])([iuv]|i?a|[iuv]?e|üe?|u?o|[aeu]i|i?ao|[oi]u|[iu]?an|[iue]n|[ei]ng|i?ang|i?ong)$" + ).deref(), + regex!("^([gkh])(u|u?a|e|uo|u?ai|[ue]i|ao|ou|u?an|[ue]n|eng|u?ang|ong)$").deref(), + regex!("^([zcs]h?|r)([iu]|u?a|e|uo|u?ai|[ue]i|ao|ou|u?an|[ue]n|eng|u?ang|ong)$").deref(), + regex!("^([jqxy])([iu]|i?a|[iu]?e|o|i?ao|[oi]u|[iu]?an|[iu]n|ing|i?ang|i?ong)$").deref(), + // 尖音,演示指法用。其中韵母 i 双写 + regex!("^([zcs])(ii|[iv]e?|üe?|i?ao|iu|[iv]a?n|üa?n|ia?ng|iong)$").deref(), + regex!("^([aeo]|[ae]i|ao|ou|[ae]ng?|er)$").deref(), + // 声母 + regex!("^([bpmfdtnlgkhjqxr]|[zcs]h?)-?$").deref(), + // 非音节形式的韵母 + regex!("^([yw])-?$").deref(), + regex!( + "^-?([iuv]|[iu]?[ao]|[iuv]?e|üe?|u?[ae]i|ui|i?ao|i?ou|iu|[iuv]?an|üa?n|[iuv]n|u?en|[iu]?ang|ing|u?eng|i?ong)?$" + ).deref(), + ]); +} + +pub fn 输入方案() -> 输入方案定义<'static> { + 输入方案定义 { + 名称: "小鹤双拼", + 布局: &小鹤双拼助记键盘布局, + 指法: 击键方式 /* 连 */::并击, + 键位映射: 字母表, + 转写: 转写定义 { + 编码预览: &[] /* 小鹤转全拼 */, + 键位提示: &字母转键位 /* []全拼转小鹤 */, + 输入棱镜: &小鹤转全拼 /* [] */ /* 键位转字母 */, + 词库棱镜: &[] /* 字母转键位 */, + 拼式验证规则: &貌似拼音, + }, + } +} diff --git a/src/theory/early_middle_chinese.rs b/src/theory/early_middle_chinese.rs index fa5d6ed..d3bfefc 100644 --- a/src/theory/early_middle_chinese.rs +++ b/src/theory/early_middle_chinese.rs @@ -1,122 +1,17 @@ use lazy_regex::regex; use lazy_static::lazy_static; -use crate::definition::{觸鍵方式, 輸入方案定義, 轉寫法定義, 鍵位定義}; -use crate::gear::layout::{ - 上檔盤面, 基本盤面, 大寫字母盤面, 盤面定義, 盤面選擇碼, 配列, 鍵盤佈局, 鍵面刻印, -}; +use crate::definition::{ 击键方式, 转写定义, 输入方案定义, 键位映射定义 }; +use crate::gear::layout::{ 上档盘面, 基本盘面, 大写字母盘面 }; +use crate::gear::layout::{ 盘面定义, 盘面序号, 键盘布局, 键盘配列, 键面刻印 }; use crate::key_code::KeyCode; -use crate::spelling_algebra::拼寫運算; -use crate::{盤面, 變換, 鍵面}; - -macro_rules! 鍵位 { - ($輸入碼: ident => $鍵碼: path) => { - 鍵位定義 { - 輸入碼: stringify!($輸入碼), - 鍵碼: $鍵碼, - } - }; -} - -const 並擊鍵序: &[鍵位定義] = &[ - 鍵位!(心 => KeyCode::A), - 鍵位!(清 => KeyCode::Q), - 鍵位!(精 => KeyCode::Z), - 鍵位!(曉 => KeyCode::S), - 鍵位!(來 => KeyCode::W), - 鍵位!(匣 => KeyCode::X), - 鍵位!(羣 => KeyCode::D), - 鍵位!(定 => KeyCode::E), - 鍵位!(並 => KeyCode::C), - 鍵位!(見 => KeyCode::F), - 鍵位!(端 => KeyCode::R), - 鍵位!(幫 => KeyCode::V), - 鍵位!(溪 => KeyCode::G), - 鍵位!(透 => KeyCode::T), - 鍵位!(滂 => KeyCode::B), - 鍵位!(果 => KeyCode::Space), - 鍵位!(止 => KeyCode::J), - 鍵位!(流 => KeyCode::U), - 鍵位!(假 => KeyCode::L), - 鍵位!(遇 => KeyCode::O), - 鍵位!(曾 => KeyCode::K), - 鍵位!(臻 => KeyCode::I), - 鍵位!(深 => KeyCode::Comma), - 鍵位!(入 => KeyCode::Semicolon), - 鍵位!(上 => KeyCode::P), - 鍵位!(去 => KeyCode::Slash), -]; +use crate::spelling_algebra::拼写运算; +use crate::{ 盘面, 键面 }; +use crate::变换; +use crate::键位映射; -lazy_static! { - static ref 並擊碼表示: Box<[拼寫運算::<'static>]> = Box::new([ - 變換!("精匣", "莊"), - 變換!("清來定", "崇"), - 變換!("清來", "初"), - 變換!("心曉羣", "俟"), - 變換!("心曉", "生"), - 變換!("精幫", "章"), - 變換!("清定端", "常"), - 變換!("清端", "昌"), - 變換!("心羣見", "船"), - 變換!("心見", "書"), - 變換!("清定", "從"), - 變換!("心羣", "邪"), - 變換!("並幫", "明"), - 變換!("來定端", "娘"), - 變換!("定端", "泥"), - 變換!("來端", "知"), - 變換!("來透", "徹"), - 變換!("來定", "澄"), - 變換!("曉羣見", "日"), - 變換!("羣見", "疑"), - 變換!("曉羣", "云"), - 變換!("心定", "以"), - 變換!("^([果止流假遇曾臻深上去入])", "影$1"), - 變換!("果止", "蟹"), - 變換!("果流", "效"), - 變換!("果深", "咸"), - 變換!("果臻", "山"), - 變換!("果曾", "宕"), - 變換!("遇曾", "江"), - 變換!("止曾", "梗"), - 變換!("流曾", "通"), - ]); - static ref 並擊碼鍵位: Box<[拼寫運算<'static>]> = Box::new([ - 變換!("莊", "精匣"), - 變換!("崇", "清來定"), - 變換!("初", "清來"), - 變換!("俟", "心曉羣"), - 變換!("生", "心曉"), - 變換!("章", "精幫"), - 變換!("常", "清定端"), - 變換!("昌", "清端"), - 變換!("船", "心羣見"), - 變換!("書", "心見"), - 變換!("從", "清定"), - 變換!("邪", "心羣"), - 變換!("明", "並幫"), - 變換!("娘", "來定端"), - 變換!("泥", "定端"), - 變換!("知", "來端"), - 變換!("徹", "來透"), - 變換!("澄", "來定"), - 變換!("日", "曉羣見"), - 變換!("疑", "羣見"), - 變換!("云", "曉羣"), - 變換!("以", "心定"), - 變換!("影", ""), - 變換!("蟹", "果止"), - 變換!("效", "果流"), - 變換!("咸", "果深"), - 變換!("山", "果臻"), - 變換!("宕", "果曾"), - 變換!("江", "遇曾"), - 變換!("梗", "止曾"), - 變換!("通", "流曾"), - ]); -} - -const 早期中古漢語拼音盤面: 盤面定義<'static> = 盤面![ +const 早期中古汉语拼音盘面: 盘面定义<'static> = + 盘面![ [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], [ 清 來 定 端 透 空 流 臻 遇 上 _ _ ], [ 心 曉 羣 見 溪 空 止 曾 假 入 _ ], @@ -124,24 +19,122 @@ const 早期中古漢語拼音盤面: 盤面定義<'static> = 盤面![ [ 果 _ 果 ] ]; -const 早期中古漢語並擊佈局: 鍵盤佈局 = 鍵盤佈局 { - 盤面: &[基本盤面, 上檔盤面, 大寫字母盤面, 早期中古漢語拼音盤面], - 默認盤面: 盤面選擇碼(4), - 首選配列: 配列::正交直列, +const 早期中古汉语并击布局: 键盘布局 = 键盘布局 { + 盘面: &[基本盘面, 上档盘面, 大写字母盘面, 早期中古汉语拼音盘面], + 默认盘面: 盘面序号(4), + 默认配列: 键盘配列::正交直列, }; -pub fn 早期中古漢語輸入方案() -> 輸入方案定義<'static> { - 輸入方案定義 { - 名稱: "早期中古漢語", - 佈局: &早期中古漢語並擊佈局, - 指法: 觸鍵方式::並擊, - 字根表: 並擊鍵序, - 轉寫法: 轉寫法定義 { - 輸入碼表示: &並擊碼表示, - 輸入碼鍵位: &並擊碼鍵位, - 拼式轉寫規則: &[], - 字根拆分規則: &[], - 拼式驗證規則: &[], +const 并击键位映射: &[键位映射定义] = &[ + 键位映射!(心 => KeyCode::A), + 键位映射!(清 => KeyCode::Q), + 键位映射!(精 => KeyCode::Z), + 键位映射!(曉 => KeyCode::S), + 键位映射!(來 => KeyCode::W), + 键位映射!(匣 => KeyCode::X), + 键位映射!(羣 => KeyCode::D), + 键位映射!(定 => KeyCode::E), + 键位映射!(並 => KeyCode::C), + 键位映射!(見 => KeyCode::F), + 键位映射!(端 => KeyCode::R), + 键位映射!(幫 => KeyCode::V), + 键位映射!(溪 => KeyCode::G), + 键位映射!(透 => KeyCode::T), + 键位映射!(滂 => KeyCode::B), + 键位映射!(果 => KeyCode::Space), + 键位映射!(止 => KeyCode::J), + 键位映射!(流 => KeyCode::U), + 键位映射!(假 => KeyCode::L), + 键位映射!(遇 => KeyCode::O), + 键位映射!(曾 => KeyCode::K), + 键位映射!(臻 => KeyCode::I), + 键位映射!(深 => KeyCode::Comma), + 键位映射!(入 => KeyCode::Semicolon), + 键位映射!(上 => KeyCode::P), + 键位映射!(去 => KeyCode::Slash), +]; + +lazy_static! { + static ref 并击码表示: Box<[拼写运算<'static>]> = Box::new([ + 变换!("精匣", "莊"), + 变换!("清來定", "崇"), + 变换!("清來", "初"), + 变换!("心曉羣", "俟"), + 变换!("心曉", "生"), + 变换!("精幫", "章"), + 变换!("清定端", "常"), + 变换!("清端", "昌"), + 变换!("心羣見", "船"), + 变换!("心見", "書"), + 变换!("清定", "從"), + 变换!("心羣", "邪"), + 变换!("並幫", "明"), + 变换!("來定端", "娘"), + 变换!("定端", "泥"), + 变换!("來端", "知"), + 变换!("來透", "徹"), + 变换!("來定", "澄"), + 变换!("曉羣見", "日"), + 变换!("羣見", "疑"), + 变换!("曉羣", "云"), + 变换!("心定", "以"), + 变换!("^([果止流假遇曾臻深上去入])", "影$1"), + 变换!("果止", "蟹"), + 变换!("果流", "效"), + 变换!("果深", "咸"), + 变换!("果臻", "山"), + 变换!("果曾", "宕"), + 变换!("遇曾", "江"), + 变换!("止曾", "梗"), + 变换!("流曾", "通"), + ]); + static ref 并击码键位: Box<[拼写运算<'static>]> = Box::new([ + 变换!("莊", "精匣"), + 变换!("崇", "清來定"), + 变换!("初", "清來"), + 变换!("俟", "心曉羣"), + 变换!("生", "心曉"), + 变换!("章", "精幫"), + 变换!("常", "清定端"), + 变换!("昌", "清端"), + 变换!("船", "心羣見"), + 变换!("書", "心見"), + 变换!("從", "清定"), + 变换!("邪", "心羣"), + 变换!("明", "並幫"), + 变换!("娘", "來定端"), + 变换!("泥", "定端"), + 变换!("知", "來端"), + 变换!("徹", "來透"), + 变换!("澄", "來定"), + 变换!("日", "曉羣見"), + 变换!("疑", "羣見"), + 变换!("云", "曉羣"), + 变换!("以", "心定"), + 变换!("影", ""), + 变换!("蟹", "果止"), + 变换!("效", "果流"), + 变换!("咸", "果深"), + 变换!("山", "果臻"), + 变换!("宕", "果曾"), + 变换!("江", "遇曾"), + 变换!("梗", "止曾"), + 变换!("通", "流曾"), + ]); +} + +pub fn 输入方案() -> 输入方案定义<'static> { + 输入方案定义 { + 名称: "早期中古汉语", + 布局: &早期中古汉语并击布局, + 指法: 击键方式::并击, + 键位映射: 并击键位映射, + 转写: 转写定义 { + 编码预览: &并击码表示, + 键位提示: &并击码键位, + 输入棱镜: &[], + 词库棱镜: &[], + 拼式验证规则: &[], }, } } diff --git a/src/theory/late_middle_chinese.rs b/src/theory/late_middle_chinese.rs index 3220025..b166270 100644 --- a/src/theory/late_middle_chinese.rs +++ b/src/theory/late_middle_chinese.rs @@ -1,122 +1,17 @@ use lazy_regex::regex; use lazy_static::lazy_static; -use crate::definition::{觸鍵方式, 輸入方案定義, 轉寫法定義, 鍵位定義}; -use crate::gear::layout::{ - 上檔盤面, 基本盤面, 大寫字母盤面, 盤面定義, 盤面選擇碼, 配列, 鍵盤佈局, 鍵面刻印, -}; +use crate::definition::{ 击键方式, 转写定义, 输入方案定义, 键位映射定义 }; +use crate::gear::layout::{ 上档盘面, 基本盘面, 大写字母盘面 }; +use crate::gear::layout::{ 盘面定义, 盘面序号, 键盘布局, 键盘配列, 键面刻印 }; use crate::key_code::KeyCode; -use crate::spelling_algebra::拼寫運算; -use crate::{盤面, 變換, 鍵面}; - -macro_rules! 鍵位 { - ($輸入碼: ident => $鍵碼: path) => { - 鍵位定義 { - 輸入碼: stringify!($輸入碼), - 鍵碼: $鍵碼, - } - }; -} - -const 並擊鍵序: &[鍵位定義] = &[ - 鍵位!(心 => KeyCode::S), - 鍵位!(清 => KeyCode::W), - 鍵位!(精 => KeyCode::X), - 鍵位!(曉 => KeyCode::D), - 鍵位!(來 => KeyCode::E), - 鍵位!(非 => KeyCode::C), - 鍵位!(見 => KeyCode::F), - 鍵位!(端 => KeyCode::R), - 鍵位!(幫 => KeyCode::V), - 鍵位!(溪 => KeyCode::G), - 鍵位!(透 => KeyCode::T), - 鍵位!(滂 => KeyCode::B), - 鍵位!(氣 => KeyCode::A), - 鍵位!(果 => KeyCode::Space), - 鍵位!(止 => KeyCode::J), - 鍵位!(流 => KeyCode::U), - 鍵位!(假 => KeyCode::L), - 鍵位!(遇 => KeyCode::O), - 鍵位!(曾 => KeyCode::K), - 鍵位!(臻 => KeyCode::I), - 鍵位!(深 => KeyCode::Comma), - 鍵位!(入 => KeyCode::Semicolon), - 鍵位!(上 => KeyCode::P), - 鍵位!(去 => KeyCode::Slash), -]; +use crate::spelling_algebra::拼写运算; +use crate::{ 盘面, 键面 }; +use crate::变换; +use crate::键位映射; -lazy_static! { - static ref 並擊碼表示: Box<[拼寫運算::<'static>]> = Box::new([ - 變換!("幫氣", "並"), - 變換!("精非幫", "微"), - 變換!("非幫", "明"), - 變換!("非滂", "敷"), - 變換!("非氣", "奉"), - 變換!("端氣", "定"), - 變換!("清來端", "娘"), - 變換!("來端", "泥"), - 變換!("清端", "知"), - 變換!("清透氣", "澄"), - 變換!("清透", "徹"), - 變換!("清氣", "從"), - 變換!("心氣", "邪"), - 變換!("精非", "照"), - 變換!("清來氣", "牀"), - 變換!("清來", "穿"), - 變換!("心曉見", "日"), - 變換!("心曉氣", "禪"), - 變換!("心曉", "審"), - 變換!("見氣", "羣"), - 變換!("曉見", "疑"), - 變換!("曉氣", "匣"), - 變換!("來氣", "喻"), - 變換!("^([果止流假遇曾臻深上去入])", "影$1"), - 變換!("果止", "蟹"), - 變換!("果流", "效"), - 變換!("果深", "咸"), - 變換!("果臻", "山"), - 變換!("果曾", "宕"), - 變換!("遇曾", "江"), - 變換!("止曾", "梗"), - 變換!("流曾", "通"), - ]); - static ref 並擊碼鍵位: Box<[拼寫運算<'static>]> = Box::new([ - 變換!("並", "幫氣"), - 變換!("微", "精非幫"), - 變換!("明", "非幫"), - 變換!("敷", "非滂"), - 變換!("奉", "非氣"), - 變換!("定", "端氣"), - 變換!("娘", "清來端"), - 變換!("泥", "來端"), - 變換!("知", "清端"), - 變換!("澄", "清透氣"), - 變換!("徹", "清透"), - 變換!("從", "清氣"), - 變換!("邪", "心氣"), - 變換!("照", "精非"), - 變換!("牀", "清來氣"), - 變換!("穿", "清來"), - 變換!("日", "心曉見"), - 變換!("禪", "心曉氣"), - 變換!("審", "心曉"), - 變換!("羣", "見氣"), - 變換!("疑", "曉見"), - 變換!("匣", "曉氣"), - 變換!("喻", "來氣"), - 變換!("影", ""), - 變換!("蟹", "果止"), - 變換!("效", "果流"), - 變換!("咸", "果深"), - 變換!("山", "果臻"), - 變換!("宕", "果曾"), - 變換!("江", "遇曾"), - 變換!("梗", "止曾"), - 變換!("通", "流曾"), - ]); -} - -const 晚期中古漢語拼音盤面: 盤面定義<'static> = 盤面![ +const 晚期中古汉语拼音盘面: 盘面定义<'static> = + 盘面![ [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], [ 空 清 來 端 透 空 流 臻 遇 上 _ _ ], [ 氣 心 曉 見 溪 空 止 曾 假 入 _ ], @@ -124,24 +19,122 @@ const 晚期中古漢語拼音盤面: 盤面定義<'static> = 盤面![ [ 果 _ 果 ] ]; -const 晚期中古漢語並擊佈局: 鍵盤佈局 = 鍵盤佈局 { - 盤面: &[基本盤面, 上檔盤面, 大寫字母盤面, 晚期中古漢語拼音盤面], - 默認盤面: 盤面選擇碼(4), - 首選配列: 配列::正交直列, +const 晚期中古汉语并击布局: 键盘布局 = 键盘布局 { + 盘面: &[基本盘面, 上档盘面, 大写字母盘面, 晚期中古汉语拼音盘面], + 默认盘面: 盘面序号(4), + 默认配列: 键盘配列::正交直列, }; -pub fn 晚期中古漢語輸入方案() -> 輸入方案定義<'static> { - 輸入方案定義 { - 名稱: "晚期中古漢語", - 佈局: &晚期中古漢語並擊佈局, - 指法: 觸鍵方式::並擊, - 字根表: 並擊鍵序, - 轉寫法: 轉寫法定義 { - 輸入碼表示: &並擊碼表示, - 輸入碼鍵位: &並擊碼鍵位, - 拼式轉寫規則: &[], - 字根拆分規則: &[], - 拼式驗證規則: &[], +const 并击键位映射: &[键位映射定义] = &[ + 键位映射!(心 => KeyCode::S), + 键位映射!(清 => KeyCode::W), + 键位映射!(精 => KeyCode::X), + 键位映射!(曉 => KeyCode::D), + 键位映射!(來 => KeyCode::E), + 键位映射!(非 => KeyCode::C), + 键位映射!(見 => KeyCode::F), + 键位映射!(端 => KeyCode::R), + 键位映射!(幫 => KeyCode::V), + 键位映射!(溪 => KeyCode::G), + 键位映射!(透 => KeyCode::T), + 键位映射!(滂 => KeyCode::B), + 键位映射!(氣 => KeyCode::A), + 键位映射!(果 => KeyCode::Space), + 键位映射!(止 => KeyCode::J), + 键位映射!(流 => KeyCode::U), + 键位映射!(假 => KeyCode::L), + 键位映射!(遇 => KeyCode::O), + 键位映射!(曾 => KeyCode::K), + 键位映射!(臻 => KeyCode::I), + 键位映射!(深 => KeyCode::Comma), + 键位映射!(入 => KeyCode::Semicolon), + 键位映射!(上 => KeyCode::P), + 键位映射!(去 => KeyCode::Slash), +]; + +lazy_static! { + static ref 并击码表示: Box<[拼写运算<'static>]> = Box::new([ + 变换!("幫氣", "並"), + 变换!("精非幫", "微"), + 变换!("非幫", "明"), + 变换!("非滂", "敷"), + 变换!("非氣", "奉"), + 变换!("端氣", "定"), + 变换!("清來端", "娘"), + 变换!("來端", "泥"), + 变换!("清端", "知"), + 变换!("清透氣", "澄"), + 变换!("清透", "徹"), + 变换!("清氣", "從"), + 变换!("心氣", "邪"), + 变换!("精非", "照"), + 变换!("清來氣", "牀"), + 变换!("清來", "穿"), + 变换!("心曉見", "日"), + 变换!("心曉氣", "禪"), + 变换!("心曉", "審"), + 变换!("見氣", "羣"), + 变换!("曉見", "疑"), + 变换!("曉氣", "匣"), + 变换!("來氣", "喻"), + 变换!("^([果止流假遇曾臻深上去入])", "影$1"), + 变换!("果止", "蟹"), + 变换!("果流", "效"), + 变换!("果深", "咸"), + 变换!("果臻", "山"), + 变换!("果曾", "宕"), + 变换!("遇曾", "江"), + 变换!("止曾", "梗"), + 变换!("流曾", "通"), + ]); + static ref 并击码键位: Box<[拼写运算<'static>]> = Box::new([ + 变换!("並", "幫氣"), + 变换!("微", "精非幫"), + 变换!("明", "非幫"), + 变换!("敷", "非滂"), + 变换!("奉", "非氣"), + 变换!("定", "端氣"), + 变换!("娘", "清來端"), + 变换!("泥", "來端"), + 变换!("知", "清端"), + 变换!("澄", "清透氣"), + 变换!("徹", "清透"), + 变换!("從", "清氣"), + 变换!("邪", "心氣"), + 变换!("照", "精非"), + 变换!("牀", "清來氣"), + 变换!("穿", "清來"), + 变换!("日", "心曉見"), + 变换!("禪", "心曉氣"), + 变换!("審", "心曉"), + 变换!("羣", "見氣"), + 变换!("疑", "曉見"), + 变换!("匣", "曉氣"), + 变换!("喻", "來氣"), + 变换!("影", ""), + 变换!("蟹", "果止"), + 变换!("效", "果流"), + 变换!("咸", "果深"), + 变换!("山", "果臻"), + 变换!("宕", "果曾"), + 变换!("江", "遇曾"), + 变换!("梗", "止曾"), + 变换!("通", "流曾"), + ]); +} + +pub fn 输入方案() -> 输入方案定义<'static> { + 输入方案定义 { + 名称: "晚期中古汉语", + 布局: &晚期中古汉语并击布局, + 指法: 击键方式::并击, + 键位映射: 并击键位映射, + 转写: 转写定义 { + 编码预览: &并击码表示, + 键位提示: &并击码键位, + 输入棱镜: &[], + 词库棱镜: &[], + 拼式验证规则: &[], }, } } diff --git a/src/theory/mod.rs b/src/theory/mod.rs index 046bdac..83fb46e 100644 --- a/src/theory/mod.rs +++ b/src/theory/mod.rs @@ -2,6 +2,7 @@ pub mod alphabet; pub mod cantonese; pub mod combo_jyutping; pub mod combo_pinyin; +pub mod double_pinyin_fly; pub mod early_middle_chinese; pub mod late_middle_chinese; pub mod modern_chinese; diff --git a/src/theory/modern_chinese.rs b/src/theory/modern_chinese.rs index 469a044..7074cc2 100644 --- a/src/theory/modern_chinese.rs +++ b/src/theory/modern_chinese.rs @@ -1,103 +1,17 @@ use lazy_regex::regex; use lazy_static::lazy_static; -use crate::definition::{觸鍵方式, 輸入方案定義, 轉寫法定義, 鍵位定義}; -use crate::gear::layout::{ - 上檔盤面, 基本盤面, 大寫字母盤面, 盤面定義, 盤面選擇碼, 配列, 鍵盤佈局, 鍵面刻印, -}; +use crate::definition::{ 击键方式, 转写定义, 输入方案定义, 键位映射定义 }; +use crate::gear::layout::{ 上档盘面, 基本盘面, 大写字母盘面 }; +use crate::gear::layout::{ 盘面定义, 盘面序号, 键盘布局, 键盘配列, 键面刻印 }; use crate::key_code::KeyCode; -use crate::spelling_algebra::拼寫運算; -use crate::{盤面, 變換, 轉寫, 鍵面}; - -macro_rules! 鍵位 { - ($輸入碼: ident => $鍵碼: path) => { - 鍵位定義 { - 輸入碼: stringify!($輸入碼), - 鍵碼: $鍵碼, - } - }; -} - -const 並擊鍵序: &[鍵位定義] = &[ - 鍵位!(心 => KeyCode::S), - 鍵位!(清 => KeyCode::W), - 鍵位!(精 => KeyCode::X), - 鍵位!(曉 => KeyCode::D), - 鍵位!(來 => KeyCode::E), - 鍵位!(非 => KeyCode::C), - 鍵位!(見 => KeyCode::F), - 鍵位!(端 => KeyCode::R), - 鍵位!(幫 => KeyCode::V), - 鍵位!(溪 => KeyCode::G), - 鍵位!(透 => KeyCode::T), - 鍵位!(滂 => KeyCode::B), - 鍵位!(齊 => KeyCode::J), - 鍵位!(模 => KeyCode::U), - 鍵位!(魚 => KeyCode::M), - 鍵位!(麻 => KeyCode::Space), - 鍵位!(痕 => KeyCode::K), - 鍵位!(支 => KeyCode::I), - 鍵位!(歌 => KeyCode::L), - 鍵位!(波 => KeyCode::O), -]; +use crate::spelling_algebra::拼写运算; +use crate::{ 变换, 转写 }; +use crate::{ 盘面, 键面 }; +use crate::键位映射; -lazy_static! { - static ref 並擊碼表示: Box<[拼寫運算::<'static>]> = Box::new([ - 變換!("非幫", "明"), - 變換!("來端", "泥"), - 變換!("精非", "照"), - 變換!("清來", "穿"), - 變換!("心曉", "審"), - 變換!("曉見", "日"), - 變換!("^([齊模魚麻痕支歌波])", "影$1"), - 變換!("([齊魚])歌", "${1}皆"), - 變換!("模麻支波", "唐合"), - 變換!("麻痕歌", "唐"), - 變換!("痕歌", "庚"), - 變換!("齊支波", "東齊"), - 變換!("模支波", "東"), - 變換!("麻痕", "寒"), - 變換!("麻支", "開"), - 變換!("模支$", "微合"), - 變換!("支歌", "微"), - 變換!("麻波", "豪"), - 變換!("齊支$", "侯齊"), - 變換!("支波", "侯"), - 變換!("影支$", "影兒"), - 變換!("齊(.+)$", "${1}齊"), - 變換!("模(.+)$", "${1}合"), - 變換!("魚(.+)$", "${1}撮"), - 變換!("^([精清心照穿審日])$", "$1支"), - ]); - static ref 並擊碼鍵位: Box<[拼寫運算<'static>]> = Box::new([ - 變換!("^([精清心照穿審日])支$", "$1"), - 變換!("明", "非幫"), - 變換!("泥", "來端"), - 變換!("照", "精非"), - 變換!("穿", "清來"), - 變換!("審", "心曉"), - 變換!("日", "曉見"), - 變換!("影", ""), - 變換!("唐合", "模麻支波"), - 變換!("唐", "麻痕歌"), - 變換!("庚", "痕歌"), - 變換!("東齊", "齊支波"), - 變換!("東", "模支波"), - 變換!("寒", "麻痕"), - 變換!("開", "麻支"), - 變換!("微合", "模支"), - 變換!("微", "支歌"), - 變換!("豪", "麻波"), - 變換!("侯齊", "齊支"), - 變換!("侯", "支波"), - 轉寫!("兒皆", "支歌"), - 變換!("([麻痕支歌波]+)齊$", "齊$1"), - 變換!("([麻痕支歌波]+)合$", "模$1"), - 變換!("([麻痕支歌波]+)撮$", "魚$1"), - ]); -} - -const 現代漢語拼音盤面: 盤面定義<'static> = 盤面![ +const 现代汉语拼音盘面: 盘面定义<'static> = + 盘面![ [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], [ 空 清 來 端 透 空 模 支 波 空 _ _ ], [ 空 心 曉 見 溪 空 齊 痕 歌 空 _ ], @@ -105,24 +19,103 @@ const 現代漢語拼音盤面: 盤面定義<'static> = 盤面![ [ 麻 _ 麻 ] ]; -const 現代漢語並擊佈局: 鍵盤佈局 = 鍵盤佈局 { - 盤面: &[基本盤面, 上檔盤面, 大寫字母盤面, 現代漢語拼音盤面], - 默認盤面: 盤面選擇碼(4), - 首選配列: 配列::正交直列, +const 现代汉语并击布局: 键盘布局 = 键盘布局 { + 盘面: &[基本盘面, 上档盘面, 大写字母盘面, 现代汉语拼音盘面], + 默认盘面: 盘面序号(4), + 默认配列: 键盘配列::正交直列, }; -pub fn 現代漢語輸入方案() -> 輸入方案定義<'static> { - 輸入方案定義 { - 名稱: "現代漢語", - 佈局: &現代漢語並擊佈局, - 指法: 觸鍵方式::並擊, - 字根表: 並擊鍵序, - 轉寫法: 轉寫法定義 { - 輸入碼表示: &並擊碼表示, - 輸入碼鍵位: &並擊碼鍵位, - 拼式轉寫規則: &[], - 字根拆分規則: &[], - 拼式驗證規則: &[], +const 并击键位映射: &[键位映射定义] = &[ + 键位映射!(心 => KeyCode::S), + 键位映射!(清 => KeyCode::W), + 键位映射!(精 => KeyCode::X), + 键位映射!(曉 => KeyCode::D), + 键位映射!(來 => KeyCode::E), + 键位映射!(非 => KeyCode::C), + 键位映射!(見 => KeyCode::F), + 键位映射!(端 => KeyCode::R), + 键位映射!(幫 => KeyCode::V), + 键位映射!(溪 => KeyCode::G), + 键位映射!(透 => KeyCode::T), + 键位映射!(滂 => KeyCode::B), + 键位映射!(齊 => KeyCode::J), + 键位映射!(模 => KeyCode::U), + 键位映射!(魚 => KeyCode::M), + 键位映射!(麻 => KeyCode::Space), + 键位映射!(痕 => KeyCode::K), + 键位映射!(支 => KeyCode::I), + 键位映射!(歌 => KeyCode::L), + 键位映射!(波 => KeyCode::O), +]; + +lazy_static! { + static ref 并击码表示: Box<[拼写运算<'static>]> = Box::new([ + 变换!("非幫", "明"), + 变换!("來端", "泥"), + 变换!("精非", "照"), + 变换!("清來", "穿"), + 变换!("心曉", "審"), + 变换!("曉見", "日"), + 变换!("^([齊模魚麻痕支歌波])", "影$1"), + 变换!("([齊魚])歌", "${1}皆"), + 变换!("模麻支波", "唐合"), + 变换!("麻痕歌", "唐"), + 变换!("痕歌", "庚"), + 变换!("齊支波", "東齊"), + 变换!("模支波", "東"), + 变换!("麻痕", "寒"), + 变换!("麻支", "開"), + 变换!("模支$", "微合"), + 变换!("支歌", "微"), + 变换!("麻波", "豪"), + 变换!("齊支$", "侯齊"), + 变换!("支波", "侯"), + 变换!("影支$", "影兒"), + 变换!("齊(.+)$", "${1}齊"), + 变换!("模(.+)$", "${1}合"), + 变换!("魚(.+)$", "${1}撮"), + 变换!("^([精清心照穿審日])$", "$1支"), + ]); + static ref 并击码键位: Box<[拼写运算<'static>]> = Box::new([ + 变换!("^([精清心照穿審日])支$", "$1"), + 变换!("明", "非幫"), + 变换!("泥", "來端"), + 变换!("照", "精非"), + 变换!("穿", "清來"), + 变换!("審", "心曉"), + 变换!("日", "曉見"), + 变换!("影", ""), + 变换!("唐合", "模麻支波"), + 变换!("唐", "麻痕歌"), + 变换!("庚", "痕歌"), + 变换!("東齊", "齊支波"), + 变换!("東", "模支波"), + 变换!("寒", "麻痕"), + 变换!("開", "麻支"), + 变换!("微合", "模支"), + 变换!("微", "支歌"), + 变换!("豪", "麻波"), + 变换!("侯齊", "齊支"), + 变换!("侯", "支波"), + 转写!("兒皆", "支歌"), + 变换!("([麻痕支歌波]+)齊$", "齊$1"), + 变换!("([麻痕支歌波]+)合$", "模$1"), + 变换!("([麻痕支歌波]+)撮$", "魚$1"), + ]); +} + +pub fn 输入方案() -> 输入方案定义<'static> { + 输入方案定义 { + 名称: "现代汉语", + 布局: &现代汉语并击布局, + 指法: 击键方式::并击, + 键位映射: 并击键位映射, + 转写: 转写定义 { + 编码预览: &并击码表示, + 键位提示: &并击码键位, + 输入棱镜: &[], + 词库棱镜: &[], + 拼式验证规则: &[], }, } } diff --git a/src/theory/old_chinese.rs b/src/theory/old_chinese.rs index 6238a12..a175d72 100644 --- a/src/theory/old_chinese.rs +++ b/src/theory/old_chinese.rs @@ -1,143 +1,17 @@ use lazy_regex::regex; use lazy_static::lazy_static; -use crate::definition::{觸鍵方式, 輸入方案定義, 轉寫法定義, 鍵位定義}; -use crate::gear::layout::{ - 上檔盤面, 基本盤面, 大寫字母盤面, 盤面定義, 盤面選擇碼, 配列, 鍵盤佈局, 鍵面刻印, -}; +use crate::definition::{ 击键方式, 转写定义, 输入方案定义, 键位映射定义 }; +use crate::gear::layout::{ 上档盘面, 基本盘面, 大写字母盘面 }; +use crate::gear::layout::{ 盘面定义, 盘面序号, 键盘布局, 键盘配列, 键面刻印 }; use crate::key_code::KeyCode; -use crate::spelling_algebra::拼寫運算; -use crate::{盤面, 變換, 鍵面}; - -macro_rules! 鍵位 { - ($輸入碼: ident => $鍵碼: path) => { - 鍵位定義 { - 輸入碼: stringify!($輸入碼), - 鍵碼: $鍵碼, - } - }; -} - -const 並擊鍵序: &[鍵位定義] = &[ - 鍵位!(心 => KeyCode::A), - 鍵位!(清 => KeyCode::Q), - 鍵位!(精 => KeyCode::Z), - 鍵位!(曉 => KeyCode::S), - 鍵位!(來 => KeyCode::W), - 鍵位!(匣 => KeyCode::X), - 鍵位!(羣 => KeyCode::D), - 鍵位!(定 => KeyCode::E), - 鍵位!(並 => KeyCode::C), - 鍵位!(見 => KeyCode::F), - 鍵位!(端 => KeyCode::R), - 鍵位!(幫 => KeyCode::V), - 鍵位!(溪 => KeyCode::G), - 鍵位!(透 => KeyCode::T), - 鍵位!(滂 => KeyCode::B), - 鍵位!(魚 => KeyCode::Space), - 鍵位!(支 => KeyCode::H), - 鍵位!(侯 => KeyCode::Y), - 鍵位!(之 => KeyCode::N), - 鍵位!(脂 => KeyCode::J), - 鍵位!(幽 => KeyCode::U), - 鍵位!(微 => KeyCode::M), - 鍵位!(蒸 => KeyCode::K), - 鍵位!(文 => KeyCode::I), - 鍵位!(深 => KeyCode::Comma), - 鍵位!(職 => KeyCode::L), - 鍵位!(物 => KeyCode::O), - 鍵位!(緝 => KeyCode::Dot), - 鍵位!(代 => KeyCode::Semicolon), - 鍵位!(隊 => KeyCode::P), - 鍵位!(內 => KeyCode::Slash), -]; +use crate::spelling_algebra::拼写运算; +use crate::{ 盘面, 键面 }; +use crate::变换; +use crate::键位映射; -lazy_static! { - static ref 並擊碼表示: Box<[拼寫運算::<'static>]> = Box::new([ - 變換!("精匣", "莊"), - 變換!("清來定", "崇"), - 變換!("清來", "初"), - 變換!("心曉羣", "俟"), - 變換!("心曉", "生"), - 變換!("精幫", "章"), - 變換!("清定端", "常"), - 變換!("清端", "昌"), - 變換!("心羣見", "船"), - 變換!("心見", "書"), - 變換!("清定", "從"), - 變換!("心羣", "邪"), - 變換!("並幫", "明"), - 變換!("來定端", "娘"), - 變換!("定端", "泥"), - 變換!("來端", "知"), - 變換!("來透", "徹"), - 變換!("來定", "澄"), - 變換!("曉羣見", "日"), - 變換!("羣見", "疑"), - 變換!("^([魚支侯之脂幽微蒸文深職物緝代隊內])", "影$1"), - 變換!("魚幽職", "藥"), - 變換!("魚幽代", "豹"), - 變換!("魚幽", "宵"), - 變換!("魚文", "元"), - 變換!("魚物", "月"), - 變換!("魚蒸", "陽"), - 變換!("魚微", "歌"), - 變換!("魚職", "鐸"), - 變換!("幽職", "覺"), - 變換!("支職", "錫"), - 變換!("魚深", "談"), - 變換!("侯職", "屋"), - 變換!("支蒸", "耕"), - 變換!("脂職", "質"), - 變換!("脂文", "真"), - 變換!("幽蒸", "終"), - 變換!("支緝", "盍"), - 變換!("侯蒸", "東"), - ]); - static ref 並擊碼鍵位: Box<[拼寫運算<'static>]> = Box::new([ - 變換!("莊", "精匣"), - 變換!("崇", "清來定"), - 變換!("初", "清來"), - 變換!("俟", "心曉羣"), - 變換!("生", "心曉"), - 變換!("章", "精幫"), - 變換!("常", "清定端"), - 變換!("昌", "清端"), - 變換!("船", "心羣見"), - 變換!("書", "心見"), - 變換!("從", "清定"), - 變換!("邪", "心羣"), - 變換!("明", "並幫"), - 變換!("娘", "來定端"), - 變換!("泥", "定端"), - 變換!("知", "來端"), - 變換!("徹", "來透"), - 變換!("澄", "來定"), - 變換!("日", "曉羣見"), - 變換!("疑", "羣見"), - 變換!("影", ""), - 變換!("藥", "魚幽職"), - 變換!("豹", "魚幽代"), - 變換!("宵", "魚幽"), - 變換!("元", "魚文"), - 變換!("月", "魚物"), - 變換!("陽", "魚蒸"), - 變換!("歌", "魚微"), - 變換!("鐸", "魚職"), - 變換!("覺", "幽職"), - 變換!("錫", "支職"), - 變換!("談", "魚深"), - 變換!("屋", "侯職"), - 變換!("耕", "支蒸"), - 變換!("質", "脂職"), - 變換!("真", "脂文"), - 變換!("終", "幽蒸"), - 變換!("盍", "支緝"), - 變換!("東", "侯蒸"), - ]); -} - -const 上古漢語拼音盤面: 盤面定義<'static> = 盤面![ +const 上古汉语拼音盘面: 盘面定义<'static> = + 盘面![ [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], [ 清 來 定 端 透 侯 幽 文 物 隊 _ _ ], [ 心 曉 羣 見 溪 支 脂 蒸 職 代 _ _ ], @@ -145,24 +19,143 @@ const 上古漢語拼音盤面: 盤面定義<'static> = 盤面![ [ 魚 _ 魚 ] ]; -const 上古漢語並擊佈局: 鍵盤佈局 = 鍵盤佈局 { - 盤面: &[基本盤面, 上檔盤面, 大寫字母盤面, 上古漢語拼音盤面], - 默認盤面: 盤面選擇碼(4), - 首選配列: 配列::正交直列, +const 上古汉语并击布局: 键盘布局 = 键盘布局 { + 盘面: &[基本盘面, 上档盘面, 大写字母盘面, 上古汉语拼音盘面], + 默认盘面: 盘面序号(4), + 默认配列: 键盘配列::正交直列, }; -pub fn 上古漢語輸入方案() -> 輸入方案定義<'static> { - 輸入方案定義 { - 名稱: "上古漢語", - 佈局: &上古漢語並擊佈局, - 指法: 觸鍵方式::並擊, - 字根表: 並擊鍵序, - 轉寫法: 轉寫法定義 { - 輸入碼表示: &並擊碼表示, - 輸入碼鍵位: &並擊碼鍵位, - 拼式轉寫規則: &[], - 字根拆分規則: &[], - 拼式驗證規則: &[], +const 并击键位映射: &[键位映射定义] = &[ + 键位映射!(心 => KeyCode::A), + 键位映射!(清 => KeyCode::Q), + 键位映射!(精 => KeyCode::Z), + 键位映射!(曉 => KeyCode::S), + 键位映射!(來 => KeyCode::W), + 键位映射!(匣 => KeyCode::X), + 键位映射!(羣 => KeyCode::D), + 键位映射!(定 => KeyCode::E), + 键位映射!(並 => KeyCode::C), + 键位映射!(見 => KeyCode::F), + 键位映射!(端 => KeyCode::R), + 键位映射!(幫 => KeyCode::V), + 键位映射!(溪 => KeyCode::G), + 键位映射!(透 => KeyCode::T), + 键位映射!(滂 => KeyCode::B), + 键位映射!(魚 => KeyCode::Space), + 键位映射!(支 => KeyCode::H), + 键位映射!(侯 => KeyCode::Y), + 键位映射!(之 => KeyCode::N), + 键位映射!(脂 => KeyCode::J), + 键位映射!(幽 => KeyCode::U), + 键位映射!(微 => KeyCode::M), + 键位映射!(蒸 => KeyCode::K), + 键位映射!(文 => KeyCode::I), + 键位映射!(深 => KeyCode::Comma), + 键位映射!(職 => KeyCode::L), + 键位映射!(物 => KeyCode::O), + 键位映射!(緝 => KeyCode::Dot), + 键位映射!(代 => KeyCode::Semicolon), + 键位映射!(隊 => KeyCode::P), + 键位映射!(內 => KeyCode::Slash), +]; + +lazy_static! { + static ref 并击码表示: Box<[拼写运算<'static>]> = Box::new([ + 变换!("精匣", "莊"), + 变换!("清來定", "崇"), + 变换!("清來", "初"), + 变换!("心曉羣", "俟"), + 变换!("心曉", "生"), + 变换!("精幫", "章"), + 变换!("清定端", "常"), + 变换!("清端", "昌"), + 变换!("心羣見", "船"), + 变换!("心見", "書"), + 变换!("清定", "從"), + 变换!("心羣", "邪"), + 变换!("並幫", "明"), + 变换!("來定端", "娘"), + 变换!("定端", "泥"), + 变换!("來端", "知"), + 变换!("來透", "徹"), + 变换!("來定", "澄"), + 变换!("曉羣見", "日"), + 变换!("羣見", "疑"), + 变换!("^([魚支侯之脂幽微蒸文深職物緝代隊內])", "影$1"), + 变换!("魚幽職", "藥"), + 变换!("魚幽代", "豹"), + 变换!("魚幽", "宵"), + 变换!("魚文", "元"), + 变换!("魚物", "月"), + 变换!("魚蒸", "陽"), + 变换!("魚微", "歌"), + 变换!("魚職", "鐸"), + 变换!("幽職", "覺"), + 变换!("支職", "錫"), + 变换!("魚深", "談"), + 变换!("侯職", "屋"), + 变换!("支蒸", "耕"), + 变换!("脂職", "質"), + 变换!("脂文", "真"), + 变换!("幽蒸", "終"), + 变换!("支緝", "盍"), + 变换!("侯蒸", "東"), + ]); + static ref 并击码键位: Box<[拼写运算<'static>]> = Box::new([ + 变换!("莊", "精匣"), + 变换!("崇", "清來定"), + 变换!("初", "清來"), + 变换!("俟", "心曉羣"), + 变换!("生", "心曉"), + 变换!("章", "精幫"), + 变换!("常", "清定端"), + 变换!("昌", "清端"), + 变换!("船", "心羣見"), + 变换!("書", "心見"), + 变换!("從", "清定"), + 变换!("邪", "心羣"), + 变换!("明", "並幫"), + 变换!("娘", "來定端"), + 变换!("泥", "定端"), + 变换!("知", "來端"), + 变换!("徹", "來透"), + 变换!("澄", "來定"), + 变换!("日", "曉羣見"), + 变换!("疑", "羣見"), + 变换!("影", ""), + 变换!("藥", "魚幽職"), + 变换!("豹", "魚幽代"), + 变换!("宵", "魚幽"), + 变换!("元", "魚文"), + 变换!("月", "魚物"), + 变换!("陽", "魚蒸"), + 变换!("歌", "魚微"), + 变换!("鐸", "魚職"), + 变换!("覺", "幽職"), + 变换!("錫", "支職"), + 变换!("談", "魚深"), + 变换!("屋", "侯職"), + 变换!("耕", "支蒸"), + 变换!("質", "脂職"), + 变换!("真", "脂文"), + 变换!("終", "幽蒸"), + 变换!("盍", "支緝"), + 变换!("東", "侯蒸"), + ]); +} + +pub fn 输入方案() -> 输入方案定义<'static> { + 输入方案定义 { + 名称: "上古汉语", + 布局: &上古汉语并击布局, + 指法: 击键方式::并击, + 键位映射: 并击键位映射, + 转写: 转写定义 { + 编码预览: &并击码表示, + 键位提示: &并击码键位, + 输入棱镜: &[], + 词库棱镜: &[], + 拼式验证规则: &[], }, } } diff --git a/src/theory/old_mandarin.rs b/src/theory/old_mandarin.rs index 8d1e013..91f8bf3 100644 --- a/src/theory/old_mandarin.rs +++ b/src/theory/old_mandarin.rs @@ -1,93 +1,17 @@ use lazy_regex::regex; use lazy_static::lazy_static; -use crate::definition::{觸鍵方式, 輸入方案定義, 轉寫法定義, 鍵位定義}; -use crate::gear::layout::{ - 上檔盤面, 基本盤面, 大寫字母盤面, 盤面定義, 盤面選擇碼, 配列, 鍵盤佈局, 鍵面刻印, -}; +use crate::definition::{ 击键方式, 转写定义, 输入方案定义, 键位映射定义 }; +use crate::gear::layout::{ 上档盘面, 基本盘面, 大写字母盘面 }; +use crate::gear::layout::{ 盘面定义, 盘面序号, 键盘布局, 键盘配列, 键面刻印 }; use crate::key_code::KeyCode; -use crate::spelling_algebra::拼寫運算; -use crate::{盤面, 變換, 鍵面}; - -macro_rules! 鍵位 { - ($輸入碼: ident => $鍵碼: path) => { - 鍵位定義 { - 輸入碼: stringify!($輸入碼), - 鍵碼: $鍵碼, - } - }; -} - -const 並擊鍵序: &[鍵位定義] = &[ - 鍵位!(心 => KeyCode::S), - 鍵位!(清 => KeyCode::W), - 鍵位!(精 => KeyCode::X), - 鍵位!(曉 => KeyCode::D), - 鍵位!(來 => KeyCode::E), - 鍵位!(非 => KeyCode::C), - 鍵位!(見 => KeyCode::F), - 鍵位!(端 => KeyCode::R), - 鍵位!(幫 => KeyCode::V), - 鍵位!(溪 => KeyCode::G), - 鍵位!(透 => KeyCode::T), - 鍵位!(滂 => KeyCode::B), - 鍵位!(家 => KeyCode::Space), - 鍵位!(齊 => KeyCode::J), - 鍵位!(魚 => KeyCode::U), - 鍵位!(支 => KeyCode::M), - 鍵位!(車 => KeyCode::L), - 鍵位!(歌 => KeyCode::O), - 鍵位!(庚 => KeyCode::K), - 鍵位!(真 => KeyCode::I), - 鍵位!(侵 => KeyCode::Comma), -]; +use crate::spelling_algebra::拼写运算; +use crate::{ 盘面, 键面 }; +use crate::变换; +use crate::键位映射; -lazy_static! { - static ref 並擊碼表示: Box<[拼寫運算::<'static>]> = Box::new([ - 變換!("精非幫", "微"), - 變換!("非幫", "明"), - 變換!("來端", "泥"), - 變換!("心曉見", "日"), - 變換!("曉見", "疑"), - 變換!("精非", "照"), - 變換!("清來", "穿"), - 變換!("心曉", "審"), - 變換!("^([家齊魚支庚真侵車歌])", "影$1"), - 變換!("魚庚", "東"), - 變換!("家庚", "江"), - 變換!("家真", "寒"), - 變換!("車真", "先"), - 變換!("歌真", "桓"), - 變換!("車侵", "廉"), - 變換!("家侵", "監"), - 變換!("家齊", "皆"), - 變換!("家魚", "蕭"), - 變換!("魚歌", "尤"), - ]); - static ref 並擊碼鍵位: Box<[拼寫運算<'static>]> = Box::new([ - 變換!("微", "精非幫"), - 變換!("明", "非幫"), - 變換!("泥", "來端"), - 變換!("疑", "曉見"), - 變換!("照", "精非"), - 變換!("穿", "清來"), - 變換!("日", "心曉見"), - 變換!("審", "心曉"), - 變換!("影", ""), - 變換!("東", "魚庚"), - 變換!("江", "家庚"), - 變換!("寒", "家真"), - 變換!("先", "車真"), - 變換!("桓", "歌真"), - 變換!("廉", "車侵"), - 變換!("監", "家侵"), - 變換!("皆", "家齊"), - 變換!("蕭", "家魚"), - 變換!("尤", "魚歌"), - ]); -} - -const 近古漢語拼音盤面: 盤面定義<'static> = 盤面![ +const 近古汉语拼音盘面: 盘面定义<'static> = + 盘面![ [ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ], [ 空 清 來 端 透 空 魚 真 歌 空 _ _ ], [ 空 心 曉 見 溪 空 齊 庚 車 空 _ ], @@ -95,24 +19,93 @@ const 近古漢語拼音盤面: 盤面定義<'static> = 盤面![ [ 家 _ 家 ] ]; -const 近古漢語並擊佈局: 鍵盤佈局 = 鍵盤佈局 { - 盤面: &[基本盤面, 上檔盤面, 大寫字母盤面, 近古漢語拼音盤面], - 默認盤面: 盤面選擇碼(4), - 首選配列: 配列::正交直列, +const 近古汉语并击布局: 键盘布局 = 键盘布局 { + 盘面: &[基本盘面, 上档盘面, 大写字母盘面, 近古汉语拼音盘面], + 默认盘面: 盘面序号(4), + 默认配列: 键盘配列::正交直列, }; -pub fn 近古漢語輸入方案() -> 輸入方案定義<'static> { - 輸入方案定義 { - 名稱: "近古漢語", - 佈局: &近古漢語並擊佈局, - 指法: 觸鍵方式::並擊, - 字根表: 並擊鍵序, - 轉寫法: 轉寫法定義 { - 輸入碼表示: &並擊碼表示, - 輸入碼鍵位: &並擊碼鍵位, - 拼式轉寫規則: &[], - 字根拆分規則: &[], - 拼式驗證規則: &[], +const 并击键位映射: &[键位映射定义] = &[ + 键位映射!(心 => KeyCode::S), + 键位映射!(清 => KeyCode::W), + 键位映射!(精 => KeyCode::X), + 键位映射!(曉 => KeyCode::D), + 键位映射!(來 => KeyCode::E), + 键位映射!(非 => KeyCode::C), + 键位映射!(見 => KeyCode::F), + 键位映射!(端 => KeyCode::R), + 键位映射!(幫 => KeyCode::V), + 键位映射!(溪 => KeyCode::G), + 键位映射!(透 => KeyCode::T), + 键位映射!(滂 => KeyCode::B), + 键位映射!(家 => KeyCode::Space), + 键位映射!(齊 => KeyCode::J), + 键位映射!(魚 => KeyCode::U), + 键位映射!(支 => KeyCode::M), + 键位映射!(車 => KeyCode::L), + 键位映射!(歌 => KeyCode::O), + 键位映射!(庚 => KeyCode::K), + 键位映射!(真 => KeyCode::I), + 键位映射!(侵 => KeyCode::Comma), +]; + +lazy_static! { + static ref 并击码表示: Box<[拼写运算<'static>]> = Box::new([ + 变换!("精非幫", "微"), + 变换!("非幫", "明"), + 变换!("來端", "泥"), + 变换!("心曉見", "日"), + 变换!("曉見", "疑"), + 变换!("精非", "照"), + 变换!("清來", "穿"), + 变换!("心曉", "審"), + 变换!("^([家齊魚支庚真侵車歌])", "影$1"), + 变换!("魚庚", "東"), + 变换!("家庚", "江"), + 变换!("家真", "寒"), + 变换!("車真", "先"), + 变换!("歌真", "桓"), + 变换!("車侵", "廉"), + 变换!("家侵", "監"), + 变换!("家齊", "皆"), + 变换!("家魚", "蕭"), + 变换!("魚歌", "尤"), + ]); + static ref 并击码键位: Box<[拼写运算<'static>]> = Box::new([ + 变换!("微", "精非幫"), + 变换!("明", "非幫"), + 变换!("泥", "來端"), + 变换!("疑", "曉見"), + 变换!("照", "精非"), + 变换!("穿", "清來"), + 变换!("日", "心曉見"), + 变换!("審", "心曉"), + 变换!("影", ""), + 变换!("東", "魚庚"), + 变换!("江", "家庚"), + 变换!("寒", "家真"), + 变换!("先", "車真"), + 变换!("桓", "歌真"), + 变换!("廉", "車侵"), + 变换!("監", "家侵"), + 变换!("皆", "家齊"), + 变换!("蕭", "家魚"), + 变换!("尤", "魚歌"), + ]); +} + +pub fn 输入方案() -> 输入方案定义<'static> { + 输入方案定义 { + 名称: "近古汉语", + 布局: &近古汉语并击布局, + 指法: 击键方式::并击, + 键位映射: 并击键位映射, + 转写: 转写定义 { + 编码预览: &并击码表示, + 键位提示: &并击码键位, + 输入棱镜: &[], + 词库棱镜: &[], + 拼式验证规则: &[], }, } } diff --git a/src/view/caption.rs b/src/view/caption.rs index f5950ab..34998ec 100644 --- a/src/view/caption.rs +++ b/src/view/caption.rs @@ -4,16 +4,16 @@ use crate::gear::caption::字幕表示; #[component] pub fn Rime字幕屏( - 是否顯示光標: Signal, - 按進度顯示字幕: Signal>, + 是否显示光标: Signal, + 按进度显示字幕: Signal> ) -> impl IntoView { view! {
{ - move || 按進度顯示字幕().map(|字幕| view! { + move || 按进度显示字幕().map(|字幕| view! { {字幕.已完成} - {字幕.指標文字} + {字幕.指标文字} {字幕.未完成} }) } diff --git a/src/view/exercise_menu.rs b/src/view/exercise_menu.rs index 1b3b41e..a3ada41 100644 --- a/src/view/exercise_menu.rs +++ b/src/view/exercise_menu.rs @@ -2,42 +2,42 @@ use leptos::html; use leptos::logging::log; use leptos::prelude::*; -use crate::action::動作給一參數; -use crate::drill::練習題; +use crate::action::动作给一参数; +use crate::drill::练习题; #[component] -pub fn Rime練習題選單( - 預設練習題: Signal<&'static [練習題<'static>]>, - 當選題號: Signal>, - 選中題號: impl 動作給一參數, +pub fn Rime练习题选单( + 预设练习题: Signal<&'static [练习题<'static>]>, + 当前题号: Signal>, + 选择题号: impl 动作给一参数 ) -> impl IntoView { - let 練習題選單的引用 = NodeRef::::new(); + let 练习题列表 = NodeRef::::new(); let _ = Effect::new(move |_| { - if let Some(輸入欄) = 練習題選單的引用.get() { - let 選項序號 = 當選題號() - .and_then(|題號| 題號.try_into().ok()) + if let Some(输入栏) = 练习题列表.get() { + let 选项序号 = 当前题号() + .and_then(|题号| 题号.try_into().ok()) .unwrap_or(-1); - 輸入欄.set_selected_index(選項序號); - let _ = 輸入欄.focus(); + 输入栏.set_selected_index(选项序号); + let _ = 输入栏.focus(); } }); view! { diff --git a/src/view/input_code.rs b/src/view/input_code.rs index e53d772..5dcc3e0 100644 --- a/src/view/input_code.rs +++ b/src/view/input_code.rs @@ -2,81 +2,81 @@ use leptos::html; use leptos::prelude::*; use leptos_use::on_click_outside; -use crate::action::{動作, 動作給一參數}; +use crate::action::{ 动作给一参数, 动作 }; #[derive(Clone, Copy, PartialEq)] -pub enum 回顯區佈局 { - 單欄, - 左右對照, +pub enum 回显区布局 { + 单栏, + 左右对照, } #[component] -pub fn Rime編碼回顯區( - 佈局: Signal<回顯區佈局>, - 輸入碼: Signal, - 轉寫碼: Signal>, +pub fn Rime编码回显区( + 布局: Signal<回显区布局>, + 输入码: Signal, + 转写码: Signal> ) -> impl IntoView { view! { {輸入碼} - - {轉寫碼} + class:single-column=move || { 布局() == 回显区布局::单栏 } + class:left-column=move || { 布局() == 回显区布局::左右对照 } + >{输入码} + + {转写码} } } #[component] -pub fn Rime反查輸入欄( - 反查碼: Signal>, - 示例輸入: Signal, - 反查碼變更: impl 動作給一參數, +pub fn Rime反查输入栏( + 反查码: Signal>, + 示例输入: Signal, + 反查码变更: impl 动作给一参数 ) -> impl IntoView { - let 反查輸入欄的引用 = NodeRef::::new(); - 反查輸入欄的引用.on_load(|輸入欄| { - 輸入欄.select(); + let 反查输入栏的引用 = NodeRef::::new(); + 反查输入栏的引用.on_load(|输入栏| { + 输入栏.select(); }); view! { } } #[derive(Clone, Copy, PartialEq)] -pub enum 編碼欄顯示選項 { - 無顯示, - 顯示實況, - 顯示反查, +pub enum 编码栏显示选项 { + 无显示, + 显示实况, + 显示反查, } #[component] -pub fn Rime編碼欄( - 顯示選項: Signal<編碼欄顯示選項>, - 輸入正確: Signal, - 點擊動作: impl 動作, - 關閉輸入欄: impl 動作, - children: Children, +pub fn Rime编码栏( + 显示选项: Signal<编码栏显示选项>, + 输入正确: Signal, + 点击动作: impl 动作, + 关闭输入栏: impl 动作, + children: Children ) -> impl IntoView { let target = NodeRef::::new(); let _ = on_click_outside(target, move |_| { - 關閉輸入欄(); + 关闭输入栏(); }); view! {
{children()}
diff --git a/src/view/keyboard.rs b/src/view/keyboard.rs index 7395fad..83e2daa 100644 --- a/src/view/keyboard.rs +++ b/src/view/keyboard.rs @@ -1,142 +1,142 @@ use leptos::prelude::*; use crate::gear::layout::{ - 功能鍵::衆功能鍵, 盤面選擇碼, 矩陣座標, 配列, 鍵盤佈局, 鍵面刻印, 鍵面映射, + 功能键::众功能键, 盘面序号, 矩阵坐标, 键盘布局, 键盘配列, 键面刻印, 键面映射, }; use crate::key_code::KeyCode; -pub trait 鍵面標註法 { - fn 鍵碼(&self) -> KeyCode; - fn 刻印(&self) -> 鍵面刻印; - fn 是否空鍵(&self) -> bool; - fn 是否後備盤面(&self) -> bool; - fn 是否功能鍵(&self) -> bool { - 衆功能鍵.iter().any(|功能鍵| 功能鍵.鍵碼 == self.鍵碼()) +pub trait 键面标注法 { + fn 键码(&self) -> KeyCode; + fn 刻印(&self) -> 键面刻印; + fn 是否空键(&self) -> bool; + fn 是否后备盘面(&self) -> bool; + fn 是否功能键(&self) -> bool { + 众功能键.iter().any(|功能键| 功能键.键码 == self.键码()) } fn 是否空格(&self) -> bool { - self.鍵碼() == KeyCode::Space + self.键码() == KeyCode::Space } } -pub trait 鍵面動態着色法 { - fn 鍵位提示(&self, 鍵: KeyCode) -> bool; - fn 是否落鍵(&self, 鍵: KeyCode) -> bool; - fn 是否擊中(&self, 鍵: KeyCode) -> bool; +pub trait 键面动态着色法 { + fn 键位提示(&self, 键: KeyCode) -> bool; + fn 是否落键(&self, 键: KeyCode) -> bool; + fn 是否击中(&self, 键: KeyCode) -> bool; } #[derive(Clone, Copy)] -struct 選擇鍵面 { - 佈局: 鍵盤佈局, - 鍵碼: KeyCode, - 目標盤面: 盤面選擇碼, - 座標: 矩陣座標, +struct 选择键面 { + 布局: 键盘布局, + 键码: KeyCode, + 目标盘面: 盘面序号, + 坐标: 矩阵坐标, } -impl 選擇鍵面 { +impl 选择键面 { fn new( - 佈局: 鍵盤佈局, 鍵碼: KeyCode, 目標盤面: 盤面選擇碼, 座標: 矩陣座標 + 布局: 键盘布局, 键码: KeyCode, 目标盘面: 盘面序号, 坐标: 矩阵坐标 ) -> Self { Self { - 佈局, - 鍵碼, - 目標盤面, - 座標, + 布局, + 键码, + 目标盘面, + 坐标, } } - fn 有效盤面(&self) -> Option<(usize, 鍵面刻印)> { - self.佈局.選擇盤面(self.目標盤面, self.座標) + fn 有效盘面(&self) -> Option<(usize, 键面刻印)> { + self.布局.选择盘面(self.目标盘面, self.坐标) } } -impl 鍵面標註法 for 選擇鍵面 { - fn 鍵碼(&self) -> KeyCode { - self.鍵碼 +impl 键面标注法 for 选择键面 { + fn 键码(&self) -> KeyCode { + self.键码 } - fn 刻印(&self) -> 鍵面刻印 { - self.有效盤面() - .map_or(鍵面刻印::透明, move |(_, 刻印)| 刻印) + fn 刻印(&self) -> 键面刻印 { + self.有效盘面() + .map_or(键面刻印::透明, move |(_, 刻印)| 刻印) } - fn 是否空鍵(&self) -> bool { + fn 是否空键(&self) -> bool { !self - .有效盤面() - .is_some_and(|(_, 刻印)| matches!(刻印, 鍵面刻印::有刻 { .. })) + .有效盘面() + .is_some_and(|(_, 刻印)| matches!(刻印, 键面刻印::有刻 { .. })) } - fn 是否後備盤面(&self) -> bool { - self.有效盤面() - .is_some_and(|(盤面, _)| 盤面 != self.目標盤面.頂層盤面()) + fn 是否后备盘面(&self) -> bool { + self.有效盘面() + .is_some_and(|(盘面, _)| 盘面 != self.目标盘面.顶层盘面()) } } -impl 鍵面標註法 for 鍵面映射 { - fn 鍵碼(&self) -> KeyCode { - self.鍵碼 +impl 键面标注法 for 键面映射 { + fn 键码(&self) -> KeyCode { + self.键码 } - fn 刻印(&self) -> 鍵面刻印 { + fn 刻印(&self) -> 键面刻印 { self.刻印 } - fn 是否空鍵(&self) -> bool { - self.刻印 == 鍵面刻印::無刻 + fn 是否空键(&self) -> bool { + self.刻印 == 键面刻印::无刻 } - fn 是否後備盤面(&self) -> bool { - self.刻印 == 鍵面刻印::透明 + fn 是否后备盘面(&self) -> bool { + self.刻印 == 键面刻印::透明 } } #[component] -pub fn Rime鍵圖(鍵: KeyCode, 標註法: Signal, 着色法: U) -> impl IntoView +pub fn Rime键图(键: KeyCode, 标注法: Signal, 着色法: U) -> impl IntoView where - T: 鍵面標註法 + Copy + Send + Sync + 'static, - U: 鍵面動態着色法 + Copy + Send + Sync + 'static, + T: 键面标注法 + Copy + Send + Sync + 'static, + U: 键面动态着色法 + Copy + Send + Sync + 'static, { view! {
- {move || 標註法.read().刻印().左側刻印文字()} + {move || 标注法.read().刻印().左侧刻印文字()}
- {move || 標註法.read().刻印().上方刻印文字()} - {move || 標註法.read().刻印().居中刻印文字()} - {move || 標註法.read().刻印().下方刻印文字()} + {move || 标注法.read().刻印().上方刻印文字()} + {move || 标注法.read().刻印().居中刻印文字()} + {move || 标注法.read().刻印().下方刻印文字()}
- {move || 標註法.read().刻印().右側刻印文字()} + {move || 标注法.read().刻印().右侧刻印文字()}
} } #[component] -pub fn Rime鍵盤圖( - 配列: ReadSignal<配列>, - 鍵盤佈局: Signal<鍵盤佈局>, - 目標盤面: Signal<盤面選擇碼>, +pub fn Rime键盘图( + 键盘配列: ReadSignal<键盘配列>, + 键盘布局: Signal<键盘布局>, + 目标盘面: Signal<盘面序号>, 着色法: T, ) -> impl IntoView where - T: 鍵面動態着色法 + Copy + Send + Sync + 'static, + T: 键面动态着色法 + Copy + Send + Sync + 'static, { view! {
- { move || 配列.read().矩陣().iter().enumerate().map(|(行座標, 行)| view! { + { move || 键盘配列.read().矩阵().iter().enumerate().map(|(行座标, 行)| view! {
{ 行.iter().enumerate() - .filter(|(_, &鍵)| 鍵 != KeyCode::No) - .map(|(列座標, &鍵)| { - let 標註法 = Signal::derive(move || 選擇鍵面::new(鍵盤佈局(), 鍵, 目標盤面(), 矩陣座標(行座標, 列座標))); + .filter(|(_, &键)| 键 != KeyCode::No) + .map(|(列座标, &键)| { + let 标注法 = Signal::derive(move || 选择键面::new(键盘布局(), 键, 目标盘面(), 矩阵坐标(行座标, 列座标))); view! { - + } }).collect_view() }
diff --git a/src/view/layout_menu.rs b/src/view/layout_menu.rs index 4016051..134faad 100644 --- a/src/view/layout_menu.rs +++ b/src/view/layout_menu.rs @@ -3,41 +3,42 @@ use leptos::logging::log; use leptos::prelude::*; use strum::IntoEnumIterator; -use crate::action::動作給一參數; -use crate::gear::layout::配列; +use crate::action::动作给一参数; +use crate::gear::layout::键盘配列; #[component] -pub fn Rime配列選單( - 已選配列: ReadSignal<配列>, - 選用配列: impl 動作給一參數<配列>, +pub fn Rime配列选单( + 已选配列: ReadSignal<键盘配列>, + 选用配列: impl 动作给一参数<键盘配列> ) -> impl IntoView { - let 配列選單的引用 = NodeRef::::new(); + let 配列选单的引用 = NodeRef::::new(); let _ = Effect::new(move |_| { - if let Some(輸入欄) = 配列選單的引用.get() { - let 選項序號: i32 = 配列::iter() - .position(|配列| 配列 == 已選配列()) - .and_then(|序號| 序號.try_into().ok()) + if let Some(输入栏) = 配列选单的引用.get() { + let 选项序号: i32 = 键盘配列 + ::iter() + .position(|键盘配列| 键盘配列 == 已选配列()) + .and_then(|序号| 序号.try_into().ok()) .unwrap_or(-1); - 輸入欄.set_selected_index(選項序號); - let _ = 輸入欄.focus(); + 输入栏.set_selected_index(选项序号); + let _ = 输入栏.focus(); } }); view! { diff --git a/src/view/status_bar.rs b/src/view/status_bar.rs index 68b6032..b680895 100644 --- a/src/view/status_bar.rs +++ b/src/view/status_bar.rs @@ -1,35 +1,31 @@ use leptos::prelude::*; -use crate::action::動作; -use crate::gear::{ - layout::配列, - theory::{方案選單, 方案選項}, -}; +use crate::action::动作; +use crate::gear::{ layout::键盘配列, theory::{ 方案列表, 方案选项 } }; #[component] -pub fn Rime狀態欄( - 現行方案: ReadSignal<方案選項>, - 已選配列: ReadSignal<配列>, - 點擊方案: impl 動作, - 點擊配列: impl 動作, +pub fn Rime状态栏( + 当前方案: ReadSignal<方案选项>, + 已选配列: ReadSignal<键盘配列>, + 点击方案: impl 动作, + 点击配列: impl 动作 ) -> impl IntoView { - let 方案名稱 = move || { - let 選中項 = 現行方案.read(); - 方案選單 - .iter() - .find(|某項| 某項.0 == *選中項) - .map_or("無方案", |此項| 此項.1.名稱) + let 方案名称 = move || { + let 选中项 = 当前方案.read(); + 方案列表.iter() + .find(|某项| 某项.0 == *选中项) + .map_or("无方案", |此项| 此项.1.名称) }; view! {
-
+
方案 - {方案名稱} + {方案名称}
"|" -
- 佈局 - {已選配列.read().to_string()} +
+ 布局 + {已选配列.read().to_string()}
} diff --git a/src/view/theory_menu.rs b/src/view/theory_menu.rs index dece448..8a3f0dd 100644 --- a/src/view/theory_menu.rs +++ b/src/view/theory_menu.rs @@ -2,42 +2,42 @@ use leptos::html; use leptos::logging::log; use leptos::prelude::*; -use crate::action::動作給一參數; -use crate::gear::theory::{方案選單, 方案選項}; +use crate::action::动作给一参数; +use crate::gear::theory::{ 方案列表, 方案选项 }; #[component] -pub fn Rime方案選單( - 現行方案: ReadSignal<方案選項>, - 選中方案: impl 動作給一參數<方案選項>, +pub fn Rime方案选单( + 当前方案: ReadSignal<方案选项>, + 选中方案: impl 动作给一参数<方案选项> ) -> impl IntoView { - let 方案選單的引用 = NodeRef::::new(); + let 方案选单的引用 = NodeRef::::new(); let _ = Effect::new(move |_| { - if let Some(輸入欄) = 方案選單的引用.get() { - let 選項序號: i32 = 方案選單 + if let Some(输入栏) = 方案选单的引用.get() { + let 选项序号: i32 = 方案列表 .iter() - .position(|&(方案, _)| 方案 == 現行方案()) - .and_then(|序號| 序號.try_into().ok()) + .position(|&(方案, _)| 方案 == 当前方案()) + .and_then(|序号| 序号.try_into().ok()) .unwrap_or(-1); - 輸入欄.set_selected_index(選項序號); - let _ = 輸入欄.focus(); + 输入栏.set_selected_index(选项序号); + let _ = 输入栏.focus(); } }); view! { diff --git a/tool/custom_attribute_macro/Cargo.toml b/tool/custom_attribute_macro/Cargo.toml new file mode 100644 index 0000000..8b10d3a --- /dev/null +++ b/tool/custom_attribute_macro/Cargo.toml @@ -0,0 +1,21 @@ +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[package] +name = "custom_attribute_macro" +edition = "2021" +version = "0.0.1" + +[package.metadata] +update_date = "2025-12-31" + +[lib] +proc-macro = true + +[dependencies] +parse_cargo_toml = { path = "../parse_cargo_toml" } + +chrono = "0.4" +proc-macro2 = "1.0" +quote = "1.0" +semver = "1.0" +syn = "2.0" diff --git a/tool/custom_attribute_macro/src/lib.rs b/tool/custom_attribute_macro/src/lib.rs new file mode 100644 index 0000000..55f5529 --- /dev/null +++ b/tool/custom_attribute_macro/src/lib.rs @@ -0,0 +1,88 @@ +use parse_cargo_toml::get_package_info; +use chrono::NaiveDate; +use proc_macro::TokenStream; +use quote::quote; +use semver::Version; +use syn::{parse_macro_input, Item}; + +#[proc_macro_attribute] +pub fn deprecated_until(attr: TokenStream, item: TokenStream) -> TokenStream { + // 解析参数,格式如 "1.2.3 2025-12-31"(SemVer + 空格 + yyyy-mm-dd) + let attr_str = attr.to_string(); + + // 移除引号 + let attr_str = attr_str.trim_matches('"').to_string(); + + // 按空格分割参数 + let parts: Vec<&str> = attr_str.split_whitespace().collect(); + if parts.len() != 2 { + panic!("无效的格式:应为 '主版本号.次版本号.修订号 yyyy-mm-dd',例如:'1.2.3 2025-12-31'"); + } + + let until_semver_str = parts[0]; + let until_date_str = parts[1]; + + // 解析 until 的版本号和日期 + let until_version = Version::parse(until_semver_str).expect("无效的版本号格式"); + let until_date = NaiveDate::parse_from_str(until_date_str, "%Y-%m-%d") + .expect("无效的日期格式,请使用 yyyy-mm-dd 格式"); + + // 从 Cargo.toml 获取当前包的版本和更新日期 + let (current_version, current_date) = get_package_info().expect("无法从 Cargo.toml 读取包信息"); + + let input = parse_macro_input!(item as Item); + + // 版本比较逻辑:先比较版本号(主版本 > 次版本 > 修订号),如果相等则比较日期 + let had_deprecated = if current_version > until_version { + true + } else if current_version == until_version { + current_date > until_date + } else { + false + }; + + let will_deprecated = if !had_deprecated { + if current_version.major == until_version.major { + // 副版本号比期限小1或相等,且未达到禁用条件 + current_version.minor == until_version.minor + || current_version.minor == until_version.minor - 1 + } else { + false + } + } else { + false // 已经禁用了就不算"即将禁用" + }; + + if had_deprecated { + // 如果当前版本 > until 版本,则应用 #[deprecated] 属性 + let note = format!( + "\n此功能在 {} 版本({})之后已被弃用,请尽快更新\n(当前版本为 {} 版本({})", + until_semver_str, until_date_str, current_version, current_date + ); + + let deprecated_item = quote! { + #[deprecated(note = #note)] + #input + }; + + deprecated_item.into() + } else if will_deprecated { + // 如果当前版本 > until 版本,则应用 #[deprecated] 属性 + let note = format!( + "\n此功能在 {} 版本({})之后即将被弃用,请尽快更新\n(当前版本为 {} 版本({})", + until_semver_str, until_date_str, current_version, current_date + ); + + let deprecated_item = quote! { + #[deprecated(note = #note)] + #input + }; + deprecated_item.into() + } else { + // 否则,不应用弃用属性 + let normal_item = quote! { + #input + }; + normal_item.into() + } +} diff --git a/tool/parse_cargo_toml/Cargo.toml b/tool/parse_cargo_toml/Cargo.toml new file mode 100644 index 0000000..3f6a939 --- /dev/null +++ b/tool/parse_cargo_toml/Cargo.toml @@ -0,0 +1,14 @@ +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[package] +name = "parse_cargo_toml" +edition = "2021" +version = "0.0.1" + +[package.metadata] +update_date = "2025-12-31" + +[dependencies] +chrono = "0.4" +semver = "1.0" +toml = "0.9" diff --git a/tool/parse_cargo_toml/src/lib.rs b/tool/parse_cargo_toml/src/lib.rs new file mode 100644 index 0000000..df2e026 --- /dev/null +++ b/tool/parse_cargo_toml/src/lib.rs @@ -0,0 +1,55 @@ +use chrono::NaiveDate; +use semver::Version; +use std::fs; +// use custom_attribute_macro::deprecated_until; + +pub fn get_package_info() -> Result<(Version, NaiveDate), Box> { + // 获取当前工作目录(宏被调用的项目目录) + let cargo_toml_path = find_cargo_toml()?; + + // 读取 Cargo.toml 内容 + let toml_content = fs::read_to_string(&cargo_toml_path)?; + + // 解析 TOML + let toml_value: toml::Value = toml::from_str(&toml_content)?; + + // 获取 package.version + let version_str = toml_value + .get("package") + .and_then(|p| p.get("version")) + .and_then(|v| v.as_str()) + .ok_or("在 Cargo.toml 中未找到 package.version 字段")?; + + let current_version = Version::parse(version_str)?; + + // 获取 package.metadata.update_date + let date_str = toml_value + .get("package") + .and_then(|p| p.get("metadata")) + .and_then(|m| m.get("update_date")) + .and_then(|d| d.as_str()) + .ok_or("在 Cargo.toml 中未找到 package.metadata.update_date 字段")?; + + let current_date = NaiveDate::parse_from_str(date_str, "%Y-%m-%d")?; + + Ok((current_version, current_date)) +} + +/// 查找 Cargo.toml 文件 +fn find_cargo_toml() -> Result> { + let mut current_dir = std::env::current_dir()?; + + loop { + let cargo_toml_path = current_dir.join("Cargo.toml"); + if cargo_toml_path.exists() { + return Ok(cargo_toml_path); + } + + // 向上级目录查找 + if !current_dir.pop() { + break; + } + } + + Err("在当前目录或父目录中未找到 Cargo.toml 文件".into()) +}