mirror of
https://github.com/keymanapp/keyman.git
synced 2026-10-22 05:47:41 +00:00
chore(web): Merge branch 'master' into refactor/web/osk-centralized-gestures
This commit is contained in:
commit
abbeff8faa
113 changed files with 2151 additions and 993 deletions
38
HISTORY.md
38
HISTORY.md
|
|
@ -1,5 +1,43 @@
|
|||
# Keyman Version History
|
||||
|
||||
## 15.0.78 alpha 2021-06-30
|
||||
|
||||
* fix(web): console errors when using SHIFT w help-text 'osk' (#5392)
|
||||
|
||||
## 15.0.77 alpha 2021-06-29
|
||||
|
||||
* fix(windows): #5336 appcontext get to handle small buffer (#5383)
|
||||
* fix(common): get handle caller buffer size small than internal Fixes … (#5390)
|
||||
|
||||
## 15.0.76 alpha 2021-06-28
|
||||
|
||||
* feat(web): Add option useAlerts to control alerts() (#5302)
|
||||
* chore(android): Add help on Settings option to change spacebar caption (#5375)
|
||||
* feat(android): hide textarea for perf (#5376)
|
||||
* chore: keyboard_info.source.json 1.0.6 (#5379)
|
||||
* refactor(android): setKeyboard and setKeymanLanguage (#5338)
|
||||
* feat(web): Merge keyboard stub with error stub (#5340)
|
||||
* feat(linux): Add reference index page (#5370)
|
||||
* fix(linux): Fix restarting ibus when running with sudo (#5371)
|
||||
* refactor(linux): Centralize paths (#5372)
|
||||
* fix(linux): Save QR code in temporary directory (#5373)
|
||||
|
||||
## 15.0.75 alpha 2021-06-25
|
||||
|
||||
* fix(android): rotation is not updating keyboard (#5247)
|
||||
* fix(windows): osk scaling mismatch on horz axis (#5341)
|
||||
* fix(linux): Don't add duplicate entries when reinstalling keyboard (#5363)
|
||||
* fix(linux): fix tab completion for command line tools (#5362)
|
||||
* feat(web): Update addLanguageKeyboards to return a Promise (#5260)
|
||||
* feat(web): Add option useAlerts to control alerts() (#5302)
|
||||
|
||||
## 15.0.74 alpha 2021-06-24
|
||||
|
||||
* fix(android): fixes application of nextlayer for subkeys with customized layer setting (#5350)
|
||||
* feat(common/core/web): engine correction-prep optimizations (#5319)
|
||||
* feat(linux): Add support for impish (Ubuntu 21.10) (#5334)
|
||||
* fix(linux): Add libglib2.0-bin to keyman Depends 🍒 (#5360)
|
||||
|
||||
## 15.0.73 alpha 2021-06-23
|
||||
|
||||
* chore(windows): add engine test framework (#5337)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
15.0.74
|
||||
15.0.79
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
ta.readOnly = false;
|
||||
|
||||
// Tell KMW the default banner height to use
|
||||
com.keyman.osk.Banner.DEFAULT_HEIGHT =
|
||||
com.keyman.osk.Banner.DEFAULT_HEIGHT =
|
||||
Math.ceil(window.jsInterface.getDefaultBannerHeight() / window.devicePixelRatio);
|
||||
|
||||
kmw.addEventListener('keyboardloaded', setIsChiral);
|
||||
|
|
@ -128,49 +128,10 @@
|
|||
return true;
|
||||
}
|
||||
|
||||
function setKeymanLanguage(keyboardName, internalName, languageName, langId, kbdFile, font, oskFont, package) {
|
||||
var kmw=window['keyman'];
|
||||
var kbdInterface=window.KeymanWeb;
|
||||
|
||||
// Defaults for missing arguments
|
||||
switch (arguments.length) {
|
||||
case 1:
|
||||
internalName = keyboardName;
|
||||
if (keyboardName == 'English') {
|
||||
internalName = 'us';
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
languageName = keyboardName;
|
||||
break;
|
||||
case 3:
|
||||
langId='';
|
||||
break;
|
||||
case 6:
|
||||
oskFont = font;
|
||||
break;
|
||||
}
|
||||
|
||||
var k = {
|
||||
KN:keyboardName,
|
||||
KI:'Keyboard_'+internalName,
|
||||
KLC:langId,
|
||||
KL:languageName,
|
||||
KF:kbdFile,
|
||||
KP:package
|
||||
};
|
||||
if (font) {
|
||||
k.KFont = font;
|
||||
//window.console.log('keyboard.html assigning k.KFont = ' + font);
|
||||
}
|
||||
if (oskFont) {
|
||||
k.KOskFont = oskFont;
|
||||
//window.console.log('keyboard.html assigning k.KOskFont = ' + oskFont);
|
||||
}
|
||||
kbdInterface.registerStub(k);
|
||||
|
||||
kmw['setActiveKeyboard'](package + '::Keyboard_'+internalName,langId);
|
||||
kmw['osk']['show'](true);
|
||||
function setKeymanLanguage(k) {
|
||||
KeymanWeb.registerStub(k);
|
||||
keyman.setActiveKeyboard(k.KP + '::'+k.KI, k.KLC);
|
||||
keyman.osk.show(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -320,7 +281,7 @@
|
|||
|
||||
function executePopupKey(keyID, keyText) {
|
||||
var kmw=window['keyman'];
|
||||
|
||||
|
||||
// KMW only needs keyID to process the popup key. keyText merely logged to console
|
||||
//window.console.log('executePopupKey('+keyID+'); keyText: ' + keyText);
|
||||
kmw['executePopupKey'](keyID);
|
||||
|
|
@ -366,8 +327,6 @@
|
|||
</style>
|
||||
</head>
|
||||
<body class="kmw-embedded keyman-app">
|
||||
<center>
|
||||
<textarea id="ta" cols="1" rows="1" style="position:absolute; left:-500px; top:0px;"></textarea>
|
||||
</center>
|
||||
<textarea id="ta" cols="1" rows="1" style="display: none;"></textarea>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -507,60 +507,37 @@ final class KMKeyboard extends WebView {
|
|||
KMManager.getLatestKeyboardFileVersion(getContext(), packageID, keyboardID) : null;
|
||||
}
|
||||
|
||||
if(kOskFont == null || kOskFont.isEmpty())
|
||||
kOskFont = kFont;
|
||||
|
||||
JSONObject jDisplayFont = makeFontPaths(kFont);
|
||||
JSONObject jOskFont = makeFontPaths(kOskFont);
|
||||
|
||||
txtFont = getFontFilename(jDisplayFont);
|
||||
oskFont = getFontFilename(jOskFont);
|
||||
|
||||
String kbKey = KMString.format("%s_%s", languageID, keyboardID);
|
||||
|
||||
setKeyboardRoot(packageID);
|
||||
String keyboardPath = makeKeyboardPath(packageID, keyboardID, keyboardVersion);
|
||||
|
||||
String tFont = "''";
|
||||
String oFont = null;
|
||||
if (kFont == null) {
|
||||
txtFont = "";
|
||||
} else {
|
||||
if (FileUtils.hasFontExtension(kFont)) {
|
||||
txtFont = kFont;
|
||||
tFont = KMString.format("{\"family\":\"font_family_%s\",\"files\":[\"%s%s\"]}", kFont.substring(0, kFont.length() - 4), keyboardRoot, kFont);
|
||||
} else {
|
||||
txtFont = getFontFilename(kFont);
|
||||
if (!txtFont.isEmpty()) {
|
||||
tFont = makeFontPaths(kFont);
|
||||
}
|
||||
}
|
||||
JSONObject reg = new JSONObject();
|
||||
try {
|
||||
reg.put("KN", keyboardName);
|
||||
reg.put("KI", "Keyboard_" + keyboardID);
|
||||
reg.put("KLC", languageID);
|
||||
reg.put("KL", languageName);
|
||||
reg.put("KF", keyboardPath);
|
||||
reg.put("KP", packageID);
|
||||
|
||||
if (jDisplayFont != null) reg.put("KFont", jDisplayFont);
|
||||
if (jOskFont != null) reg.put("KOskFont", jOskFont);
|
||||
} catch(JSONException e) {
|
||||
KMLog.LogException(TAG, "", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (kOskFont == null || kOskFont.isEmpty()) {
|
||||
oskFont = null;
|
||||
} else {
|
||||
if (FileUtils.hasFontExtension(kOskFont)) {
|
||||
oskFont = kOskFont;
|
||||
oFont = KMString.format("{\"family\":\"font_family_%s\",\"files\":[\"%s%s\"]}", kOskFont.substring(0, kOskFont.length() - 4), keyboardRoot, kOskFont);
|
||||
} else {
|
||||
oskFont = getFontFilename(kOskFont);
|
||||
if (!oskFont.isEmpty()) {
|
||||
oFont = makeFontPaths(kOskFont);
|
||||
} else {
|
||||
oskFont = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (oFont == null) {
|
||||
oFont = tFont;
|
||||
}
|
||||
|
||||
if (tFont.equals("''")) {
|
||||
tFont = fontUndefined;
|
||||
}
|
||||
if (oFont.equals("''")) {
|
||||
oFont = fontUndefined;
|
||||
}
|
||||
|
||||
// Escape single-quoted names for javascript call
|
||||
keyboardName = keyboardName.replaceAll("\'", "\\\\'"); // Double-escaped-backslash b/c regex.
|
||||
languageName = languageName.replaceAll("\'", "\\\\'");
|
||||
|
||||
String jsFormat = "setKeymanLanguage('%s','%s','%s','%s','%s', %s, %s, '%s')";
|
||||
String jsString = KMString.format(jsFormat, keyboardName, keyboardID, languageName, languageID, keyboardPath, tFont, oFont, packageID);
|
||||
String jsString = KMString.format("setKeymanLanguage(%s)", reg.toString());
|
||||
loadJavascript(jsString);
|
||||
|
||||
this.packageID = packageID;
|
||||
|
|
@ -695,17 +672,16 @@ final class KMKeyboard extends WebView {
|
|||
/**
|
||||
* getFontFilename
|
||||
* Parse a Font JSON object and return the font filename (ending in .ttf or .otf)
|
||||
* @param jsonString String - Font JSON object as a string
|
||||
* @param fontObj JSONObject - Font JSON object
|
||||
* @return String - Filename for the font. If font is invalid, return ""
|
||||
*/
|
||||
private String getFontFilename(String jsonString) {
|
||||
private String getFontFilename(JSONObject fontObj) {
|
||||
String font = "";
|
||||
if (jsonString == null || jsonString.isEmpty()) {
|
||||
if (fontObj == null) {
|
||||
return font;
|
||||
}
|
||||
try {
|
||||
JSONObject fontObj = new JSONObject(jsonString);
|
||||
JSONArray sourceArray = fontObj.optJSONArray(KMManager.KMKey_FontSource);
|
||||
JSONArray sourceArray = fontObj.optJSONArray(KMManager.KMKey_FontFiles);
|
||||
if (sourceArray != null) {
|
||||
String fontFile;
|
||||
int length = sourceArray.length();
|
||||
|
|
@ -717,7 +693,7 @@ final class KMKeyboard extends WebView {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
String fontFile = fontObj.optString(KMManager.KMKey_FontSource);
|
||||
String fontFile = fontObj.optString(KMManager.KMKey_FontFiles);
|
||||
if (fontFile != null) {
|
||||
if (FileUtils.hasFontExtension(fontFile)) {
|
||||
font = fontFile;
|
||||
|
|
@ -1058,10 +1034,24 @@ final class KMKeyboard extends WebView {
|
|||
* 1. Replace "source" keys for "files" keys
|
||||
* 2. Create full font paths for .ttf or .svg
|
||||
* @param font String font JSON object as a string
|
||||
* @return String of modified font information with full paths. If font is invalid, return "''"
|
||||
* @return JSONObject of modified font information with full paths. If font is invalid, return `null`
|
||||
*/
|
||||
private String makeFontPaths(String font) {
|
||||
private JSONObject makeFontPaths(String font) {
|
||||
|
||||
if(font == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (FileUtils.hasFontExtension(font)) {
|
||||
JSONObject jfont = new JSONObject();
|
||||
jfont.put(KMManager.KMKey_FontFamily, font.substring(0, font.length()-4));
|
||||
JSONArray jfiles = new JSONArray();
|
||||
jfiles.put(keyboardRoot + font);
|
||||
jfont.put(KMManager.KMKey_FontFiles, jfiles);
|
||||
return jfont;
|
||||
}
|
||||
|
||||
JSONObject fontObj = new JSONObject(font);
|
||||
JSONArray sourceArray;
|
||||
String fontFile;
|
||||
|
|
@ -1076,7 +1066,7 @@ final class KMKeyboard extends WebView {
|
|||
if (obj instanceof String) {
|
||||
fontFile = fontObj.getString(KMManager.KMKey_FontFiles);
|
||||
fontObj.put(KMManager.KMKey_FontFiles, keyboardRoot + obj);
|
||||
return fontObj.toString();
|
||||
return fontObj;
|
||||
} else if (obj instanceof JSONArray) {
|
||||
sourceArray = fontObj.optJSONArray(KMManager.KMKey_FontFiles);
|
||||
if (sourceArray != null) {
|
||||
|
|
@ -1085,17 +1075,17 @@ final class KMKeyboard extends WebView {
|
|||
if (FileUtils.hasFontExtension(fontFile)) {
|
||||
fontObj.put(KMManager.KMKey_FontFiles, keyboardRoot + fontFile);
|
||||
fontObj.remove(KMManager.KMKey_FontSource);
|
||||
return fontObj.toString();
|
||||
return fontObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
KMLog.LogException(TAG, "", e);
|
||||
return "''";
|
||||
return null;
|
||||
}
|
||||
|
||||
return font;
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ public final class KMManager {
|
|||
public static final String KMKey_OskFont = "oskFont";
|
||||
public static final String KMKey_FontSource = "source";
|
||||
public static final String KMKey_FontFiles = "files";
|
||||
public static final String KMKey_FontFamily = "family";
|
||||
public static final String KMKey_KeyboardModified = "lastModified";
|
||||
public static final String KMKey_KeyboardRTL = "rtl";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,78 +1,18 @@
|
|||
# Keyman for Android & Keyman Engine for Android
|
||||
|
||||
## Prerequisites
|
||||
* Android Studio 4.1+
|
||||
* Java SE Development Kit 8
|
||||
* [Node.js](https://nodejs.org/) 14.17+ (for building KeymanWeb)
|
||||
* [Pandoc](#Install-Pandoc) for generating offline help
|
||||
|
||||
## Install Java
|
||||
It is recommended to use openJDK because of oracle license issues.
|
||||
Tested with latest release for openJDK 8 from
|
||||
https://github.com/ojdkbuild/ojdkbuild
|
||||
|
||||
1. Download and unpack the zip archive
|
||||
2. On on windows: use the default java path C:\Program Files\Java to avoid error message "Error 0x80010135 Path Too Long".
|
||||
3. Aso set an environment variable for JAVA_HOME e.g C:\Program Files\Java\openjdk-1.8.0.232-1
|
||||
See [build configuration](../docs/build/index.md) for details on how to configure your build environment.
|
||||
|
||||
## Keyman Minimum Android Requirements
|
||||
Keyman for Android has a minSdkVersion of 21 for [Android 5.0 Lollipop](https://developer.android.com/about/versions/lollipop)
|
||||
|
||||
## Setup Android Studio
|
||||
|
||||
1. Download [Android Studio](https://developer.android.com/studio/index.html) and install with these [instructions](https://developer.android.com/studio/install.html).
|
||||
2. For Windows users, set environment variable **ANDROID_HOME** to the location of your Android SDK. The default installation location is **C:\Users\\[USER]\AppData\Local\Android\sdk** where [USER] is your username. You may need to log out and log back in to take effect.
|
||||
|
||||
For MacOS/Linux users, add the following to **~/.bashrc** or **~/.bash_profile**
|
||||
```bash
|
||||
export ANDROID_HOME=$HOME/Android/Sdk
|
||||
export PATH=$PATH:$ANDROID_HOME/tools
|
||||
```
|
||||
For MacOS users, add the following (adjusted appropriately) to **~/.bashrc** or **~/.bash_profile** if your Java version is too strange for gradlew to understand (e.g., 11.0.2)
|
||||
```bash
|
||||
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
|
||||
echo $JAVA_HOME #should output: /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home
|
||||
```
|
||||
3. For Windows users, from a Git Bash Prompt window, cd to the **sdk/tools/bin** folder and accept all the SDK license agreements
|
||||
```
|
||||
yes | ./sdkmanager.bat --licenses
|
||||
```
|
||||
For MacOS users, from a Terminal window, cd to the **~/Library/Android/sdk/tools/bin** folder and accept all the SDK license agreements
|
||||
```bash
|
||||
yes | ./sdkmanager --licenses
|
||||
```
|
||||
4. If you plan to test on a physical device via USB, install the appropriate [OEM USB drivers](https://developer.android.com/studio/run/oem-usb.html)
|
||||
5. Install [Java SE Development Kit](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
|
||||
|
||||
## Keyman for Android Development
|
||||
Keyman for Android (formerly named KMAPro) can be built from a command line (preferred) or Android Studio.
|
||||
|
||||
Building Keyman Web is a precursor for compiling KMEA, so verify your system has all the [Minimum Web Compilation Requirements](../web/README.md#minimum-web-compilation-requirements)
|
||||
|
||||
### Install JQ
|
||||
jq 1.6+ is used during the build process to determine the latest versions of the default keyboard (sil_euro_latin.kmp) and lexical-model (en.nrc.mtnt.model.kmp) packages to download. For builds on Windows, jq is already included in `/resources/build/`
|
||||
|
||||
On Linux
|
||||
`sudo apt install jq`
|
||||
|
||||
### Install Pandoc
|
||||
Pandoc is used during the build process to generate the app's offline help.
|
||||
Install from https://pandoc.org/installing.html
|
||||
|
||||
### Crash Reporting
|
||||
Keyman for Android uses [Sentry](https://sentry.io) for crash reporting at a server https://sentry.keyman.com. The analytics for Debug are associated with an App Bundle ID `com.tavultesoft.kmapro.debug`.
|
||||
|
||||
#### Setting up sentry-cli
|
||||
Contact the Keyman team if you need access to sentry.keyman.com for development.
|
||||
You will also need to install [sentry-cli](https://docs.sentry.io/cli/installation/) for uploading Debug symbols.
|
||||
After setting up your personal [Auth token](http://sentry.keyman.com/settings/account/api/auth-tokens/), add the following to **~/.bashrc**
|
||||
```bash
|
||||
export SENTRY_AUTH_TOKEN={your Sentry auth token}
|
||||
export SENTRY_URL=https://sentry.keyman.com
|
||||
export SENTRY_ORG=keyman
|
||||
export SENTRY_PROJECT=keyman-android
|
||||
```
|
||||
To validate your configuration, from the `android/` folder run `sentry-cli info`.
|
||||
|
||||
### Compiling From Command Line
|
||||
1. Launch a command prompt and cd to the directory **keyman/android**
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ title: What's New
|
|||
Here are some of the new features we have added to Keyman 15.0 for Android:
|
||||
|
||||
* Meet Google Play's target API level requirement of 30 (Android 11)
|
||||
* Add a settings option to change the displayed keyboard name on the spacebar
|
||||
|
||||
[ Watch a video](https://youtu.be/ehk0Bts28JE)
|
||||
that highlights some of these new features.
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 49 KiB |
BIN
android/help/android_images/spacebar-caption-ap.png
Normal file
BIN
android/help/android_images/spacebar-caption-ap.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -38,6 +38,20 @@ For installed keyboard packages, click on this to associate another language wit
|
|||
If all the languages for a keyboard have already been installed,
|
||||
this won't change anything.
|
||||
|
||||
## Change Display Language
|
||||

|
||||
|
||||
Click on this to change the display language of the Keyman for Android app. The list of available languages come from [translate.keyman.com](https://translate.keyman.com). If a translation is available, Keyman for Android will default to the device's default locale.
|
||||
|
||||
## Spacebar Caption
|
||||
Click on this to change the displayed keyboard name on the spacebar. The options are:
|
||||
* Language name
|
||||
* Keyboard name
|
||||
* Language name + Keyboard name
|
||||
* Blank
|
||||
|
||||

|
||||
|
||||
## Enable Keyman as system-wide keyboard
|
||||
By default, installed Keyman keyboards are only available to use within the Keyman app. Click on this setting to
|
||||
bring up the Android system configuration so Keyman can be added as a system-wide keyboard.
|
||||
|
|
@ -45,11 +59,6 @@ bring up the Android system configuration so Keyman can be added as a system-wid
|
|||
## Set Keyman as default keyboard
|
||||
Click on this to bring up the Android system configuration for setting Keyman as the default system-wide keyboard.
|
||||
|
||||
## Change Display Language
|
||||

|
||||
|
||||
Click on this to change the display language of the Keyman for Android app. The list of available languages come from [translate.keyman.com](https://translate.keyman.com). If a translation is available, Keyman for Android will default to the device's default locale.
|
||||
|
||||
## Always show banner
|
||||
This toggle is reserved for future features. When off, the text suggestion banner is only displayed when
|
||||
the dictionary is enabled. The language associated with the keyboard must match the language associated with
|
||||
|
|
|
|||
|
|
@ -1,235 +1,12 @@
|
|||
# How to build the keyboard processor
|
||||
|
||||
## Prerequisites
|
||||
See [build configuration](../../../../docs/build/index.md) for details on how to configure your build environment.
|
||||
|
||||
- Bash (for Windows, included with Git for Windows)
|
||||
- Python 3
|
||||
- Meson build system 0.45+ (0.56+ for WASM)
|
||||
- ninja 1.8+
|
||||
- C++14 or later compiler (VC++ 2019 or later for Windows).
|
||||
- lib std::fs
|
||||
- kmcomp (for tests) -- must be added to path
|
||||
- Rust 1.50+ from <https://www.rust-lang.org/tools/install> (or `cargo` package on Linux)
|
||||
|
||||
For WASM builds:
|
||||
- Meson build system 0.56+
|
||||
- emscripten 2.0.23+ <https://emscripten.org/docs/getting_started/downloads.html>
|
||||
- WasmPack 0.9.1+ <https://github.com/rustwasm/wasm-pack>
|
||||
- ninja 1.10+ for WASM
|
||||
|
||||
### Windows
|
||||
|
||||
* Install Git for Windows: <https://gitforwindows.org/>
|
||||
|
||||
* Install Python 3:
|
||||
|
||||
You can get the official Python installer from the official Python site:
|
||||
<https://www.python.org/downloads/windows/>
|
||||
|
||||
Ensure you have Python3 correctly installed and can run the command `pip`.
|
||||
|
||||
Ensure that Python 3 is on the path ahead of Python 2 (if installed).
|
||||
|
||||
* Install meson:
|
||||
|
||||
```bash
|
||||
python -m pip install meson
|
||||
```
|
||||
|
||||
* Install [ninja](https://ninja-build.org/) 1.10+:
|
||||
|
||||
```bash
|
||||
choco install ninja
|
||||
```
|
||||
|
||||
* Install Rust:
|
||||
|
||||
After downloading and running the executable from:
|
||||
<https://www.rust-lang.org/tools/install>
|
||||
|
||||
Run the command:
|
||||
|
||||
```bash
|
||||
rustup target add i686-pc-windows-msvc
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
* Install wasm-pack:
|
||||
<https://github.com/rustwasm/wasm-pack/releases/download/v0.9.1/wasm-pack-init.exe>
|
||||
|
||||
* Install Emscripten:
|
||||
<https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install>
|
||||
|
||||
* Add emcc to PATH (probably upstream\enscripten)
|
||||
|
||||
#### Windows environment
|
||||
|
||||
On Windows you may need to set `SDKVER` environment variable to the current
|
||||
Windows SDK version, if it cannot be automatically detected.
|
||||
|
||||
```bash
|
||||
export SDKVER=10.0.19041.0
|
||||
```
|
||||
|
||||
#### kmcomp
|
||||
|
||||
Note on paths for kmcomp:
|
||||
|
||||
The search path can be edited through System settings / Advanced system settings
|
||||
/ Environment Variables / User environment variables.
|
||||
|
||||
If you have Keyman Developer installed, kmcomp should be on the path already;
|
||||
otherwise add `%KeymanDeveloperPath%` to your path.
|
||||
|
||||
If you do not have Keyman Developer installed, add the path where you extracted
|
||||
the kmcomp archive.
|
||||
|
||||
### Linux
|
||||
|
||||
#### Ubuntu and Debian
|
||||
|
||||
* Install Python
|
||||
|
||||
```bash
|
||||
sudo apt install python3
|
||||
```
|
||||
|
||||
* Upgrade Meson from version included with Python (WASM builds):
|
||||
|
||||
```bash
|
||||
sudo apt install meson
|
||||
```
|
||||
|
||||
* Install Rust:
|
||||
|
||||
```bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
* Install wasm-pack (WASM builds):
|
||||
|
||||
```bash
|
||||
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
```
|
||||
|
||||
* Install Enscripten (including adding to path with `emsdk_env.sh`) (WASM builds):
|
||||
<https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install>
|
||||
|
||||
You may also need the `kmcomp` wrapper - see below.
|
||||
|
||||
#### Other Linux distributions
|
||||
|
||||
* Install Python 3 and pip
|
||||
|
||||
You will be able to install a python3 package in any reputable recent version of
|
||||
linux using its package manager if it's not already installed. Ensure that `pip`
|
||||
is also installed.
|
||||
|
||||
* Install meson:
|
||||
|
||||
```bash
|
||||
python3 -m pip install meson
|
||||
```
|
||||
|
||||
* Install Rust from <https://www.rust-lang.org/tools/install>, then:
|
||||
|
||||
```bash
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
* Install wasm-pack (WASM builds):
|
||||
|
||||
```bash
|
||||
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
```
|
||||
|
||||
* Install Enscripten (WASM builds):
|
||||
<https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install>
|
||||
|
||||
* Add emcc to PATH (probably upstream/enscripten)
|
||||
|
||||
You may also need the `kmcomp` wrapper - see below.
|
||||
|
||||
#### kmcomp - All Linux platforms
|
||||
|
||||
If you want to rebuild keyboards for tests, you need a wrapper `kmcomp` shell
|
||||
script:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
wine `dirname "$0"`/kmcomp.exe "$@"
|
||||
```
|
||||
|
||||
Place this in the same folder as you extracted kmcomp.exe, and
|
||||
`chmod +x kmcomp`. Add the folder to the path (e.g.
|
||||
`export PATH=/path/to/kmcomp:$PATH`, which you can add to `.bashrc`).
|
||||
|
||||
### macOS
|
||||
|
||||
* Install Python 3
|
||||
|
||||
You can get the official Python installer from the official Python site:
|
||||
<https://www.python.org/downloads/mac-osx/>
|
||||
|
||||
* Install meson:
|
||||
|
||||
```bash
|
||||
brew install meson # if you haven't already installed via pip
|
||||
```
|
||||
|
||||
* Install Rust:
|
||||
|
||||
```bash
|
||||
curl https://sh.rustup.rs -sSf | sh
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
* Install wasm-pack:
|
||||
|
||||
```bash
|
||||
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
```
|
||||
|
||||
* Install Enscripten (including environment update):
|
||||
<https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install>
|
||||
|
||||
#### kmcomp
|
||||
|
||||
If you want to rebuild keyboards for tests, you'll also need WINE:
|
||||
|
||||
```bash
|
||||
brew tap homebrew/cask-versions
|
||||
brew install --cask --no-quarantine wine-stable
|
||||
```
|
||||
|
||||
And you will also need a wrapper `kmcomp` shell script:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
wine64 `dirname "$0"`/kmcomp.exe "$@"
|
||||
```
|
||||
|
||||
Place this in the same folder as you extracted kmcomp.exe, and
|
||||
`chmod +x kmcomp`. Add the folder to the path (e.g.
|
||||
`export PATH=/path/to/kmcomp:$PATH`, which you can add to `.bashrc`).
|
||||
|
||||
## Building -- all platforms
|
||||
## Building
|
||||
|
||||
On all platforms, use `build.sh`.
|
||||
|
||||
* To build native libraries and tests:
|
||||
|
||||
```bash
|
||||
./build.sh --debug
|
||||
```
|
||||
|
||||
* To build WASM libraries and tests:
|
||||
|
||||
```bash
|
||||
./build.sh --platform wasm
|
||||
```
|
||||
|
||||
* See `./build.sh --help` for more details
|
||||
|
||||
## Note on kmcomp
|
||||
|
|
|
|||
|
|
@ -29,6 +29,19 @@ void KMX_Context::Add(KMX_WCHAR ch)
|
|||
//DebugLog("KMX_Context::Add(%x): EXIT [%d]: %s", ch, pos, Debug_UnicodeString(CurContext));
|
||||
}
|
||||
|
||||
KMX_WCHAR *KMX_Context::BufMax(int n)
|
||||
{
|
||||
KMX_WCHAR *p = (KMX_WCHAR *) u16chr(CurContext, 0);
|
||||
if(CurContext == p || n == 0) return p; // empty context or 0 characters requested, return pointer to end of context
|
||||
|
||||
KMX_WCHAR *q = p;
|
||||
for(; p != NULL && p > CurContext && (intptr_t)(q-p) < n; p = decxstr(p, CurContext))
|
||||
; // ; on new line to tell compiler empty loop is intentional
|
||||
|
||||
if((intptr_t)(q-p) > n) p = incxstr(p); // Copes with deadkey or supplementary pair at start of returned buffer making it too long
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
KMX_WCHAR *KMX_Context::Buf(int n)
|
||||
{
|
||||
|
|
@ -63,11 +76,17 @@ void KMX_Context::Reset()
|
|||
|
||||
void KMX_Context::Get(KMX_WCHAR *buf, int bufsize)
|
||||
{
|
||||
for(KMX_WCHAR *p = CurContext; *p && bufsize > 0; p++, bufsize--)
|
||||
for (KMX_WCHAR *p = this->BufMax(bufsize); *p && bufsize > 0; p++, bufsize--)
|
||||
{
|
||||
*buf = *p; buf++;
|
||||
if(*p >= 0xD800 && *p <= 0xDBFF) { *buf = *(++p); bufsize--; buf++; }
|
||||
*buf = *p;
|
||||
if(Uni_IsSurrogate1(*p) && bufsize - 2 > 0) {
|
||||
buf++; p++;
|
||||
*buf = *p;
|
||||
bufsize--;
|
||||
}
|
||||
buf++;
|
||||
}
|
||||
|
||||
*buf = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,15 +21,89 @@ private:
|
|||
|
||||
public:
|
||||
KMX_Context();
|
||||
|
||||
/**
|
||||
* @brief Copy "source" AppContext to this AppContext
|
||||
*
|
||||
* @param source KMX_Context to copy
|
||||
*/
|
||||
void CopyFrom(KMX_Context *source);
|
||||
|
||||
/**
|
||||
* @brief Add a single code unit to the Current Context. Not necessarily a complete code point
|
||||
*
|
||||
* @param Code unit to add
|
||||
*/
|
||||
void Add(KMX_WCHAR ch);
|
||||
|
||||
/**
|
||||
* @brief Removes a single code point from the end of the CurContext closest to the caret;
|
||||
* i.e. it will be both code units if a surrogate pair. If it is a deadkey it will
|
||||
* remove three code points: UC_SENTINEL, CODE_DEADKEY and deadkey value.
|
||||
*/
|
||||
void Delete();
|
||||
|
||||
/**
|
||||
* @brief Clears the CurContext and resets the position - pos - index
|
||||
*/
|
||||
void Reset();
|
||||
|
||||
/**
|
||||
* @brief Copies the characters in CurContext to supplied buffer.
|
||||
* If bufsize is reached before the entire context was copied, the buf
|
||||
* will be truncated to number of valid characters possible with null character
|
||||
* termination. e.g. it will be one code unit less than bufsize if that would
|
||||
* have meant splitting a surrogate pair
|
||||
* @param buf The data buffer to copy current context
|
||||
* @param bufsize The number of code units ie size of the KMX_WCHAR buffer - not the code points
|
||||
*/
|
||||
void Get(KMX_WCHAR *buf, int bufsize);
|
||||
|
||||
/**
|
||||
* @brief Sets the CurContext to the supplied buf character array and updates the pos index.
|
||||
*
|
||||
* @param buf
|
||||
*/
|
||||
void Set(const KMX_WCHAR *buf);
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to the character in the current context buffer which
|
||||
* will have at most n valid xstring units remaining until the null terminating
|
||||
* character. It will be one code unit less than bufsize if that would
|
||||
* have meant splitting a surrogate pair or deadkey.
|
||||
*
|
||||
* @param n The maximum number of valid xstring units (not code points or code units)
|
||||
* @return KMX_WCHAR* Pointer to the start postion for a buffer of maximum n xstring units
|
||||
*/
|
||||
KMX_WCHAR *Buf(int n);
|
||||
KMX_WCHAR *GetFullContext() { return CurContext; }
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to the character in the current context buffer which
|
||||
* will have at most n code units remaining until the the null terminating character.
|
||||
* Note: Unlike BufMax there is no checking for truncation of code points.
|
||||
* e.g. the pointer may point to a code unit that is half of a surrogate pair.
|
||||
*
|
||||
* @param n
|
||||
* @return KMX_WCHAR* Pointer to the start postion for a buffer of maximum n characters
|
||||
*/
|
||||
KMX_WCHAR *BufMax(int n);
|
||||
|
||||
/**
|
||||
* @brief Return a pointer to the CurContext buffer
|
||||
*
|
||||
* @return KMX_WCHAR*
|
||||
*/
|
||||
const KMX_WCHAR *GetFullContext() { return CurContext; }
|
||||
/**
|
||||
* @brief Returns TRUE if the last xstring unit in the context is a deadkey
|
||||
*
|
||||
* @return BOOL
|
||||
*/
|
||||
KMX_BOOL CharIsDeadkey();
|
||||
/**
|
||||
* @brief Returns TRUE if the last xstring unit in the CurContext is a surrogate pair.
|
||||
* @return BOOL
|
||||
*/
|
||||
KMX_BOOL CharIsSurrogatePair();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/input-processor",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/input-processor",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "The core text and prediction processing engine for KeymanWeb",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
},
|
||||
"homepage": "https://github.com/keymanapp/keyman#readme",
|
||||
"devDependencies": {
|
||||
"@keymanapp/lexical-model-compiler": "^15.0.74",
|
||||
"@keymanapp/resources-gosh": "^15.0.74",
|
||||
"@keymanapp/lexical-model-compiler": "^15.0.79",
|
||||
"@keymanapp/resources-gosh": "^15.0.79",
|
||||
"@types/node": "^11.9.4",
|
||||
"chai": "^4.3.4",
|
||||
"mocha": "^8.4.0",
|
||||
|
|
@ -34,11 +34,11 @@
|
|||
"mocha": "mocha"
|
||||
},
|
||||
"dependencies": {
|
||||
"@keymanapp/keyboard-processor": "^15.0.74",
|
||||
"@keymanapp/lexical-model-layer": "^15.0.74",
|
||||
"@keymanapp/models-types": "^15.0.74",
|
||||
"@keymanapp/web-environment": "^15.0.74",
|
||||
"@keymanapp/web-utils": "^15.0.74",
|
||||
"@keymanapp/keyboard-processor": "^15.0.79",
|
||||
"@keymanapp/lexical-model-layer": "^15.0.79",
|
||||
"@keymanapp/models-types": "^15.0.79",
|
||||
"@keymanapp/web-environment": "^15.0.79",
|
||||
"@keymanapp/web-utils": "^15.0.79",
|
||||
"eventemitter3": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,9 @@ describe('InputProcessor', function() {
|
|||
// Assumes no SMP chars in the source, which is fine.
|
||||
let context = new com.keyman.text.Mock(coreSourceCode, coreSourceCode._kmwLength());
|
||||
|
||||
this.timeout(250); // 250 ms, excluding text import.
|
||||
this.timeout(500); // 500 ms, excluding text import.
|
||||
// These often run on VMs, so we'll be a bit generous.
|
||||
|
||||
let core = new InputProcessor(); // I mean, it IS long context, and time
|
||||
// thresholding is disabled within Node.
|
||||
|
||||
|
|
@ -137,8 +139,13 @@ describe('InputProcessor', function() {
|
|||
// Assumes no SMP chars in the source, which is fine.
|
||||
let context = new com.keyman.text.Mock(coreSourceCode, coreSourceCode._kmwLength());
|
||||
|
||||
this.timeout(250); // 250 ms, excluding text import.
|
||||
let core = new InputProcessor(); // I mean, it IS long context, and time
|
||||
this.timeout(500); // 500 ms, excluding text import.
|
||||
// These often run on VMs, so we'll be a bit generous.
|
||||
//
|
||||
// Keep at the same 'order of magnitude' as the
|
||||
// 'without fat-fingers' test.
|
||||
|
||||
let core = new InputProcessor(); // It IS long context, and time
|
||||
// thresholding is disabled within Node.
|
||||
|
||||
core.activeKeyboard = keyboard;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/keyboard-processor",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/keyboard-processor",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "Core module for Keyman keyboard support in KeymanWeb.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
},
|
||||
"homepage": "https://github.com/keymanapp/keyman#readme",
|
||||
"devDependencies": {
|
||||
"@keymanapp/resources-gosh": "^15.0.74",
|
||||
"@keymanapp/resources-gosh": "^15.0.79",
|
||||
"chai": "^4.3.4",
|
||||
"mocha": "^8.4.0",
|
||||
"mocha-teamcity-reporter": "^4.0.0",
|
||||
|
|
@ -32,9 +32,9 @@
|
|||
"mocha": "mocha"
|
||||
},
|
||||
"dependencies": {
|
||||
"@keymanapp/models-types": "^15.0.74",
|
||||
"@keymanapp/web-environment": "^15.0.74",
|
||||
"@keymanapp/web-utils": "^15.0.74",
|
||||
"@keymanapp/models-types": "^15.0.79",
|
||||
"@keymanapp/web-environment": "^15.0.79",
|
||||
"@keymanapp/web-utils": "^15.0.79",
|
||||
"@types/node": "^11.9.4"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
common/core/web/tools/recorder/package-lock.json
generated
2
common/core/web/tools/recorder/package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/recorder-core",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/recorder-core",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "Core classes used to develop KeymanWeb test cases based on keystrokes",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
|
@ -17,10 +17,10 @@
|
|||
},
|
||||
"homepage": "https://github.com/keymanapp/keyman#readme",
|
||||
"dependencies": {
|
||||
"@keymanapp/keyboard-processor": "^15.0.74",
|
||||
"@keymanapp/models-types": "^15.0.74",
|
||||
"@keymanapp/web-environment": "^15.0.74",
|
||||
"@keymanapp/web-utils": "^15.0.74"
|
||||
"@keymanapp/keyboard-processor": "^15.0.79",
|
||||
"@keymanapp/models-types": "^15.0.79",
|
||||
"@keymanapp/web-environment": "^15.0.79",
|
||||
"@keymanapp/web-utils": "^15.0.79"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^3.8.3"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/web-sentry-manager",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/web-sentry-manager",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "Common setup for KeymanWeb's Sentry-based error reporting",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
"typescript": "^3.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@keymanapp/web-environment": "^15.0.74",
|
||||
"@keymanapp/web-environment": "^15.0.79",
|
||||
"@sentry/browser": "^5.27.4"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
common/core/web/utils/package-lock.json
generated
2
common/core/web/utils/package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/web-utils",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/web-utils",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "Common utility functions used throughout other Keyman packages",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
|
@ -20,8 +20,8 @@
|
|||
},
|
||||
"homepage": "https://github.com/keymanapp/keyman#readme",
|
||||
"devDependencies": {
|
||||
"@keymanapp/resources-gosh": "^15.0.74",
|
||||
"@keymanapp/web-environment": "^15.0.74",
|
||||
"@keymanapp/resources-gosh": "^15.0.79",
|
||||
"@keymanapp/web-environment": "^15.0.79",
|
||||
"@types/node": "^14.0.5",
|
||||
"typescript": "^3.8.3"
|
||||
}
|
||||
|
|
|
|||
2
common/models/templates/package-lock.json
generated
2
common/models/templates/package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/models-templates",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/models-templates",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "Backing model implementations (templates) for Keyman's modelling layer",
|
||||
"keywords": [
|
||||
"lm",
|
||||
|
|
@ -42,8 +42,8 @@
|
|||
"url": "https://github.com/keymanapp/keyman/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@keymanapp/models-types": "^15.0.74",
|
||||
"@keymanapp/web-utils": "^15.0.74",
|
||||
"@keymanapp/models-types": "^15.0.79",
|
||||
"@keymanapp/web-utils": "^15.0.79",
|
||||
"@types/chai": "^4.2.11",
|
||||
"@types/mocha": "^7.0.2",
|
||||
"@types/node": "^14.0.4",
|
||||
|
|
@ -52,6 +52,6 @@
|
|||
"typescript": "^3.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@keymanapp/models-wordbreakers": "^15.0.74"
|
||||
"@keymanapp/models-wordbreakers": "^15.0.79"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
common/models/types/package-lock.json
generated
2
common/models/types/package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/models-types",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/models-types",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "Type definitions in used in the modeling (lexical model/predictive text) component of Keyman.",
|
||||
"types": "./index.d.ts",
|
||||
"scripts": {
|
||||
|
|
|
|||
2
common/models/wordbreakers/package-lock.json
generated
2
common/models/wordbreakers/package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/models-wordbreakers",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/models-wordbreakers",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "Word breakers bundled in the modeling layer",
|
||||
"keywords": [
|
||||
"lexical model",
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
"url": "https://github.com/keymanapp/keyman/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@keymanapp/models-types": "^15.0.74",
|
||||
"@keymanapp/models-types": "^15.0.79",
|
||||
"@types/chai": "^4.2.11",
|
||||
"@types/mocha": "^7.0.2",
|
||||
"chai": "^4.3.4",
|
||||
|
|
|
|||
2
common/predictive-text/package-lock.json
generated
2
common/predictive-text/package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/lexical-model-layer",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/lexical-model-layer",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "Keyman/Predictive Text integration layer",
|
||||
"main": "build/index.js",
|
||||
"scripts": {
|
||||
|
|
@ -21,8 +21,8 @@
|
|||
},
|
||||
"homepage": "https://github.com/keymanapp/keyman#readme",
|
||||
"devDependencies": {
|
||||
"@keymanapp/models-types": "^15.0.74",
|
||||
"@keymanapp/resources-gosh": "^15.0.74",
|
||||
"@keymanapp/models-types": "^15.0.79",
|
||||
"@keymanapp/resources-gosh": "^15.0.79",
|
||||
"@types/node": "^10.17.21",
|
||||
"chai": "^4.3.4",
|
||||
"karma": "^6.3.2",
|
||||
|
|
@ -46,10 +46,10 @@
|
|||
"typescript": "^3.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@keymanapp/models-templates": "^15.0.74",
|
||||
"@keymanapp/models-wordbreakers": "^15.0.74",
|
||||
"@keymanapp/web-environment": "^15.0.74",
|
||||
"@keymanapp/web-utils": "^15.0.74",
|
||||
"@keymanapp/models-templates": "^15.0.79",
|
||||
"@keymanapp/models-wordbreakers": "^15.0.79",
|
||||
"@keymanapp/web-environment": "^15.0.79",
|
||||
"@keymanapp/web-utils": "^15.0.79",
|
||||
"es6-shim": "^0.35.5",
|
||||
"string.prototype.codepointat": "^0.2.1",
|
||||
"string.prototype.startswith": "^0.2.0"
|
||||
|
|
|
|||
2
developer/js/package-lock.json
generated
2
developer/js/package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/lexical-model-compiler",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/lexical-model-compiler",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "Keyman Developer lexical model compiler",
|
||||
"keywords": [
|
||||
"keyboard",
|
||||
|
|
@ -37,14 +37,14 @@
|
|||
"node": ">=12.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@keymanapp/models-types": "^15.0.74",
|
||||
"@keymanapp/models-types": "^15.0.79",
|
||||
"commander": "^3.0.0",
|
||||
"typescript": "^3.8.3",
|
||||
"xml2js": "^0.4.19"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@keymanapp/models-templates": "^15.0.74",
|
||||
"@keymanapp/models-wordbreakers": "^15.0.74",
|
||||
"@keymanapp/models-templates": "^15.0.79",
|
||||
"@keymanapp/models-wordbreakers": "^15.0.79",
|
||||
"@types/chai": "^4.1.7",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/node": "^10.14.6",
|
||||
|
|
|
|||
25
docs/build/index.md
vendored
Normal file
25
docs/build/index.md
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# How to configure your build environment
|
||||
|
||||
Keyman has a wide range of dependencies. We are working to reduce the complexity of setting up a development environment over time, but this document should give you all you need in order to start contributing to Keyman.
|
||||
|
||||
## Development Platforms
|
||||
|
||||
* [Linux - Ubuntu](linux-ubuntu.md)
|
||||
* [macOS](macos.md)
|
||||
* [Windows](windows.md)
|
||||
|
||||
## Additional Configuration Documentation
|
||||
|
||||
Additional notes are available in the following documents:
|
||||
|
||||
* [sentry-cli configuration](sentry-cli.md)
|
||||
|
||||
Older notes:
|
||||
|
||||
* [Keyman for Android notes](old/android-notes.md)
|
||||
* [Keyman for iOS notes](old/ios-notes.md)
|
||||
* [Keyman for macOS notes](old/macos-notes.md)
|
||||
* [KeymanWeb notes](old/web-notes.md)
|
||||
* [Keyman Core Desktop notes](old/core-desktop-notes.md)
|
||||
|
||||
Many folders may also contain other build instructions in README.md files.
|
||||
3
docs/build/linux-ubuntu.md
vendored
Normal file
3
docs/build/linux-ubuntu.md
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Setup your Keyman build environment on Ubuntu
|
||||
|
||||
TODO
|
||||
101
docs/build/macos.md
vendored
Normal file
101
docs/build/macos.md
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# Setup your Keyman build environment on macOS
|
||||
|
||||
## Target Projects
|
||||
|
||||
On macOS, you can build the following projects:
|
||||
|
||||
* Keyman for Android
|
||||
* Keyman for iOS
|
||||
* Keyman for macOS
|
||||
* KeymanWeb
|
||||
|
||||
The following libraries can also be built:
|
||||
|
||||
* Common/Core/Desktop (macOS, wasm targets)
|
||||
* Common/Core/Web
|
||||
|
||||
The following projects **cannot** be built on macOS:
|
||||
|
||||
* Keyman for Linux
|
||||
* Keyman for Windows
|
||||
* Keyman Developer
|
||||
|
||||
## System Requirements
|
||||
|
||||
* Minimum macOS version: macOS Catalina 10.15 or Big Sur 11.0
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Many dependencies are only required for specific projects.
|
||||
|
||||
* XCode (iOS, macOS)
|
||||
* Install from App Store
|
||||
* Accept the Xcode license: `sudo xcodebuild -license accept`
|
||||
|
||||
The remaining dependencies can be installed via script:
|
||||
`resources/devbox/macos/macos.sh`
|
||||
|
||||
This script will also update your environment to the values in:
|
||||
`resources/devbox/macos/keyman.macos.env.sh`
|
||||
|
||||
It will also add these environment settings to your `~/.bashrc`.
|
||||
|
||||
These dependencies are also listed below if you'd prefer to install manually.
|
||||
|
||||
## Shared Dependencies
|
||||
|
||||
* Shared: HomeBrew, Bash 5.0+, jq, Python 3, Meson, Ninja, Rust, coreutils, Pandoc
|
||||
|
||||
```shell
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
brew install bash jq python3 meson ninja rustup-init coreutils pandoc rustup-init
|
||||
```
|
||||
|
||||
* Web: node.js, emscripten, wasm-pack, openjdk 8
|
||||
|
||||
```shell
|
||||
brew install node emscripten wasm-pack openjdk@8
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
* iOS: swiftlint, carthage
|
||||
|
||||
```shell
|
||||
brew install swiftlint carthage
|
||||
```
|
||||
|
||||
* macOS: carthage, cocoapods
|
||||
|
||||
```shell
|
||||
brew install carthage cocoapods
|
||||
```
|
||||
|
||||
* Android: openjdk 8, Android SDK, Android Studio, Ant, Gradle, Maven
|
||||
|
||||
```shell
|
||||
brew install openjdk@8 android-sdk android-studio ant gradle maven
|
||||
# update path
|
||||
source ../resources/devbox/macos/keyman.macos.env.sh
|
||||
# optionally install sdk images
|
||||
sdkmanager "system-images;android-30;google_apis;armeabi-v7a"
|
||||
sdkmanager --update
|
||||
sdkmanager --licenses
|
||||
```
|
||||
|
||||
* kmcomp (optional): WINE
|
||||
- Required to build keyboards using kmcomp
|
||||
|
||||
```bash
|
||||
brew tap homebrew/cask-versions
|
||||
brew install --cask --no-quarantine wine-stable
|
||||
```
|
||||
|
||||
* sentry-cli (optional)
|
||||
- Uploading symbols for Sentry-based error reporting
|
||||
|
||||
```
|
||||
brew install getsentry/tools/sentry-cli
|
||||
```
|
||||
|
||||
* Run Android Studio once after installation to install additional components
|
||||
such as emulator images and SDK updates.
|
||||
56
docs/build/old/android-notes.md
vendored
Normal file
56
docs/build/old/android-notes.md
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Keyman for Android configuration notes
|
||||
|
||||
WARNING: these are old configuration notes. See [index.md](../index.md) for current steps.
|
||||
|
||||
* Android Studio 4.1+
|
||||
* Java SE Development Kit 8
|
||||
* [Node.js](https://nodejs.org/) 14.17+ (for building KeymanWeb)
|
||||
* [Pandoc](#Install-Pandoc) for generating offline help
|
||||
|
||||
## Install Java
|
||||
It is recommended to use openJDK because of Oracle license issues.
|
||||
Tested with latest release for openJDK 8 from
|
||||
https://github.com/ojdkbuild/ojdkbuild
|
||||
|
||||
1. Download and unpack the zip archive
|
||||
2. On windows: use the default java path C:\Program Files\Java to avoid error message "Error 0x80010135 Path Too Long".
|
||||
3. Also set an environment variable for JAVA_HOME e.g C:\Program Files\Java\openjdk-1.8.0.232-1
|
||||
|
||||
## Setup Android Studio
|
||||
|
||||
1. Download [Android Studio](https://developer.android.com/studio/index.html) and install with these [instructions](https://developer.android.com/studio/install.html).
|
||||
2. For Windows users, set environment variable **ANDROID_HOME** to the location of your Android SDK. The default installation location is **C:\Users\\[USER]\AppData\Local\Android\sdk** where [USER] is your username. You may need to log out and log back in to take effect.
|
||||
|
||||
For MacOS/Linux users, add the following to **~/.bashrc** or **~/.bash_profile**
|
||||
|
||||
```bash
|
||||
export ANDROID_HOME=$HOME/Android/Sdk
|
||||
export PATH=$PATH:$ANDROID_HOME/tools
|
||||
```
|
||||
For MacOS users, add the following (adjusted appropriately) to **~/.bashrc** or **~/.bash_profile** if your Java version is too strange for gradlew to understand (e.g., 11.0.2)
|
||||
|
||||
```bash
|
||||
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
|
||||
echo $JAVA_HOME #should output: /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home
|
||||
```
|
||||
3. For Windows users, from a Git Bash Prompt window, cd to the **sdk/tools/bin** folder and accept all the SDK license agreements
|
||||
|
||||
```
|
||||
yes | ./sdkmanager.bat --licenses
|
||||
```
|
||||
For MacOS users, from a Terminal window, cd to the **~/Library/Android/sdk/tools/bin** folder and accept all the SDK license agreements
|
||||
```bash
|
||||
yes | ./sdkmanager --licenses
|
||||
```
|
||||
4. If you plan to test on a physical device via USB, install the appropriate [OEM USB drivers](https://developer.android.com/studio/run/oem-usb.html)
|
||||
5. Install [Java SE Development Kit](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
|
||||
|
||||
### Install JQ
|
||||
jq 1.6+ is used during the build process to determine the latest versions of the default keyboard (sil_euro_latin.kmp) and lexical-model (en.nrc.mtnt.model.kmp) packages to download. For builds on Windows, jq is already included in `/resources/build/`
|
||||
|
||||
On Linux
|
||||
`sudo apt install jq`
|
||||
|
||||
### Install Pandoc
|
||||
Pandoc is used during the build process to generate the app's offline help.
|
||||
Install from https://pandoc.org/installing.html
|
||||
231
docs/build/old/core-desktop-notes.md
vendored
Normal file
231
docs/build/old/core-desktop-notes.md
vendored
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
# Common/Core/Desktop configuration notes
|
||||
|
||||
WARNING: these are old configuration notes. See [index.md](../index.md) for current steps.
|
||||
|
||||
- Bash (for Windows, included with Git for Windows)
|
||||
- Python 3
|
||||
- Meson build system 0.45+ (0.56+ for WASM)
|
||||
- ninja 1.8+
|
||||
- C++14 or later compiler (VC++ 2019 or later for Windows).
|
||||
- lib std::fs
|
||||
- kmcomp (for tests) -- must be added to path
|
||||
- Rust 1.50+ from <https://www.rust-lang.org/tools/install> (or `cargo` package on Linux)
|
||||
|
||||
For WASM builds:
|
||||
- Meson build system 0.56+
|
||||
- emscripten 2.0.23+ <https://emscripten.org/docs/getting_started/downloads.html>
|
||||
- WasmPack 0.9.1+ <https://github.com/rustwasm/wasm-pack>
|
||||
- ninja 1.10+ for WASM
|
||||
|
||||
### Windows
|
||||
|
||||
* Install Git for Windows: <https://gitforwindows.org/>
|
||||
|
||||
* Install Python 3:
|
||||
|
||||
You can get the official Python installer from the official Python site:
|
||||
<https://www.python.org/downloads/windows/>
|
||||
|
||||
Ensure you have Python3 correctly installed and can run the command `pip`.
|
||||
|
||||
Ensure that Python 3 is on the path ahead of Python 2 (if installed).
|
||||
|
||||
* Install meson:
|
||||
|
||||
```bash
|
||||
python -m pip install meson
|
||||
```
|
||||
|
||||
* Install [ninja](https://ninja-build.org/) 1.10+:
|
||||
|
||||
```bash
|
||||
choco install ninja
|
||||
```
|
||||
|
||||
* Install Rust:
|
||||
|
||||
After downloading and running the executable from:
|
||||
<https://www.rust-lang.org/tools/install>
|
||||
|
||||
Run the command:
|
||||
|
||||
```bash
|
||||
rustup target add i686-pc-windows-msvc
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
* Install wasm-pack:
|
||||
<https://github.com/rustwasm/wasm-pack/releases/download/v0.9.1/wasm-pack-init.exe>
|
||||
|
||||
* Install Emscripten:
|
||||
<https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install>
|
||||
|
||||
* Add emcc to PATH (probably upstream\enscripten)
|
||||
|
||||
#### Windows environment
|
||||
|
||||
On Windows you may need to set `SDKVER` environment variable to the current
|
||||
Windows SDK version, if it cannot be automatically detected.
|
||||
|
||||
```bash
|
||||
export SDKVER=10.0.19041.0
|
||||
```
|
||||
|
||||
#### kmcomp
|
||||
|
||||
Note on paths for kmcomp:
|
||||
|
||||
The search path can be edited through System settings / Advanced system settings
|
||||
/ Environment Variables / User environment variables.
|
||||
|
||||
If you have Keyman Developer installed, kmcomp should be on the path already;
|
||||
otherwise add `%KeymanDeveloperPath%` to your path.
|
||||
|
||||
If you do not have Keyman Developer installed, add the path where you extracted
|
||||
the kmcomp archive.
|
||||
|
||||
### Linux
|
||||
|
||||
#### Ubuntu and Debian
|
||||
|
||||
* Install Python
|
||||
|
||||
```bash
|
||||
sudo apt install python3
|
||||
```
|
||||
|
||||
* Upgrade Meson from version included with Python (WASM builds):
|
||||
|
||||
```bash
|
||||
sudo apt install meson
|
||||
```
|
||||
|
||||
* Install Rust:
|
||||
|
||||
```bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
* Install wasm-pack (WASM builds):
|
||||
|
||||
```bash
|
||||
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
```
|
||||
|
||||
* Install Enscripten (including adding to path with `emsdk_env.sh`) (WASM builds):
|
||||
<https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install>
|
||||
|
||||
You may also need the `kmcomp` wrapper - see below.
|
||||
|
||||
#### Other Linux distributions
|
||||
|
||||
* Install Python 3 and pip
|
||||
|
||||
You will be able to install a python3 package in any reputable recent version of
|
||||
linux using its package manager if it's not already installed. Ensure that `pip`
|
||||
is also installed.
|
||||
|
||||
* Install meson:
|
||||
|
||||
```bash
|
||||
python3 -m pip install meson
|
||||
```
|
||||
|
||||
* Install Rust from <https://www.rust-lang.org/tools/install>, then:
|
||||
|
||||
```bash
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
* Install wasm-pack (WASM builds):
|
||||
|
||||
```bash
|
||||
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
```
|
||||
|
||||
* Install Enscripten (WASM builds):
|
||||
<https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install>
|
||||
|
||||
* Add emcc to PATH (probably upstream/enscripten)
|
||||
|
||||
You may also need the `kmcomp` wrapper - see below.
|
||||
|
||||
#### kmcomp - All Linux platforms
|
||||
|
||||
If you want to rebuild keyboards for tests, you need a wrapper `kmcomp` shell
|
||||
script:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
wine `dirname "$0"`/kmcomp.exe "$@"
|
||||
```
|
||||
|
||||
Place this in the same folder as you extracted kmcomp.exe, and
|
||||
`chmod +x kmcomp`. Add the folder to the path (e.g.
|
||||
`export PATH=/path/to/kmcomp:$PATH`, which you can add to `.bashrc`).
|
||||
|
||||
### macOS
|
||||
|
||||
* Install Python 3
|
||||
|
||||
You can get the official Python installer from the official Python site:
|
||||
<https://www.python.org/downloads/mac-osx/>
|
||||
|
||||
* Install meson:
|
||||
|
||||
```bash
|
||||
brew install meson # if you haven't already installed via pip
|
||||
```
|
||||
|
||||
* Install Rust:
|
||||
|
||||
```bash
|
||||
curl https://sh.rustup.rs -sSf | sh
|
||||
rustup target add wasm32-unknown-unknown
|
||||
```
|
||||
|
||||
* Install wasm-pack:
|
||||
|
||||
```bash
|
||||
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
```
|
||||
|
||||
* Install Enscripten (including environment update):
|
||||
<https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install>
|
||||
|
||||
#### kmcomp
|
||||
|
||||
If you want to rebuild keyboards for tests, you'll also need WINE:
|
||||
|
||||
```bash
|
||||
brew tap homebrew/cask-versions
|
||||
brew install --cask --no-quarantine wine-stable
|
||||
```
|
||||
|
||||
And you will also need a wrapper `kmcomp` shell script:
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
wine64 `dirname "$0"`/kmcomp.exe "$@"
|
||||
```
|
||||
|
||||
Place this in the same folder as you extracted kmcomp.exe, and
|
||||
`chmod +x kmcomp`. Add the folder to the path (e.g.
|
||||
`export PATH=/path/to/kmcomp:$PATH`, which you can add to `.bashrc`).
|
||||
|
||||
## Building -- all platforms
|
||||
|
||||
On all platforms, use `build.sh`.
|
||||
|
||||
* To build native libraries and tests:
|
||||
|
||||
```bash
|
||||
./build.sh --debug
|
||||
```
|
||||
|
||||
* To build WASM libraries and tests:
|
||||
|
||||
```bash
|
||||
./build.sh --platform wasm
|
||||
```
|
||||
21
docs/build/old/ios-notes.md
vendored
Normal file
21
docs/build/old/ios-notes.md
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Keyman for iOS configuration notes
|
||||
|
||||
WARNING: these are old configuration notes. See [macos.md](../macos.md) for current steps.
|
||||
|
||||
## Prerequisites
|
||||
* Xcode 11
|
||||
* iOS 9+
|
||||
* SwiftLint (`brew install swiftlint`)
|
||||
* Carthage 0.37+ (`brew install carthage`)
|
||||
* Pandoc (`brew install pandoc`)
|
||||
- Used solely to generate offline help.
|
||||
* Coreutils (`brew install coreutils`)
|
||||
* sentry-cli (`brew install getsentry/tools/sentry-cli`) to utilize Sentry-based error reporting
|
||||
* jq (`brew install jq`)
|
||||
* `bash` (`brew install bash`)
|
||||
* Building Keyman Web is a precursor for compiling KMEI, so verify your system has all the [Minimum Web Compilation Requirements](../web/README.md#minimum-web-compilation-requirements), including (but not limited to):
|
||||
- [Node.js](https://nodejs.org/) 8.9+ (for building the embedded KeymanWeb engine)
|
||||
- [Java 7+](https://adoptopenjdk.net/releases.html)
|
||||
|
||||
Note that the `brew` command mentioned above is Homebrew, which may be found at https://brew.sh/.
|
||||
While not strictly necessary, it certainly simplifies installing the prerequisites above.
|
||||
17
docs/build/old/macos-notes.md
vendored
Normal file
17
docs/build/old/macos-notes.md
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Keyman for macOS configuration notes
|
||||
|
||||
WARNING: these are old configuration notes. See [macos.md](../macos.md) for current steps.
|
||||
|
||||
## Mac Tools Requirements/Setup
|
||||
|
||||
* Install [Homebrew] *technically optional, but highly recommended*
|
||||
* Install Xcode 12.0+
|
||||
* Accept the Xcode license `sudo xcodebuild -license accept`
|
||||
* Install [Carthage] (`brew install carthage`) *see Homebrew note below*
|
||||
* Install [cocoapods] (`brew install cocoapods`)
|
||||
* Install [coreutils] (`brew install coreutils`)
|
||||
|
||||
[Homebrew]: https://brew.sh/
|
||||
[Carthage]: https://github.com/Carthage/Carthage/blob/master/README.md
|
||||
[cocoapods]: https://cocoapods.org/
|
||||
[coreutils]: https://www.gnu.org/software/coreutils/
|
||||
18
docs/build/old/web-notes.md
vendored
Normal file
18
docs/build/old/web-notes.md
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# KeymanWeb configuration notes
|
||||
|
||||
WARNING: these are old configuration notes. See [index.md](../index.md) for current steps.
|
||||
|
||||
## Minimum Web Compilation Requirements
|
||||
|
||||
* [Java 7+](https://adoptopenjdk.net/releases.html) (required by the Google Closure Compiler)
|
||||
* This can be ignored for Keyman Developer builds.
|
||||
* A local installation of [Node.js](https://nodejs.org/) v8.9+.
|
||||
* Builds will call `npm install` to automatically install further necessary build dependencies.
|
||||
|
||||
* Linux users can run the following to update to LTS version of nodejs
|
||||
|
||||
```
|
||||
sudo apt-get install python-software-properties
|
||||
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
|
||||
sudo apt-get install nodejs
|
||||
```
|
||||
15
docs/build/sentry-cli.md
vendored
Normal file
15
docs/build/sentry-cli.md
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Setting up sentry-cli
|
||||
|
||||
Contact the Keyman team if you need access to sentry.keyman.com for development.
|
||||
You will also need to install [sentry-cli](https://docs.sentry.io/cli/installation/) for uploading Debug symbols.
|
||||
After setting up your personal [Auth token](http://sentry.keyman.com/settings/account/api/auth-tokens/), add the following to **~/.bashrc**
|
||||
|
||||
```bash
|
||||
export SENTRY_AUTH_TOKEN={your Sentry auth token}
|
||||
export SENTRY_URL=https://sentry.keyman.com
|
||||
export SENTRY_ORG=keyman
|
||||
# select the appropriate project here:
|
||||
export SENTRY_PROJECT=keyman-android
|
||||
```
|
||||
|
||||
To validate your configuration, for example for keyman-android, from the `android/` folder run `sentry-cli info`.
|
||||
3
docs/build/windows.md
vendored
Normal file
3
docs/build/windows.md
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Setup your Keyman build environment on Windows
|
||||
|
||||
TODO
|
||||
|
|
@ -1,25 +1,9 @@
|
|||
# Keyman for iOS
|
||||
|
||||
## Prerequisites
|
||||
* Xcode 11
|
||||
* iOS 9+
|
||||
* SwiftLint (`brew install swiftlint`)
|
||||
* Carthage 0.37+ (`brew install carthage`)
|
||||
* Pandoc (`brew install pandoc`)
|
||||
- Used solely to generate offline help.
|
||||
* Coreutils (`brew install coreutils`)
|
||||
* sentry-cli (`brew install getsentry/tools/sentry-cli`) to utilize Sentry-based error reporting
|
||||
* jq (`brew install jq`)
|
||||
* `bash` (`brew install bash`)
|
||||
* Building Keyman Web is a precursor for compiling KMEI, so verify your system has all the [Minimum Web Compilation Requirements](../web/README.md#minimum-web-compilation-requirements), including (but not limited to):
|
||||
- [Node.js](https://nodejs.org/) 8.9+ (for building the embedded KeymanWeb engine)
|
||||
- [Java 7+](https://adoptopenjdk.net/releases.html)
|
||||
|
||||
Note that the `brew` command mentioned above is Homebrew, which may be found at https://brew.sh/.
|
||||
While not strictly necessary, it certainly simplifies installing the prerequisites above.
|
||||
See [build configuration](../docs/build/index.md) for details on how to configure your build environment.
|
||||
|
||||
## Keyman App
|
||||
|
||||
The source for our published iOS Keyman app is found within the **keyman/** subdirectory. This project only contains
|
||||
the views specific to the Keyman app, while the core functionality is found in KeymanEngine.framework.
|
||||
|
||||
|
|
@ -94,11 +78,3 @@ The KeymanEngine project contains a demo app that demonstrates usage of the fram
|
|||
create a system keyboard.
|
||||
|
||||
To build the samples, `cd` into the project directory and run `./build.sh`.
|
||||
|
||||
### Compiling the app's offline help
|
||||
Extra prerequisite:
|
||||
* `wget` (`brew install wget`)
|
||||
|
||||
The script `build-help.sh` uses the `wget` tool to construct an offline bundle from the current
|
||||
online version of help on help.keyman.com. When significant changes to help content have been
|
||||
made, it is advisable to manually re-run this script to update the app's offline content.
|
||||
|
|
@ -20,5 +20,5 @@
|
|||
"ts-node",
|
||||
"typescript"
|
||||
],
|
||||
"version": "15.0.74"
|
||||
"version": "15.0.79"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ DEBIAN_SUITES=($UNSTABLE_CODENAME $TESTING_CODENAME $STABLE_CODENAME $STABLE_BAC
|
|||
"experimental" "unstable" "testing" "stable")
|
||||
|
||||
# List of Ubuntu suites. Update these when needed.
|
||||
UBUNTU_SUITES=("hirsute" "groovy" "focal" "bionic")
|
||||
UBUNTU_SUITES=("impish" "hirsute" "groovy" "focal" "bionic")
|
||||
|
||||
# Mirrors to use. Update these to your preferred mirror.
|
||||
DEBIAN_MIRROR="deb.debian.org"
|
||||
|
|
|
|||
2
linux/Jenkinsfile
vendored
2
linux/Jenkinsfile
vendored
|
|
@ -5,6 +5,6 @@
|
|||
@Library('lsdev-pipeline-library') _
|
||||
|
||||
keymanPackaging {
|
||||
distributionsToPackage = 'bionic focal groovy hirsute'
|
||||
distributionsToPackage = 'bionic focal groovy hirsute impish'
|
||||
arches = 'amd64 i386'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,4 +5,5 @@ title: Version History
|
|||
A frequent updated changelog for Keyman is kept at [help.keyman.com/version-history](https://help.keyman.com/version-history) on the Keyman Help website.
|
||||
|
||||
## Related Topics
|
||||
|
||||
* [What's New](whatsnew)
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ title: About Keyman
|
|||
|
||||
* [Welcome to Keyman](welcome)
|
||||
* [What's New](whatsnew)
|
||||
* [Version History](history)
|
||||
* [Version History](history)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ title: Welcome to Keyman
|
|||
Thank you for installing Keyman for Linux. Whether you're a new or returning user, we believe you will appreciate the significant enhancements in this latest version of Keyman for Linux.
|
||||
|
||||
## What is Keyman for Linux?
|
||||
|
||||
Keyman for Linux makes it possible to type in over 1,000 languages in any Linux application.
|
||||
|
||||
Keyman for Linux also supports KMFL keyboards, so your existing KMFL keyboards will continue to work.
|
||||
|
||||
[Click here](../start/) to get started.
|
||||
[Click here](../start/) to get started.
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ Here are some of the new features we have added to Keyman for Linux 14.0:
|
|||
* Improved user interface
|
||||
* Improved support for KDE, Gnome, Arch Linux
|
||||
|
||||
[ Watch a video](https://youtu.be/4W9Z9_IFUII)
|
||||
[](https://youtu.be/4W9Z9_IFUII)
|
||||
that highlights some of these new features.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ title: Common Questions
|
|||
---
|
||||
|
||||
## Q. How do I install Keyman for Linux?
|
||||
|
||||
**A.** In Ubuntu and Wasta-Linux, Keyman for Linux can be installed via launchpad:
|
||||
|
||||
```bash
|
||||
sudo add-apt-repository ppa:keymanapp/keyman
|
||||
sudo apt-get update
|
||||
|
|
@ -11,22 +13,25 @@ sudo apt-get upgrade
|
|||
sudo apt-get install keyman onboard-keyman
|
||||
```
|
||||
|
||||
An older version of Keyman for Linux packages is also available in any current Debian at:
|
||||
An older version of Keyman for Linux packages is also available in any current Debian at:
|
||||
[https://packages.debian.org/keyman](https://packages.debian.org/keyman)
|
||||
|
||||
|
||||
## Q. How do I install a Keyman keyboard?
|
||||
|
||||
**A.** Follow this [guide](../start/installing-keyboard) for installing Keyman keyboards.
|
||||
|
||||
## Q. What's the relationship between Keyman for Linux and KMFL?
|
||||
|
||||
**A.** Keyman for Linux and KMFL are released together in the Keyman
|
||||
[PPA](https://en.wikipedia.org/wiki/Ubuntu#Package_Archives), but are separate. The installation
|
||||
instructions above will install Keyman, not KMFL. KMFL was developed as a black-box clone of Keyman
|
||||
for Windows years ago; after Keyman was released as open source it became possible to share the
|
||||
for Windows years ago; after Keyman was released as open source it became possible to share the
|
||||
code base between Windows and Linux. Keyman for Linux is the long-term supported solution.
|
||||
|
||||
## Q. Can I have Keyman for Linux and KMFL installed at the same time?
|
||||
|
||||
**A.** Yes. To install KMFL on Ubuntu:
|
||||
|
||||
```bash
|
||||
sudo add-apt-repository ppa:keymanapp/keyman
|
||||
sudo apt-get update
|
||||
|
|
@ -35,22 +40,27 @@ sudo apt-get install ibus-kmfl
|
|||
```
|
||||
|
||||
## Q. If I already had KMFL installed, how can I uninstall KMFL before installing Keyman?
|
||||
|
||||
**A.** It is good to remove any keyboards from ibus e.g. KMFL keyboards before you remove KMFL.
|
||||
Then, to remove KMFL:
|
||||
|
||||
```bash
|
||||
sudo dpkg --purge ibus-kmfl libkmfl
|
||||
```
|
||||
|
||||
## Q. How do I display the On-screen Keyboard (OSK)?
|
||||
|
||||
**A.** From the launcher, enter `onboard`
|
||||
|
||||

|
||||
|
||||
## Q. What Linux distros will Keyman work with?
|
||||
|
||||
**A.** Keyman runs on Debian, Ubuntu, Wasta Linux and can be compiled to run from source in most distributions.
|
||||
|
||||
**Note:** Keyman for Linux no longer supports Ubuntu 16.04 LTS (Xenial Xerus).
|
||||
|
||||
## Q. Will my existing Windows Keyman keyboard work with Keyman for Linux?
|
||||
|
||||
**A.** Most keyboards will work without change. A small subset of keyboards require features which
|
||||
are not yet available in Keyman for Linux. These features will be progressively implemented.
|
||||
|
|
|
|||
|
|
@ -1,20 +1,23 @@
|
|||
---
|
||||
title: Keyman for Linux 14.0 Help
|
||||
title: Keyman for Linux 15.0 Help
|
||||
---
|
||||
|
||||
Need help using Keyman for Linux? In time, this product documentation will grow and explain frequently asked questions.
|
||||
|
||||
## [About Keyman for Linux](about/)
|
||||
|
||||
* [Welcome to Keyman](about/welcome)
|
||||
* [What's New](about/whatsnew)
|
||||
* [Version History](about/history)
|
||||
|
||||
## [Getting Started](start/)
|
||||
|
||||
* [Installing a keyboard](start/installing-keyboard)
|
||||
|
||||
## [Common Questions](common/)
|
||||
|
||||
## Ask for Help
|
||||
|
||||
[Ask other users in the SIL Keyman Community](https://community.software.sil.org/c/keyman)
|
||||
|
||||
## Help Topics
|
||||
|
|
|
|||
25
linux/help/reference/index.md
Normal file
25
linux/help/reference/index.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
title: Keyman 15.0 for Linux Reference
|
||||
---
|
||||
|
||||
## Keyman 15.0 for Linux Overview
|
||||
|
||||
Keyman for Linux makes it possible for you to type in over 1,000 languages on Linux.
|
||||
|
||||
[km-config](km-config) \
|
||||
Keyman keyboards installation and information
|
||||
|
||||
[km-kvk2ldml](km-kvk2ldml) \
|
||||
Convert a Keyman on-screen keyboard file to LDML
|
||||
|
||||
[km-package-get](km-package-get) \
|
||||
Download a Keyman keyboard package
|
||||
|
||||
[km-package-install](km-package-install) \
|
||||
Install a Keyman keyboard package
|
||||
|
||||
[km-package-list-installed](km-package-list-installed) \
|
||||
List installed Keyman keyboard packages
|
||||
|
||||
[km-package-uninstall](km-package-uninstall) \
|
||||
Uninstall a Keyman keyboard package
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: Getting Started"
|
||||
title: Getting Started
|
||||
---
|
||||
|
||||
* [How To - Installing Keyboards with Keyman for Linux](installing-keyboard)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ Alternatively from the command line run `km-config`.
|
|||

|
||||
|
||||
## Download from Keyman cloud repository
|
||||
|
||||
From Keyman Configuration, click "Download". At the search page, enter the keyboard you want to download.
|
||||
|
||||

|
||||
|
|
@ -17,6 +18,7 @@ Clicking the keyboard brings the keyboard page which has a link for installation
|
|||

|
||||
|
||||
## Install Local .kmp keyboard package
|
||||
|
||||
Keyman for Linux can also install keyboards from local .kmp keyboard packages. From Keyman Configuration,
|
||||
click "Install". Then browse to the local .kmp keyboard package and install.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
keyman-config (14.0.276-2) experimental; urgency=medium
|
||||
|
||||
* Team upload
|
||||
* Add libglib2.0-bin to keyman Depends (closes: #990226)
|
||||
|
||||
-- Gunnar Hjalmarsson <gunnarhj@debian.org> Wed, 23 Jun 2021 15:28:27 +0200
|
||||
|
||||
keyman-config (14.0.276-1) experimental; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ Homepage: https://www.keyman.com
|
|||
Package: keyman
|
||||
Architecture: all
|
||||
Depends:
|
||||
libglib2.0-bin,
|
||||
python3-keyman-config,
|
||||
${misc:Depends},
|
||||
Recommends:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
km-config.bash-completion km-config
|
||||
km-kvk2ldml.bash-completion km-kvk2ldml
|
||||
km-package-get.bash-completion km-package-get
|
||||
km-package-install.bash-completion km-package-install
|
||||
|
|
|
|||
25
linux/keyman-config/keyman_config/deprecated_decorator.py
Normal file
25
linux/keyman-config/keyman_config/deprecated_decorator.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/python3
|
||||
# based on https://stackoverflow.com/a/40301488
|
||||
import logging
|
||||
|
||||
|
||||
string_types = (type(b''), type(u''))
|
||||
|
||||
|
||||
def deprecated(reason):
|
||||
if isinstance(reason, string_types):
|
||||
# The @deprecated is used with a 'reason'.
|
||||
def decorator(func1):
|
||||
def new_func1(*args, **kwargs):
|
||||
logging.warning("Call to deprecated function '{name}': {reason}.".format(
|
||||
name=func1.__name__, reason=reason))
|
||||
return func1(*args, **kwargs)
|
||||
return new_func1
|
||||
return decorator
|
||||
else:
|
||||
# The @deprecated is used without any 'reason'.
|
||||
def new_func2(*args, **kwargs):
|
||||
func2 = reason
|
||||
logging.warning("Call to deprecated function '{name}'.".format(name=func2.__name__))
|
||||
return func2(*args, **kwargs)
|
||||
return new_func2
|
||||
|
|
@ -6,7 +6,16 @@ import logging
|
|||
import requests
|
||||
import requests_cache
|
||||
import os
|
||||
from gi.repository import GObject
|
||||
from keyman_config import KeymanApiUrl, KeymanDownloadsUrl
|
||||
from keyman_config.deprecated_decorator import deprecated
|
||||
|
||||
|
||||
class InstallLocation(GObject.GEnum):
|
||||
OS = 1
|
||||
Shared = 2
|
||||
User = 3
|
||||
Unknown = 99
|
||||
|
||||
|
||||
def get_package_download_data(packageID, weekCache=False):
|
||||
|
|
@ -19,9 +28,9 @@ def get_package_download_data(packageID, weekCache=False):
|
|||
Returns:
|
||||
dict: Keyboard data
|
||||
"""
|
||||
logging.info("Getting download data for package %s", packageID)
|
||||
api_url = KeymanDownloadsUrl + "/api/keyboard/1.0/" + packageID
|
||||
logging.debug("At URL %s", api_url)
|
||||
logging.info('Getting download data for package %s', packageID)
|
||||
api_url = KeymanDownloadsUrl + '/api/keyboard/1.0/' + packageID
|
||||
logging.debug('At URL %s', api_url)
|
||||
cache_dir = keyman_cache_dir()
|
||||
current_dir = os.getcwd()
|
||||
if weekCache:
|
||||
|
|
@ -32,7 +41,7 @@ def get_package_download_data(packageID, weekCache=False):
|
|||
requests_cache.install_cache(cache_name='keyman_cache', backend='sqlite', expire_after=expire_after)
|
||||
now = time.ctime(int(time.time()))
|
||||
response = requests.get(api_url)
|
||||
logging.debug("Time: {0} / Used Cache: {1}".format(now, response.from_cache))
|
||||
logging.debug('Time: {0} / Used Cache: {1}'.format(now, response.from_cache))
|
||||
os.chdir(current_dir)
|
||||
requests_cache.core.uninstall_cache()
|
||||
if response.status_code == 200:
|
||||
|
|
@ -51,9 +60,9 @@ def get_keyboard_data(keyboardID, weekCache=False):
|
|||
Returns:
|
||||
dict: Keyboard data
|
||||
"""
|
||||
logging.info("Getting data for keyboard %s", keyboardID)
|
||||
api_url = KeymanApiUrl + "/keyboard/" + keyboardID
|
||||
logging.debug("At URL %s", api_url)
|
||||
logging.info('Getting data for keyboard %s', keyboardID)
|
||||
api_url = KeymanApiUrl + '/keyboard/' + keyboardID
|
||||
logging.debug('At URL %s', api_url)
|
||||
cache_dir = keyman_cache_dir()
|
||||
current_dir = os.getcwd()
|
||||
if weekCache:
|
||||
|
|
@ -64,7 +73,7 @@ def get_keyboard_data(keyboardID, weekCache=False):
|
|||
requests_cache.install_cache(cache_name='keyman_cache', backend='sqlite', expire_after=expire_after)
|
||||
now = time.ctime(int(time.time()))
|
||||
response = requests.get(api_url)
|
||||
logging.debug("Time: {0} / Used Cache: {1}".format(now, response.from_cache))
|
||||
logging.debug('Time: {0} / Used Cache: {1}'.format(now, response.from_cache))
|
||||
os.chdir(current_dir)
|
||||
requests_cache.core.uninstall_cache()
|
||||
if response.status_code == 200:
|
||||
|
|
@ -91,28 +100,54 @@ def keyman_cache_dir():
|
|||
Returns:
|
||||
str: path of user keyman cache folder
|
||||
"""
|
||||
home = os.path.expanduser("~")
|
||||
cachebase = os.environ.get("XDG_CACHE_HOME", os.path.join(home, ".cache"))
|
||||
km_cache = os.path.join(cachebase, "keyman")
|
||||
home = os.path.expanduser('~')
|
||||
cachebase = os.environ.get('XDG_CACHE_HOME', os.path.join(home, '.cache'))
|
||||
km_cache = os.path.join(cachebase, 'keyman')
|
||||
if not os.path.isdir(km_cache):
|
||||
os.mkdir(km_cache)
|
||||
return km_cache
|
||||
|
||||
|
||||
def _get_data_base_dir(area):
|
||||
if area == InstallLocation.User:
|
||||
return os.environ.get('XDG_DATA_HOME',
|
||||
os.path.join(os.path.expanduser('~'), '.local', 'share'))
|
||||
if area == InstallLocation.Shared:
|
||||
return '/usr/local/share'
|
||||
return '/usr/share'
|
||||
|
||||
|
||||
@deprecated('Use get_keyman_dir(InstallLocation.User) instead')
|
||||
def user_keyman_dir():
|
||||
home = os.path.expanduser("~")
|
||||
datahome = os.environ.get("XDG_DATA_HOME", os.path.join(home, ".local", "share"))
|
||||
return os.path.join(datahome, "keyman")
|
||||
return get_keyman_dir(InstallLocation.User)
|
||||
|
||||
|
||||
def get_keyman_dir(area):
|
||||
return os.path.join(_get_data_base_dir(area), 'keyman')
|
||||
|
||||
|
||||
@deprecated('Use get_keyman_font_dir(InstallLocation.User) instead')
|
||||
def user_keyman_font_dir():
|
||||
home = os.path.expanduser("~")
|
||||
datahome = os.environ.get("XDG_DATA_HOME", os.path.join(home, ".local", "share"))
|
||||
return os.path.join(datahome, "fonts", "keyman")
|
||||
return os.path.join(_get_data_base_dir(InstallLocation.User), 'fonts', 'keyman')
|
||||
|
||||
|
||||
def get_keyman_font_dir(area, keyboardid):
|
||||
return os.path.join(_get_data_base_dir(area), 'fonts', 'keyman', keyboardid)
|
||||
|
||||
|
||||
@deprecated('Use get_keyboard_dir(InstallLocation.User, keyboardid) instead')
|
||||
def user_keyboard_dir(keyboardid):
|
||||
return os.path.join(user_keyman_dir(), keyboardid)
|
||||
return get_keyboard_dir(InstallLocation.User, keyboardid)
|
||||
|
||||
|
||||
def get_keyboard_dir(area, keyboardid):
|
||||
return os.path.join(_get_data_base_dir(area), 'keyman', keyboardid)
|
||||
|
||||
|
||||
def get_keyman_doc_dir(area, keyboardid):
|
||||
if area == InstallLocation.User:
|
||||
return get_keyboard_dir(area, keyboardid)
|
||||
return os.path.join(_get_data_base_dir(area), 'doc', 'keyman')
|
||||
|
||||
|
||||
def get_kmp_file(downloaddata, cache=False):
|
||||
|
|
@ -126,7 +161,7 @@ def get_kmp_file(downloaddata, cache=False):
|
|||
str: path where kmp file has been downloaded
|
||||
"""
|
||||
if 'kmp' not in downloaddata:
|
||||
logging.info("get_kmp.py: Package does not have a kmp file available")
|
||||
logging.info('get_kmp.py: Package does not have a kmp file available')
|
||||
return None
|
||||
|
||||
downloadfile = os.path.join(get_download_folder(), os.path.basename(downloaddata['kmp']))
|
||||
|
|
@ -146,7 +181,7 @@ def download_kmp_file(url, kmpfile, cache=False):
|
|||
Returns:
|
||||
str: path where kmp file has been downloaded
|
||||
"""
|
||||
logging.info("Download URL: %s", url)
|
||||
logging.info('Download URL: %s', url)
|
||||
downloadfile = None
|
||||
|
||||
if cache:
|
||||
|
|
@ -162,11 +197,11 @@ def download_kmp_file(url, kmpfile, cache=False):
|
|||
try:
|
||||
response = requests.get(url) # , stream=True)
|
||||
except requests.exceptions.ConnectionError:
|
||||
logging.error("Connection error downloading %s", url)
|
||||
logging.error('Connection error downloading %s', url)
|
||||
return downloadfile
|
||||
|
||||
if cache:
|
||||
logging.debug("Time: {0} / Used Cache: {1}".format(now, response.from_cache))
|
||||
logging.debug('Time: {0} / Used Cache: {1}'.format(now, response.from_cache))
|
||||
os.chdir(current_dir)
|
||||
requests_cache.core.uninstall_cache()
|
||||
|
||||
|
|
@ -190,6 +225,6 @@ def get_kmp(packageID):
|
|||
if (downloaddata):
|
||||
return get_kmp_file(downloaddata)
|
||||
else:
|
||||
logging.warning("get_kmp.py: Could not get download information about keyboard package.")
|
||||
logging.warning('get_kmp.py: Could not get download information about keyboard package.')
|
||||
return None
|
||||
return
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import os
|
||||
import time
|
||||
import gi
|
||||
import logging
|
||||
|
|
@ -68,15 +69,21 @@ def restart_ibus_subp():
|
|||
|
||||
|
||||
def restart_ibus(bus=None):
|
||||
try:
|
||||
if not bus:
|
||||
bus = get_ibus_bus()
|
||||
logging.info("restarting IBus")
|
||||
bus.exit(True)
|
||||
bus.destroy()
|
||||
except Exception as e:
|
||||
logging.warning("Failed to restart IBus")
|
||||
logging.warning(e)
|
||||
realuser = os.environ.get('SUDO_USER')
|
||||
if realuser:
|
||||
# we have been called with `sudo`. Restart ibus for the real user.
|
||||
logging.info('restarting IBus by subprocess for user %s', realuser)
|
||||
subprocess.run(['sudo', '-u', realuser, 'ibus', 'restart'])
|
||||
else:
|
||||
try:
|
||||
if not bus:
|
||||
bus = get_ibus_bus()
|
||||
logging.info("restarting IBus")
|
||||
bus.exit(True)
|
||||
bus.destroy()
|
||||
except Exception as e:
|
||||
logging.warning("Failed to restart IBus")
|
||||
logging.warning(e)
|
||||
|
||||
|
||||
def bus_has_engine(bus, name):
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ from enum import Enum
|
|||
from keyman_config import _
|
||||
from keyman_config.canonical_language_code_utils import CanonicalLanguageCodeUtils
|
||||
from keyman_config.fcitx_util import is_fcitx_running, restart_fcitx
|
||||
from keyman_config.get_kmp import get_keyboard_data, user_keyboard_dir, user_keyman_font_dir
|
||||
from keyman_config.get_kmp import get_keyboard_data, get_keyboard_dir, get_keyman_doc_dir
|
||||
from keyman_config.get_kmp import get_keyman_font_dir, InstallLocation
|
||||
from keyman_config.kmpmetadata import get_metadata, KMFileTypes
|
||||
from keyman_config.convertico import extractico, checkandsaveico
|
||||
from keyman_config.kvk2ldml import convert_kvk_to_ldml, output_ldml
|
||||
|
|
@ -51,7 +52,7 @@ class InstallKmp():
|
|||
self.kmpdocdir = ''
|
||||
self.kmpfontdir = ''
|
||||
|
||||
def _check_keyman_dir(basedir, error_message):
|
||||
def _check_keyman_dir(self, basedir, error_message):
|
||||
# check if keyman subdir exists
|
||||
keyman_dir = os.path.join(basedir, "keyman")
|
||||
if os.path.isdir(keyman_dir):
|
||||
|
|
@ -89,17 +90,17 @@ class InstallKmp():
|
|||
_("You do not have permissions to install the font files to the shared font area "
|
||||
"/usr/local/share/fonts"))
|
||||
|
||||
return self._install_kmp(inputfile, online, language)
|
||||
return self._install_kmp(inputfile, online, language, InstallLocation.Shared)
|
||||
|
||||
def install_kmp_user(self, inputfile, online=False, language=None):
|
||||
return self._install_kmp(inputfile, online, language, InstallLocation.User)
|
||||
|
||||
def _install_kmp(self, inputfile, online, language, area):
|
||||
self.packageID = self._extract_package_id(inputfile)
|
||||
self.packageDir = user_keyboard_dir(self.packageID)
|
||||
self.kmpdocdir = self.packageDir
|
||||
self.kmpfontdir = os.path.join(user_keyman_font_dir(), self.packageID)
|
||||
self.packageDir = get_keyboard_dir(area, self.packageID)
|
||||
self.kmpdocdir = get_keyman_doc_dir(area, self.packageID)
|
||||
self.kmpfontdir = get_keyman_font_dir(area, self.packageID)
|
||||
|
||||
return self._install_kmp(inputfile, online, language)
|
||||
|
||||
def _install_kmp(self, inputfile, online, language):
|
||||
if not os.path.isdir(self.packageDir):
|
||||
os.makedirs(self.packageDir)
|
||||
|
||||
|
|
@ -228,7 +229,9 @@ class InstallKmp():
|
|||
# install all kmx for first lang not just packageID
|
||||
for kb in keyboards:
|
||||
ibus_keyboard_id = get_ibus_keyboard_id(kb, packageDir, language)
|
||||
sources.append(('ibus', ibus_keyboard_id))
|
||||
input_source = ('ibus', ibus_keyboard_id)
|
||||
if input_source not in sources:
|
||||
sources.append(input_source)
|
||||
|
||||
gnomeKeyboardsUtil.write_input_sources(sources)
|
||||
return ''
|
||||
|
|
|
|||
|
|
@ -11,26 +11,26 @@ import webbrowser
|
|||
import tempfile
|
||||
import gi
|
||||
|
||||
from keyman_config.fcitx_util import is_fcitx_running
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('WebKit2', '4.0')
|
||||
|
||||
from gi.repository import Gtk, WebKit2
|
||||
from distutils.version import StrictVersion
|
||||
from keyman_config import _
|
||||
from keyman_config.fcitx_util import is_fcitx_running
|
||||
from keyman_config.install_kmp import install_kmp, extract_kmp, get_metadata, InstallError, InstallStatus
|
||||
from keyman_config.list_installed_kmp import get_kmp_version
|
||||
from keyman_config.kmpmetadata import get_fonts
|
||||
from keyman_config.welcome import WelcomeView
|
||||
from keyman_config.uninstall_kmp import uninstall_kmp
|
||||
from keyman_config.get_kmp import user_keyboard_dir
|
||||
from keyman_config.get_kmp import InstallLocation, get_keyboard_dir, get_keyman_dir
|
||||
from keyman_config.accelerators import bind_accelerator, init_accel
|
||||
|
||||
|
||||
def find_keyman_image(image_file):
|
||||
img_path = os.path.join("/usr/share/keyman/icons", image_file)
|
||||
img_path = os.path.join(get_keyman_dir(InstallLocation.OS), "icons", image_file)
|
||||
if not os.path.isfile(img_path):
|
||||
img_path = os.path.join("/usr/local/share/keyman/icons/", image_file)
|
||||
img_path = os.path.join(get_keyman_dir(InstallLocation.Shared), "icons", image_file)
|
||||
if not os.path.isfile(img_path):
|
||||
img_path = os.path.join("keyman_config/icons/", image_file)
|
||||
if not os.path.isfile(img_path):
|
||||
|
|
@ -302,7 +302,7 @@ class InstallKmpWindow(Gtk.Dialog):
|
|||
result = install_kmp(self.kmpfile, self.online, language=self.language)
|
||||
if result:
|
||||
# If install_kmp returns a string, it is an instruction for the end user,
|
||||
# because for fcitx they will need to take extra steps to complete
|
||||
# because for fcitx they will need to take extra steps to complete
|
||||
# installation themselves.
|
||||
dialog = Gtk.MessageDialog(
|
||||
self, 0, Gtk.MessageType.INFO,
|
||||
|
|
@ -315,7 +315,8 @@ class InstallKmpWindow(Gtk.Dialog):
|
|||
if self.viewwindow:
|
||||
self.viewwindow.refresh_installed_kmp()
|
||||
keyboardid = os.path.basename(os.path.splitext(self.kmpfile)[0])
|
||||
welcome_file = os.path.join(user_keyboard_dir(keyboardid), "welcome.htm")
|
||||
welcome_file = os.path.join(get_keyboard_dir(InstallLocation.User, keyboardid),
|
||||
"welcome.htm")
|
||||
if os.path.isfile(welcome_file):
|
||||
uri_path = pathlib.Path(welcome_file).as_uri()
|
||||
logging.debug(uri_path)
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
# Keyboard details window
|
||||
|
||||
import json
|
||||
import os.path
|
||||
from os import path
|
||||
import qrcode
|
||||
import tempfile
|
||||
|
||||
import gi
|
||||
from gi.repository import Gtk
|
||||
|
|
@ -40,8 +41,8 @@ class KeyboardDetailsView(Gtk.Dialog):
|
|||
|
||||
self.set_border_width(6)
|
||||
|
||||
packageDir = os.path.join(kmp['areapath'], kmp['packageID'])
|
||||
kmp_json = os.path.join(packageDir, "kmp.json")
|
||||
packageDir = path.join(kmp['areapath'], kmp['packageID'])
|
||||
kmp_json = path.join(packageDir, "kmp.json")
|
||||
info, system, options, keyboards, files = parsemetadata(kmp_json)
|
||||
|
||||
if info is None:
|
||||
|
|
@ -58,15 +59,15 @@ class KeyboardDetailsView(Gtk.Dialog):
|
|||
return
|
||||
|
||||
kbdata = None
|
||||
jsonfile = os.path.join(packageDir, kmp['packageID'] + ".json")
|
||||
if os.path.isfile(jsonfile):
|
||||
jsonfile = path.join(packageDir, kmp['packageID'] + ".json")
|
||||
if path.isfile(jsonfile):
|
||||
with open(jsonfile, "r") as read_file:
|
||||
kbdata = json.load(read_file)
|
||||
|
||||
grid = Gtk.Grid()
|
||||
# grid.set_column_homogeneous(True)
|
||||
|
||||
# kbdatapath = os.path.join("/usr/local/share/keyman", kmp["id"], kmp["id"] + ".json")
|
||||
# kbdatapath = path.join("/usr/local/share/keyman", kmp["id"], kmp["id"] + ".json")
|
||||
|
||||
# Package info
|
||||
|
||||
|
|
@ -162,8 +163,8 @@ class KeyboardDetailsView(Gtk.Dialog):
|
|||
if keyboards:
|
||||
for kbd in keyboards:
|
||||
kbdata = None
|
||||
jsonfile = os.path.join(packageDir, kbd['id'] + ".json")
|
||||
if os.path.isfile(jsonfile):
|
||||
jsonfile = path.join(packageDir, kbd['id'] + ".json")
|
||||
if path.isfile(jsonfile):
|
||||
with open(jsonfile, "r") as read_file:
|
||||
kbdata = json.load(read_file)
|
||||
|
||||
|
|
@ -182,7 +183,7 @@ class KeyboardDetailsView(Gtk.Dialog):
|
|||
grid.attach_next_to(lbl_kbd_file, prevlabel, Gtk.PositionType.BOTTOM, 1, 1)
|
||||
prevlabel = lbl_kbd_file
|
||||
label = Gtk.Label()
|
||||
label.set_text(os.path.join(packageDir, kbd['id'] + ".kmx"))
|
||||
label.set_text(path.join(packageDir, kbd['id'] + ".kmx"))
|
||||
label.set_halign(Gtk.Align.START)
|
||||
label.set_selectable(True)
|
||||
grid.attach_next_to(label, lbl_kbd_file, Gtk.PositionType.RIGHT, 1, 1)
|
||||
|
|
@ -291,8 +292,8 @@ class KeyboardDetailsView(Gtk.Dialog):
|
|||
# prevlabel = label8
|
||||
# #TODO need to know which area keyboard is installed in to show this
|
||||
# # label = Gtk.Label()
|
||||
# # welcome_file = os.path.join("/usr/local/share/doc/keyman", kmp["id"], "welcome.htm")
|
||||
# # if os.path.isfile(welcome_file):
|
||||
# # welcome_file = path.join("/usr/local/share/doc/keyman", kmp["id"], "welcome.htm")
|
||||
# # if path.isfile(welcome_file):
|
||||
# # label.set_text(_("Installed"))
|
||||
# # else:
|
||||
# # label.set_text(_("Not installed"))
|
||||
|
|
@ -323,9 +324,9 @@ class KeyboardDetailsView(Gtk.Dialog):
|
|||
prevlabel = lbl_pad
|
||||
|
||||
# If it doesn't exist, generate QR code to share keyboard package
|
||||
path_qr = packageDir + "/qrcode.png"
|
||||
path_qr = path.join(tempfile.gettempdir(), kmp['packageID'] + '_qrcode.png')
|
||||
url = KeymanComUrl + "/go/keyboard/" + kmp['packageID'] + "/share"
|
||||
if not os.path.isfile(path_qr):
|
||||
if not path.isfile(path_qr):
|
||||
qr = qrcode.QRCode(
|
||||
version=1,
|
||||
error_correction=qrcode.constants.ERROR_CORRECT_H,
|
||||
|
|
|
|||
|
|
@ -2,41 +2,14 @@
|
|||
|
||||
import os
|
||||
import json
|
||||
from gi.repository import GObject
|
||||
from keyman_config.kmpmetadata import parsemetadata, parseinfdata
|
||||
from keyman_config.get_kmp import user_keyman_dir
|
||||
|
||||
|
||||
class InstallArea(GObject.GEnum):
|
||||
IA_OS = 1
|
||||
IA_SHARED = 2
|
||||
IA_USER = 3
|
||||
IA_UNKNOWN = 99
|
||||
from keyman_config.get_kmp import get_keyman_dir, InstallLocation
|
||||
from keyman_config.deprecated_decorator import deprecated
|
||||
|
||||
|
||||
@deprecated('Use get_keyman_dir(area) instead')
|
||||
def get_install_area_path(area):
|
||||
"""
|
||||
Get the path of an install area.
|
||||
|
||||
Args:
|
||||
area (InstallArea): install area to check
|
||||
InstallArea.IA_USER: ~/.local/share/keyman
|
||||
InstallArea.IA_SHARED: /usr/local/share/keyman
|
||||
InstallArea.IA_OS: /usr/share/keyman
|
||||
InstallArea.IA_UNKNOWN: /usr/share/keyman
|
||||
|
||||
Returns:
|
||||
string: path of the install area
|
||||
"""
|
||||
check_path = "/usr/share/keyman"
|
||||
if area == InstallArea.IA_USER:
|
||||
check_path = user_keyman_dir()
|
||||
elif area == InstallArea.IA_SHARED:
|
||||
check_path = "/usr/local/share/keyman"
|
||||
elif area == InstallArea.IA_OS:
|
||||
check_path = "/usr/share/keyman"
|
||||
|
||||
return check_path
|
||||
return get_keyman_dir(area)
|
||||
|
||||
|
||||
def get_installed_kmp(area):
|
||||
|
|
@ -44,10 +17,10 @@ def get_installed_kmp(area):
|
|||
Get list of installed kmp in an install area.
|
||||
|
||||
Args:
|
||||
area (InstallArea): install area to check
|
||||
InstallArea.IA_USER: ~/.local/share/keyman
|
||||
InstallArea.IA_SHARED: /usr/local/share/keyman
|
||||
InstallArea.IA_OS: /usr/share/keyman
|
||||
area (InstallLocation): install area to check
|
||||
InstallLocation.User: ~/.local/share/keyman
|
||||
InstallLocation.Shared: /usr/local/share/keyman
|
||||
InstallLocation.OS: /usr/share/keyman
|
||||
Returns:
|
||||
list: Installed kmp
|
||||
dict: Keyboard
|
||||
|
|
@ -59,7 +32,7 @@ def get_installed_kmp(area):
|
|||
path (str): base path where keyboard is installed
|
||||
description (str): Keyboard description
|
||||
"""
|
||||
check_paths = [get_install_area_path(area)]
|
||||
check_paths = [get_keyman_dir(area)]
|
||||
|
||||
return get_installed_kmp_paths(check_paths)
|
||||
|
||||
|
|
@ -143,9 +116,9 @@ def get_kmp_version(packageID):
|
|||
None: if not found
|
||||
"""
|
||||
version = None
|
||||
user_kmp = get_installed_kmp(InstallArea.IA_USER)
|
||||
shared_kmp = get_installed_kmp(InstallArea.IA_SHARED)
|
||||
os_kmp = get_installed_kmp(InstallArea.IA_OS)
|
||||
user_kmp = get_installed_kmp(InstallLocation.User)
|
||||
shared_kmp = get_installed_kmp(InstallLocation.Shared)
|
||||
os_kmp = get_installed_kmp(InstallLocation.OS)
|
||||
|
||||
if packageID in os_kmp:
|
||||
version = os_kmp[packageID]['version']
|
||||
|
|
@ -180,7 +153,7 @@ def get_kmp_version_user(packageID):
|
|||
str: kmp version if kmp ID is installed
|
||||
None: if not found
|
||||
"""
|
||||
user_kmp = get_installed_kmp(InstallArea.IA_USER)
|
||||
user_kmp = get_installed_kmp(InstallLocation.User)
|
||||
if packageID in user_kmp:
|
||||
return user_kmp[packageID]['version']
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import logging
|
|||
import os.path
|
||||
from shutil import rmtree
|
||||
|
||||
from keyman_config.get_kmp import user_keyboard_dir, user_keyman_font_dir
|
||||
from keyman_config.fcitx_util import is_fcitx_running
|
||||
from keyman_config.get_kmp import InstallLocation, get_keyboard_dir, get_keyman_doc_dir, get_keyman_font_dir
|
||||
from keyman_config.kmpmetadata import get_metadata
|
||||
from keyman_config.ibus_util import uninstall_from_ibus, get_ibus_bus, restart_ibus
|
||||
from keyman_config.gnome_keyboards_util import GnomeKeyboardsUtil, get_ibus_keyboard_id, is_gnome_shell
|
||||
|
|
@ -17,13 +18,13 @@ def uninstall_kmp_shared(packageID):
|
|||
Args:
|
||||
packageID (str): Keyboard package ID
|
||||
"""
|
||||
kbdir = os.path.join('/usr/local/share/keyman', packageID)
|
||||
kbdir = get_keyboard_dir(InstallLocation.Shared, packageID)
|
||||
if not os.path.isdir(kbdir):
|
||||
logging.error("Keyboard directory for %s does not exist. Aborting", packageID)
|
||||
exit(3)
|
||||
|
||||
kbdocdir = os.path.join('/usr/local/share/doc/keyman', packageID)
|
||||
kbfontdir = os.path.join('/usr/local/share/fonts/keyman', packageID)
|
||||
kbdocdir = get_keyman_doc_dir(InstallLocation.Shared, packageID)
|
||||
kbfontdir = get_keyman_font_dir(InstallLocation.Shared, packageID)
|
||||
|
||||
logging.info("Uninstalling shared keyboard: %s", packageID)
|
||||
if not os.access(kbdir, os.X_OK | os.W_OK): # Check for write access of keyman dir
|
||||
|
|
@ -99,6 +100,10 @@ def uninstall_keyboards_from_gnome(keyboards, packageDir):
|
|||
gnomeKeyboardsUtil.write_input_sources(sources)
|
||||
|
||||
|
||||
def _uninstall_keyboards_from_fcitx5():
|
||||
return _('Please use fcitx5-configtool to remove the keyboard from the group')
|
||||
|
||||
|
||||
def uninstall_kmp_user(packageID):
|
||||
"""
|
||||
Uninstall a kmp from ~/.local/share/keyman
|
||||
|
|
@ -106,14 +111,16 @@ def uninstall_kmp_user(packageID):
|
|||
Args:
|
||||
packageID (str): Keyboard package ID
|
||||
"""
|
||||
kbdir = user_keyboard_dir(packageID)
|
||||
kbdir = get_keyboard_dir(InstallLocation.User, packageID)
|
||||
if not os.path.isdir(kbdir):
|
||||
logging.error("Keyboard directory for %s does not exist. Aborting", packageID)
|
||||
exit(3)
|
||||
logging.info("Uninstalling local keyboard: %s", packageID)
|
||||
info, system, options, keyboards, files = get_metadata(kbdir)
|
||||
if keyboards:
|
||||
if is_gnome_shell():
|
||||
if is_fcitx_running():
|
||||
_uninstall_keyboards_from_fcitx5()
|
||||
elif is_gnome_shell():
|
||||
uninstall_keyboards_from_gnome(keyboards, kbdir)
|
||||
else:
|
||||
uninstall_keyboards_from_ibus(keyboards, kbdir)
|
||||
|
|
@ -121,7 +128,7 @@ def uninstall_kmp_user(packageID):
|
|||
logging.warning("could not uninstall keyboards")
|
||||
rmtree(kbdir)
|
||||
logging.info("Removed user keyman directory: %s", kbdir)
|
||||
fontdir = os.path.join(user_keyman_font_dir(), packageID)
|
||||
fontdir = get_keyman_font_dir(InstallLocation.User, packageID)
|
||||
if os.path.isdir(fontdir):
|
||||
rmtree(fontdir)
|
||||
logging.info("Removed user keyman font directory: %s", fontdir)
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@ import subprocess
|
|||
import sys
|
||||
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
|
||||
from gi.repository import Gtk, GdkPixbuf
|
||||
|
||||
from keyman_config import _
|
||||
from keyman_config.list_installed_kmp import get_install_area_path, get_installed_kmp, InstallArea
|
||||
from keyman_config.list_installed_kmp import get_installed_kmp
|
||||
from keyman_config.welcome import WelcomeView
|
||||
from keyman_config.options import OptionsView
|
||||
from keyman_config.keyboard_details import KeyboardDetailsView
|
||||
|
|
@ -21,7 +22,7 @@ from keyman_config.downloadkeyboard import DownloadKmpWindow
|
|||
from keyman_config.install_window import InstallKmpWindow, find_keyman_image
|
||||
from keyman_config.uninstall_kmp import uninstall_kmp
|
||||
from keyman_config.accelerators import bind_accelerator, init_accel
|
||||
from keyman_config.get_kmp import user_keyboard_dir
|
||||
from keyman_config.get_kmp import InstallLocation, get_keyboard_dir, get_keyman_dir
|
||||
|
||||
|
||||
class ViewInstalledWindowBase(Gtk.Window):
|
||||
|
|
@ -122,7 +123,7 @@ class ViewInstalledWindow(ViewInstalledWindowBase):
|
|||
str, # name
|
||||
str, # version
|
||||
str, # packageID
|
||||
int, # enum InstallArea (KmpArea is GObject version)
|
||||
int, # enum InstallLocation (KmpArea is GObject version)
|
||||
str, # path to welcome file if it exists or None
|
||||
str) # path to options file if it exists or None
|
||||
|
||||
|
|
@ -219,12 +220,7 @@ class ViewInstalledWindow(ViewInstalledWindowBase):
|
|||
kmpdata = installed_kmp[kmp]
|
||||
bmppng = ".bmp.png" # Icon file extension
|
||||
|
||||
if install_area == InstallArea.IA_USER:
|
||||
path = user_keyboard_dir(kmpdata['packageID'])
|
||||
elif install_area == InstallArea.IA_SHARED:
|
||||
path = os.path.join("/usr/local/share/keyman", kmpdata['packageID'])
|
||||
else:
|
||||
path = os.path.join("/usr/share/keyman", kmpdata['packageID'])
|
||||
path = get_keyboard_dir(install_area, kmpdata['packageID'])
|
||||
|
||||
welcome_file = os.path.join(path, "welcome.htm")
|
||||
options_file = os.path.join(path, "options.htm")
|
||||
|
|
@ -252,24 +248,24 @@ class ViewInstalledWindow(ViewInstalledWindowBase):
|
|||
logging.debug("Refreshing listview")
|
||||
self.store.clear()
|
||||
self.incomplete_kmp = []
|
||||
user_kmp = get_installed_kmp(InstallArea.IA_USER)
|
||||
user_kmp = get_installed_kmp(InstallLocation.User)
|
||||
for kmp in sorted(user_kmp):
|
||||
kmpdata = user_kmp[kmp]
|
||||
if kmpdata["has_kbjson"] is False:
|
||||
self.incomplete_kmp.append(kmpdata)
|
||||
self.addlistitems(user_kmp, self.store, InstallArea.IA_USER)
|
||||
shared_kmp = get_installed_kmp(InstallArea.IA_SHARED)
|
||||
self.addlistitems(user_kmp, self.store, InstallLocation.User)
|
||||
shared_kmp = get_installed_kmp(InstallLocation.Shared)
|
||||
for kmp in sorted(shared_kmp):
|
||||
kmpdata = shared_kmp[kmp]
|
||||
if kmpdata["has_kbjson"] is False:
|
||||
self.incomplete_kmp.append(kmpdata)
|
||||
self.addlistitems(shared_kmp, self.store, InstallArea.IA_SHARED)
|
||||
os_kmp = get_installed_kmp(InstallArea.IA_OS)
|
||||
self.addlistitems(shared_kmp, self.store, InstallLocation.Shared)
|
||||
os_kmp = get_installed_kmp(InstallLocation.OS)
|
||||
for kmp in sorted(os_kmp):
|
||||
kmpdata = os_kmp[kmp]
|
||||
if kmpdata["has_kbjson"] is False:
|
||||
self.incomplete_kmp.append(kmpdata)
|
||||
self.addlistitems(os_kmp, self.store, InstallArea.IA_OS)
|
||||
self.addlistitems(os_kmp, self.store, InstallLocation.OS)
|
||||
|
||||
def on_tree_selection_changed(self, selection):
|
||||
model, treeiter = selection.get_selected()
|
||||
|
|
@ -284,7 +280,7 @@ class ViewInstalledWindow(ViewInstalledWindowBase):
|
|||
_("Settings for keyboard {package}").format(package=model[treeiter][1]))
|
||||
logging.debug("You selected %s version %s", model[treeiter][1], model[treeiter][2])
|
||||
self.about_button.set_sensitive(True)
|
||||
if model[treeiter][4] == InstallArea.IA_USER:
|
||||
if model[treeiter][4] == InstallLocation.User:
|
||||
logging.debug("Enabling uninstall button for %s in %s", model[treeiter][3], model[treeiter][4])
|
||||
self.uninstall_button.set_sensitive(True)
|
||||
else:
|
||||
|
|
@ -365,7 +361,7 @@ class ViewInstalledWindow(ViewInstalledWindowBase):
|
|||
model, treeiter = self.tree.get_selection().get_selected()
|
||||
if treeiter is not None and model[treeiter] is not None:
|
||||
logging.info("Show keyboard details of " + model[treeiter][1])
|
||||
areapath = get_install_area_path(model[treeiter][4])
|
||||
areapath = get_keyman_dir(model[treeiter][4])
|
||||
kmp = {
|
||||
"name": model[treeiter][1], "version": model[treeiter][2],
|
||||
"packageID": model[treeiter][3], "areapath": areapath
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ if __name__ == '__main__':
|
|||
parser.add_argument('--version', action='version', version='%(prog)s version ' + versionstring)
|
||||
parser.add_argument('-v', '--verbose', action='store_true', help='verbose logging')
|
||||
parser.add_argument('-vv', '--veryverbose', action='store_true', help='very verbose logging')
|
||||
parser.add_argument('-i', '--install', action='store', help='download and/or install .kmp package')
|
||||
parser.add_argument('-i', '--install', action='store', help='download and/or install .kmp ' +
|
||||
'package. INSTALL can either be a downloaded .kmp file, a file:// URL ' +
|
||||
'pointing to a .kmp file, or a keyman:// URL, possibly with a ' +
|
||||
'bcp47=<language> specified.')
|
||||
|
||||
args = parser.parse_args()
|
||||
if args.verbose:
|
||||
|
|
|
|||
36
linux/keyman-config/km-config.bash-completion
Normal file
36
linux/keyman-config/km-config.bash-completion
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#/usr/bin/env bash
|
||||
|
||||
_km-config_completions()
|
||||
{
|
||||
local cur prev opts
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
opts="-h --help -v --verbose -vv --veryverbose --version -i --install"
|
||||
|
||||
if [[ ${cur} == -* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
fi
|
||||
|
||||
# default IFS splits 'file://' into 'file', ':' and '//'
|
||||
if [ "${prev}" == ":" -a "${COMP_WORDS[COMP_CWORD-2]}" == "file" ]; then
|
||||
local flag=${COMP_WORDS[COMP_CWORD-3]}
|
||||
if [ $flag == "-i" -o $flag == "--install" ]; then
|
||||
prev=$flag
|
||||
fi
|
||||
fi
|
||||
|
||||
case "${prev}" in
|
||||
"-i"|"--install")
|
||||
local IFS=$'\n'
|
||||
compopt -o filenames
|
||||
COMPREPLY=( $(compgen -f -X "!"*.kmp -- $cur) $(compgen -d -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
complete -F _km-config_completions km-config
|
||||
|
|
@ -12,6 +12,21 @@ _km-kvk2ldml_completions()
|
|||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "${prev}" in
|
||||
"-o"|"--output")
|
||||
local IFS=$'\n'
|
||||
compopt -o filenames
|
||||
COMPREPLY=( $(compgen -f -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
local IFS=$'\n'
|
||||
compopt -o filenames
|
||||
COMPREPLY=( $(compgen -f -X "!"*.kvk -- $cur) $(compgen -d -- $cur) )
|
||||
}
|
||||
|
||||
complete -F _km-kvk2ldml_completions km-kvk2ldml
|
||||
|
|
|
|||
|
|
@ -2,31 +2,33 @@
|
|||
|
||||
_km-package-get_completions()
|
||||
{
|
||||
local cur prev opts
|
||||
local cur prev opts cache
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
opts="-h --help -v --verbose -vv --veryverbose --version"
|
||||
|
||||
cache=${XDG_CACHE_HOME:-~/.cache}/keyman/kmpdirlist
|
||||
|
||||
if [[ ${cur} == -* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
fi
|
||||
|
||||
words=""
|
||||
if [[ ! -e ~/.cache/keyman/kmpdirlist ]] ; then
|
||||
if [[ -e ./km-package-install ]]; then
|
||||
python3 -c "from imp import load_source;load_source('km_package_install', './km-package-install');from km_package_install import list_keyboards;list_keyboards()"
|
||||
else
|
||||
python3 -c "from imp import load_source;load_source('km_package_install', '/usr/bin/km-package-install');from km_package_install import list_keyboards;list_keyboards()"
|
||||
fi
|
||||
fi
|
||||
words=""
|
||||
if [[ ! -e $cache ]] ; then
|
||||
if [[ -e ./km-package-install ]]; then
|
||||
python3 -c "from imp import load_source;load_source('km_package_install', './km-package-install');from km_package_install import list_keyboards;list_keyboards()"
|
||||
else
|
||||
python3 -c "from imp import load_source;load_source('km_package_install', '/usr/bin/km-package-install');from km_package_install import list_keyboards;list_keyboards()"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -r ~/.cache/keyman/kmpdirlist ]] ; then
|
||||
for file in `cat ~/.cache/keyman/kmpdirlist`; do words="${words} ${file}"; done
|
||||
COMPREPLY=($(compgen -W "${words}" -- ${cur}))
|
||||
return 0
|
||||
fi
|
||||
if [[ -r $cache ]] ; then
|
||||
for file in `cat $cache`; do words="${words} ${file}"; done
|
||||
COMPREPLY=($(compgen -W "${words}" -- ${cur}))
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
complete -F _km-package-get_completions km-package-get
|
||||
|
|
|
|||
|
|
@ -2,21 +2,23 @@
|
|||
|
||||
_km-package-install_completions()
|
||||
{
|
||||
local cur prev opts
|
||||
local cur prev opts cache
|
||||
COMPREPLY=()
|
||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
opts="-h --help -v --verbose -vv --veryverbose --version -p --package -f --file -s --shared"
|
||||
|
||||
cache=${XDG_CACHE_HOME:-~/.cache}/keyman/kmpdirlist
|
||||
|
||||
if [[ ${cur} == -* ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
||||
return 0
|
||||
fi
|
||||
|
||||
case "${prev}" in
|
||||
"-k"|"--keyboardid")
|
||||
"-p"|"--package")
|
||||
words=""
|
||||
if [[ ! -s ~/.cache/keyman/kmpdirlist ]] ; then
|
||||
if [[ ! -s $cache ]] ; then
|
||||
if [[ -e ./km-package-install ]]; then
|
||||
python3 -c "from imp import load_source;load_source('km_package_install', './km-package-install');from km_package_install import list_keyboards;list_keyboards()"
|
||||
else
|
||||
|
|
@ -24,12 +26,18 @@ _km-package-install_completions()
|
|||
fi
|
||||
fi
|
||||
|
||||
if [[ -r ~/.cache/keyman/kmpdirlist ]] ; then
|
||||
for file in `cat ~/.cache/keyman/kmpdirlist`; do words="${words} ${file}"; done
|
||||
if [[ -r $cache ]] ; then
|
||||
for file in `cat $cache`; do words="${words} ${file}"; done
|
||||
COMPREPLY=($(compgen -W "${words}" -- ${cur}))
|
||||
return 0
|
||||
fi
|
||||
;;
|
||||
"-f"|"--file")
|
||||
local IFS=$'\n'
|
||||
compopt -o filenames
|
||||
COMPREPLY=( $(compgen -f -X "!"*.kmp -- $cur) $(compgen -d -- $cur) )
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -25,26 +25,27 @@ def main():
|
|||
logging.basicConfig(format='%(levelname)s:%(message)s')
|
||||
|
||||
all = not args.user and not args.shared and not args.os
|
||||
from keyman_config.list_installed_kmp import get_installed_kmp, get_install_area_path, InstallArea
|
||||
from keyman_config.list_installed_kmp import get_installed_kmp
|
||||
from keyman_config.get_kmp import get_keyman_dir, InstallLocation
|
||||
if args.user or all:
|
||||
installed_kmp = get_installed_kmp(InstallArea.IA_USER)
|
||||
installed_kmp = get_installed_kmp(InstallLocation.User)
|
||||
if args.verbose or args.veryverbose:
|
||||
print("--- Installed user Keyman keyboard packages (%s) ---" % (get_install_area_path(InstallArea.IA_USER)))
|
||||
print("--- Installed user Keyman keyboard packages (%s) ---" % (get_keyman_dir(InstallLocation.User)))
|
||||
else:
|
||||
print("--- Installed user Keyman keyboard packages ---")
|
||||
print_keyboards(installed_kmp, args.long)
|
||||
if args.shared or all:
|
||||
installed_kmp = get_installed_kmp(InstallArea.IA_SHARED)
|
||||
installed_kmp = get_installed_kmp(InstallLocation.Shared)
|
||||
if args.verbose or args.veryverbose:
|
||||
print("--- Installed shared Keyman keyboard packages (%s) ---" %
|
||||
(get_install_area_path(InstallArea.IA_SHARED)))
|
||||
(get_keyman_dir(InstallLocation.Shared)))
|
||||
else:
|
||||
print("--- Installed shared Keyman keyboard packages ---")
|
||||
print_keyboards(installed_kmp, args.long)
|
||||
if args.os or all:
|
||||
installed_kmp = get_installed_kmp(InstallArea.IA_OS)
|
||||
installed_kmp = get_installed_kmp(InstallLocation.OS)
|
||||
if args.verbose or args.veryverbose:
|
||||
print("--- Installed OS Keyman keyboard packages (%s) ---" % (get_install_area_path(InstallArea.IA_OS)))
|
||||
print("--- Installed OS Keyman keyboard packages (%s) ---" % (get_keyman_dir(InstallLocation.OS)))
|
||||
else:
|
||||
print("--- Installed OS Keyman keyboard packages ---")
|
||||
print_keyboards(installed_kmp, args.long)
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@ _km-package-uninstall_completions()
|
|||
shared=""
|
||||
case "${prev}" in
|
||||
"-s"|"--shared")
|
||||
for file in `ls -d /usr/local/share/keyman/*/`; do kbid="`basename ${file}`"; shared="${shared} ${kbid}"; done
|
||||
for file in $(ls -1 /usr/local/share/keyman); do kbid="`basename ${file}`"; shared="${shared} ${kbid}"; done
|
||||
COMPREPLY=($(compgen -W "${shared}" -- ${cur}))
|
||||
;;
|
||||
*)
|
||||
for file in `ls -d ~/.local/share/keyman/*/`; do kbid="`basename ${file}`"; words="${words} ${kbid}"; done
|
||||
for file in $(ls -1 ${XDG_DATA_HOME:-~/.local/share}/keyman); do kbid="`basename ${file}`"; words="${words} ${kbid}"; done
|
||||
COMPREPLY=($(compgen -W "${words}" -- ${cur}))
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# If needed set cowbuilder up for building Keyman Debian packages
|
||||
# Then cowbuilder update
|
||||
|
||||
distributions='hirsute groovy focal bionic'
|
||||
distributions='bionic focal groovy hirsute impish'
|
||||
|
||||
dpkgcheck=`dpkg-query -l cowbuilder`
|
||||
if [ $? != 0 ]; then
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ echo "ppa: ${ppa}"
|
|||
if [ "${DIST}" != "" ]; then
|
||||
distributions="${DIST}"
|
||||
else
|
||||
distributions="bionic focal groovy hirsute"
|
||||
distributions="bionic focal groovy hirsute impish"
|
||||
fi
|
||||
|
||||
if [ "${PACKAGEVERSION}" != "" ]; then
|
||||
|
|
|
|||
|
|
@ -1,13 +1,5 @@
|
|||
# Keyman for macOS
|
||||
|
||||
## Mac Tools Requirements/Setup
|
||||
|
||||
* Install [Homebrew] *technically optional, but highly recommended*
|
||||
* Install Xcode 12.0+
|
||||
* Accept the Xcode license `sudo xcodebuild -license accept`
|
||||
* Install [Carthage] (`brew install carthage`) *see Homebrew note below*
|
||||
* Install [cocoapods] (`brew install cocoapods`)
|
||||
* Install [coreutils] (`brew install coreutils`)
|
||||
|
||||
## Keyman for macOS Development
|
||||
|
||||
|
|
@ -120,9 +112,4 @@ Then run this command to fix the build environment:
|
|||
|
||||
`sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer`
|
||||
|
||||
|
||||
[Homebrew]: https://brew.sh/
|
||||
[Carthage]: https://github.com/Carthage/Carthage/blob/master/README.md
|
||||
[cocoapods]: https://cocoapods.org/
|
||||
[coreutils]: https://www.gnu.org/software/coreutils/
|
||||
[Install Keyman for macOS]: https://help.keyman.com/products/mac/current-version/start/install-keyman
|
||||
|
|
|
|||
19
resources/devbox/macos/keyman.macos.env.sh
Normal file
19
resources/devbox/macos/keyman.macos.env.sh
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
source $HOME/.cargo/env
|
||||
#echo 'export PATH="/usr/local/opt/openjdk@8/bin:$PATH"' >> ~/.zshrc
|
||||
#echo 'export PATH="/usr/local/opt/openjdk@8/bin:$PATH"' >> ~/.bashrc
|
||||
export ANT_HOME=/usr/local/opt/ant
|
||||
export MAVEN_HOME=/usr/local/opt/maven
|
||||
export GRADLE_HOME=/usr/local/opt/gradle
|
||||
export ANDROID_HOME=~/.android
|
||||
export ANDROID_SDK_ROOT="$HOME/Library/Android/sdk"
|
||||
|
||||
export PATH=$ANT_HOME/bin:$PATH
|
||||
export PATH=$MAVEN_HOME/bin:$PATH
|
||||
export PATH=$GRADLE_HOME/bin:$PATH
|
||||
export PATH=$ANDROID_HOME/tools:$PATH
|
||||
export PATH=$ANDROID_HOME/tools/bin:$PATH
|
||||
export PATH=$ANDROID_HOME/platform-tools:$PATH
|
||||
export PATH=$ANDROID_HOME/build-tools/30.0.3:$PATH
|
||||
export PATH="/usr/local/opt/openjdk@8/bin:$PATH"
|
||||
|
||||
export JAVA_HOME=/usr/local/opt/openjdk@8
|
||||
224
resources/devbox/macos/macos.sh
Executable file
224
resources/devbox/macos/macos.sh
Executable file
|
|
@ -0,0 +1,224 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
## Note: does not use standard build script include
|
||||
# adjust relative paths as necessary. Note that this will not work in a symlinked path reliably
|
||||
THIS_SCRIPT="${BASH_SOURCE[0]}"
|
||||
THIS_DIR=$(dirname "$THIS_SCRIPT")
|
||||
|
||||
# Determine which components to install
|
||||
REQUIRE_ANDROID=false
|
||||
REQUIRE_IOS=false
|
||||
REQUIRE_MACOS=false
|
||||
REQUIRE_WEB=false
|
||||
|
||||
# Optional components
|
||||
REQUIRE_KMCOMP=false
|
||||
REQUIRE_PANDOC=false
|
||||
REQUIRE_SENTRYCLI=false
|
||||
|
||||
# Parse args
|
||||
shopt -s nocasematch
|
||||
|
||||
PARAMFOUND=false
|
||||
|
||||
function print_help() {
|
||||
echo "Usage: macos.sh targets"
|
||||
echo
|
||||
echo "The targets parameter determines the platforms and components"
|
||||
echo "that this script will setup your environment to build."
|
||||
echo
|
||||
echo " group targets:"
|
||||
echo " all build all platform targets"
|
||||
echo " all-optional build all targets, including optional"
|
||||
echo
|
||||
echo " platform targets:"
|
||||
echo " android ios macos web"
|
||||
echo
|
||||
echo " optional targets:"
|
||||
echo " kmcomp Keyman keyboard compiler"
|
||||
echo " pandoc Documentation compiler"
|
||||
echo " sentry-cli sentry.keyman.com debug symbol uploader"
|
||||
echo
|
||||
echo "Note: If a target has dependencies, those will automatically"
|
||||
echo " be included."
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]] ; do
|
||||
key="$1"
|
||||
case $key in
|
||||
--help)
|
||||
print_help
|
||||
exit 0
|
||||
;;
|
||||
android)
|
||||
REQUIRE_ANDROID=true
|
||||
PARAMFOUND=true
|
||||
;;
|
||||
ios)
|
||||
REQUIRE_IOS=true
|
||||
PARAMFOUND=true
|
||||
;;
|
||||
macos)
|
||||
REQUIRE_MACOS=true
|
||||
PARAMFOUND=true
|
||||
;;
|
||||
web)
|
||||
REQUIRE_WEB=true
|
||||
PARAMFOUND=true
|
||||
;;
|
||||
kmcomp)
|
||||
REQUIRE_KMCOMP=true
|
||||
PARAMFOUND=true
|
||||
;;
|
||||
pandoc)
|
||||
REQUIRE_PANDOC=true
|
||||
PARAMFOUND=true
|
||||
;;
|
||||
sentry-cli)
|
||||
REQUIRE_SENTRYCLI=true
|
||||
PARAMFOUND=true
|
||||
;;
|
||||
all)
|
||||
REQUIRE_ANDROID=true
|
||||
REQUIRE_IOS=true
|
||||
REQUIRE_MACOS=true
|
||||
REQUIRE_WEB=true
|
||||
PARAMFOUND=true
|
||||
;;
|
||||
all-optional)
|
||||
REQUIRE_ANDROID=true
|
||||
REQUIRE_IOS=true
|
||||
REQUIRE_MACOS=true
|
||||
REQUIRE_WEB=true
|
||||
REQUIRE_KMCOMP=true
|
||||
REQUIRE_PANDOC=true
|
||||
REQUIRE_SENTRYCLI=true
|
||||
PARAMFOUND=true
|
||||
;;
|
||||
*)
|
||||
echo "Error: unrecognised parameter."
|
||||
echo
|
||||
print_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if ! $PARAMFOUND; then
|
||||
echo "Error: must specify target parameter"
|
||||
echo
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# This script will configure your development environment from a bare metal mac install. It should be idempotent.
|
||||
|
||||
echo "This script will configure your macOS computer to build Keyman, installing build tools and prerequisites."
|
||||
echo "You can also do this yourself following the notes in docs/build/macos.md."
|
||||
echo
|
||||
read -p "Press ENTER to start install"
|
||||
|
||||
if $REQUIRE_IOS || $REQUIRE_ANDROID; then
|
||||
REQUIRE_WEB=true
|
||||
fi
|
||||
|
||||
if $REQUIRE_IOS || $REQUIRE_MACOS || $REQUIRE_ANDROID; then
|
||||
REQUIRE_PANDOC=true
|
||||
fi
|
||||
|
||||
## These components are required by all development toolchains
|
||||
|
||||
# XCode command lines tools will be installed by Brew
|
||||
# xcode-select --install
|
||||
|
||||
which brew || (
|
||||
# Install Homebrew
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
) && (
|
||||
brew update
|
||||
)
|
||||
|
||||
## Install devchain components
|
||||
|
||||
BREW_ALL="bash jq python3 meson ninja rustup-init coreutils"
|
||||
BREW_WEB="node emscripten wasm-pack openjdk@8"
|
||||
BREW_IOS="swiftlint carthage"
|
||||
BREW_MACOS="carthage cocoapods"
|
||||
BREW_ANDROID="openjdk@8 android-sdk android-studio ant gradle maven"
|
||||
|
||||
brew install $BREW_ALL
|
||||
$REQUIRE_ANDROID && brew install $BREW_ANDROID
|
||||
$REQUIRE_IOS && brew install $BREW_IOS
|
||||
$REQUIRE_WEB && brew install $BREW_WEB
|
||||
$REQUIRE_MACOS && brew install $BREW_MACOS
|
||||
|
||||
$REQUIRE_PANDOC && brew install pandoc
|
||||
$REQUIRE_SENTRYCLI && brew install getsentry/tools/sentry-cli
|
||||
|
||||
# Install WINE
|
||||
$REQUIRE_KMCOMP && (
|
||||
brew tap homebrew/cask-versions
|
||||
brew install --cask --no-quarantine wine-stable
|
||||
)
|
||||
|
||||
$REQUIRE_WEB && (
|
||||
rustup-init -y -t wasm32-unknown-unknown
|
||||
)
|
||||
|
||||
source "$THIS_DIR/keyman.macos.env.sh"
|
||||
|
||||
$REQUIRE_ANDROID && (
|
||||
mkdir -p .android && touch ~/.android/repositories.cfg
|
||||
|
||||
which sdkmanager || (
|
||||
echo "Please run Android Studio to install the Android SDK tools."
|
||||
read -p "Press ENTER to continue after installation"
|
||||
PATH="$HOME/Library/Android/sdk/tools/bin:$PATH"
|
||||
)
|
||||
sdkmanager "system-images;android-30;google_apis_playstore;x86_64"
|
||||
sdkmanager --update
|
||||
sdkmanager --licenses
|
||||
)
|
||||
|
||||
# For now, we won't run this step automatically
|
||||
# as it may interfere with other dev environments
|
||||
#($REQUIRE_IOS || $REQUIRE_MACOS) && (
|
||||
# # Assumes that xcode is installed into normal path
|
||||
# # as otherwise we get only the command line tools which
|
||||
# # won't build with xcode
|
||||
# echo "Selecting default xcodebuild command line tools from /Applications/Xcode.app"
|
||||
# sudo xcode-select -s /Applications/Xcode.app
|
||||
#)
|
||||
|
||||
# Add keyman.macos.env.sh to ~/.bashrc
|
||||
|
||||
echo "Adding environment variables to ~/.bashrc..."
|
||||
if [ ! -f ~/.bashrc ] || `grep "keyman.macos.env.sh" ~/.bashrc 2>/dev/null`; then
|
||||
echo "source $THIS_DIR/keyman.macos.env.sh" >> ~/.bashrc
|
||||
fi
|
||||
|
||||
echo "Configuration has completed successfully."
|
||||
echo
|
||||
|
||||
if $REQUIRE_MACOS || $REQUIRE_IOS; then
|
||||
echo "The following components must be installed manually:"
|
||||
echo " * XCode"
|
||||
echo
|
||||
fi
|
||||
|
||||
if $REQUIRE_MACOS || $REQUIRE_IOS || $REQUIRE_ANDROID; then
|
||||
echo "The following components should be started manually after this script completes, in order to install"
|
||||
echo "additional components:"
|
||||
if $REQUIRE_MACOS || $REQUIRE_IOS; then
|
||||
echo " * XCode"
|
||||
echo "You may need to run xcode-select to choose the correct version of XCode command line tools."
|
||||
fi
|
||||
if $REQUIRE_ANDROID; then
|
||||
echo " * Android Studio"
|
||||
fi
|
||||
echo
|
||||
fi
|
||||
2
resources/gosh/package-lock.json
generated
2
resources/gosh/package-lock.json
generated
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@keymanapp/resources-gosh",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/resources-gosh",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "Good Ol' Shell",
|
||||
"author": "Marc Durdin <marc@keyman.com> (https://github.com/mcdurdin)",
|
||||
"contributors": [
|
||||
|
|
|
|||
2
resources/web-environment/package-lock.json
generated
2
resources/web-environment/package-lock.json
generated
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@keymanapp/web-environment",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@keymanapp/web-environment",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "A compilation utility for passing select environment variables into our TS builds",
|
||||
"author": "Joshua Horton <joshua_horton@sil.org> (https://github.com/jahorton)",
|
||||
"homepage": "https://github.com/keymanapp/keyman",
|
||||
|
|
@ -17,6 +17,6 @@
|
|||
"url": "https://github.com/keymanapp/keyman/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@keymanapp/resources-gosh": "^15.0.74"
|
||||
"@keymanapp/resources-gosh": "^15.0.79"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,8 @@
|
|||
# Keyman Web
|
||||
The Original Code is (C) 2017-2018 SIL International
|
||||
The Original Code is (C) SIL International
|
||||
|
||||
## Minimum Web Compilation Requirements
|
||||
|
||||
* [Java 7+](https://adoptopenjdk.net/releases.html) (required by the Google Closure Compiler)
|
||||
* This can be ignored for Keyman Developer builds.
|
||||
* A local installation of [Node.js](https://nodejs.org/) v8.9+.
|
||||
* Builds will call `npm install` to automatically install further necessary build dependencies.
|
||||
|
||||
* Linux users can run the following to update to LTS version of nodejs
|
||||
|
||||
```
|
||||
sudo apt-get install python-software-properties
|
||||
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
|
||||
sudo apt-get install nodejs
|
||||
```
|
||||
## Prerequisites
|
||||
See [build configuration](../docs/build/index.md) for details on how to configure your build environment.
|
||||
|
||||
**********************************************************************
|
||||
|
||||
|
|
|
|||
2
web/package-lock.json
generated
2
web/package-lock.json
generated
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "keyman",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "keyman",
|
||||
"version": "15.0.74",
|
||||
"version": "15.0.79",
|
||||
"description": "Facilitates text input in any language.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
},
|
||||
"homepage": "https://github.com/keymanapp/keyman#readme",
|
||||
"devDependencies": {
|
||||
"@keymanapp/resources-gosh": "^15.0.74",
|
||||
"@keymanapp/web-sentry-manager": "^15.0.74",
|
||||
"@keymanapp/resources-gosh": "^15.0.79",
|
||||
"@keymanapp/web-sentry-manager": "^15.0.79",
|
||||
"@sentry/cli": "^1.52.3",
|
||||
"chai": "^4.3.4",
|
||||
"google-closure-compiler-java": "^20200224.0.0",
|
||||
|
|
@ -52,13 +52,13 @@
|
|||
"sentry-cli": "sentry-cli"
|
||||
},
|
||||
"dependencies": {
|
||||
"@keymanapp/input-processor": "^15.0.74",
|
||||
"@keymanapp/keyboard-processor": "^15.0.74",
|
||||
"@keymanapp/lexical-model-layer": "^15.0.74",
|
||||
"@keymanapp/models-types": "^15.0.74",
|
||||
"@keymanapp/recorder-core": "^15.0.74",
|
||||
"@keymanapp/web-environment": "^15.0.74",
|
||||
"@keymanapp/web-utils": "^15.0.74",
|
||||
"@keymanapp/input-processor": "^15.0.79",
|
||||
"@keymanapp/keyboard-processor": "^15.0.79",
|
||||
"@keymanapp/lexical-model-layer": "^15.0.79",
|
||||
"@keymanapp/models-types": "^15.0.79",
|
||||
"@keymanapp/recorder-core": "^15.0.79",
|
||||
"@keymanapp/web-environment": "^15.0.79",
|
||||
"@keymanapp/web-utils": "^15.0.79",
|
||||
"@types/node": "^11.9.4",
|
||||
"es6-shim": "^0.35.5",
|
||||
"eventemitter3": "^4.0.0"
|
||||
|
|
|
|||
|
|
@ -1474,10 +1474,10 @@ namespace com.keyman.dom {
|
|||
/**
|
||||
* Function Initialization
|
||||
* Scope Public
|
||||
* @param {Object} arg object array of user-defined properties
|
||||
* @param {com.keyman.OptionType} arg object of user-defined properties
|
||||
* Description KMW window initialization
|
||||
*/
|
||||
init: (arg:any) => Promise<any> = function(this: DOMManager, arg): Promise<any> {
|
||||
init: (arg: com.keyman.OptionType) => Promise<any> = function(this: DOMManager, arg): Promise<any> {
|
||||
var i,j,c,e,p,eTextArea,eInput,opt,dTrailer,ds;
|
||||
var osk = this.keyman.osk;
|
||||
var util = this.keyman.util;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
/// <reference path="../kmwbase.ts" />
|
||||
// Includes a promise polyfill (needed for IE)
|
||||
/// <reference path="../../node_modules/es6-shim/es6-shim.min.js" />
|
||||
|
||||
namespace com.keyman.keyboards {
|
||||
class CloudRequestEntry {
|
||||
|
|
@ -68,6 +70,15 @@ namespace com.keyman.keyboards {
|
|||
}
|
||||
}
|
||||
|
||||
// Information about a keyboard that fails to get added
|
||||
export interface ErrorStub {
|
||||
language?: {
|
||||
id?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
error: Error;
|
||||
}
|
||||
export class KeyboardTag {
|
||||
stores: {[text: string]: text.ComplexKeyboardStore} = {};
|
||||
}
|
||||
|
|
@ -85,15 +96,14 @@ namespace com.keyman.keyboards {
|
|||
// Represents unspecified errors that occur when registering the results of a successful API call.
|
||||
const CLOUD_STUB_REGISTRATION_ERR = "The Cloud API failed to find an appropriate keyboard.";
|
||||
// Represents custom, specified KMW errors that occur when registering the results of a successful API call.
|
||||
const CLOUD_REGISTRATION_ERROR = "Error occurred while registering keyboards: ";
|
||||
const CLOUD_REGISTRATION_ERR = "Error occurred while registering keyboards: ";
|
||||
|
||||
const MISSING_KEYBOARD = function(kbdid: string) {
|
||||
return kbdid + ' keyboard not found.';
|
||||
}
|
||||
|
||||
interface RegistrationPromiseTuple {
|
||||
// TODO (#5044): the parameter for `resolve` should match the type of the Promise in keymanCloudRequest.
|
||||
resolve: () => void;
|
||||
resolve: (stubs: KeyboardStub[]) => void;
|
||||
reject: (err: Error) => void;
|
||||
}
|
||||
|
||||
|
|
@ -107,6 +117,8 @@ namespace com.keyman.keyboards {
|
|||
activeStub: KeyboardStub = null;
|
||||
keyboardStubs: KeyboardStub[] = [];
|
||||
|
||||
firstCall: boolean = true; // First time to call keymanCloudRequest()
|
||||
|
||||
deferredStubs: any[] = []; // The list of user-provided keyboard stub registration objects.
|
||||
deferredKRS = []; // Array of pending keyboard stubs from KRS, to register after initialization
|
||||
deferredKR = []; // Array of pending keyboards, to be installed at end of initialization
|
||||
|
|
@ -123,8 +135,9 @@ namespace com.keyman.keyboards {
|
|||
*/
|
||||
registrationResolvers: {[timeoutID: number] : RegistrationPromiseTuple} = {};
|
||||
|
||||
languageListPromise: Promise<(KeyboardStub|ErrorStub)[]> = null;
|
||||
|
||||
languageList: any[] = null; // List of keyboard languages available for KeymanCloud
|
||||
languagesPending: any[] = []; // Array of languages waiting to be registered
|
||||
|
||||
linkedScripts: HTMLScriptElement[] = [];
|
||||
|
||||
|
|
@ -566,8 +579,8 @@ namespace com.keyman.keyboards {
|
|||
// Thanks, Closure errors.
|
||||
if(!this.keymanweb.isEmbedded) {
|
||||
util.wait(false);
|
||||
util.alert(altString || msg, function() {
|
||||
this.keymanweb['setActiveKeyboard'](''); // The API call!
|
||||
util.internalAlert(altString || msg, function() {
|
||||
this.keymanweb['setActiveKeyboard'](''); // The API call!
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
|
|
@ -943,7 +956,7 @@ namespace com.keyman.keyboards {
|
|||
|
||||
if(typeof(x[i]['filename']) == 'string') {
|
||||
if(!this.addStub(x[i])) {
|
||||
alert('To use a custom keyboard, you must specify file name, keyboard name, language, language code and region code.');
|
||||
this.keymanweb.util.internalAlert('To use a custom keyboard, you must specify file name, keyboard name, language, language code and region code.');
|
||||
}
|
||||
} else {
|
||||
if(x[i]['language']) {
|
||||
|
|
@ -984,7 +997,11 @@ namespace com.keyman.keyboards {
|
|||
}
|
||||
|
||||
// Request keyboard metadata from the Keyman Cloud keyboard metadata server
|
||||
this.keymanCloudRequest(cmd,false);
|
||||
try {
|
||||
let promise = this.keymanCloudRequest(cmd,false);
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1067,11 +1084,11 @@ namespace com.keyman.keyboards {
|
|||
register(x) {
|
||||
const promiseid = x['timerid'];
|
||||
|
||||
let result: Error;
|
||||
let result: KeyboardStub[] | Error;
|
||||
try {
|
||||
result = this._registerCore(x);
|
||||
} catch(err) {
|
||||
result = new Error(CLOUD_REGISTRATION_ERROR + err);
|
||||
result = new Error(CLOUD_REGISTRATION_ERR + err);
|
||||
}
|
||||
|
||||
if(promiseid) {
|
||||
|
|
@ -1081,8 +1098,8 @@ namespace com.keyman.keyboards {
|
|||
try {
|
||||
if(result instanceof Error) {
|
||||
promiseFuncs.reject(result as Error);
|
||||
} else { // TODO (#5044): pass `result` to the `resolve` function.
|
||||
promiseFuncs.resolve();
|
||||
} else {
|
||||
promiseFuncs.resolve(result as KeyboardStub[]);
|
||||
}
|
||||
} finally {
|
||||
delete this.registrationResolvers[promiseid];
|
||||
|
|
@ -1095,8 +1112,9 @@ namespace com.keyman.keyboards {
|
|||
*
|
||||
* @param {Object} x metadata object
|
||||
**/
|
||||
private _registerCore(x): Error { // TODO (#5044): should return heterogenous type; allow array of stubs.
|
||||
private _registerCore(x): KeyboardStub[] | Error { // TODO (#5044): should return heterogenous type; allow array of stubs.
|
||||
var options=x['options'];
|
||||
let currentKeyboardStubsCount = this.keyboardStubs.length;
|
||||
|
||||
// Indicate if unable to register keyboard
|
||||
if(typeof(x['error']) == 'string') {
|
||||
|
|
@ -1129,34 +1147,60 @@ namespace com.keyman.keyboards {
|
|||
}
|
||||
} else if(options['context'] == 'language') { // Download the full list of supported keyboard languages
|
||||
this.languageList = x['languages'];
|
||||
if(this.languagesPending) {
|
||||
this.addLanguageKeyboards(this.languagesPending);
|
||||
}
|
||||
this.languagesPending = [];
|
||||
}
|
||||
|
||||
return null; // TODO (#5044): return the list of newly-registered stubs here.
|
||||
return this.keyboardStubs.slice(currentKeyboardStubsCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal handler for processing keyboard registration, used only by `register`
|
||||
*
|
||||
* @param {Object} languages Array of language names
|
||||
* @param {string[]} languages Array of language names
|
||||
* @returns {Promise<(KeyboardStub|ErrorStub)[]>} Promise of added keyboard stubs
|
||||
**/
|
||||
addLanguageKeyboards(languages) {
|
||||
var i, j, lgName, cmd, first, addAll;
|
||||
async addLanguageKeyboards(languages: string[]): Promise<(KeyboardStub|ErrorStub)[]> {
|
||||
var i, j, lgName, cmd, addAll, retPromise;
|
||||
|
||||
let errorStub: ErrorStub[] = [];
|
||||
|
||||
// Defer registering keyboards by language until the language list has been loaded
|
||||
if(this.languageList == null) {
|
||||
first = (this.languagesPending.length == 0);
|
||||
|
||||
for(i=0; i<languages.length; i++) {
|
||||
this.languagesPending.push(languages[i]);
|
||||
if (this.languageList == null) {
|
||||
if (this.firstCall) {
|
||||
this.firstCall = false;
|
||||
let promise = this.keymanCloudRequest('',true);
|
||||
// If promise is not error, then... (needs an error guard)
|
||||
promise.catch(function(error) {
|
||||
let msg = "Unable to retrieve the master language list.";
|
||||
console.error(msg, error)
|
||||
let stub: ErrorStub = {error: new Error(msg)};
|
||||
errorStub.push(stub);
|
||||
return Promise.reject(errorStub);
|
||||
});
|
||||
this.languageListPromise = promise;
|
||||
}
|
||||
|
||||
if(first) {
|
||||
this.keymanCloudRequest('',true);
|
||||
}
|
||||
let _this = this;
|
||||
retPromise = new Promise(function(resolve, reject) {
|
||||
if (_this.languageListPromise) {
|
||||
// 1: wait for the language list to be loaded properly
|
||||
_this.languageListPromise.then(function() {
|
||||
// 2: perform the actual query, now that we can find the language code
|
||||
resolve(_this.addLanguageKeyboards(languages));
|
||||
}).catch(function(error) {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
} else {
|
||||
return _this.addLanguageKeyboards(languages);
|
||||
}
|
||||
}).then(function(result) {
|
||||
if (result instanceof Error) {
|
||||
return Promise.reject(result);
|
||||
}
|
||||
return Promise.resolve(result);
|
||||
}).catch(function(error) {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
} else { // Identify and register each keyboard by language name
|
||||
cmd = '';
|
||||
for(i=0; i<languages.length; i++) {
|
||||
|
|
@ -1166,6 +1210,7 @@ namespace com.keyman.keyboards {
|
|||
lgName = lgName.substr(0,lgName.length-1);
|
||||
}
|
||||
|
||||
let languageFound: boolean = false;
|
||||
for(j=0; j<this.languageList.length; j++) {
|
||||
if(lgName == this.languageList[j]['name'].toLowerCase()) {
|
||||
if(cmd != '') {
|
||||
|
|
@ -1177,18 +1222,49 @@ namespace com.keyman.keyboards {
|
|||
cmd = cmd + '$';
|
||||
}
|
||||
|
||||
languageFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!languageFound) {
|
||||
// Construct response array of errors (failed-query keyboards)
|
||||
// that will be merged with stubs (successfully-queried keyboards)
|
||||
let stub: ErrorStub = {language: {name: lgName}, error: new Error(this.alertLanguageUnavailable(lgName))};
|
||||
errorStub.push(stub);
|
||||
}
|
||||
}
|
||||
|
||||
if(cmd == '') {
|
||||
this.keymanweb.util.alert('No keyboards are available for '+languages[0]+'. '
|
||||
+'Does it have another language name?');
|
||||
} else {
|
||||
this.keymanCloudRequest('&keyboardid='+cmd,false);
|
||||
// No command so return errors
|
||||
return Promise.reject(errorStub);
|
||||
}
|
||||
|
||||
try {
|
||||
// Merge this with errorStub
|
||||
let result:(KeyboardStub|ErrorStub)[]|Error = await this.keymanCloudRequest('&keyboardid='+cmd, false);
|
||||
if (Array.isArray(result)) {
|
||||
if (errorStub.length > 0) {
|
||||
result = result.concat(errorStub);
|
||||
return Promise.resolve(result);
|
||||
} else {
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
}
|
||||
} catch(err) {
|
||||
// We don't have language info for this ErrorStub
|
||||
console.error(err);
|
||||
let stub: ErrorStub = {error: err};
|
||||
errorStub.push(stub);
|
||||
return Promise.reject(errorStub);
|
||||
}
|
||||
}
|
||||
|
||||
if (retPromise) {
|
||||
return retPromise;
|
||||
} else {
|
||||
// No keyboards added so return empty stub
|
||||
return Promise.resolve(errorStub);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1196,8 +1272,9 @@ namespace com.keyman.keyboards {
|
|||
*
|
||||
* @param {string} cmd command string
|
||||
* @param {boolean?} byLanguage if true, context=languages, else context=keyboards
|
||||
* @returns {Promise<(KeyboardStub[]>} Promise of added keyboard stubs
|
||||
**/
|
||||
keymanCloudRequest(cmd: string, byLanguage?: boolean) {
|
||||
keymanCloudRequest(cmd: string, byLanguage?: boolean): Promise<KeyboardStub[]> {
|
||||
var kbdManager = this;
|
||||
var keymanweb = this.keymanweb;
|
||||
|
||||
|
|
@ -1208,7 +1285,7 @@ namespace com.keyman.keyboards {
|
|||
const URL='https://api.keyman.com/cloud/4.0/'
|
||||
+ ((arguments.length > 1) && byLanguage ? 'languages' : 'keyboards');
|
||||
|
||||
let promise = new Promise<void>(function(resolve: () => void, reject: (Error?) => void) {
|
||||
let promise = new Promise(function(resolve: (result: KeyboardStub[]) => void, reject: (error: Error) => void) {
|
||||
const Lscript: HTMLScriptElement = keymanweb.util._CreateElement('script');
|
||||
|
||||
const queryConfig = '?jsonp=keyman.register&languageidtype=bcp47&version='+keymanweb['version'];
|
||||
|
|
@ -1216,7 +1293,7 @@ namespace com.keyman.keyboards {
|
|||
// Set callback timer
|
||||
const timeoutID = window.setTimeout(function() {
|
||||
delete kbdManager.registrationResolvers[timeoutID];
|
||||
reject(CLOUD_TIMEOUT_ERR);
|
||||
reject(new Error(CLOUD_TIMEOUT_ERR));
|
||||
} ,10000);
|
||||
|
||||
// Save the resolve / reject functions.
|
||||
|
|
@ -1269,13 +1346,26 @@ namespace com.keyman.keyboards {
|
|||
document.getElementsByTagName('head')[0].appendChild(Lscript);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Allow the site developer to handle error messaging via this catch.
|
||||
// This current version simply maintains pre-existing behavior.
|
||||
promise.catch(function(error: Error) {
|
||||
kbdManager.serverUnavailable(error);
|
||||
throw error;
|
||||
kbdManager.serverUnavailable(error.message);
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display warning if language name unavailable to add keyboard
|
||||
* @param {string} languageName
|
||||
* @returns string of Error message
|
||||
*/
|
||||
private alertLanguageUnavailable(languageName: string): string {
|
||||
let msg = 'No keyboards are available for '+ languageName + '. '
|
||||
+'Does it have another language name?';
|
||||
this.keymanweb.util.internalAlert(msg);
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1283,9 +1373,9 @@ namespace com.keyman.keyboards {
|
|||
*
|
||||
* @param {string} cmd command string sent to Cloud
|
||||
*
|
||||
**/
|
||||
private serverUnavailable(cmd) {
|
||||
this.keymanweb.util.alert(cmd == '' ? 'Unable to connect to Keyman Cloud server!' : cmd);
|
||||
*/
|
||||
private serverUnavailable(cmd: string): void {
|
||||
this.keymanweb.util.internalAlert(cmd == '' ? 'Unable to connect to Keyman Cloud server!' : cmd);
|
||||
this.keymanweb.warned=true;
|
||||
}
|
||||
|
||||
|
|
@ -1578,4 +1668,4 @@ namespace com.keyman.keyboards {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,20 @@
|
|||
Copyright 2017-2019 SIL International
|
||||
***/
|
||||
namespace com.keyman {
|
||||
|
||||
export interface OptionType {
|
||||
root?: string;
|
||||
resources?: string;
|
||||
keyboards?: string;
|
||||
fonts?: string;
|
||||
attachType?: 'auto' | 'manual' | ''; // If blank or undefined, attachType will be assigned to "auto" or "manual"
|
||||
ui?: string;
|
||||
setActiveOnRegister?: string; // TODO: Convert to boolean. Option loader needs to be able to receive this as a string or boolean
|
||||
|
||||
// Determines whether or not KeymanWeb should display its own alert messages
|
||||
useAlerts?: boolean;
|
||||
}
|
||||
|
||||
export class KeymanBase {
|
||||
_TitleElement = null; // I1972 - KeymanWeb Titlebar should not be a link
|
||||
_IE = 0; // browser version identification
|
||||
|
|
@ -73,19 +87,21 @@ namespace com.keyman {
|
|||
touchAliasing: dom.DOMEventHandlers;
|
||||
|
||||
// Defines option-tracking object as a string map.
|
||||
options: { [name: string]: string; } = {
|
||||
'root':'',
|
||||
'resources':'',
|
||||
'keyboards':'',
|
||||
'fonts':'',
|
||||
'attachType':'',
|
||||
'ui':null,
|
||||
'setActiveOnRegister':'true'
|
||||
options: OptionType = {
|
||||
root: '',
|
||||
resources: '',
|
||||
keyboards: '',
|
||||
fonts: '',
|
||||
attachType: '',
|
||||
ui: null,
|
||||
setActiveOnRegister: 'true', // TODO: convert to boolean
|
||||
|
||||
// Determines whether or not KeymanWeb should display its own alert messages
|
||||
useAlerts: true
|
||||
};
|
||||
|
||||
|
||||
// Stub functions (defined later in code only if required)
|
||||
setDefaultDeviceOptions(opt){}
|
||||
setDefaultDeviceOptions(opt: OptionType){}
|
||||
getStyleSheetPath(s){return s;}
|
||||
getKeyboardPath(f, p?){return f;}
|
||||
KC_(n, ln, Pelem){return '';}
|
||||
|
|
@ -303,12 +319,17 @@ namespace com.keyman {
|
|||
}
|
||||
|
||||
/**
|
||||
* Add default or all keyboards for a given language
|
||||
* Add default keyboards for given language(s)
|
||||
*
|
||||
* @param {string} arg Language name (multiple arguments allowed)
|
||||
* @param {string|string[]} arg Language name (multiple arguments allowed)
|
||||
* @returns {Promise<(KeyboardStub|ErrorStub)[]>} Promise of added keyboard/error stubs
|
||||
**/
|
||||
['addKeyboardsForLanguage'](arg) {
|
||||
this.keyboardManager.addLanguageKeyboards(arguments);
|
||||
['addKeyboardsForLanguage'](arg: string[]|string) : Promise<(com.keyman.keyboards.KeyboardStub|com.keyman.keyboards.ErrorStub)[]> {
|
||||
if (typeof arg === 'string') {
|
||||
return this.keyboardManager.addLanguageKeyboards(arg.split(',').map(item => item.trim()));
|
||||
} else {
|
||||
return this.keyboardManager.addLanguageKeyboards(arg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -707,4 +728,4 @@ if(!window['keyman'] || !window['keyman']['loaded']) {
|
|||
// TODO: Eliminate the need for this. Will require more refactoring & redesign to drop.
|
||||
window['keyman'].core.languageProcessor.init();
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ namespace com.keyman.text {
|
|||
keymanweb.isEmbedded = true;
|
||||
|
||||
// Set default device options
|
||||
keymanweb.setDefaultDeviceOptions = function(opt) {
|
||||
keymanweb.setDefaultDeviceOptions = function(opt: com.keyman.OptionType) {
|
||||
opt['attachType'] = 'manual';
|
||||
device.app=opt['app'];
|
||||
device.touchable=true;
|
||||
|
|
|
|||
|
|
@ -26,11 +26,13 @@ if(!window['keyman']['initialized']) {
|
|||
|
||||
/**
|
||||
* Set default device options
|
||||
* @param {Object} opt device options object
|
||||
* @param {OptionType} opt device options object
|
||||
*/
|
||||
keymanweb.setDefaultDeviceOptions=function(opt) {
|
||||
keymanweb.setDefaultDeviceOptions = function(opt : com.keyman.OptionType) {
|
||||
// Element attachment type
|
||||
if(opt['attachType'] == '') opt['attachType'] = (device.touchable ? 'manual' : 'auto');
|
||||
if (!opt['attachType']) {
|
||||
opt['attachType'] = (device.touchable ? 'manual' : 'auto');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -40,7 +42,7 @@ if(!window['keyman']['initialized']) {
|
|||
*/
|
||||
util.wait = function(s) {
|
||||
// Keyboards loaded with page are initialized before the page is ready,
|
||||
// so cannot use the wait indicater (and don't need it, anyway)
|
||||
// so cannot use the wait indicator (and don't need it, anyway)
|
||||
// Do not display if a blocking cloud server error has occurred (to prevent multiple errors)
|
||||
var bg=this.waiting;
|
||||
if(typeof(bg) == 'undefined' || bg == null || keymanweb.warned) {
|
||||
|
|
|
|||
|
|
@ -667,7 +667,7 @@ namespace com.keyman {
|
|||
}
|
||||
|
||||
if(eot != '' && (eot.indexOf('/') < 0)) {
|
||||
eot = this.keyman.options['fonts']+eot;
|
||||
eot = this.keyman.options['fonts']+eot;
|
||||
}
|
||||
|
||||
if(svg != '' && (svg.indexOf('/') < 0)) {
|
||||
|
|
@ -903,7 +903,7 @@ namespace com.keyman {
|
|||
}
|
||||
|
||||
/**
|
||||
* Customized alert
|
||||
* Customized alert.
|
||||
*
|
||||
* @param {string} s alert text
|
||||
* @param {function()=} fn function to call when alert dismissed
|
||||
|
|
@ -915,11 +915,7 @@ namespace com.keyman {
|
|||
(nn[1] as HTMLElement).innerHTML=s;
|
||||
(nn[2] as HTMLElement).style.display='none';
|
||||
bg.style.display='block';
|
||||
if(arguments.length > 1) {
|
||||
bg.dismiss=fn;
|
||||
} else {
|
||||
bg.dismiss=null;
|
||||
}
|
||||
bg.dismiss = arguments.length > 1 ? fn : null;
|
||||
}
|
||||
|
||||
// Stub definition to be fleshed out depending upon native/embedded mode.
|
||||
|
|
@ -927,6 +923,18 @@ namespace com.keyman {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Customized internal alert. This is enabled/disabled by the option flag 'useAlerts'
|
||||
*
|
||||
* @param {string} s alert text
|
||||
* @param {function()=} fn function to call when alert dismissed
|
||||
*/
|
||||
internalAlert(s: string, fn?: () => void): void {
|
||||
if (this.keyman.options.useAlerts) {
|
||||
this.alert(s, fn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the background and keyboard loading wait message box
|
||||
* Should not be called before options are defined during initialization
|
||||
|
|
@ -1146,4 +1154,4 @@ namespace com.keyman {
|
|||
}
|
||||
}
|
||||
|
||||
import Util = com.keyman.Util;
|
||||
import Util = com.keyman.Util;
|
||||
|
|
|
|||
|
|
@ -313,7 +313,11 @@ namespace com.keyman.osk {
|
|||
source: text.MutableSystemStore,
|
||||
newValue: string) {
|
||||
if(source.value != newValue) {
|
||||
this.vkbd.layerId = newValue;
|
||||
// Prevents console errors when a keyboard only displays help.
|
||||
// Can occur when using SHIFT with sil_euro_latin on a desktop form-factor.
|
||||
if(this.vkbd) {
|
||||
this.vkbd.layerId = newValue;
|
||||
}
|
||||
this._Show();
|
||||
}
|
||||
}.bind(this);
|
||||
|
|
@ -479,8 +483,8 @@ namespace com.keyman.osk {
|
|||
*/
|
||||
showBuild() {
|
||||
let keymanweb = com.keyman.singleton;
|
||||
keymanweb.util.alert('KeymanWeb Version '+keymanweb['version']+'.'+keymanweb['build']+'<br /><br />'
|
||||
+'<span style="font-size:0.8em">Copyright © 2017 SIL International</span>');
|
||||
keymanweb.util.internalAlert('KeymanWeb Version '+keymanweb['version']+'.'+keymanweb['build']+'<br /><br />'
|
||||
+'<span style="font-size:0.8em">Copyright © 2017 SIL International</span>');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,79 +2,68 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
|
||||
<!-- Set the viewport width to match phone and tablet device widths -->
|
||||
<meta name="viewport" content="width=device-width,user-scalable=no" />
|
||||
|
||||
<!-- Set the viewport width to match phone and tablet device widths -->
|
||||
<meta name="viewport" content="width=device-width,user-scalable=no" />
|
||||
|
||||
<!-- Allow KeymanWeb to be saved to the iPhone home screen -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
|
||||
|
||||
<!-- Enable IE9 Standards mode -->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<title>KeymanWeb Sample Page - Uncompiled Source</title>
|
||||
|
||||
<!-- Your page CSS -->
|
||||
<style type='text/css'>
|
||||
<!-- Your page CSS -->
|
||||
<style type='text/css'>
|
||||
body {font-family: Tahoma,helvetica;}
|
||||
h3 {font-size: 1em;font-weight:normal;color: darkred; margin-bottom: 4px}
|
||||
.test {font-size: 1.5em; width:80%; min-height:30px; border: 1px solid gray;}
|
||||
#KeymanWebControl {width:50%;min-width:600px;}
|
||||
</style>
|
||||
|
||||
<!-- Insert uncompiled KeymanWeb source scripts -->
|
||||
#KeymanWebControl {width:50%;min-width:600px;}
|
||||
</style>
|
||||
|
||||
<!-- Insert uncompiled KeymanWeb source scripts -->
|
||||
<script src="../../release/unminified/web/keymanweb.js" type="application/javascript"></script>
|
||||
|
||||
<!--
|
||||
<!--
|
||||
For desktop browsers, a script for the user interface must be inserted here.
|
||||
|
||||
Standard UIs are toggle, button, float and toolbar.
|
||||
The toolbar UI is best for any page designed to support keyboards for
|
||||
|
||||
Standard UIs are toggle, button, float and toolbar.
|
||||
The toolbar UI is best for any page designed to support keyboards for
|
||||
a large number of languages.
|
||||
-->
|
||||
<script src="../../release/unminified/web/kmwuitoggle.js"></script>
|
||||
|
||||
|
||||
<!-- Initialization: set paths to keyboards, resources and fonts as required -->
|
||||
<script>
|
||||
// Thank you to https://stackoverflow.com/questions/22607150/getting-the-url-parameters-inside-the-html-page.
|
||||
var GetURLParameter = function(sParam) {
|
||||
var sPageURL = window.location.search.substring(1);
|
||||
var sURLVariables = sPageURL.split('&');
|
||||
for (var i = 0; i < sURLVariables.length; i++) {
|
||||
var sParameterName = sURLVariables[i].split('=');
|
||||
if (sParameterName[0] == sParam) {
|
||||
return sParameterName[1];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var attachType = GetURLParameter("mode");
|
||||
var attachText = attachType ? attachType : "default";
|
||||
|
||||
var kmw=window.keyman;
|
||||
kmw.init({
|
||||
attachType: attachType ? attachType : '',
|
||||
});
|
||||
</script>
|
||||
|
||||
// Thank you to https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
|
||||
const attachType = (new URLSearchParams(window.location.search)).get("mode");
|
||||
var attachText = attachType ? attachType : "default";
|
||||
|
||||
var kmw=window.keyman;
|
||||
kmw.init({
|
||||
attachType: attachType ? attachType : ''
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Add keyboard management script for local selection of keyboards to use -->
|
||||
<script src="../commonHeader.js"></script>
|
||||
<script src="./utilities.js"></script>
|
||||
|
||||
<script src="./utilities.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<!-- Sample page HTML -->
|
||||
<!-- Sample page HTML -->
|
||||
<body onload='loadKeyboards(1);'>
|
||||
<h2>KeymanWeb Sample Page - Attachment API Testing</h2>
|
||||
<p>This page is designed to stress-test the new attachment/enablement API model and its functions.</p>
|
||||
<p id="modeSelect">You are currently testing under the <em id="mode"> </em> attachment mode. Two other modes are available:
|
||||
<a id="attach_auto" href="./index.html?mode=auto">Auto</a> <a id="attach_manual" href="./index.html?mode=manual">Manual</a>
|
||||
<p id="modeSelect">You are currently testing under the <em id="mode"> </em> attachment mode. Two other modes are available:
|
||||
<a id="attach_auto" href="./index.html?mode=auto">Auto</a> <a id="attach_manual" href="./index.html?mode=manual">Manual</a>
|
||||
<a id="attach_default" href="./index.html">Default</a><p>
|
||||
<p>Be sure to reference the developer console for additional feedback. </p>
|
||||
</p>Note that the 'attachment' state reported is managed by this page and not reported from KeymanWeb itself;
|
||||
</p>Note that the 'attachment' state reported is managed by this page and not reported from KeymanWeb itself;
|
||||
take it as a guide at best. (Especially if on a touch device.)</p>
|
||||
<script>
|
||||
document.getElementById("mode").textContent = attachText;
|
||||
|
|
@ -88,21 +77,21 @@
|
|||
<input type='button' id='btnEditable' onclick='addEditable();' value='Create editable DIV.' />
|
||||
<hr/>
|
||||
<div>
|
||||
<!--
|
||||
<!--
|
||||
The following DIV is used to position the Button or Toolbar User Interfaces on the page.
|
||||
If omitted, those User Interfaces will appear at the top of the document body.
|
||||
(It is ignored by other User Interfaces.)
|
||||
-->
|
||||
<div id='KeymanWebControl'></div>
|
||||
<div id='KeymanWebControl'></div>
|
||||
|
||||
<div id='DynamicInputs'><h3>Inputs:</h3></div>
|
||||
<div id='DynamicTextareas'><h3>Textareas:</h3></div>
|
||||
<div id='DynamicIFrames'><h3>IFrames:</h3>
|
||||
<p><em>Note:</em> The iframe section should not actually attach/enable for touch devices
|
||||
<p><em>Note:</em> The iframe section should not actually attach/enable for touch devices
|
||||
and does not support <code>setKeyboardForControl</code>.</p>
|
||||
</div>
|
||||
<div id='DynamicDesignFrames'><h3>Design-mode IFrames:</h3>
|
||||
<p><em>Note:</em> The iframe section should not actually attach/enable for touch devices
|
||||
<p><em>Note:</em> The iframe section should not actually attach/enable for touch devices
|
||||
and does not support <code>setKeyboardForControl</code>.</p>
|
||||
</div>
|
||||
<div id='DynamicEditables'><h3><code>contenteditable</code> Elements:</h3>
|
||||
|
|
@ -112,20 +101,20 @@
|
|||
<hr/>
|
||||
<h3><a href="../index.html">Return to testing home page</a></h3>
|
||||
</body>
|
||||
|
||||
<!--
|
||||
|
||||
<!--
|
||||
*** DEVELOPER NOTE -- FIREFOX CONFIGURATION FOR TESTING ***
|
||||
*
|
||||
* If the URL bar starts with <b>file://</b>, Firefox may not load the font used
|
||||
* to display the special characters used in the On-Screen Keyboard.
|
||||
*
|
||||
* To work around this Firefox bug, navigate to <b>about:config</b>
|
||||
* and set <b>security.fileuri.strict_origin_policy</b> to <b>false</b>
|
||||
* while testing.
|
||||
*
|
||||
* to display the special characters used in the On-Screen Keyboard.
|
||||
*
|
||||
* To work around this Firefox bug, navigate to <b>about:config</b>
|
||||
* and set <b>security.fileuri.strict_origin_policy</b> to <b>false</b>
|
||||
* while testing.
|
||||
*
|
||||
* Firefox resolves website-based CSS URI references correctly without needing
|
||||
* any configuration change, so this change should only be made for file-based testing.
|
||||
*
|
||||
***
|
||||
-->
|
||||
*
|
||||
***
|
||||
-->
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,47 +1,47 @@
|
|||
// JavaScript Document samplehdr.js: Keyboard management for KeymanWeb demonstration pages
|
||||
|
||||
/*
|
||||
/*
|
||||
The keyboard name and/or BCP-47 language code must be specified for each keyboard that is to be available.
|
||||
If the same keyboard is used for several languages, it must be listed for each
|
||||
language, but the keyboard itself will only be loaded once.
|
||||
language, but the keyboard itself will only be loaded once.
|
||||
If two (or more) keyboards are to be available for a given language, both must be listed.
|
||||
Any number of keyboards may be specified in one or more calls.
|
||||
Keyboard paths may be absolute (with respect to the server root) or relative to the keyboards option path.
|
||||
Any number of keyboards may be specified in one or more calls.
|
||||
Keyboard paths may be absolute (with respect to the server root) or relative to the keyboards option path.
|
||||
The actual keyboard object will be downloaded asynchronously when first selected for use.
|
||||
|
||||
|
||||
Each argument to addKeyboards() is a string, for example:
|
||||
european2 loads the current version of the Eurolatin 2 keyboard (for its default language)
|
||||
european2@fr loads the current version of the Eurolatin 2 keyboard for French
|
||||
european2@fr@1.2 loads version 1.2 of the Eurolatin 2 keyboard for French
|
||||
|
||||
|
||||
Argument syntax also supports the following extensions:
|
||||
@fr load the current version of the default keyboard for French
|
||||
@fr$ load all available keyboards (current version) for French
|
||||
|
||||
Each call to addKeyboards() requires a single call to the remote server,
|
||||
|
||||
Each call to addKeyboards() requires a single call to the remote server,
|
||||
(unless all keyboards listed are local and fully specified) so it is better
|
||||
to use multiple arguments rather than separate function calls.
|
||||
|
||||
Calling addKeyboards() with no arguments returns a list of *all* available keyboards.
|
||||
The Toolbar (desktop browser) UI is best suited for allowing users to select
|
||||
to use multiple arguments rather than separate function calls.
|
||||
|
||||
Calling addKeyboards() with no arguments returns a list of *all* available keyboards.
|
||||
The Toolbar (desktop browser) UI is best suited for allowing users to select
|
||||
the appropriate language and keyboard in this case.
|
||||
|
||||
Keyboards may also be specified by language name using addKeyboardsForLanguage()
|
||||
for example:
|
||||
keymanweb.addKeyboardsForLanguage('Burmese');
|
||||
|
||||
|
||||
Appending $ to the language name will again cause all available keyboards for that
|
||||
language to be loaded rather than the default keyboard.
|
||||
|
||||
The first call to addKeyboardsForLanguage() makes an additional call to the
|
||||
|
||||
The first call to addKeyboardsForLanguage() makes an additional call to the
|
||||
keyman API to load the current list of keyboard/language associations.
|
||||
|
||||
In this example, the following function loads the indicated keyboards,
|
||||
and is called when the page loads.
|
||||
and is called when the page loads.
|
||||
*/
|
||||
|
||||
function loadKeyboards(nestLevel)
|
||||
{
|
||||
{
|
||||
var kmw=keyman;
|
||||
|
||||
var base_prefix = '../';
|
||||
|
|
@ -53,46 +53,46 @@
|
|||
prefix = prefix + base_prefix;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The first keyboard added will be the default keyboard for touch devices.
|
||||
// For faster loading, it may be best for the default keyboard to be
|
||||
// locally sourced.
|
||||
kmw.addKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'},
|
||||
filename:(prefix + 'us-1.0.js')});
|
||||
|
||||
|
||||
// Add more keyboards to the language menu, by keyboard name,
|
||||
// keyboard name and language code, or just the BCP-47 language code.
|
||||
// We use a different loading pattern here than in the samples version to provide a slightly different set of test cases.
|
||||
kmw.addKeyboards('french','@he');
|
||||
kmw.addKeyboards({id:'sil_euro_latin', name:'SIL EuroLatin', languages: [{id:'no'}, {id:'sv'}]}); // Loads from partial stub instead of the compact string.
|
||||
|
||||
|
||||
// Add a keyboard by language name. Note that the name must be spelled
|
||||
// correctly, or the keyboard will not be found. (Using BCP-47 codes is
|
||||
// usually easier.)
|
||||
kmw.addKeyboardsForLanguage('Dzongkha');
|
||||
|
||||
// Add a fully-specified, locally-sourced, keyboard with custom font
|
||||
|
||||
// Add a fully-specified, locally-sourced, keyboard with custom font
|
||||
kmw.addKeyboards({id:'lao_2008_basic',name:'Lao Basic',
|
||||
languages: {
|
||||
id:'lo',name:'Lao',region:'Asia',
|
||||
},
|
||||
filename:(prefix + 'lao_2008_basic-1.2.js')
|
||||
});
|
||||
});
|
||||
|
||||
// The following two optional calls should be delayed until language menus are fully loaded:
|
||||
// (a) a specific mapped input element input is focused, to ensure that the OSK appears
|
||||
// (b) a specific keyboard is loaded, rather than the keyboard last used.
|
||||
// (b) a specific keyboard is loaded, rather than the keyboard last used.
|
||||
//window.setTimeout(function(){kmw.setActiveElement('ta1',true);},2500);
|
||||
//window.setTimeout(function(){kmw.setActiveKeyboard('Keyboard_french','fr');},3000);
|
||||
|
||||
// Note that locally specified keyboards will be listed before keyboards
|
||||
|
||||
// Note that locally specified keyboards will be listed before keyboards
|
||||
// requested from the remote server by user interfaces that do not order
|
||||
// keyboards alphabetically by language.
|
||||
}
|
||||
|
||||
// Script to allow a user to add any keyboard to the keyboard menu
|
||||
|
||||
// Script to allow a user to add any keyboard to the keyboard menu
|
||||
function addKeyboard(n)
|
||||
{
|
||||
{
|
||||
var sKbd,kmw=keyman;
|
||||
switch(n)
|
||||
{
|
||||
|
|
@ -105,16 +105,17 @@
|
|||
kmw.addKeyboards('@'+sKbd);
|
||||
break;
|
||||
case 3:
|
||||
// Add keyboard for comma-separated language name(s)
|
||||
sKbd=document.getElementById('kbd_id3').value;
|
||||
kmw.addKeyboardsForLanguage(sKbd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add keyboard on Enter (as well as pressing button)
|
||||
function clickOnEnter(e,id)
|
||||
{
|
||||
e = e || window.event;
|
||||
if(e.keyCode == 13) addKeyboard(id);
|
||||
if(e.keyCode == 13) addKeyboard(id);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
<h2><a href="./platform/">Platform testing</a></h2>
|
||||
<h2><a href="./prediction-ui/">Prediction UI testing</a></h2>
|
||||
<h2><a href="./prediction-mtnt/">Prediction - robust testing</a></h2>
|
||||
<h2><a href="./promise-api/">Promise API testing</a></h2>
|
||||
<h2><a href="./toolbar/">Toolbar UI testing</a></h2>
|
||||
<h2><a href="./build-visual-keyboard/">Tests keyboard documentation rendering.</a></h2>
|
||||
<h2><a href="./sentry-integration/">Tests Sentry error-reporting functionality</a></h2>
|
||||
|
|
|
|||
130
web/testing/promise-api/index.html
Normal file
130
web/testing/promise-api/index.html
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
|
||||
<!-- Set the viewport width to match phone and tablet device widths -->
|
||||
<meta name="viewport" content="width=device-width,user-scalable=no" />
|
||||
|
||||
<!-- Allow KeymanWeb to be saved to the iPhone home screen -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
|
||||
<!-- Enable IE9 Standards mode -->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<title>KeymanWeb Testing Page - Promise API when Adding Keyboards</title>
|
||||
|
||||
<!-- Your page CSS -->
|
||||
<style type='text/css'>
|
||||
body {font-family: Tahoma,helvetica;}
|
||||
h3 {font-size: 1em;font-weight:normal;color: darkred; margin-bottom: 4px}
|
||||
.test {font-size: 1.5em; width:80%; min-height:30px; border: 1px solid gray;}
|
||||
#KeymanWebControl {width:50%;min-width:600px;}
|
||||
</style>
|
||||
|
||||
<!-- Insert uncompiled KeymanWeb source scripts -->
|
||||
<script src="../../release/unminified/web/keymanweb.js" type="application/javascript"></script>
|
||||
|
||||
<!--
|
||||
For desktop browsers, a script for the user interface must be inserted here.
|
||||
|
||||
Standard UIs are toggle, button, float and toolbar.
|
||||
The toolbar UI is best for any page designed to support keyboards for
|
||||
a large number of languages.
|
||||
-->
|
||||
<script src="../../release/unminified/web/kmwuitoggle.js"></script>
|
||||
|
||||
<!-- Initialization: set paths to keyboards, resources and fonts as required -->
|
||||
<script>
|
||||
// Thank you to https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
|
||||
const alertType = (new URLSearchParams(window.location.search)).get("useAlerts") != "false";
|
||||
var alertText = alertType ? 'enabled(default)' : 'disabled';
|
||||
|
||||
var kmw=window.keyman;
|
||||
kmw.init({
|
||||
useAlerts: alertType
|
||||
}).then(function() {
|
||||
loadKeyboards();
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Add keyboard management script for local selection of keyboards to use -->
|
||||
<script src="promisehdr.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<!-- Sample page HTML -->
|
||||
<body>
|
||||
<h2>KeymanWeb Sample Page - Promise API</h2>
|
||||
<p>This page is for testing the Promises returned from adding keyboards.
|
||||
See <a href="https://github.com/keymanapp/keyman/issues/5044">Specification #5044.</a>
|
||||
</p>
|
||||
<p>
|
||||
This test page is best used with Developer mode, as output for both successes
|
||||
and failures will be logged to the JS console.
|
||||
</p>
|
||||
<p>Visible alert-style feedback will only occur for invalid search terms, such as using "foobar"
|
||||
for any of the three keyboard-adding options at the bottom of the page.
|
||||
</p>
|
||||
|
||||
<p id="modeSelect">You are currently testing under the internal alerts <em id="mode"> </em> mode.
|
||||
Two alert modes are available:
|
||||
<a id="alert_disabled" href="./index.html?useAlerts=false">Disabled</a> or
|
||||
<a id="alert_default" href="./index.html">Enabled (Default)</a></p>
|
||||
<p>This will only affect whether or not KeymanWeb's alert modal is displayed.
|
||||
A native browser alert and dev-console error log will occur regardless of this
|
||||
setting when stub fetch errors occur.
|
||||
</p>
|
||||
|
||||
<script>
|
||||
document.getElementById("mode").textContent = alertText;
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<!--
|
||||
The following DIV is used to position the Button or Toolbar User Interfaces on the page.
|
||||
If omitted, those User Interfaces will appear at the top of the document body.
|
||||
(It is ignored by other User Interfaces.)
|
||||
-->
|
||||
<div id='KeymanWebControl'></div>
|
||||
|
||||
<h3>Type in your language in this text area:</h3>
|
||||
<textarea id='ta1' class='test' placeholder='Type here'></textarea>
|
||||
|
||||
<h3>or in this input field:</h3>
|
||||
<input class='test' value='' placeholder='or here'/>
|
||||
|
||||
<!-- The following elements show how the language menu can be dynamically extended at any time -->
|
||||
<h3>Add a keyboard by keyboard name:</h3>
|
||||
<input type='input' id='kbd_id1' class='kmw-disabled' onkeypress="clickOnEnter(event,1);"/>
|
||||
<input type='button' id='btn1' onclick='addKeyboard(1);' value='Add' />
|
||||
|
||||
<h3>Add a keyboard by BCP-47 language code:</h3>
|
||||
<input type='input' id='kbd_id2' class='kmw-disabled' onkeypress="clickOnEnter(event,2);"/>
|
||||
<input type='button' id='btn2' onclick='addKeyboard(2);' value='Add' />
|
||||
|
||||
<h3>Add a keyboard by comma-separated language name(s):</h3>
|
||||
<input type='input' id='kbd_id3' class='kmw-disabled' onkeypress="clickOnEnter(event,3);"/>
|
||||
<input type='button' id='btn3' onclick='addKeyboard(3);' value='Add' />
|
||||
|
||||
<h3><a href="./">Return to testing home page</a></h3>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
<!--
|
||||
*** DEVELOPER NOTE -- FIREFOX CONFIGURATION FOR TESTING ***
|
||||
*
|
||||
* If the URL bar starts with <b>file://</b>, Firefox may not load the font used
|
||||
* to display the special characters used in the On-Screen Keyboard.
|
||||
*
|
||||
* To work around this Firefox bug, navigate to <b>about:config</b>
|
||||
* and set <b>security.fileuri.strict_origin_policy</b> to <b>false</b>
|
||||
* while testing.
|
||||
*
|
||||
* Firefox resolves website-based CSS URI references correctly without needing
|
||||
* any configuration change, so this change should only be made for file-based testing.
|
||||
*
|
||||
***
|
||||
-->
|
||||
</html>
|
||||
130
web/testing/promise-api/promisehdr.js
Normal file
130
web/testing/promise-api/promisehdr.js
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
// JavaScript Document promisehdr.js: Keyboard management for KeymanWeb demonstration pages
|
||||
|
||||
/*
|
||||
The keyboard name and/or BCP-47 language code must be specified for each keyboard that is to be available.
|
||||
If the same keyboard is used for several languages, it must be listed for each
|
||||
language, but the keyboard itself will only be loaded once.
|
||||
If two (or more) keyboards are to be available for a given language, both must be listed.
|
||||
Any number of keyboards may be specified in one or more calls.
|
||||
Keyboard paths may be absolute (with respect to the server root) or relative to the keyboards option path.
|
||||
The actual keyboard object will be downloaded asynchronously when first selected for use.
|
||||
|
||||
Each argument to addKeyboards() is a string, for example:
|
||||
european2 loads the current version of the Eurolatin 2 keyboard (for its default language)
|
||||
european2@fr loads the current version of the Eurolatin 2 keyboard for French
|
||||
european2@fr@1.2 loads version 1.2 of the Eurolatin 2 keyboard for French
|
||||
|
||||
Argument syntax also supports the following extensions:
|
||||
@fr load the current version of the default keyboard for French
|
||||
@fr$ load all available keyboards (current version) for French
|
||||
|
||||
Each call to addKeyboards() requires a single call to the remote server,
|
||||
(unless all keyboards listed are local and fully specified) so it is better
|
||||
to use multiple arguments rather than separate function calls.
|
||||
|
||||
Calling addKeyboards() with no arguments returns a list of *all* available keyboards.
|
||||
The Toolbar (desktop browser) UI is best suited for allowing users to select
|
||||
the appropriate language and keyboard in this case.
|
||||
|
||||
Keyboards may also be specified by language name using addKeyboardsForLanguage()
|
||||
for example:
|
||||
keymanweb.addKeyboardsForLanguage('Burmese');
|
||||
|
||||
Appending $ to the language name will again cause all available keyboards for that
|
||||
language to be loaded rather than the default keyboard.
|
||||
|
||||
The first call to addKeyboardsForLanguage() makes an additional call to the
|
||||
keyman API to load the current list of keyboard/language associations.
|
||||
|
||||
In this example, the following function loads the indicated keyboards,
|
||||
and is called when the page loads.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add a keyboard by language name. Note that the name must be spelled
|
||||
correctly, or the keyboard will not be found. (Using BCP-47 codes is
|
||||
usually easier.)
|
||||
* @param {string} languages. Could be comma-separated languages
|
||||
*/
|
||||
function addKeyboardsForLanguage(languages) {
|
||||
kmw.addKeyboardsForLanguage(languages.split(',').map(item => item.trim())).then(result => {
|
||||
console.log('Adding ' + languages + ': ', result);
|
||||
}).catch(errorStubs => {
|
||||
// Consumer decides how to handle errors
|
||||
errorStubs.forEach(e => console.error(e));
|
||||
|
||||
// We'll also concat the error messages to an alert
|
||||
let errorMessages = errorStubs.map(e => e.error.message).join('\n');
|
||||
alert(errorMessages);
|
||||
});
|
||||
}
|
||||
|
||||
function loadKeyboards()
|
||||
{
|
||||
var kmw=keyman;
|
||||
|
||||
// The first keyboard added will be the default keyboard for touch devices.
|
||||
// For faster loading, it may be best for the default keyboard to be
|
||||
// locally sourced.
|
||||
kmw.addKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'},
|
||||
filename:'../us-1.0.js'});
|
||||
|
||||
// Add more keyboards to the language menu, by keyboard name,
|
||||
// keyboard name and language code, or just the BCP-47 language code.
|
||||
// We use a different loading pattern here than in the samples version to provide a slightly different set of test cases.
|
||||
kmw.addKeyboards('french','@he');
|
||||
kmw.addKeyboards({id:'sil_euro_latin', name:'SIL EuroLatin', languages: [{id:'no'}, {id:'sv'}]}); // Loads from partial stub instead of the compact string.
|
||||
|
||||
// Add a keyboard by language name. Note that the name must be spelled
|
||||
// correctly, or the keyboard will not be found. (Using BCP-47 codes is
|
||||
// usually easier.)
|
||||
addKeyboardsForLanguage('Dzongkha');
|
||||
|
||||
// Add a fully-specified, locally-sourced, keyboard with custom font
|
||||
kmw.addKeyboards({id:'lao_2008_basic',name:'Lao Basic',
|
||||
languages: {
|
||||
id:'lo',name:'Lao',region:'Asia'
|
||||
},
|
||||
filename:'../lao_2008_basic-1.2.js'
|
||||
});
|
||||
|
||||
// The following two optional calls should be delayed until language menus are fully loaded:
|
||||
// (a) a specific mapped input element input is focused, to ensure that the OSK appears
|
||||
// (b) a specific keyboard is loaded, rather than the keyboard last used.
|
||||
//window.setTimeout(function(){kmw.setActiveElement('ta1',true);},2500);
|
||||
//window.setTimeout(function(){kmw.setActiveKeyboard('Keyboard_french','fr');},3000);
|
||||
|
||||
// Note that locally specified keyboards will be listed before keyboards
|
||||
// requested from the remote server by user interfaces that do not order
|
||||
// keyboards alphabetically by language.
|
||||
}
|
||||
|
||||
// Script to allow a user to add any keyboard to the keyboard menu
|
||||
function addKeyboard(n)
|
||||
{
|
||||
var sKbd,kmw=keyman;
|
||||
switch(n)
|
||||
{
|
||||
case 1:
|
||||
sKbd=document.getElementById('kbd_id1').value;
|
||||
kmw.addKeyboards(sKbd);
|
||||
break;
|
||||
case 2:
|
||||
sKbd=document.getElementById('kbd_id2').value.toLowerCase();
|
||||
kmw.addKeyboards('@'+sKbd);
|
||||
break;
|
||||
case 3:
|
||||
// Add keyboard for comma-separated language name(s)
|
||||
sKbd=document.getElementById('kbd_id3').value;
|
||||
addKeyboardsForLanguage(sKbd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add keyboard on Enter (as well as pressing button)
|
||||
function clickOnEnter(e,id)
|
||||
{
|
||||
e = e || window.event;
|
||||
if(e.keyCode == 13) addKeyboard(id);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue