Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Hanyu Pinyin conversion support #614

Merged
merged 5 commits into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/collect_swift_coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/bash

function convert_to_markdown_table() {
local input="$1"

echo "$input" | tr '-' '\n' | sed '/^$/d' | awk '
BEGIN {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: we can put this script to a file and invoke it as awk -f <file>.

table_border="| "
}
{
if (NR == 1) {
# Process the header, ensuring there is space between each column
gsub(/ +/, " | ", $0)
print table_border $0 " |"

# Generate the separator line
n = split($0, headers, /\|/)
sep_line = "|"
for (i = 1; i <= n; i++) {
sep_line = sep_line " --- |"
}
print sep_line
} else if ($0 !~ /^-+$/) {
# Process data rows, ensuring there is space between each column
gsub(/ +/, " | ", $0)
print table_border $0 " |"
}
}'
}

XCTEST_PATH="$(find . -name '*.xctest')"

COMMENT_FILE="codecov_comment.md"

for path in $XCTEST_PATH; do
filename=$(basename "$path")
echo "## Test path: $filename" >>$COMMENT_FILE
echo '' >>$COMMENT_FILE
report=$(xcrun llvm-cov report ${path}/Contents/MacOS/*PackageTests -instr-profile ${path}/../codecov/default.profdata -ignore-filename-regex='.build/|Tests/')

convert_to_markdown_table "$report" >>$COMMENT_FILE
echo '' >>$COMMENT_FILE

done
26 changes: 16 additions & 10 deletions .github/workflows/continuous-integration-workflow-xcode-latest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ on: [push, pull_request]
jobs:
build:
name: Build and Test with Latest Xcode
runs-on: macOS-13
runs-on: macOS-15
# env:
# DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer
steps:
- uses: actions/checkout@v4
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: "^15.1.0"
xcode-version: "^16.1.0"
- name: Build McBopomofoLMLibTest
run: cmake -DENABLE_TEST=1 -S . -B build
working-directory: Source/Engine
Expand All @@ -30,22 +30,20 @@ jobs:
- name: Run Gramambular2Test
run: make runGramambular2Test
working-directory: Source/Engine/gramambular2/build
- name: Test McBopomofo App Bundle
run: xcodebuild -scheme McBopomofo -configuration Debug test
- name: Test CandidateUI
run: swift test
run: swift test --enable-code-coverage
working-directory: Packages/CandidateUI
- name: Test OpenCCBridge
run: swift test
run: swift test --enable-code-coverage
working-directory: Packages/OpenCCBridge
- name: Test BopomofoBraille
run: swift test
working-directory: Packages/OpenCCBridge
run: swift test --enable-code-coverage
working-directory: Packages/BopomofoBraille
- name: Test NSStringUtils
run: swift test
run: swift test --enable-code-coverage
working-directory: Packages/NSStringUtils
- name: Test ChineseNumbers
run: swift test
run: swift test --enable-code-coverage
working-directory: Packages/ChineseNumbers
- name: Clean McBopomofo for testing
run: xcodebuild -scheme McBopomofo -configuration Debug clean
Expand All @@ -62,3 +60,11 @@ jobs:
- name: Test data files
run: make check
working-directory: Source/Data
- name: "Collect test results"
if: github.event_name == 'push'
run: bash .github/collect_swift_coverage.sh
- name: Create commit comment
if: github.event_name == 'push'
uses: peter-evans/commit-comment@v3
with:
body-path: 'codecov_comment.md'
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ xcuserdata
.swiftpm
.vscode
__pycache__
codecov_comment.md
80 changes: 28 additions & 52 deletions McBopomofoTests/AssociatedPhrasesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,36 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

import XCTest
import Testing

@testable import McBopomofo

class AssociatedPhrasesTests: XCTestCase {
@Suite("Associated Phrases Testing")
final class AssociatedPhrasesTests {

var handler = KeyHandler()
var chineseConversionEnabled: Bool = false

override func setUpWithError() throws {
init() async throws {
chineseConversionEnabled = Preferences.chineseConversionEnabled
Preferences.chineseConversionEnabled = false
LanguageModelManager.loadDataModels()
handler = KeyHandler()
handler.inputMode = .bopomofo
}

override func tearDownWithError() throws {
deinit {
Preferences.chineseConversionEnabled = chineseConversionEnabled
}

func testBuildingAssociatedPhrasesState() {
@Test(
"Test building an associated phrase from characters",
arguments: [
("u6", "ㄧ", "一")
])
func testBuildingAssociatedPhrasesState(keySequence: String, reading: String, value: String) {
var state: InputState = InputState.Empty()
let keys = Array("u6").map {
let keys = Array(keySequence).map {
String($0)
}
for key in keys {
Expand All @@ -58,17 +64,23 @@ class AssociatedPhrasesTests: XCTestCase {
}
guard
let associatedPhrases = handler.buildAssociatedPhraseState(
withPreviousState: state, prefixCursorAt: 1, reading: "ㄧ", value: "一",
withPreviousState: state, prefixCursorAt: 1, reading: reading, value: value,
selectedCandidateIndex: 0, useVerticalMode: false, useShiftKey: false)
as? InputState.AssociatedPhrases
else {
XCTFail("There should be an associated phrase state")
Issue.record("There should be an associated phrase state")
return
}
XCTAssert(associatedPhrases.candidates.count > 0)
#expect(associatedPhrases.candidates.count > 0)
}

func testAssociatedPhrasesStatePunctuation1() {
@Test(
"Test building an associated phrase from punctuations",
arguments: [
("『", "『』"),
("《", "《》"),
])
func testAssociatedPhrasesStatePunctuation1(input: String, result: String) {
var state: InputState = InputState.Empty()
let keys = Array("{").map {
String($0)
Expand All @@ -84,62 +96,26 @@ class AssociatedPhrasesTests: XCTestCase {
}
guard
let associatedPhrases = handler.buildAssociatedPhraseState(
withPreviousState: state, prefixCursorAt: 1, reading: "_punctuation_{", value: "『",
withPreviousState: state, prefixCursorAt: 1, reading: "_punctuation_{",
value: input,
selectedCandidateIndex: 0, useVerticalMode: false, useShiftKey: false)
as? InputState.AssociatedPhrases
else {
XCTFail("There should be an associated phrase state")
Issue.record("There should be an associated phrase state")
return
}
XCTAssert(associatedPhrases.candidates.count > 0)
#expect(associatedPhrases.candidates.count > 0)
let candidate = associatedPhrases.candidates[0]

handler.fixNodeForAssociatedPhraseWithPrefix(
at: associatedPhrases.prefixCursorIndex, prefixReading: associatedPhrases.prefixReading,
prefixValue: associatedPhrases.prefixValue, associatedPhraseReading: candidate.reading,
associatedPhraseValue: candidate.value)
guard let inputting = handler.buildInputtingState() as? InputState.Inputting else {
XCTFail("There should be an inputting state")
Issue.record("There should be an inputting state")
return
}
XCTAssertTrue(inputting.composingBuffer == "『』")
}

func testAssociatedPhrasesStatePunctuation2() {
var state: InputState = InputState.Empty()
let keys = Array("{").map {
String($0)
}
for key in keys {
let input = KeyHandlerInput(
inputText: key, keyCode: 0, charCode: charCode(key), flags: [],
isVerticalMode: false)
handler.handle(input: input, state: state) { newState in
state = newState
} errorCallback: {
}
}
guard
let associatedPhrases = handler.buildAssociatedPhraseState(
withPreviousState: state, prefixCursorAt: 1, reading: "_punctuation_{", value: "《",
selectedCandidateIndex: 0, useVerticalMode: false, useShiftKey: false)
as? InputState.AssociatedPhrases
else {
XCTFail("There should be an associated phrase state")
return
}
XCTAssert(associatedPhrases.candidates.count > 0)
let candidate = associatedPhrases.candidates[0]

handler.fixNodeForAssociatedPhraseWithPrefix(
at: associatedPhrases.prefixCursorIndex, prefixReading: associatedPhrases.prefixReading,
prefixValue: associatedPhrases.prefixValue, associatedPhraseReading: candidate.reading,
associatedPhraseValue: candidate.value)
guard let inputting = handler.buildInputtingState() as? InputState.Inputting else {
XCTFail("There should be an inputting state")
return
}
XCTAssertTrue(inputting.composingBuffer == "《》")
#expect(inputting.composingBuffer == result)
}

}
11 changes: 7 additions & 4 deletions McBopomofoTests/DictionaryServiceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,24 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

import XCTest
import Testing

@testable import McBopomofo

final class DictionaryServiceTests: XCTestCase {
@Suite("Dictionary Service Tests")
final class DictionaryServiceTests {

@Test
func testSpeak() {
let result = DictionaryServices.shared.lookUp(
phrase: "你", withServiceAtIndex: 0, state: InputState.Empty()
) { _ in

}
XCTAssertTrue(result)
#expect(result)
}

@Test
func testDictionaryService() {
let count = DictionaryServices.shared.services.count
for index in 0..<count {
Expand All @@ -57,7 +60,7 @@ final class DictionaryServiceTests: XCTestCase {
callbackCalled = true
}
if !callbackCalled {
XCTAssertTrue(result)
#expect(result)
}
}
}
Expand Down
Loading