From e645a1f747eef66bdda987fa201986cc7176aa86 Mon Sep 17 00:00:00 2001 From: mtgto Date: Sun, 9 Mar 2025 16:13:48 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=E6=8E=A5=E9=A0=AD=E8=BE=9E=E3=83=BB?= =?UTF-8?q?=E6=8E=A5=E5=B0=BE=E8=BE=9E=E5=85=A5=E5=8A=9B=E3=82=92=E3=82=AD?= =?UTF-8?q?=E3=83=BC=E3=83=90=E3=82=A4=E3=83=B3=E3=83=89=E3=81=AB=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- macSKK/KeyBinding.swift | 12 +++++++ macSKK/StateMachine.swift | 52 ++++++++++++++++++----------- macSKK/en.lproj/Localizable.strings | 1 + macSKK/ja.lproj/Localizable.strings | 1 + macSKKTests/StateMachineTests.swift | 2 ++ 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/macSKK/KeyBinding.swift b/macSKK/KeyBinding.swift index 7fb0a4ed..a46bcd97 100644 --- a/macSKK/KeyBinding.swift +++ b/macSKK/KeyBinding.swift @@ -63,6 +63,8 @@ struct KeyBinding: Identifiable, Hashable { case registerPaste /// 選択した文字列を辞書から逆引きして再変換をする。デフォルトはCtrl-/キー case reconvert + /// 接頭辞・接尾辞の入力。デフォルトは ">" (Shift-.キー) + case affix /// 英数キー /// TODO: カスタマイズできなくする? case eisu @@ -94,6 +96,14 @@ struct KeyBinding: Identifiable, Hashable { } else { return false } + case .affix: + if case .composing(_) = inputMethodState { + return true + } else if case .selecting(_) = inputMethodState { + return true + } else { + return false + } default: return true } @@ -303,6 +313,8 @@ struct KeyBinding: Identifiable, Hashable { return KeyBinding(action, [Input(key: .character("y"), modifierFlags: .control)]) case .reconvert: return KeyBinding(action, [Input(key: .character("/"), modifierFlags: [.control])]) + case .affix: + return KeyBinding(action, [Input(key: .character("."), modifierFlags: .shift)]) case .eisu: return KeyBinding(action, [Input(key: .code(0x66), modifierFlags: [])]) case .kana: diff --git a/macSKK/StateMachine.swift b/macSKK/StateMachine.swift index 768e7891..3ca23041 100644 --- a/macSKK/StateMachine.swift +++ b/macSKK/StateMachine.swift @@ -346,7 +346,7 @@ final class StateMachine { case .eisu: // 何もしない (OSがIMEの切り替えはしてくれる) return true - case .space, .unregister, .backwardCandidate, .toggleAndFixKana, nil: + case .space, .unregister, .backwardCandidate, .toggleAndFixKana, .affix, nil: break } @@ -791,6 +791,23 @@ final class StateMachine { updateMarkedText() } return true + case .affix: + if state.inputMode == .direct { + break + } else if composing.text.isEmpty { + // 接尾辞の入力開始として扱う + let converted = Global.kanaRule.convert(romaji + ">", punctuation: Global.punctuation) + return handleComposingPrintable( + input: ">", + converted: converted, + action: action, + composing: composing, + specialState: specialState) + } else { + // 接頭辞が入力されたものとして ">" より前で変換を開始する + let newComposing = composing.trim(kanaRule: Global.kanaRule).appendText(Romaji.Moji(firstRomaji: "", kana: ">")) + return handleComposingStartConvert(action, composing: newComposing, specialState: specialState) + } case .up, .down, .registerPaste, .eisu, .kana, .toggleKana, .reconvert: return true case .abbrev, .unregister, .backwardCandidate, .none: @@ -834,11 +851,6 @@ final class StateMachine { let text = composing.text let okuri = composing.okuri - if input == "." && action.shiftIsPressed() && state.inputMode != .direct && !composing.text.isEmpty { // ">" - // 接頭辞が入力されたものとして ">" より前で変換を開始する - let newComposing = composing.trim(kanaRule: Global.kanaRule).appendText(Romaji.Moji(firstRomaji: "", kana: ">")) - return handleComposingStartConvert(action, composing: newComposing, specialState: specialState) - } switch state.inputMode { case .hiragana, .katakana, .hankaku: // lowercaseMapにエントリがある場合はエントリの方のキーが入力されたと見做す @@ -1168,6 +1180,19 @@ final class StateMachine { updateCandidates(selecting: nil) updateMarkedText() return true + case .affix: + // 選択中候補で確定し、接尾辞入力に移行。 + // カーソル位置より右に文字列がある場合は接頭辞入力として扱う (無視してもいいかも) + addWordToUserDict(yomi: selecting.yomi, okuri: selecting.okuri, candidate: selecting.candidates[selecting.candidateIndex]) + updateCandidates(selecting: nil) + addFixedText(selecting.fixedText(dropLast: false)) + if let remain = selecting.remain { + state.inputMethod = .composing(ComposingState(isShift: true, text: remain, romaji: "")) + updateMarkedText() + } else { + state.inputMethod = .composing(ComposingState(isShift: true, text: [], okuri: nil, romaji: "")) + } + return handle(action) case .registerPaste, .delete, .eisu, .kana, .reconvert: return true case .toggleKana, .toggleAndFixKana, .direct, .zenkaku, .abbrev, .japanese: @@ -1177,20 +1202,7 @@ final class StateMachine { } if let input = action.event.charactersIgnoringModifiers { - if input == "." && action.shiftIsPressed() { - // 選択中候補で確定し、接尾辞入力に移行。 - // カーソル位置より右に文字列がある場合は接頭辞入力として扱う (無視してもいいかも) - addWordToUserDict(yomi: selecting.yomi, okuri: selecting.okuri, candidate: selecting.candidates[selecting.candidateIndex]) - updateCandidates(selecting: nil) - addFixedText(selecting.fixedText(dropLast: false)) - if let remain = selecting.remain { - state.inputMethod = .composing(ComposingState(isShift: true, text: remain, romaji: "")) - updateMarkedText() - } else { - state.inputMethod = .composing(ComposingState(isShift: true, text: [], okuri: nil, romaji: "")) - } - return handle(action) - } else if selecting.candidateIndex >= inlineCandidateCount { + if selecting.candidateIndex >= inlineCandidateCount { if let first = input.lowercased().first, let index = Global.selectCandidateKeys.firstIndex(of: first), index < displayCandidateCount { let diff = index - (selecting.candidateIndex - inlineCandidateCount) % displayCandidateCount if selecting.candidateIndex + diff < selecting.candidates.count { diff --git a/macSKK/en.lproj/Localizable.strings b/macSKK/en.lproj/Localizable.strings index 6dc146eb..072d66e3 100644 --- a/macSKK/en.lproj/Localizable.strings +++ b/macSKK/en.lproj/Localizable.strings @@ -124,6 +124,7 @@ "KeyBindingActionUnregister" = "Unregister selected candidate"; "KeyBindingActionRegisterpaste" = "Paste on register"; "KeyBindingActionReconvert" = "Reconvert selected text"; +"KeyBindingActionAffix" = "Prefix/Suffix"; "KeyBindingActionEisu" = "Eisu Key"; "KeyBindingActionKana" = "Kana Key"; diff --git a/macSKK/ja.lproj/Localizable.strings b/macSKK/ja.lproj/Localizable.strings index b0af2f12..576413fc 100644 --- a/macSKK/ja.lproj/Localizable.strings +++ b/macSKK/ja.lproj/Localizable.strings @@ -124,6 +124,7 @@ "KeyBindingActionUnregister" = "選択中の変換候補の削除"; "KeyBindingActionRegisterpaste" = "登録モードでペースト"; "KeyBindingActionReconvert" = "選択テキストを再変換"; +"KeyBindingActionAffix" = "接頭辞/接尾辞"; "KeyBindingActionEisu" = "英数キー"; "KeyBindingActionKana" = "かなキー"; diff --git a/macSKKTests/StateMachineTests.swift b/macSKKTests/StateMachineTests.swift index e1e1bbec..93e6805d 100644 --- a/macSKKTests/StateMachineTests.swift +++ b/macSKKTests/StateMachineTests.swift @@ -3460,6 +3460,8 @@ final class StateMachineTests: XCTestCase { return withShift ? .unregister : .backwardCandidate case ";": return withShift ? nil : .stickyShift + case ".": + return withShift ? .affix : nil case "/": return withShift ? nil : .abbrev case " ": From 2e7e7de0579142479435ac7308d5ff387e061a10 Mon Sep 17 00:00:00 2001 From: mtgto Date: Sun, 9 Mar 2025 16:40:53 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=E3=82=AD=E3=83=BC=E3=83=90=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E3=83=89=E5=88=A4=E5=AE=9A=E3=81=AF=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?charactersIgnoringModifiers=E3=82=92=E8=A6=8B=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- macSKK/CurrentInput.swift | 7 ++----- macSKK/Settings/KeyEventView.swift | 2 +- macSKKTests/CurrentInputTests.swift | 4 +++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/macSKK/CurrentInput.swift b/macSKK/CurrentInput.swift index f086285a..c425aa8e 100644 --- a/macSKK/CurrentInput.swift +++ b/macSKK/CurrentInput.swift @@ -18,12 +18,9 @@ struct CurrentInput: Equatable { } init(event: NSEvent) { - if event.modifierFlags.contains(.shift), let character = event.characters?.lowercased().first, Key.characters.contains(character) { - // Shiftを押しながら入力されたキーはキーバインド設定から登録した場合は (NSEvent#charactersIgnoringModifiersが記号のほうを返すため) - // .character("!") のように記号のほうをもっているが、IMKInputController#handleに渡されるNSEventの - // charactersIgnoringModifiersは記号のほうではない ("!"なら"1"になっている) ため、charactersのほうを見る + if let character = event.charactersIgnoringModifiers?.lowercased().first, Key.characters.contains(character) { key = .character(character) - } else if let character = event.charactersIgnoringModifiers?.lowercased().first, Key.characters.contains(character) { + } else if let character = event.characters?.lowercased().first, Key.characters.contains(character) { key = .character(character) } else { key = .code(event.keyCode) diff --git a/macSKK/Settings/KeyEventView.swift b/macSKK/Settings/KeyEventView.swift index b3de92ee..c827562e 100644 --- a/macSKK/Settings/KeyEventView.swift +++ b/macSKK/Settings/KeyEventView.swift @@ -20,7 +20,7 @@ struct KeyEventView: View { .onAppear { eventMonitor = NSEvent.addLocalMonitorForEvents(matching: [.keyDown]) { event in characters = event.characters ?? "" - charactersIgnoringModifiers = event.charactersIgnoringModifiers ?? "" + charactersIgnoringModifiers = event.characters(byApplyingModifiers: []) ?? "" keyCode = event.keyCode.description var modifiers: [String] = [] if event.modifierFlags.contains(.capsLock) { diff --git a/macSKKTests/CurrentInputTests.swift b/macSKKTests/CurrentInputTests.swift index 713193e6..1b0c1b9e 100644 --- a/macSKKTests/CurrentInputTests.swift +++ b/macSKKTests/CurrentInputTests.swift @@ -24,11 +24,13 @@ final class CurrentInputTests: XCTestCase { let inputShiftQ = CurrentInput(key: .character("q"), modifierFlags: .shift) let eventQ = generateKeyEvent(modifierFlags: [], characters: "q") let eventShiftQ = generateKeyEvent(modifierFlags: .shift, characters: "q") - + let affix = generateKeyEvent(modifierFlags: .shift, characters: ">", charactersIgnoringModifiers: ".") + XCTAssertEqual(inputQ, CurrentInput(event: eventQ)) XCTAssertEqual(inputShiftQ, CurrentInput(event: eventShiftQ)) XCTAssertNotEqual(inputQ, CurrentInput(event: eventShiftQ)) XCTAssertNotEqual(inputShiftQ, CurrentInput(event: eventQ)) + XCTAssertEqual(CurrentInput(event: affix).key, .character(".")) } func testCurrentInputKeyCodeWithShift() {