Skip to content

Commit 3185363

Browse files
authored
Merge pull request #58 from azooKey/feat/replace_default_extension
feat: 濁点化などのアクションをreplace_defaultの拡張として表現可能に
2 parents e96edba + edb114f commit 3185363

11 files changed

Lines changed: 99 additions & 13 deletions

File tree

json/howToMake.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ azooKeyでは`"input"`の他にいくつかの動作を行うことができま
9797
| select_candidate | type: str<br /> value: int | 引数で指定した候補を選択状態にします。typeは4種類あります。`"first"`(最初の候補)と`"last"`(最後の候補)の場合は`"value"`の指定は不要です。`"exact"`(value個目の候補を選択)と`"offset"`(value個隣の候補を選択)の場合は`"value"`に数値を指定してください。 |
9898
| complete | なし | 変換を確定します |
9999
| replace_last_characters | table: {str: str} | カーソル文頭方向の文字列を引数のtableに基づいて置換します。例えばカーソル文頭方向の文字列が`"abcdef"`であり、テーブルに`"def":":="`が指定されている場合は`"abc:="`と置換されます。 |
100-
| replace_default | なし | azooKeyが標準で用いている「濁点・半濁点・小書き・大文字・小文字」の切り替えアクションです。 |
100+
| replace_default | replace_type: str, dakuten, handakutenなど<br />fallbacks: [str] | azooKeyが標準で用いている「濁点・半濁点・小書き・大文字・小文字」の切り替えアクションです。 |
101101
| smart_delete | direction: str<br />targets: [str] | directionに`"forward"`または`"backward"`を指定します。targetsに指定した文字のいずれかがカーソル進行方向に現れるまで削除を繰り返します。例えば文頭方向の文字列が`"Yes, it is"`であり、`"direction": "backward", "targets": [","]`であった場合、この操作の実行後に`" it is"`が削除されます。 |
102102
| smart_delete_default | なし | azooKeyが標準で用いている「文頭まで削除」のアクションです。 |
103103
| smart_move_cursor | direction: str<br />targets: [str] | directionに`"forward"`または`"backward"`を指定します。targetsに指定した文字のいずれかがカーソル進行方向に現れるまでカーソルの移動を繰り返します。例えば文頭方向の文字列が`"Yes, it is"`であり、`"direction": "backward", "target": [","]`であった場合、この操作の実行後にカーソルが`"Yes,| it is"`まで移動します。 |

python/howToMake.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ azooKeyでは`InputAction`の他にいくつかの動作を行うことができ
8585
| SelectCandidateAction | type: str<br /> value: int | 引数で指定した候補を選択状態にします。typeは4種類あります。`"first"`(最初の候補)と`"last"`(最後の候補)の場合は`"value"`の指定は不要です。`"exact"`(value個目の候補を選択)と`"offset"`(value個隣の候補を選択)の場合は`"value"`に数値を指定してください。 |
8686
| CompleteAction | なし | 変換を確定します |
8787
| ReplaceLastCharactersAction | table: {str: str} | カーソル文頭方向の文字列を引数のtableに基づいて置換します。例えばカーソル文頭方向の文字列が`"abcdef"`であり、テーブルに`"def":":="`が指定されている場合は`"abc:="`と置換されます。 |
88-
| ReplaceDefaultAction | なし | azooKeyが標準で用いている「濁点・半濁点・小書き・大文字・小文字」の切り替えアクションです。 |
88+
| ReplaceDefaultAction | replace_type: ReplaceType<br />fallbacks: list[ReplaceType] | azooKeyが標準で用いている「濁点・半濁点・小書き・大文字・小文字」の切り替えアクションです。 |
8989
| SmartDeleteAction | direction: ScanDirection<br />targets: list[str] | directionに`ScanDirection.forward`または`ScanDirection.backward`を指定します。targetsに指定した文字のいずれかがカーソル進行方向に現れるまで削除を繰り返します。例えば文頭方向の文字列が`"Yes, it is"`であり、`direction = ScanDirection.backward, target = [","]`であった場合、この操作の実行後に`" it is"`が削除されます。 |
9090
| SmartDeleteDefaultAction | なし | azooKeyが標準で用いている「文頭まで削除」のアクションです。 |
9191
| SmartMoveCursorAction | direction: ScanDirection<br />target: list[str] | directionに`ScanDirection.forward`または`ScanDirection.backward`を指定します。targetsに指定した文字のいずれかがカーソル進行方向に現れるまでカーソルの移動を繰り返します。例えば文頭方向の文字列が`"Yes, it is"`であり、`direction = ScanDirection.backward, target = [","]`であった場合、この操作の実行後にカーソルが`"Yes,| it is"`まで移動します。 |

python/source/actions.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,31 @@ def __init__(self, table: dict[str, str]):
6161
"""
6262
self.table = table
6363

64+
@unique
65+
class ReplaceType(str, Enum):
66+
default = "default"
67+
dakuten = "dakuten"
68+
handakuten = "handakuten"
69+
kogaki = "kogaki"
70+
6471

6572
class ReplaceDefaultAction(metaclass=ActionMeta):
6673
"""
6774
azooKeyデフォルトの置換アクション
6875
"""
6976
type = "replace_default"
77+
def __init__(self, replace_type: ReplaceType = ReplaceType.default, fallbacks: list[ReplaceType] = []):
78+
"""
79+
最後の文字を置換するアクション
80+
Parameters
81+
----------
82+
replace_type: ReplaceType
83+
置換の種類。
84+
fallbacks: list[ReplaceType]
85+
最初に設定した置換が成功しなかった場合のフォールバック
86+
"""
87+
self.replace_type = replace_type
88+
self.fallbacks = fallbacks
7089

7190

7291
@unique

python/test/test_actions.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,15 +139,20 @@ def test_SmartDeleteAction(self):
139139
}
140140
self.assertEqual(expected_json, actual)
141141

142-
def test_NoArgumentsAction(self):
143-
"""test method for actions without arguments
142+
def test_ReplaceDefaultAction(self):
143+
"""test method for ReplaceDefault
144144
"""
145-
actual = to_json(ReplaceDefaultAction())
145+
actual = to_json(ReplaceDefaultAction(ReplaceType.handakuten, fallbacks=[ReplaceType.default]))
146146
expected_json = {
147147
"type": "replace_default",
148+
"replace_type": "handakuten",
149+
"fallbacks": ["default"]
148150
}
149151
self.assertEqual(expected_json, actual)
150152

153+
def test_NoArgumentsAction(self):
154+
"""test method for actions without arguments
155+
"""
151156
actual = to_json(SmartDeleteDefaultAction())
152157
expected_json = {
153158
"type": "smart_delete_default",

swift/examples/Samples/FlickGreek.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ extension Samples {
5151
.gridFit(.init(x: 1, y: 3)): .custom(
5252
.init(
5353
design: .init(label: .text("a/A"), color: .normal),
54-
press_actions: [.replaceDefault],
54+
press_actions: [.replaceDefault(.default)],
5555
longpress_actions: .none,
5656
variations: [
5757
.init(

swift/howToMake.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ azooKeyでは`input`の他にいくつかの動作を行うことができます
8787
| .selectCandidate | CandidateSelection | 引数で指定した候補を選択状態にします |
8888
| .complete | なし | 変換を確定します |
8989
| .replaceLastCharacters | [String: String] | カーソル文頭方向の文字列を引数に基づいて置換します。例えばカーソル文頭方向の文字列が`"abcdef"`であり、テーブルに`"def":":="`が指定されている場合は`"abc:="`と置換されます。 |
90-
| .replaceDefault | なし | azooKeyが標準で用いている「濁点・半濁点・小書き・大文字・小文字」の切り替えアクションです。 |
90+
| .replaceDefault | ReplaceBehavior | azooKeyが標準で用いている「濁点・半濁点・小書き・大文字・小文字」の切り替えアクションです。 |
9191
| .smartDelete | ScanItem | 引数で指定した方向に、指定した文字を見つけるまで削除を繰り返します。例えば文頭方向の文字列が`"Yes, it is"`であり、方向が`.backward`かつ文字の指定が` [","]`であった場合、この操作の実行後に`" it is"`が削除されます。 |
9292
| .smartDeleteDefault | なし | azooKeyが標準で用いている「文頭まで削除」のアクションです。 |
9393
| .smartMoveCursor | ScanItem | 引数で指定した方向に、指定した文字を見つけるまで移動を繰り返します。例えば文頭方向の文字列が`"Yes, it is"`であり、方向が`.backward`かつ文字の指定が` [","]`であった場合、この操作の実行後に`"Yes,| it is"`まで移動します。 |

swift/sources/CustardActions.swift

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,33 @@ public extension CandidateSelection {
147147
}
148148
}
149149

150+
public struct ReplaceBehavior: Hashable, Sendable {
151+
public init(type: ReplaceBehavior.ReplaceType, fallbacks: [ReplaceBehavior.ReplaceType] = []) {
152+
self.type = type
153+
self.fallbacks = fallbacks
154+
}
155+
156+
public static let `default` = Self(type: .default, fallbacks: [])
157+
public enum ReplaceType: String, Codable, Hashable, Sendable {
158+
/// デフォルト。
159+
/// - a→A→a
160+
/// - あ→ぁ→あ
161+
/// - は→ば→ぱ→は
162+
/// - つ→っ→づ→つ
163+
case `default`
164+
/// 濁点化のみ行う
165+
case dakuten
166+
/// 半濁点化のみ行う
167+
case handakuten
168+
/// 小書き化のみ行う
169+
case kogaki
170+
}
171+
/// 置換の振る舞い
172+
public var type: ReplaceType
173+
/// 置換が行われなかった場合、次に試す置換
174+
public var fallbacks: [ReplaceType]
175+
}
176+
150177
/// - アクション
151178
/// - actions done in key pressing
152179
public enum CodableActionData: Codable, Hashable, Sendable {
@@ -158,7 +185,7 @@ public enum CodableActionData: Codable, Hashable, Sendable {
158185
case paste
159186

160187
/// - exchange character "あ→ぁ", "は→ば", "a→A"
161-
case replaceDefault
188+
case replaceDefault(ReplaceBehavior)
162189

163190
/// - replace string at the trailing of cursor following to specified table
164191
case replaceLastCharacters([String: String])
@@ -220,6 +247,7 @@ public extension CodableActionData {
220247
case direction, targets
221248
case scheme_type, target
222249
case selection
250+
case replace_type, fallbacks
223251
}
224252

225253
private enum ValueType: String, Codable {
@@ -311,6 +339,14 @@ public extension CodableActionData {
311339
switch self {
312340
case let .input(value):
313341
try container.encode(value, forKey: .text)
342+
case let .replaceDefault(value):
343+
// デフォルト値以外の場合のみ明示的にエンコード
344+
if value.type != .default {
345+
try container.encode(value.type, forKey: .replace_type)
346+
}
347+
if !value.fallbacks.isEmpty {
348+
try container.encode(value.fallbacks, forKey: .fallbacks)
349+
}
314350
case let .replaceLastCharacters(value):
315351
try container.encode(value, forKey: .table)
316352
case let .delete(value), let .moveCursor(value):
@@ -325,7 +361,7 @@ public extension CodableActionData {
325361
try container.encode(value, forKey: .selection)
326362
case let .moveTab(value):
327363
try CodableTabArgument(tab: value).containerEncode(container: &container)
328-
case .dismissKeyboard, .enableResizingMode, .toggleTabBar, .toggleCursorBar, .toggleCapsLockState, .complete, .smartDeleteDefault, .replaceDefault, .paste: break
364+
case .dismissKeyboard, .enableResizingMode, .toggleTabBar, .toggleCursorBar, .toggleCapsLockState, .complete, .smartDeleteDefault, .paste: break
329365
}
330366
}
331367

@@ -337,7 +373,9 @@ public extension CodableActionData {
337373
let value = try container.decode(String.self, forKey: .text)
338374
self = .input(value)
339375
case .replace_default:
340-
self = .replaceDefault
376+
let replaceType = try container.decodeIfPresent(ReplaceBehavior.ReplaceType.self, forKey: .replace_type) ?? .default
377+
let fallbacks = try container.decodeIfPresent([ReplaceBehavior.ReplaceType].self, forKey: .fallbacks) ?? []
378+
self = .replaceDefault(.init(type: replaceType, fallbacks: fallbacks))
341379
case .replace_last_characters:
342380
let value = try container.decode([String: String].self, forKey: .table)
343381
self = .replaceLastCharacters(value)

swift/tests/CustardKitTests/CustardInterfaceVariationKeyTest.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ final class CustardInterfaceVariationKeyTest: XCTestCase {
2929

3030
func testEncode() {
3131
do {
32-
let target = CustardInterfaceVariationKey.init(design: .init(label: .systemImage("que")), press_actions: [.dismissKeyboard, .complete, .replaceDefault], longpress_actions: .none)
32+
let target = CustardInterfaceVariationKey.init(design: .init(label: .systemImage("que")), press_actions: [.dismissKeyboard, .complete, .replaceDefault(.default)], longpress_actions: .none)
3333
XCTAssertEqual(target.quickEncodeDecode(), target)
3434
}
3535
do {

swift/tests/CustardKitTests/DecodeCodableActionTest.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,21 @@ final class DecodeCodableActionTest: XCTestCase {
208208
{"type": "replace_default"}
209209
"""
210210
let decoded = CodableActionData.quickDecode(target: target)
211-
XCTAssertEqual(decoded, .replaceDefault)
211+
XCTAssertEqual(decoded, .replaceDefault(.default))
212+
}
213+
do {
214+
let target = """
215+
{"type": "replace_default", "replace_type": "dakuten"}
216+
"""
217+
let decoded = CodableActionData.quickDecode(target: target)
218+
XCTAssertEqual(decoded, .replaceDefault(.init(type: .dakuten, fallbacks: [])))
219+
}
220+
do {
221+
let target = """
222+
{"type": "replace_default", "replace_type": "dakuten", "fallbacks": ["default"]}
223+
"""
224+
let decoded = CodableActionData.quickDecode(target: target)
225+
XCTAssertEqual(decoded, .replaceDefault(.init(type: .dakuten, fallbacks: [.default])))
212226
}
213227
do {
214228
let target = """

swift/tests/CustardKitTests/EncodeCodableActionTest.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,13 @@ final class EncodeCodableActionTest: XCTestCase {
5858
XCTAssertEqual(CodableActionData.moveTab(.system(.flick_numbersymbols)).quickEncodeDecode(), .moveTab(.system(.flick_numbersymbols)))
5959
}
6060

61+
func testEncodeReplaceDefault() {
62+
XCTAssertQuickEncodeDecode(CodableActionData.replaceDefault(.default))
63+
XCTAssertQuickEncodeDecode(CodableActionData.replaceDefault(.init(type: .default, fallbacks: [.dakuten])).quickEncodeDecode())
64+
XCTAssertQuickEncodeDecode(CodableActionData.replaceDefault(.init(type: .handakuten, fallbacks: [.default])))
65+
}
66+
6167
func testEncodeNoArgumentActions() {
62-
XCTAssertEqual(CodableActionData.replaceDefault.quickEncodeDecode(), .replaceDefault)
6368
XCTAssertEqual(CodableActionData.smartDeleteDefault.quickEncodeDecode(), .smartDeleteDefault)
6469
XCTAssertEqual(CodableActionData.complete.quickEncodeDecode(), .complete)
6570
XCTAssertEqual(CodableActionData.enableResizingMode.quickEncodeDecode(), .enableResizingMode)

0 commit comments

Comments
 (0)