Skip to content

Commit 1053038

Browse files
authored
Merge branch 'main' into conjugation-declension
2 parents 2418846 + 79efa68 commit 1053038

11 files changed

Lines changed: 78 additions & 48 deletions

File tree

.pre-commit-config.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@ repos:
2020
- id: trailing-whitespace
2121
- id: end-of-file-fixer
2222
- id: check-yaml
23-
# - id: check-added-large-files
2423

2524
- repo: https://github.com/realm/SwiftLint
26-
rev: 0.62.2
25+
rev: 0.63.1
2726
hooks:
2827
- id: swiftlint
2928
name: run swiftlint linting check

CONTRIBUTING.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ If you have questions or would like to communicate with the team, please [join u
1616
- [Learning the tech stack](#learning-the-tech)
1717
- [Development environment](#dev-env)
1818
- [Note on debugging](#note-on-debugging)
19+
- [Build Schemes Selection](#build-scheme)
1920
- [Testing](#testing)
2021
- [Issues and projects](#issues-projects)
2122
- [Bug reports](#bug-reports)
@@ -126,16 +127,19 @@ pre-commit install
126127

127128
4. Open the Scribe-iOS directory in Xcode
128129

129-
5. In order to run Scribe on an emulator:
130+
5. The application has 2 build schemes, Conjugate and Scribe for the verb conjugation and the language keyboards applications
131+
- There are other build schemes for individual keyboard which don't need to be selected unless you're trying to debug a keyboard
132+
- More about this could be read in the [Build Schemes Selection](#build-scheme) section
130133

134+
6. In order to run Scribe on an emulator:
131135
- Read the [documentation from Apple](https://developer.apple.com/documentation/xcode/running-your-app-in-the-simulator-or-on-a-device) if need be
132136
- In the top bar select Scribe as the scheme
133137
- If you're debugging you'll need to select the keyboard you're testing as the scheme (see the [note on debugging](#note-on-debugging) below)
134138
- Select a device to run the app on
135139
- Press the run button marked `Start the active scheme`
136140
- From here code edits that are made will be reflected in the app each time the active scheme is restarted
137141

138-
6. Build the developer documentation by selecting `Product` > `Build Documentation` (^⇧⌘D)
142+
7. Build the developer documentation by selecting `Product` > `Build Documentation` (^⇧⌘D)
139143

140144
> [!NOTE]
141145
> Feel free to contact the team in the [iOS room on Matrix](https://matrix.to/#/#ScribeiOS:matrix.org) if you're having problems getting your environment setup!
@@ -152,6 +156,17 @@ The Xcode debugger often doesn't work as expected for Scribe as the keyboards th
152156
- When you get a window telling you to "choose an app to run", don't choose Scribe as you might expect, but instead scroll down and select Xcode Previews
153157
- Occasionally you'll be met with just a black screen on startup, in which case you can press Home (or ⇧-⌘-H) and then go directly to Scribe or an app for keyboard testing
154158

159+
<a id="build-scheme"></a>
160+
161+
## Build Schemes Selection [``](#contents)
162+
163+
The project includes two build schemes, each corresponding to a different application.There are other targets corresponding to the individual keyboards which are shipped within the `Scribe` target.
164+
165+
Build schemes can be selected from the top bar next to device selection.
166+
167+
1. Scribe → Scribe Language Keyboards app (IME)
168+
2. Conjugate → Scribe Conjugate verb conjugation app
169+
155170
<a id="testing"></a>
156171

157172
## Testing [``](#contents)

Keyboards/DataManager/ContractManager.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// SPDX-License-Identifier: GPL-3.0-or-later
22
import Foundation
33

4-
/** ContractManager is responsible for loading and caching DataContract instances
5-
based on language codes.
6-
*/
4+
/**
5+
* ContractManager is responsible for loading and caching DataContract instances based on language codes.
6+
*/
77
class ContractManager {
88
static let shared = ContractManager()
99
private var contractCache: [String: DataContract] = [:]
@@ -18,7 +18,7 @@ class ContractManager {
1818
return cached
1919
}
2020

21-
// Load JSON file (e.g., "de.json", "en.json", "es.json")
21+
// Load JSON file (e.g., "de.json", "en.json", "es.json").
2222
guard let jsonResourcePath = Bundle.main.path(
2323
forResource: languageCode,
2424
ofType: "json"

Keyboards/DataManager/DataContract.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// SPDX-License-Identifier: GPL-3.0-or-later
22
import Foundation
33

4-
/** DataContract represents the structure of the data used in the application.
5-
*/
4+
/**
5+
* DataContract represents the structure of the data used in the application.
6+
*/
67
struct DataContract: Codable {
78
let numbers: [String: String]?
89
let genders: GenderContract?

Keyboards/DataManager/GenderManager.swift

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: GPL-3.0-or-later
22
import Foundation
33

4-
/// Manages gender query logic based on data contracts
4+
/// Manages gender query logic based on data contracts.
55
class GenderManager {
66
static let shared = GenderManager()
77

@@ -14,11 +14,12 @@ class GenderManager {
1414
let fallbackGender: String?
1515
}
1616

17-
/**Builds the appropriate gender queries based on the contract structure
18-
- Parameters:
19-
- word: The word to query
20-
- contract: The data contract defining gender structure
21-
- Returns: Array of query info objects to execute
17+
/**
18+
* Builds the appropriate gender queries based on the contract structure
19+
* - Parameters:
20+
* - word: The word to query
21+
* - contract: The data contract defining gender structure
22+
* - Returns: Array of query info objects to execute
2223
*/
2324
func buildGenderQueries(word: String, contract: DataContract) -> [GenderQueryInfo] {
2425

@@ -35,21 +36,21 @@ class GenderManager {
3536
return []
3637
}
3738

38-
// MARK: - Private Helper Methods
39+
// MARK: Private Helper Methods
3940

40-
/// Checks if the data contract defines a single, canonical gender column
41+
/// Checks if the data contract defines a single, canonical gender column.
4142
private func hasCanonicalGender(_ contract: DataContract) -> Bool {
4243
return contract.genders?.canonical?.first?.isEmpty == false
4344
}
4445

45-
/// Checks if the data contract defines separate columns for masculine and feminine genders
46+
/// Checks if the data contract defines separate columns for masculine and feminine genders.
4647
private func hasMasculineFeminine(_ contract: DataContract) -> Bool {
4748
let hasMasculine = !(contract.genders?.masculines?.isEmpty ?? true)
4849
let hasFeminine = !(contract.genders?.feminines?.isEmpty ?? true)
4950
return hasMasculine && hasFeminine
5051
}
5152

52-
/// Builds query for canonical gender structure
53+
/// Builds query for canonical gender structure.
5354
private func buildCanonicalQuery(word: String, contract: DataContract) -> GenderQueryInfo? {
5455
guard let nounCol = contract.numbers?.keys.first,
5556
let genderCol = contract.genders?.canonical?.first else {
@@ -70,11 +71,11 @@ class GenderManager {
7071
)
7172
}
7273

73-
/// Builds queries for masculine/feminine gender structure
74+
/// Builds queries for masculine/feminine gender structure.
7475
private func buildMasculineFeminineQueries(word: String, contract: DataContract) -> [GenderQueryInfo] {
7576
var queries: [GenderQueryInfo] = []
7677

77-
// Masculine column query
78+
// Masculine column query.
7879
if let masculineCol = contract.genders?.masculines?.first {
7980
let query = """
8081
SELECT `\(masculineCol)` FROM nouns
@@ -88,7 +89,7 @@ class GenderManager {
8889
))
8990
}
9091

91-
// Feminine column query
92+
// Feminine column query.
9293
if let feminineCol = contract.genders?.feminines?.first {
9394
let query = """
9495
SELECT `\(feminineCol)` FROM nouns

Keyboards/DataManager/LanguageDBManager.swift

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -291,15 +291,15 @@ extension LanguageDBManager {
291291
args: StatementArguments(queryInfo.args)
292292
)
293293

294-
// For canonical gender: results are the actual genders
294+
// For canonical gender: results are the actual genders.
295295
if queryInfo.fallbackGender == nil {
296296
for gender in results where !gender.isEmpty {
297297
if !allGenders.contains(gender) {
298298
allGenders.append(gender)
299299
}
300300
}
301301
}
302-
// For masculine/feminine: if any result, use fallback
302+
// For masculine/feminine: if any result, use fallback.
303303
else {
304304
if !results.isEmpty && !results[0].isEmpty,
305305
let fallback = queryInfo.fallbackGender,
@@ -359,7 +359,7 @@ extension LanguageDBManager {
359359

360360
/// Query preposition form of word in `prepositions`.
361361
func queryPrepForm(of word: String) -> [String] {
362-
// Check if this language's database has grammaticalCase column
362+
// Check if this language's database has grammaticalCase column.
363363
guard hasGrammaticalCaseColumn() else {
364364
return [""]
365365
}
@@ -440,11 +440,8 @@ extension LanguageDBManager {
440440
/// Query specific form of word in `verbs`.
441441
///
442442
/// - Parameters:
443-
/// - word: The value to search for
444-
/// - identifierColumn: The column to search in (default: "infinitive" or "verb" for Swedish)
445443
/// - outputCols: Specific form want to output
446-
func queryVerb(of word: String, identifierColumn: String? = nil, with outputCols: [String]) -> [String] {
447-
let columnName = identifierColumn ?? ((controllerLanguage == "Swedish") ? "verb" : "infinitive")
444+
func queryVerb(of word: String, with outputCols: [String]) -> [String] {
448445
let query = """
449446
SELECT
450447
*

Keyboards/DataManager/PluralManager.swift

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ class PluralManager {
1313
let args: [String]
1414
}
1515

16-
/**Builds a query to find the plural form of a word based on the contract structure
17-
- Parameters:
18-
- word: The singular word to find the plural for
19-
- contract: The data contract defining the database structure
20-
- Returns: Query info to execute, or nil if contract is invalid
16+
/**
17+
* Builds a query to find the plural form of a word based on the contract structure
18+
* - Parameters:
19+
* - word: The singular word to find the plural for
20+
* - contract: The data contract defining the database structure
21+
* - Returns: Query info to execute, or nil if contract is invalid
2122
*/
2223
func buildPluralQuery(word: String, contract: DataContract?) -> [PluralQueryInfo] { // ← Return array!
2324
guard let contract = contract,
@@ -29,7 +30,7 @@ class PluralManager {
2930

3031
var queries: [PluralQueryInfo] = []
3132

32-
// Build a query for EACH singular/plural pair
33+
// Build a query for EACH singular/plural pair.
3334
for (singularCol, pluralCol) in numbers {
3435
let query = """
3536
SELECT `\(singularCol)`, `\(pluralCol)`
@@ -47,9 +48,10 @@ class PluralManager {
4748
return queries
4849
}
4950

50-
/**Builds a query to get all plural forms for a language
51-
- Parameter contract: The data contract defining plural columns
52-
- Returns: Query info to execute, or nil if contract is invalid
51+
/**
52+
* Builds a query to get all plural forms for a language
53+
* - Parameter contract: The data contract defining plural columns.
54+
* - Returns: Query info to execute, or nil if contract is invalid.
5355
*/
5456
func buildAllPluralsQuery(contract: DataContract?) -> PluralQueryInfo? {
5557
guard let contract = contract,

Keyboards/KeyboardsBase/KeyboardViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1471,7 +1471,7 @@ class KeyboardViewController: UIInputViewController {
14711471
// Drop non-unique values in case the lexicon has added words that were already present.
14721472
LanguageDBManager.shared.deleteNonUniqueAutocompletions()
14731473

1474-
// Load plural words for the current language
1474+
// Load plural words for the current language.
14751475
if let allPlurals = LanguageDBManager.shared.queryAllPluralForms() {
14761476
pluralWords = Set(allPlurals.map { $0.lowercased() })
14771477
}

Keyboards/KeyboardsBase/ScribeFunctionality/Annotate.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ let prepAnnotationConversionDict = [
3232
"Russian": ["Acc": "Вин", "Dat": "Дат", "Gen": "Род", "Loc": "Мес", "Pre": "Пре", "Ins": "Инс"]
3333
]
3434

35-
// Converts full gender names to abbreviations (e.g., "feminine" → "F")
35+
// Converts full gender names to abbreviations (e.g., "feminine" → "F").
3636
func convertFullGenderToAbbr(_ genderFull: String) -> String {
3737
let genderMap: [String: String] = [
3838
"feminine": "F",
@@ -46,7 +46,7 @@ func convertFullGenderToAbbr(_ genderFull: String) -> String {
4646
return genderMap[genderFull.lowercased()] ?? genderFull
4747
}
4848

49-
// Converts full preposition to abbreviations
49+
// Converts full preposition to abbreviations.
5050
func convertFullPrepositionToAbbr(_ prepositionFull: String) -> String {
5151
let prepositionMap: [String: String] = [
5252
"genitive case": "Gen",
@@ -72,7 +72,7 @@ func wordAnnotation(wordToAnnotate: String, KVC: KeyboardViewController) {
7272
// Get gender(s)
7373
let nounForm = LanguageDBManager.shared.queryNounForm(of: wordToAnnotate)[0]
7474
if !nounForm.isEmpty {
75-
// nounForm might already be "M/F" if multiple genders found
75+
// nounForm might already be "M/F" if multiple genders found.
7676
genderAnnotations = nounForm.components(separatedBy: "/")
7777
}
7878

@@ -81,13 +81,13 @@ func wordAnnotation(wordToAnnotate: String, KVC: KeyboardViewController) {
8181
pluralAnnotation = "PL"
8282
}
8383

84-
// Combine: gender(s) first, then PL if applicable
84+
// Combine: gender(s) first, then PL if applicable.
8585
var allAnnotations = genderAnnotations
8686
if let pl = pluralAnnotation, !allAnnotations.contains("PL") {
8787
allAnnotations.append(pl)
8888
}
8989

90-
// Join back with "/"
90+
// Join back with "/".
9191
let combinedNounForm = allAnnotations.joined(separator: "/")
9292

9393
prepAnnotationForm = LanguageDBManager.shared.queryPrepForm(of: wordToAnnotate.lowercased())[0]
@@ -171,7 +171,7 @@ func wordAnnotation(wordToAnnotate: String, KVC: KeyboardViewController) {
171171

172172
if ["feminine", "masculine", "neuter", "common"].contains(annotationToDisplay.lowercased()) {
173173
annotationToDisplay = convertFullGenderToAbbr(annotationToDisplay)
174-
annotationsToAssign[i] = annotationToDisplay // Update the array too
174+
annotationsToAssign[i] = annotationToDisplay // update the array too
175175
}
176176

177177
if nounFormToColorDict.keys.contains(annotationToDisplay) {

README.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Check out Scribe's [architecture diagrams](https://github.com/scribe-org/Organiz
3838
- [Contributing](#contributing)
3939
- [Environment Setup](#environment-setup)
4040
- [App Setup](#app-setup)
41+
- [Codebase Overview](#codebase-overview)
4142
- [Supported Languages](#supported-languages)
4243
- [Keyboard Features](#keyboard-features)
4344
- [Featured By](#featured-by)
@@ -177,7 +178,6 @@ pre-commit install
177178
4. Open the Scribe-iOS directory in Xcode
178179

179180
5. In order to run Scribe on an emulator:
180-
181181
- Read the [documentation from Apple](https://developer.apple.com/documentation/xcode/running-your-app-in-simulator-or-on-a-device) if need be
182182
- In the top bar select Scribe as the scheme
183183
- If you're debugging you'll need to select the keyboard you're testing as the scheme (see the [note on debugging](#note-on-debugging) below)
@@ -198,6 +198,21 @@ pre-commit install
198198

199199
# App Setup [``](#contents)
200200

201+
<a id="codebase-overview"></a>
202+
203+
### Codebase Overview
204+
205+
The Scribe-iOS codebase consists of two separate applications.
206+
207+
- Keyboard Application — the Scribe Language Keyboards application (IME)
208+
209+
- Conjugate Application — the Scribe verb conjugations application
210+
211+
To select each variant you should select the scheme from the top bar next to device selection.
212+
213+
1. Scribe → Scribe Language Keyboards app (IME)
214+
2. Conjugate → Scribe Conjugate verb conjugation app
215+
201216
Users access Scribe language keyboards through the following:
202217

203218
- Download **Scribe - Language Keyboards** from the [App Store](https://apps.apple.com/app/scribe-language-keyboards/id1596613886)

0 commit comments

Comments
 (0)