Skip to content

Commit

Permalink
Merge pull request #275 from mtgto/fix-right-page
Browse files Browse the repository at this point in the history
変換候補選択時に右キーでページ遷移できない場合にクラッシュするバグを修正
  • Loading branch information
mtgto authored Jan 11, 2025
2 parents 121d16b + e8613c4 commit 03bd6eb
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 39 deletions.
76 changes: 37 additions & 39 deletions macSKK/StateMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1054,37 +1054,7 @@ final class StateMachine {
} else {
diff = 1
}
if selecting.candidateIndex + diff < selecting.candidates.count {
let newSelectingState = selecting.addCandidateIndex(diff: diff)
state.inputMethod = .selecting(newSelectingState)
updateCandidates(selecting: newSelectingState)
} else {
if case .register(let registerState, let prev) = specialState {
state.specialState = .register(RegisterState(
prev: RegisterState.PrevState(
mode: selecting.prev.mode,
composing: selecting.prev.composing),
yomi: selecting.yomi),
prev: prev + [registerState])
} else if specialState != nil {
state.inputMethod = .normal
state.inputMode = selecting.prev.mode
} else {
state.specialState = .register(
RegisterState(
prev: RegisterState.PrevState(
mode: selecting.prev.mode,
composing: selecting.prev.composing),
yomi: selecting.yomi),
prev: [])
state.inputMethod = .normal
state.inputMode = .hiragana
inputMethodEventSubject.send(.modeChanged(.hiragana, action.cursorPosition))
}
updateCandidates(selecting: nil)
}
updateMarkedText()
return true
return handleSelectingNext(action, diff: diff, selecting: selecting, specialState: specialState)
case .backwardCandidate:
return handleSelectingPrevious(diff: -1, selecting: selecting)
case .tab:
Expand All @@ -1108,14 +1078,8 @@ final class StateMachine {
return true
}
case .right:
if selecting.candidateIndex >= inlineCandidateCount {
// 次ページの先頭
let diff = displayCandidateCount - (selecting.candidateIndex - inlineCandidateCount) % displayCandidateCount
return handleSelectingPrevious(diff: diff, selecting: selecting)
} else {
// AquaSKKと同様に何もしない (IMKCandidates表示時はそちらの移動に使われる)
return true
}
let diff = displayCandidateCount - (selecting.candidateIndex - inlineCandidateCount) % displayCandidateCount
return handleSelectingNext(action, diff: diff, selecting: selecting, specialState: specialState)
case .startOfLine:
// 現ページの先頭
let diff = -(selecting.candidateIndex - inlineCandidateCount) % displayCandidateCount
Expand Down Expand Up @@ -1206,6 +1170,40 @@ final class StateMachine {
return true
}

@MainActor private func handleSelectingNext(_ action: Action, diff: Int, selecting: SelectingState, specialState: SpecialState?) -> Bool {
if selecting.candidateIndex + diff < selecting.candidates.count {
let newSelectingState = selecting.addCandidateIndex(diff: diff)
state.inputMethod = .selecting(newSelectingState)
updateCandidates(selecting: newSelectingState)
} else {
if case .register(let registerState, let prev) = specialState {
state.specialState = .register(RegisterState(
prev: RegisterState.PrevState(
mode: selecting.prev.mode,
composing: selecting.prev.composing),
yomi: selecting.yomi),
prev: prev + [registerState])
} else if specialState != nil {
state.inputMethod = .normal
state.inputMode = selecting.prev.mode
} else {
state.specialState = .register(
RegisterState(
prev: RegisterState.PrevState(
mode: selecting.prev.mode,
composing: selecting.prev.composing),
yomi: selecting.yomi),
prev: [])
state.inputMethod = .normal
state.inputMode = .hiragana
inputMethodEventSubject.send(.modeChanged(.hiragana, action.cursorPosition))
}
updateCandidates(selecting: nil)
}
updateMarkedText()
return true
}

func setMode(_ mode: InputMode) {
state.inputMode = mode
}
Expand Down
54 changes: 54 additions & 0 deletions macSKKTests/StateMachineTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2641,6 +2641,60 @@ final class StateMachineTests: XCTestCase {
wait(for: [expectation], timeout: 1.0)
}

@MainActor func testHandleSelectingLeftRight() {
Global.dictionary.setEntries(["": "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".map { Word(String($0)) }])

let stateMachine = StateMachine(initialState: IMEState(inputMode: .hiragana))
let expectation = XCTestExpectation()
expectation.expectedFulfillmentCount = 2
stateMachine.inputMethodEvent.collect(12).sink { events in
XCTAssertEqual(events[0], .markedText(MarkedText([.markerCompose, .plain("")])))
XCTAssertEqual(events[1], .markedText(MarkedText([.markerSelect, .emphasized("1")])))
XCTAssertEqual(events[2], .markedText(MarkedText([.markerSelect, .emphasized("2")])))
XCTAssertEqual(events[3], .markedText(MarkedText([.markerSelect, .emphasized("3")])))
XCTAssertEqual(events[4], .markedText(MarkedText([.markerSelect, .emphasized("4")])), "変換候補パネルが表示開始")
XCTAssertEqual(events[5], .markedText(MarkedText([.markerSelect, .emphasized("D")])), "9個先のDを表示")
XCTAssertEqual(events[6], .markedText(MarkedText([.markerSelect, .emphasized("M")])), "9個先のMを表示")
XCTAssertEqual(events[7], .markedText(MarkedText([.markerSelect, .emphasized("N")])))
XCTAssertEqual(events[8], .markedText(MarkedText([.markerSelect, .emphasized("V")])), "Mの9個先のVを表示")
XCTAssertEqual(events[9], .markedText(MarkedText([.markerSelect, .emphasized("W")])))
XCTAssertEqual(events[10], .modeChanged(.hiragana, .zero))
XCTAssertEqual(events[11], .markedText(MarkedText([.plain("[登録:あ]")])))
expectation.fulfill()
}.store(in: &cancellables)
stateMachine.candidateEvent.collect(9).sink { events in
XCTAssertEqual(events[0]?.selected.word, "1")
XCTAssertEqual(events[1]?.selected.word, "2")
XCTAssertEqual(events[2]?.selected.word, "3")
XCTAssertEqual(events[3]?.selected.word, "4")
XCTAssertEqual(events[3]?.page?.current, 0, "0オリジン")
XCTAssertEqual(events[3]?.page?.total, 4, "35個の変換候補があり、最初3つはインライン表示して残りを4ページで表示する")
XCTAssertEqual(events[4]?.selected.word, "D")
XCTAssertEqual(events[4]?.page?.current, 1)
XCTAssertEqual(events[5]?.selected.word, "M")
XCTAssertEqual(events[5]?.page?.current, 2)
XCTAssertEqual(events[6]?.selected.word, "N")
XCTAssertEqual(events[6]?.page?.current, 2)
XCTAssertEqual(events[7]?.selected.word, "V")
XCTAssertEqual(events[7]?.page?.current, 3)
XCTAssertEqual(events[8]?.selected.word, "W")
XCTAssertEqual(events[8]?.page?.current, 3)
expectation.fulfill()
}.store(in: &cancellables)
XCTAssertTrue(stateMachine.handle(printableKeyEventAction(character: "a", withShift: true)))
XCTAssertTrue(stateMachine.handle(printableKeyEventAction(character: " ")))
XCTAssertTrue(stateMachine.handle(printableKeyEventAction(character: " ")))
XCTAssertTrue(stateMachine.handle(printableKeyEventAction(character: " ")))
XCTAssertTrue(stateMachine.handle(printableKeyEventAction(character: " ")))
XCTAssertTrue(stateMachine.handle(rightKeyAction))
XCTAssertTrue(stateMachine.handle(rightKeyAction))
XCTAssertTrue(stateMachine.handle(downKeyAction))
XCTAssertTrue(stateMachine.handle(rightKeyAction))
XCTAssertTrue(stateMachine.handle(downKeyAction))
XCTAssertTrue(stateMachine.handle(rightKeyAction))
wait(for: [expectation], timeout: 1.0)
}

@MainActor func testHandleSelectingCtrlACtrlE() {
Global.dictionary.setEntries(["": [Word(""), Word(""), Word(""), Word(""), Word("")]])

Expand Down

0 comments on commit 03bd6eb

Please sign in to comment.