Merge pull request #54 from ShikiSuen/upd/1.3.4
v1.3.4 // Maintenance release, fixing certain behaviors with UserPhrases.
This commit is contained in:
commit
de552cdf5c
|
@ -67,7 +67,7 @@
|
|||
<window title="vChewing Installer" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" animationBehavior="default" titlebarAppearsTransparent="YES" id="371">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
|
||||
<rect key="contentRect" x="335" y="390" width="533" height="457"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1600" height="875"/>
|
||||
<value key="minSize" type="size" width="533" height="457"/>
|
||||
<value key="maxSize" type="size" width="533" height="457"/>
|
||||
<view key="contentView" id="372">
|
||||
|
@ -271,7 +271,6 @@ Gw
|
|||
<connections>
|
||||
<outlet property="appCopyrightLabel" destination="03l-rN-zf9" id="XS5-cZ-k9H"/>
|
||||
<outlet property="appEULAContent" destination="47J-tO-8TZ" id="kRU-X2-8kX"/>
|
||||
<outlet property="appNameLabel" destination="bzR-Oa-BZa" id="swF-1l-dhS"/>
|
||||
<outlet property="appVersionLabel" destination="z1m-8k-Z63" id="75X-uy-0Iz"/>
|
||||
<outlet property="cancelButton" destination="592" id="710"/>
|
||||
<outlet property="installButton" destination="575" id="709"/>
|
||||
|
@ -283,7 +282,7 @@ Gw
|
|||
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="" animationBehavior="default" id="gHl-Hx-eQn">
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="283" y="305" width="480" height="180"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1600" height="875"/>
|
||||
<view key="contentView" id="wAe-c8-Vh9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="180"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13150" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13150"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="ShareViewController" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="view" destination="1" id="2"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="388" height="202"/>
|
||||
<subviews>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="1uM-r7-H1c">
|
||||
<rect key="frame" x="302" y="3" width="82" height="32"/>
|
||||
<buttonCell key="cell" type="push" title="Send" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="2l4-PO-we5">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<string key="keyEquivalent">D</string>
|
||||
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="send:" target="-2" id="yic-EC-GGk"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="NVE-vN-dkz">
|
||||
<rect key="frame" x="224" y="3" width="82" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="60" id="cP1-hK-9ZX"/>
|
||||
</constraints>
|
||||
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="6Up-t3-mwm">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<string key="keyEquivalent" base64-UTF8="YES">
|
||||
Gw
|
||||
</string>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="cancel:" target="-2" id="Qav-AK-DGt"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="aNc-0i-CWK">
|
||||
<rect key="frame" x="140" y="170" width="108" height="17"/>
|
||||
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="My Service Title" id="0xp-rC-2gr">
|
||||
<font key="font" metaFont="systemBold"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
</textField>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="4M6-D5-WIf">
|
||||
<rect key="frame" x="110" y="170" width="22" height="22"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="22" id="BOe-aZ-Njc"/>
|
||||
<constraint firstAttribute="height" constant="22" id="zLg-1a-wlZ"/>
|
||||
</constraints>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="q3u-Am-ZIA"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="1uM-r7-H1c" firstAttribute="leading" secondItem="NVE-vN-dkz" secondAttribute="trailing" constant="8" id="1UO-J1-LbJ"/>
|
||||
<constraint firstItem="NVE-vN-dkz" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="1" secondAttribute="leading" constant="20" symbolic="YES" id="3N9-qo-UfS"/>
|
||||
<constraint firstAttribute="bottom" secondItem="1uM-r7-H1c" secondAttribute="bottom" constant="10" id="4wH-De-nMF"/>
|
||||
<constraint firstAttribute="bottom" secondItem="NVE-vN-dkz" secondAttribute="bottom" constant="10" id="USG-Gg-of3"/>
|
||||
<constraint firstItem="1uM-r7-H1c" firstAttribute="leading" secondItem="NVE-vN-dkz" secondAttribute="trailing" constant="8" id="a8N-vS-Ew9"/>
|
||||
<constraint firstItem="aNc-0i-CWK" firstAttribute="centerY" secondItem="4M6-D5-WIf" secondAttribute="centerY" constant="2.5" id="ilP-G0-GVG"/>
|
||||
<constraint firstItem="NVE-vN-dkz" firstAttribute="width" secondItem="1uM-r7-H1c" secondAttribute="width" id="qPo-ky-Fcw"/>
|
||||
<constraint firstAttribute="trailing" secondItem="1uM-r7-H1c" secondAttribute="trailing" constant="10" id="qfT-cw-QQ2"/>
|
||||
<constraint firstAttribute="centerX" secondItem="aNc-0i-CWK" secondAttribute="centerX" id="uV3-Wn-RA3"/>
|
||||
<constraint firstItem="aNc-0i-CWK" firstAttribute="leading" secondItem="4M6-D5-WIf" secondAttribute="trailing" constant="10" id="vFR-5i-Dvo"/>
|
||||
<constraint firstItem="aNc-0i-CWK" firstAttribute="top" secondItem="1" secondAttribute="top" constant="15" id="vpR-tf-ebx"/>
|
||||
</constraints>
|
||||
</customView>
|
||||
</objects>
|
||||
</document>
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>icon</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionAttributes</key>
|
||||
<dict>
|
||||
<key>NSExtensionActivationRule</key>
|
||||
<dict>
|
||||
<key>NSExtensionActivationSupportsText</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.share-services</string>
|
||||
<key>NSExtensionPrincipalClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).ShareViewController</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.temporary-exception.mach-register.global-name</key>
|
||||
<string>org_atelierInmu_inputmethod_vChewing</string>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// ShareViewController.swift
|
||||
// KeyboardExtension
|
||||
//
|
||||
// Created by ShikiSuen on 2022/2/20.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
class ShareViewController: NSViewController {
|
||||
|
||||
override var nibName: NSNib.Name? {
|
||||
return NSNib.Name("ShareViewController")
|
||||
}
|
||||
|
||||
override func loadView() {
|
||||
super.loadView()
|
||||
|
||||
// Insert code here to customize the view
|
||||
let item = self.extensionContext!.inputItems[0] as! NSExtensionItem
|
||||
if let attachments = item.attachments {
|
||||
NSLog("Attachments = %@", attachments as NSArray)
|
||||
} else {
|
||||
NSLog("No Attachments")
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func send(_ sender: AnyObject?) {
|
||||
let outputItem = NSExtensionItem()
|
||||
// Complete implementation by setting the appropriate value on the output item
|
||||
|
||||
let outputItems = [outputItem]
|
||||
self.extensionContext!.completeRequest(returningItems: outputItems, completionHandler: nil)
|
||||
}
|
||||
|
||||
@IBAction func cancel(_ sender: AnyObject?) {
|
||||
let cancelError = NSError(domain: NSCocoaErrorDomain, code: NSUserCancelledError, userInfo: nil)
|
||||
self.extensionContext!.cancelRequest(withError: cancelError)
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
|
@ -8,48 +8,48 @@
|
|||
<string>vChewingKeyLayout</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>KLInfo_Zhuyin Dachen</key>
|
||||
<key>KLInfo_vChewingDachen</key>
|
||||
<dict>
|
||||
<key>TICapsLockLanguageSwitchCapable</key>
|
||||
<false/>
|
||||
<key>TISInputSourceID</key>
|
||||
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyindachen</string>
|
||||
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingDachen</string>
|
||||
<key>TISIntendedLanguage</key>
|
||||
<string>zh-Hanb</string>
|
||||
</dict>
|
||||
<key>KLInfo_Zhuyin ETen</key>
|
||||
<key>KLInfo_vChewingETen</key>
|
||||
<dict>
|
||||
<key>TICapsLockLanguageSwitchCapable</key>
|
||||
<false/>
|
||||
<key>TISInputSourceID</key>
|
||||
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyineten</string>
|
||||
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingETen</string>
|
||||
<key>TISIntendedLanguage</key>
|
||||
<string>zh-Hanb</string>
|
||||
</dict>
|
||||
<key>KLInfo_Zhuyin IBM</key>
|
||||
<key>KLInfo_vChewingIBM</key>
|
||||
<dict>
|
||||
<key>TICapsLockLanguageSwitchCapable</key>
|
||||
<false/>
|
||||
<key>TISInputSourceID</key>
|
||||
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyinibm</string>
|
||||
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingIBM</string>
|
||||
<key>TISIntendedLanguage</key>
|
||||
<string>zh-Hanb</string>
|
||||
</dict>
|
||||
<key>KLInfo_Zhuyin MiTAC</key>
|
||||
<key>KLInfo_vChewingMiTAC</key>
|
||||
<dict>
|
||||
<key>TICapsLockLanguageSwitchCapable</key>
|
||||
<false/>
|
||||
<key>TISInputSourceID</key>
|
||||
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyinmitac</string>
|
||||
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingMiTAC</string>
|
||||
<key>TISIntendedLanguage</key>
|
||||
<string>zh-Hanb</string>
|
||||
</dict>
|
||||
<key>KLInfo_Zhuyin Seigyou</key>
|
||||
<key>KLInfo_vChewingSeigyou</key>
|
||||
<dict>
|
||||
<key>TICapsLockLanguageSwitchCapable</key>
|
||||
<false/>
|
||||
<key>TISInputSourceID</key>
|
||||
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyinseigyou</string>
|
||||
<string>org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingSeigyou</string>
|
||||
<key>TISIntendedLanguage</key>
|
||||
<string>zh-Hanb</string>
|
||||
</dict>
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.1" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
|
||||
<!--Last edited by Ukelele version 351 on 2022-02-14 at 17:15 (GMT+8)-->
|
||||
<keyboard group="126" id="-1524" name="Zhuyin Dachen" maxout="1">
|
||||
<keyboard group="126" id="-1524" name="vChewing Dachen" maxout="1">
|
||||
<layouts>
|
||||
<layout first="0" last="17" mapSet="16c" modifiers="f4"/>
|
||||
<layout first="18" last="18" mapSet="a88" modifiers="f4"/>
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.1" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
|
||||
<!--Last edited by Ukelele version 351 on 2022-02-14 at 17:29 (GMT+8)-->
|
||||
<keyboard group="126" id="-2369" name="Zhuyin ETen" maxout="1">
|
||||
<keyboard group="126" id="-2369" name="vChewing ETen" maxout="1">
|
||||
<layouts>
|
||||
<layout first="0" last="17" mapSet="16c" modifiers="f4"/>
|
||||
<layout first="18" last="18" mapSet="a88" modifiers="f4"/>
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.1" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
|
||||
<!--Last edited by Ukelele version 351 on 2022-02-14 at 17:36 (GMT+8)-->
|
||||
<keyboard group="126" id="-28630" name="Zhuyin IBM" maxout="1">
|
||||
<keyboard group="126" id="-28630" name="vChewing IBM" maxout="1">
|
||||
<layouts>
|
||||
<layout first="0" last="17" mapSet="16c" modifiers="f4"/>
|
||||
<layout first="18" last="18" mapSet="a88" modifiers="f4"/>
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.1" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
|
||||
<!--Last edited by Ukelele version 351 on 2022-02-14 at 17:15 (GMT+8)-->
|
||||
<keyboard group="126" id="-7969" name="Zhuyin MiTAC" maxout="1">
|
||||
<keyboard group="126" id="-7969" name="vChewing MiTAC" maxout="1">
|
||||
<layouts>
|
||||
<layout first="0" last="17" mapSet="16c" modifiers="f4"/>
|
||||
<layout first="18" last="18" mapSet="a88" modifiers="f4"/>
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.1" encoding="UTF-8"?>
|
||||
<!DOCTYPE keyboard SYSTEM "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
|
||||
<!--Last edited by Ukelele version 351 on 2022-02-14 at 17:40 (GMT+8)-->
|
||||
<keyboard group="126" id="-17519" name="Zhuyin Seigyou" maxout="1">
|
||||
<keyboard group="126" id="-17519" name="vChewing Seigyou" maxout="1">
|
||||
<layouts>
|
||||
<layout first="0" last="17" mapSet="16c" modifiers="f4"/>
|
||||
<layout first="18" last="18" mapSet="a88" modifiers="f4"/>
|
Binary file not shown.
|
@ -1 +1 @@
|
|||
Subproject commit 36a71ee9d2e58611cd8466a1908f0a30274e261e
|
||||
Subproject commit 6dc73cd3edd47c85089db8f58e92f0c821e67ed6
|
|
@ -142,8 +142,8 @@ struct VersionUpdateApi {
|
|||
@objc(AppDelegate)
|
||||
class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelegate, FSEventStreamHelperDelegate {
|
||||
func helper(_ helper: FSEventStreamHelper, didReceive events: [FSEventStreamHelper.Event]) {
|
||||
// 拖一秒鐘再重載,畢竟有些有特殊需求的使用者可能會想使用巨型自訂語彙檔案。
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
|
||||
// 拖 100ms 再重載,畢竟有些有特殊需求的使用者可能會想使用巨型自訂語彙檔案。
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
|
||||
if Preferences.shouldAutoReloadUserDataFiles {
|
||||
mgrLangModel.loadUserPhrases()
|
||||
mgrLangModel.loadUserPhraseReplacement()
|
||||
|
@ -159,7 +159,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, ctlNonModalAlertWindowDelega
|
|||
private var ctlAboutWindowInstance: ctlAboutWindow? // New About Window
|
||||
private var checkTask: URLSessionTask?
|
||||
private var updateNextStepURL: URL?
|
||||
private var fsStreamHelper = FSEventStreamHelper(path: mgrLangModel.dataFolderPath, queue: DispatchQueue(label: "User Phrases"))
|
||||
private var fsStreamHelper = FSEventStreamHelper(path: mgrLangModel.dataFolderPath, queue: DispatchQueue(label: "vChewing User Phrases"))
|
||||
|
||||
// 補上 dealloc
|
||||
deinit {
|
||||
|
|
|
@ -182,9 +182,9 @@ class InputState: NSObject {
|
|||
let (exactEnd, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location + markedRange.length)
|
||||
let selectedReadings = readings[exactBegin..<exactEnd]
|
||||
let joined = selectedReadings.joined(separator: "-")
|
||||
let exist = mgrLangModel.checkIfExist(userPhrase: text, key: joined)
|
||||
let exist = mgrLangModel.checkIfUserPhraseExist(userPhrase: text, mode: ctlInputMethod.currentKeyHandler.inputMode, key: joined)
|
||||
if exist {
|
||||
return String(format: NSLocalizedString("\"%@\" already exists.", comment: ""), text)
|
||||
return String(format: NSLocalizedString("\"%@\" already exists, ENTER to boost its priority.", comment: ""), text)
|
||||
}
|
||||
|
||||
return String(format: NSLocalizedString("\"%@\" selected. ENTER to add user phrase.", comment: ""), text)
|
||||
|
@ -246,12 +246,16 @@ class InputState: NSObject {
|
|||
if markedRange.length > kMaxMarkRangeLength {
|
||||
return false
|
||||
}
|
||||
return markedRange.length >= kMinMarkRangeLength && markedRange.length <= kMaxMarkRangeLength
|
||||
}
|
||||
|
||||
@objc var chkIfUserPhraseExists: Bool {
|
||||
let text = (composingBuffer as NSString).substring(with: markedRange)
|
||||
let (exactBegin, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location)
|
||||
let (exactEnd, _) = (composingBuffer as NSString).characterIndex(from: markedRange.location + markedRange.length)
|
||||
let selectedReadings = readings[exactBegin..<exactEnd]
|
||||
let joined = selectedReadings.joined(separator: "-")
|
||||
return mgrLangModel.checkIfExist(userPhrase: text, key: joined) == false
|
||||
return mgrLangModel.checkIfUserPhraseExist(userPhrase: text, mode: ctlInputMethod.currentKeyHandler.inputMode, key: joined) == true
|
||||
}
|
||||
|
||||
@objc var userPhrase: String {
|
||||
|
|
|
@ -17,28 +17,23 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import "Mandarin.h"
|
||||
|
||||
#import "Gramambular.h"
|
||||
#import "vChewingLM.h"
|
||||
#import "UserOverrideModel.h"
|
||||
#import "mgrLangModel_Privates.h"
|
||||
#import "KeyHandler.h"
|
||||
#import "LMInstantiator.h"
|
||||
#import "Mandarin.h"
|
||||
#import "mgrLangModel_Privates.h"
|
||||
#import "UserOverrideModel.h"
|
||||
#import "vChewing-Swift.h"
|
||||
#import <string>
|
||||
|
||||
// C++ namespace usages
|
||||
using namespace std;
|
||||
using namespace Taiyan::Mandarin;
|
||||
using namespace Taiyan::Gramambular;
|
||||
using namespace vChewing;
|
||||
|
||||
InputMode imeModeCHT = @"org.atelierInmu.inputmethod.vChewing.IMECHT";
|
||||
InputMode imeModeCHS = @"org.atelierInmu.inputmethod.vChewing.IMECHS";
|
||||
InputMode imeModeNULL = @"org.atelierInmu.inputmethod.vChewing.IMENULL";
|
||||
|
||||
static const double kEpsilon = 0.000001;
|
||||
|
||||
static double FindHighestScore(const vector<NodeAnchor> &nodes, double epsilon) {
|
||||
static double FindHighestScore(const std::vector<Taiyan::Gramambular::NodeAnchor> &nodes, double epsilon) {
|
||||
double highestScore = 0.0;
|
||||
for (auto ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) {
|
||||
double score = ni->node->highestUnigramScore();
|
||||
|
@ -49,16 +44,15 @@ static double FindHighestScore(const vector<NodeAnchor> &nodes, double epsilon)
|
|||
return highestScore + epsilon;
|
||||
}
|
||||
|
||||
// sort helper
|
||||
class NodeAnchorDescendingSorter
|
||||
{
|
||||
class NodeAnchorDescendingSorter {
|
||||
public:
|
||||
bool operator()(const NodeAnchor &a, const NodeAnchor &b) const {
|
||||
bool operator()(const Taiyan::Gramambular::NodeAnchor &a, const Taiyan::Gramambular::NodeAnchor &b) const
|
||||
{
|
||||
return a.node->key().length() > b.node->key().length();
|
||||
}
|
||||
};
|
||||
|
||||
// if DEBUG is defined, a DOT file (GraphViz format) will be written to the
|
||||
;// if DEBUG is defined, a DOT file (GraphViz format) will be written to the
|
||||
// specified path every time the grid is walked
|
||||
#if DEBUG
|
||||
static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
||||
|
@ -71,7 +65,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
Taiyan::Mandarin::BopomofoReadingBuffer *_bpmfReadingBuffer;
|
||||
|
||||
// language model
|
||||
vChewing::vChewingLM *_languageModel;
|
||||
vChewing::LMInstantiator *_languageModel;
|
||||
|
||||
// user override model
|
||||
vChewing::UserOverrideModel *_userOverrideModel;
|
||||
|
@ -96,8 +90,8 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
- (void)setInputMode:(NSString *)value
|
||||
{
|
||||
NSString *newInputMode;
|
||||
vChewingLM *newLanguageModel;
|
||||
UserOverrideModel *newUserOverrideModel;
|
||||
vChewing::LMInstantiator *newLanguageModel;
|
||||
vChewing::UserOverrideModel *newUserOverrideModel;
|
||||
|
||||
if ([value isKindOfClass:[NSString class]] && [value isEqual:imeModeCHS]) {
|
||||
newInputMode = imeModeCHS;
|
||||
|
@ -120,7 +114,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
|
||||
if (_builder) {
|
||||
delete _builder;
|
||||
_builder = new BlockReadingBuilder(_languageModel);
|
||||
_builder = new Taiyan::Gramambular::BlockReadingBuilder(_languageModel);
|
||||
_builder->setJoinSeparator("-");
|
||||
}
|
||||
|
||||
|
@ -146,7 +140,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_bpmfReadingBuffer = new BopomofoReadingBuffer(BopomofoKeyboardLayout::StandardLayout());
|
||||
_bpmfReadingBuffer = new Taiyan::Mandarin::BopomofoReadingBuffer(Taiyan::Mandarin::BopomofoKeyboardLayout::StandardLayout());
|
||||
|
||||
// create the lattice builder
|
||||
_languageModel = [mgrLangModel lmCHT];
|
||||
|
@ -154,8 +148,8 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
_languageModel->setCNSEnabled(Preferences.cns11643Enabled);
|
||||
_userOverrideModel = [mgrLangModel userOverrideModelCHT];
|
||||
|
||||
_builder = new BlockReadingBuilder(_languageModel);
|
||||
|
||||
_builder = new Taiyan::Gramambular::BlockReadingBuilder(_languageModel);
|
||||
|
||||
// each Mandarin syllable is separated by a hyphen
|
||||
_builder->setJoinSeparator("-");
|
||||
_inputMode = imeModeCHT;
|
||||
|
@ -168,31 +162,31 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
NSInteger layout = Preferences.keyboardLayout;
|
||||
switch (layout) {
|
||||
case KeyboardLayoutStandard:
|
||||
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::StandardLayout());
|
||||
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::StandardLayout());
|
||||
break;
|
||||
case KeyboardLayoutEten:
|
||||
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::ETenLayout());
|
||||
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::ETenLayout());
|
||||
break;
|
||||
case KeyboardLayoutHsu:
|
||||
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::HsuLayout());
|
||||
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::HsuLayout());
|
||||
break;
|
||||
case KeyboardLayoutEten26:
|
||||
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::ETen26Layout());
|
||||
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::ETen26Layout());
|
||||
break;
|
||||
case KeyboardLayoutIBM:
|
||||
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::IBMLayout());
|
||||
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::IBMLayout());
|
||||
break;
|
||||
case KeyboardLayoutMiTAC:
|
||||
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::MiTACLayout());
|
||||
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::MiTACLayout());
|
||||
break;
|
||||
case KeyboardLayoutFakeSeigyou:
|
||||
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::FakeSeigyouLayout());
|
||||
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::FakeSeigyouLayout());
|
||||
break;
|
||||
case KeyboardLayoutHanyuPinyin:
|
||||
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::HanyuPinyinLayout());
|
||||
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::HanyuPinyinLayout());
|
||||
break;
|
||||
default:
|
||||
_bpmfReadingBuffer->setKeyboardLayout(BopomofoKeyboardLayout::StandardLayout());
|
||||
_bpmfReadingBuffer->setKeyboardLayout(Taiyan::Mandarin::BopomofoKeyboardLayout::StandardLayout());
|
||||
Preferences.keyboardLayout = KeyboardLayoutStandard;
|
||||
}
|
||||
}
|
||||
|
@ -200,8 +194,8 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
- (void)fixNodeWithValue:(NSString *)value
|
||||
{
|
||||
size_t cursorIndex = [self _actualCandidateCursorIndex];
|
||||
string stringValue = [value UTF8String];
|
||||
NodeAnchor selectedNode = _builder->grid().fixNodeSelectedCandidate(cursorIndex, stringValue);
|
||||
std::string stringValue(value.UTF8String);
|
||||
Taiyan::Gramambular::NodeAnchor selectedNode = _builder->grid().fixNodeSelectedCandidate(cursorIndex, stringValue);
|
||||
if (!Preferences.useSCPCTypingMode) { // 不要針對逐字選字模式啟用臨時半衰記憶模型。
|
||||
// If the length of the readings and the characters do not match,
|
||||
// it often means it is a special symbol and it should not be stored
|
||||
|
@ -234,10 +228,10 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
_walkedNodes.clear();
|
||||
}
|
||||
|
||||
- (string)_currentLayout
|
||||
- (std::string)_currentLayout
|
||||
{
|
||||
NSString *keyboardLayoutName = Preferences.keyboardLayoutName;
|
||||
string layout = string(keyboardLayoutName.UTF8String) + string("_");
|
||||
std::string layout = std::string(keyboardLayoutName.UTF8String) + std::string("_");
|
||||
return layout;
|
||||
}
|
||||
|
||||
|
@ -348,7 +342,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
composeReading |= (!_bpmfReadingBuffer->isEmpty() && ([input isSpace] || [input isEnterCharCode] || [input isEnter]));
|
||||
if (composeReading) {
|
||||
// combine the reading
|
||||
string reading = _bpmfReadingBuffer->syllable().composedString();
|
||||
std::string reading = _bpmfReadingBuffer->syllable().composedString();
|
||||
|
||||
// see if we have a unigram for this
|
||||
if (!_languageModel->hasUnigramsForKey(reading)) {
|
||||
|
@ -365,12 +359,12 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
NSString *poppedText = [self _popOverflowComposingTextAndWalk];
|
||||
|
||||
// get user override model suggestion
|
||||
string overrideValue = (Preferences.useSCPCTypingMode) ? "" :
|
||||
std::string overrideValue = (Preferences.useSCPCTypingMode) ? "" :
|
||||
_userOverrideModel->suggest(_walkedNodes, _builder->cursorIndex(), [[NSDate date] timeIntervalSince1970]);
|
||||
|
||||
if (!overrideValue.empty()) {
|
||||
size_t cursorIndex = [self _actualCandidateCursorIndex];
|
||||
vector<NodeAnchor> nodes = _builder->grid().nodesCrossingOrEndingAt(cursorIndex);
|
||||
std::vector<Taiyan::Gramambular::NodeAnchor> nodes = _builder->grid().nodesCrossingOrEndingAt(cursorIndex);
|
||||
double highestScore = FindHighestScore(nodes, kEpsilon);
|
||||
_builder->grid().overrideNodeScoreForSelectedCandidate(cursorIndex, overrideValue, static_cast<float>(highestScore));
|
||||
}
|
||||
|
@ -411,13 +405,13 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
return YES;
|
||||
}
|
||||
|
||||
// MARK: Space and Down, plus PageUp / PageDn / PageLeft / PageRight.
|
||||
// keyCode 125 = Down, charCode 32 = Space
|
||||
if (_bpmfReadingBuffer->isEmpty() &&
|
||||
[state isKindOfClass:[InputStateNotEmpty class]] &&
|
||||
([input isExtraChooseCandidateKey] || [input isExtraChooseCandidateKeyReverse]
|
||||
// MARK: Space and Down, plus PageUp / PageDn / PageLeft / PageRight.
|
||||
// keyCode 125 = Down, charCode 32 = Space
|
||||
if (_bpmfReadingBuffer->isEmpty() &&
|
||||
[state isKindOfClass:[InputStateNotEmpty class]] &&
|
||||
([input isExtraChooseCandidateKey] || [input isExtraChooseCandidateKeyReverse]
|
||||
|| [input isSpace] || [input isPageDown] || [input isPageUp]
|
||||
|| (input.useVerticalMode && ([input isVerticalModeOnlyChooseCandidateKey])))) {
|
||||
|| (input.useVerticalMode && ([input isVerticalModeOnlyChooseCandidateKey])))) {
|
||||
if ([input isSpace]) {
|
||||
// if the spacebar is NOT set to be a selection key
|
||||
if ([input isShiftHold] || !Preferences.chooseCandidateUsingSpace) {
|
||||
|
@ -521,7 +515,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
InputStateSymbolTable *symbolState = [[InputStateSymbolTable alloc] initWithNode:root useVerticalMode:input.useVerticalMode];
|
||||
stateCallback(symbolState);
|
||||
return YES;
|
||||
// if (_languageModel->hasUnigramsForKey(string("_punctuation_list"))) {
|
||||
// if (_languageModel->hasUnigramsForKey("_punctuation_list"))) {
|
||||
// if (_bpmfReadingBuffer->isEmpty()) {
|
||||
// _builder->insertReadingAtCursor(string("_punctuation_list"));
|
||||
// NSString *poppedText = [self _popOverflowComposingTextAndWalk];
|
||||
|
@ -540,28 +534,30 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
// MARK: Punctuation
|
||||
// if nothing is matched, see if it's a punctuation key for current layout.
|
||||
|
||||
string punctuationNamePrefix;
|
||||
std::string punctuationNamePrefix;
|
||||
if ([input isControlHold]) {
|
||||
punctuationNamePrefix = string("_ctrl_punctuation_");
|
||||
punctuationNamePrefix = std::string("_ctrl_punctuation_");
|
||||
} else if (Preferences.halfWidthPunctuationEnabled) {
|
||||
punctuationNamePrefix = string("_half_punctuation_");
|
||||
punctuationNamePrefix = std::string("_half_punctuation_");
|
||||
} else {
|
||||
punctuationNamePrefix = string("_punctuation_");
|
||||
punctuationNamePrefix = std::string("_punctuation_");
|
||||
}
|
||||
string layout = [self _currentLayout];
|
||||
string customPunctuation = punctuationNamePrefix + layout + string(1, (char) charCode);
|
||||
std::string layout = [self _currentLayout];
|
||||
std::string customPunctuation = punctuationNamePrefix + layout + std::string(1, (char) charCode);
|
||||
if ([self _handlePunctuation:customPunctuation state:state usingVerticalMode:input.useVerticalMode stateCallback:stateCallback errorCallback:errorCallback]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
// if nothing is matched, see if it's a punctuation key.
|
||||
string punctuation = punctuationNamePrefix + string(1, (char) charCode);
|
||||
std::string punctuation = punctuationNamePrefix + std::string(1, (char) charCode);
|
||||
if ([self _handlePunctuation:punctuation state:state usingVerticalMode:input.useVerticalMode stateCallback:stateCallback errorCallback:errorCallback]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ((char) charCode >= 'A' && (char) charCode <= 'Z') {
|
||||
string letter = string("_letter_") + string(1, (char) charCode);
|
||||
// Lukhnos 這裡的處理反而會使得 Apple 倚天注音動態鍵盤佈局「敲不了半形大寫英文」的缺點曝露無疑,所以注釋掉。
|
||||
// 至於他試圖用這種處理來解決的上游 UPR293 的問題,其實針對詞庫檔案的排序做點手腳就可以解決。威注音本來也就是這麼做的。
|
||||
if (/*[state isKindOfClass:[InputStateNotEmpty class]] && */(char) charCode >= 'A' && (char) charCode <= 'Z') {
|
||||
std::string letter = std::string("_letter_") + std::string(1, (char) charCode);
|
||||
if ([self _handlePunctuation:letter state:state usingVerticalMode:input.useVerticalMode stateCallback:stateCallback errorCallback:errorCallback]) {
|
||||
return YES;
|
||||
}
|
||||
|
@ -845,7 +841,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)_handlePunctuation:(string)customPunctuation state:(InputState *)state usingVerticalMode:(BOOL)useVerticalMode stateCallback:(void (^)(InputState *))stateCallback errorCallback:(void (^)(void))errorCallback
|
||||
- (BOOL)_handlePunctuation:(std::string)customPunctuation state:(InputState *)state usingVerticalMode:(BOOL)useVerticalMode stateCallback:(void (^)(InputState *))stateCallback errorCallback:(void (^)(void))errorCallback
|
||||
{
|
||||
if (!_languageModel->hasUnigramsForKey(customPunctuation)) {
|
||||
return NO;
|
||||
|
@ -1150,23 +1146,23 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
}
|
||||
|
||||
if (Preferences.useSCPCTypingMode) {
|
||||
string layout = [self _currentLayout];
|
||||
string punctuationNamePrefix;
|
||||
std::string layout = [self _currentLayout];
|
||||
std::string punctuationNamePrefix;
|
||||
if ([input isControlHold]) {
|
||||
punctuationNamePrefix = string("_ctrl_punctuation_");
|
||||
punctuationNamePrefix = std::string("_ctrl_punctuation_");
|
||||
} else if (Preferences.halfWidthPunctuationEnabled) {
|
||||
punctuationNamePrefix = string("_half_punctuation_");
|
||||
punctuationNamePrefix = std::string("_half_punctuation_");
|
||||
} else {
|
||||
punctuationNamePrefix = string("_punctuation_");
|
||||
punctuationNamePrefix = std::string("_punctuation_");
|
||||
}
|
||||
string customPunctuation = punctuationNamePrefix + layout + string(1, (char) charCode);
|
||||
string punctuation = punctuationNamePrefix + string(1, (char) charCode);
|
||||
std::string customPunctuation = punctuationNamePrefix + layout + std::string(1, (char) charCode);
|
||||
std::string punctuation = punctuationNamePrefix + std::string(1, (char) charCode);
|
||||
|
||||
BOOL shouldAutoSelectCandidate = _bpmfReadingBuffer->isValidKey((char) charCode) || _languageModel->hasUnigramsForKey(customPunctuation) ||
|
||||
_languageModel->hasUnigramsForKey(punctuation);
|
||||
|
||||
if (!shouldAutoSelectCandidate && (char) charCode >= 'A' && (char) charCode <= 'Z') {
|
||||
string letter = string("_letter_") + string(1, (char) charCode);
|
||||
std::string letter = std::string("_letter_") + std::string(1, (char) charCode);
|
||||
if (_languageModel->hasUnigramsForKey(letter)) {
|
||||
shouldAutoSelectCandidate = YES;
|
||||
}
|
||||
|
@ -1206,9 +1202,9 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
// we must do some Unicode codepoint counting to find the actual cursor location for the client
|
||||
// i.e. we need to take UTF-16 into consideration, for which a surrogate pair takes 2 UniChars
|
||||
// locations
|
||||
for (vector<NodeAnchor>::iterator wi = _walkedNodes.begin(), we = _walkedNodes.end(); wi != we; ++wi) {
|
||||
for (std::vector<Taiyan::Gramambular::NodeAnchor>::iterator wi = _walkedNodes.begin(), we = _walkedNodes.end(); wi != we; ++wi) {
|
||||
if ((*wi).node) {
|
||||
string nodeStr = (*wi).node->currentKeyValue().value;
|
||||
std::string nodeStr = (*wi).node->currentKeyValue().value;
|
||||
NSString *valueString = [NSString stringWithUTF8String:nodeStr.c_str()];
|
||||
[composingBuffer appendString:valueString];
|
||||
|
||||
|
@ -1274,7 +1270,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
// retrieve the most likely trellis, i.e. a Maximum Likelihood Estimation
|
||||
// of the best possible Mandarain characters given the input syllables,
|
||||
// using the Viterbi algorithm implemented in the Gramambular library
|
||||
Walker walker(&_builder->grid());
|
||||
Taiyan::Gramambular::Walker walker(&_builder->grid());
|
||||
|
||||
// the reverse walk traces the trellis from the end
|
||||
_walkedNodes = walker.reverseWalk(_builder->grid().width());
|
||||
|
@ -1284,7 +1280,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
|
||||
// if DEBUG is defined, a GraphViz file is written to kGraphVizOutputfile
|
||||
#if DEBUG
|
||||
string dotDump = _builder->grid().dumpDOT();
|
||||
std::string dotDump = _builder->grid().dumpDOT();
|
||||
NSString *dotStr = [NSString stringWithUTF8String:dotDump.c_str()];
|
||||
NSError *error = nil;
|
||||
|
||||
|
@ -1307,7 +1303,7 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
|
||||
if (_builder->grid().width() > (size_t) composingBufferSize) {
|
||||
if (_walkedNodes.size() > 0) {
|
||||
NodeAnchor &anchor = _walkedNodes[0];
|
||||
Taiyan::Gramambular::NodeAnchor &anchor = _walkedNodes[0];
|
||||
poppedText = [NSString stringWithUTF8String:anchor.node->currentKeyValue().value.c_str()];
|
||||
_builder->removeHeadReadings(anchor.spanningLength);
|
||||
}
|
||||
|
@ -1322,15 +1318,15 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
NSMutableArray *candidatesArray = [[NSMutableArray alloc] init];
|
||||
|
||||
size_t cursorIndex = [self _actualCandidateCursorIndex];
|
||||
vector<NodeAnchor> nodes = _builder->grid().nodesCrossingOrEndingAt(cursorIndex);
|
||||
std::vector<Taiyan::Gramambular::NodeAnchor> nodes = _builder->grid().nodesCrossingOrEndingAt(cursorIndex);
|
||||
|
||||
// sort the nodes, so that longer nodes (representing longer phrases) are placed at the top of the candidate list
|
||||
stable_sort(nodes.begin(), nodes.end(), NodeAnchorDescendingSorter());
|
||||
|
||||
// then use the C++ trick to retrieve the candidates for each node at/crossing the cursor
|
||||
for (vector<NodeAnchor>::iterator ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) {
|
||||
const vector<KeyValuePair> &candidates = (*ni).node->candidates();
|
||||
for (vector<KeyValuePair>::const_iterator ci = candidates.begin(), ce = candidates.end(); ci != ce; ++ci) {
|
||||
for (std::vector<Taiyan::Gramambular::NodeAnchor>::iterator ni = nodes.begin(), ne = nodes.end(); ni != ne; ++ni) {
|
||||
const std::vector<Taiyan::Gramambular::KeyValuePair> &candidates = (*ni).node->candidates();
|
||||
for (std::vector<Taiyan::Gramambular::KeyValuePair>::const_iterator ci = candidates.begin(), ce = candidates.end(); ci != ce; ++ci) {
|
||||
[candidatesArray addObject:[NSString stringWithUTF8String:(*ci).value.c_str()]];
|
||||
}
|
||||
}
|
||||
|
@ -1359,8 +1355,8 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
- (NSArray *)_currentReadings
|
||||
{
|
||||
NSMutableArray *readingsArray = [[NSMutableArray alloc] init];
|
||||
vector<std::string> v = _builder->readings();
|
||||
for (vector<std::string>::iterator it_i = v.begin(); it_i != v.end(); ++it_i) {
|
||||
std::vector<std::string> v = _builder->readings();
|
||||
for (std::vector<std::string>::iterator it_i = v.begin(); it_i != v.end(); ++it_i) {
|
||||
[readingsArray addObject:[NSString stringWithUTF8String:it_i->c_str()]];
|
||||
}
|
||||
return readingsArray;
|
||||
|
@ -1368,9 +1364,9 @@ static NSString *const kGraphVizOutputfile = @"/tmp/vChewing-visualization.dot";
|
|||
|
||||
- (nullable InputState *)buildAssociatePhraseStateWithKey:(NSString *)key useVerticalMode:(BOOL)useVerticalMode
|
||||
{
|
||||
string cppKey = string(key.UTF8String);
|
||||
std::string cppKey = std::string(key.UTF8String);
|
||||
if (_languageModel->hasAssociatedPhrasesForKey(cppKey)) {
|
||||
vector<string> phrases = _languageModel->associatedPhrasesForKey(cppKey);
|
||||
std::vector<std::string> phrases = _languageModel->associatedPhrasesForKey(cppKey);
|
||||
NSMutableArray <NSString *> *array = [NSMutableArray array];
|
||||
for (auto phrase: phrases) {
|
||||
NSString *item = [[NSString alloc] initWithUTF8String:phrase.c_str()];
|
||||
|
|
|
@ -37,7 +37,7 @@ class LMConsolidator
|
|||
public:
|
||||
static bool CheckPragma(const char *path);
|
||||
static bool FixEOF(const char *path);
|
||||
static bool ConsolidateContent(const char *path, bool shouldsort);
|
||||
static bool ConsolidateContent(const char *path, bool shouldsort, bool shouldCheckPragma);
|
||||
};
|
||||
|
||||
} // namespace vChewing
|
||||
|
|
|
@ -71,8 +71,8 @@ bool LMConsolidator::FixEOF(const char *path)
|
|||
} // END: EOF FIXER.
|
||||
|
||||
// CONTENT CONSOLIDATOR. CREDIT: Shiki Suen.
|
||||
bool LMConsolidator::ConsolidateContent(const char *path, bool shouldsort) {
|
||||
if (LMConsolidator::CheckPragma(path) && !shouldsort){
|
||||
bool LMConsolidator::ConsolidateContent(const char *path, bool shouldsort, bool shouldCheckPragma) {
|
||||
if (LMConsolidator::CheckPragma(path) && !shouldsort && shouldCheckPragma){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,13 @@ class ctlInputMethod: IMKInputController {
|
|||
private var keyHandler: KeyHandler = KeyHandler()
|
||||
private var state: InputState = InputState.Empty()
|
||||
|
||||
// 想讓 keyHandler 能夠被外界調查狀態與參數的話,就得對 keyHandler 做常態處理。
|
||||
// 這樣 InputState 可以藉由這個 ctlInputMethod 了解到當前的輸入模式是簡體中文還是繁體中文。
|
||||
// 然而,要是直接對 keyHandler 做常態處理的話,反而會導致 keyHandlerInput 無法協同處理。
|
||||
// 所以才需要「currentKeyHandler」這個假 keyHandler。
|
||||
// 這個「currentKeyHandler」僅用來讓其他模組知道當前的輸入模式是什麼模式,除此之外別無屌用。
|
||||
static var currentKeyHandler: KeyHandler = KeyHandler()
|
||||
|
||||
// MARK: - IMKInputController methods
|
||||
|
||||
override init!(server: IMKServer!, delegate: Any!, client inputClient: Any!) {
|
||||
|
@ -157,6 +164,8 @@ class ctlInputMethod: IMKInputController {
|
|||
keyHandler.inputMode = newInputMode
|
||||
self.handle(state: .Empty(), client: client)
|
||||
}
|
||||
// 讓外界知道目前的簡繁體輸入模式。
|
||||
ctlInputMethod.currentKeyHandler.inputMode = keyHandler.inputMode
|
||||
}
|
||||
|
||||
// MARK: - IMKServerInput protocol methods
|
||||
|
@ -603,7 +612,7 @@ extension ctlInputMethod: KeyHandlerDelegate {
|
|||
if !state.validToWrite {
|
||||
return false
|
||||
}
|
||||
mgrLangModel.writeUserPhrase(state.userPhrase, inputMode: keyHandler.inputMode)
|
||||
mgrLangModel.writeUserPhrase(state.userPhrase, inputMode: keyHandler.inputMode, areWeDuplicating: state.chkIfUserPhraseExists)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,22 +17,22 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef VCHEWINGLM_H
|
||||
#define VCHEWINGLM_H
|
||||
#ifndef LMInstantiator_H
|
||||
#define LMInstantiator_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "UserPhrasesLM.h"
|
||||
#include "ParselessLM.h"
|
||||
#include "CNSLM.h"
|
||||
#include "PhraseReplacementMap.h"
|
||||
#include "AssociatedPhrases.h"
|
||||
#include "CNSLM.h"
|
||||
#include "ParselessLM.h"
|
||||
#include "PhraseReplacementMap.h"
|
||||
#include "UserPhrasesLM.h"
|
||||
#include <stdio.h>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace vChewing {
|
||||
|
||||
using namespace Taiyan::Gramambular;
|
||||
|
||||
/// vChewingLM is a facade for managing a set of models including
|
||||
/// LMInstantiator is a facade for managing a set of models including
|
||||
/// the input method language model, user phrases and excluded phrases.
|
||||
///
|
||||
/// It is the primary model class that the input controller and grammar builder
|
||||
|
@ -41,7 +41,7 @@ using namespace Taiyan::Gramambular;
|
|||
/// if there are valid unigrams, and use returned unigrams to produce the final
|
||||
/// results.
|
||||
///
|
||||
/// vChewingLM combine and transform the unigrams from the primary language
|
||||
/// LMInstantiator combine and transform the unigrams from the primary language
|
||||
/// model and user phrases. The process is
|
||||
///
|
||||
/// 1) Get the original unigrams.
|
||||
|
@ -54,10 +54,10 @@ using namespace Taiyan::Gramambular;
|
|||
/// model while launching and to load the user phrases anytime if the custom
|
||||
/// files are modified. It does not keep the reference of the data pathes but
|
||||
/// you have to pass the paths when you ask it to do loading.
|
||||
class vChewingLM : public LanguageModel {
|
||||
class LMInstantiator : public Taiyan::Gramambular::LanguageModel {
|
||||
public:
|
||||
vChewingLM();
|
||||
~vChewingLM();
|
||||
LMInstantiator();
|
||||
~LMInstantiator();
|
||||
|
||||
/// Asks to load the primary language model at the given path.
|
||||
/// @param languageModelPath The path of the language model.
|
||||
|
@ -83,14 +83,14 @@ public:
|
|||
void loadPhraseReplacementMap(const char* phraseReplacementPath);
|
||||
|
||||
/// Not implemented since we do not have data to provide bigram function.
|
||||
const vector<Bigram> bigramsForKeys(const string& preceedingKey, const string& key);
|
||||
const std::vector<Taiyan::Gramambular::Bigram> bigramsForKeys(const std::string& preceedingKey, const std::string& key);
|
||||
/// Returns a list of available unigram for the given key.
|
||||
/// @param key A string represents the BPMF reading or a symbol key. For
|
||||
/// @param key A std::string represents the BPMF reading or a symbol key. For
|
||||
/// example, it you pass "ㄇㄚ", it returns "嗎", "媽", and so on.
|
||||
const vector<Unigram> unigramsForKey(const string& key);
|
||||
const std::vector<Taiyan::Gramambular::Unigram> unigramsForKey(const std::string& key);
|
||||
/// If the model has unigrams for the given key.
|
||||
/// @param key The key.
|
||||
bool hasUnigramsForKey(const string& key);
|
||||
bool hasUnigramsForKey(const std::string& key);
|
||||
|
||||
/// Enables or disables phrase replacement.
|
||||
void setPhraseReplacementEnabled(bool enabled);
|
||||
|
@ -107,10 +107,10 @@ public:
|
|||
/// If the external converted is enabled or not.
|
||||
bool externalConverterEnabled();
|
||||
/// Sets a lambda to let the values of unigrams could be converted by it.
|
||||
void setExternalConverter(std::function<string(string)> externalConverter);
|
||||
void setExternalConverter(std::function<std::string(std::string)> externalConverter);
|
||||
|
||||
const vector<std::string> associatedPhrasesForKey(const string& key);
|
||||
bool hasAssociatedPhrasesForKey(const string& key);
|
||||
const std::vector<std::string> associatedPhrasesForKey(const std::string& key);
|
||||
bool hasAssociatedPhrasesForKey(const std::string& key);
|
||||
|
||||
|
||||
protected:
|
||||
|
@ -121,9 +121,9 @@ protected:
|
|||
/// @param insertedValues The values for unigrams already in the results.
|
||||
/// It helps to prevent duplicated unigrams. Please note that the method
|
||||
/// has a side effect that it inserts values to `insertedValues`.
|
||||
const vector<Unigram> filterAndTransformUnigrams(const vector<Unigram> unigrams,
|
||||
const std::unordered_set<string>& excludedValues,
|
||||
std::unordered_set<string>& insertedValues);
|
||||
const std::vector<Taiyan::Gramambular::Unigram> filterAndTransformUnigrams(const std::vector<Taiyan::Gramambular::Unigram> unigrams,
|
||||
const std::unordered_set<std::string>& excludedValues,
|
||||
std::unordered_set<std::string>& insertedValues);
|
||||
|
||||
ParselessLM m_languageModel;
|
||||
CNSLM m_cnsModel;
|
||||
|
@ -134,7 +134,7 @@ protected:
|
|||
bool m_phraseReplacementEnabled;
|
||||
bool m_cnsEnabled;
|
||||
bool m_externalConverterEnabled;
|
||||
std::function<string(string)> m_externalConverter;
|
||||
std::function<std::string(std::string)> m_externalConverter;
|
||||
};
|
||||
};
|
||||
|
|
@ -17,17 +17,17 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "vChewingLM.h"
|
||||
#include "LMInstantiator.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
using namespace vChewing;
|
||||
namespace vChewing {
|
||||
|
||||
vChewingLM::vChewingLM()
|
||||
LMInstantiator::LMInstantiator()
|
||||
{
|
||||
}
|
||||
|
||||
vChewingLM::~vChewingLM()
|
||||
LMInstantiator::~LMInstantiator()
|
||||
{
|
||||
m_languageModel.close();
|
||||
m_userPhrases.close();
|
||||
|
@ -37,7 +37,7 @@ vChewingLM::~vChewingLM()
|
|||
m_associatedPhrases.close();
|
||||
}
|
||||
|
||||
void vChewingLM::loadLanguageModel(const char* languageModelDataPath)
|
||||
void LMInstantiator::loadLanguageModel(const char* languageModelDataPath)
|
||||
{
|
||||
if (languageModelDataPath) {
|
||||
m_languageModel.close();
|
||||
|
@ -45,12 +45,12 @@ void vChewingLM::loadLanguageModel(const char* languageModelDataPath)
|
|||
}
|
||||
}
|
||||
|
||||
bool vChewingLM::isDataModelLoaded()
|
||||
bool LMInstantiator::isDataModelLoaded()
|
||||
{
|
||||
return m_languageModel.isLoaded();
|
||||
}
|
||||
|
||||
void vChewingLM::loadCNSData(const char* cnsDataPath)
|
||||
void LMInstantiator::loadCNSData(const char* cnsDataPath)
|
||||
{
|
||||
if (cnsDataPath) {
|
||||
m_cnsModel.close();
|
||||
|
@ -58,12 +58,12 @@ void vChewingLM::loadCNSData(const char* cnsDataPath)
|
|||
}
|
||||
}
|
||||
|
||||
bool vChewingLM::isCNSDataLoaded()
|
||||
bool LMInstantiator::isCNSDataLoaded()
|
||||
{
|
||||
return m_cnsModel.isLoaded();
|
||||
}
|
||||
|
||||
void vChewingLM::loadUserPhrases(const char* userPhrasesDataPath,
|
||||
void LMInstantiator::loadUserPhrases(const char* userPhrasesDataPath,
|
||||
const char* excludedPhrasesDataPath)
|
||||
{
|
||||
if (userPhrasesDataPath) {
|
||||
|
@ -76,7 +76,7 @@ void vChewingLM::loadUserPhrases(const char* userPhrasesDataPath,
|
|||
}
|
||||
}
|
||||
|
||||
void vChewingLM::loadUserAssociatedPhrases(const char *userAssociatedPhrasesPath)
|
||||
void LMInstantiator::loadUserAssociatedPhrases(const char *userAssociatedPhrasesPath)
|
||||
{
|
||||
if (userAssociatedPhrasesPath) {
|
||||
m_associatedPhrases.close();
|
||||
|
@ -84,7 +84,7 @@ void vChewingLM::loadUserAssociatedPhrases(const char *userAssociatedPhrasesPath
|
|||
}
|
||||
}
|
||||
|
||||
void vChewingLM::loadPhraseReplacementMap(const char* phraseReplacementPath)
|
||||
void LMInstantiator::loadPhraseReplacementMap(const char* phraseReplacementPath)
|
||||
{
|
||||
if (phraseReplacementPath) {
|
||||
m_phraseReplacement.close();
|
||||
|
@ -92,49 +92,49 @@ void vChewingLM::loadPhraseReplacementMap(const char* phraseReplacementPath)
|
|||
}
|
||||
}
|
||||
|
||||
const vector<Bigram> vChewingLM::bigramsForKeys(const string& preceedingKey, const string& key)
|
||||
const std::vector<Taiyan::Gramambular::Bigram> LMInstantiator::bigramsForKeys(const std::string& preceedingKey, const std::string& key)
|
||||
{
|
||||
return vector<Bigram>();
|
||||
return std::vector<Taiyan::Gramambular::Bigram>();
|
||||
}
|
||||
|
||||
const vector<Unigram> vChewingLM::unigramsForKey(const string& key)
|
||||
const std::vector<Taiyan::Gramambular::Unigram> LMInstantiator::unigramsForKey(const std::string& key)
|
||||
{
|
||||
if (key == " ") {
|
||||
vector<Unigram> spaceUnigrams;
|
||||
Unigram g;
|
||||
std::vector<Taiyan::Gramambular::Unigram> spaceUnigrams;
|
||||
Taiyan::Gramambular::Unigram g;
|
||||
g.keyValue.key = " ";
|
||||
g.keyValue.value= " ";
|
||||
g.keyValue.value = " ";
|
||||
g.score = 0;
|
||||
spaceUnigrams.push_back(g);
|
||||
return spaceUnigrams;
|
||||
}
|
||||
|
||||
vector<Unigram> allUnigrams;
|
||||
vector<Unigram> userUnigrams;
|
||||
vector<Unigram> cnsUnigrams;
|
||||
std::vector<Taiyan::Gramambular::Unigram> allUnigrams;
|
||||
std::vector<Taiyan::Gramambular::Unigram> userUnigrams;
|
||||
std::vector<Taiyan::Gramambular::Unigram> cnsUnigrams;
|
||||
|
||||
unordered_set<string> excludedValues;
|
||||
unordered_set<string> insertedValues;
|
||||
std::unordered_set<std::string> excludedValues;
|
||||
std::unordered_set<std::string> insertedValues;
|
||||
|
||||
if (m_excludedPhrases.hasUnigramsForKey(key)) {
|
||||
vector<Unigram> excludedUnigrams = m_excludedPhrases.unigramsForKey(key);
|
||||
std::vector<Taiyan::Gramambular::Unigram> excludedUnigrams = m_excludedPhrases.unigramsForKey(key);
|
||||
transform(excludedUnigrams.begin(), excludedUnigrams.end(),
|
||||
inserter(excludedValues, excludedValues.end()),
|
||||
[](const Unigram& u) { return u.keyValue.value; });
|
||||
[](const Taiyan::Gramambular::Unigram& u) { return u.keyValue.value; });
|
||||
}
|
||||
|
||||
if (m_userPhrases.hasUnigramsForKey(key)) {
|
||||
vector<Unigram> rawUserUnigrams = m_userPhrases.unigramsForKey(key);
|
||||
std::vector<Taiyan::Gramambular::Unigram> rawUserUnigrams = m_userPhrases.unigramsForKey(key);
|
||||
userUnigrams = filterAndTransformUnigrams(rawUserUnigrams, excludedValues, insertedValues);
|
||||
}
|
||||
|
||||
if (m_languageModel.hasUnigramsForKey(key)) {
|
||||
vector<Unigram> rawGlobalUnigrams = m_languageModel.unigramsForKey(key);
|
||||
std::vector<Taiyan::Gramambular::Unigram> rawGlobalUnigrams = m_languageModel.unigramsForKey(key);
|
||||
allUnigrams = filterAndTransformUnigrams(rawGlobalUnigrams, excludedValues, insertedValues);
|
||||
}
|
||||
|
||||
if (m_cnsModel.hasUnigramsForKey(key) && m_cnsEnabled) {
|
||||
vector<Unigram> rawCNSUnigrams = m_cnsModel.unigramsForKey(key);
|
||||
std::vector<Taiyan::Gramambular::Unigram> rawCNSUnigrams = m_cnsModel.unigramsForKey(key);
|
||||
cnsUnigrams = filterAndTransformUnigrams(rawCNSUnigrams, excludedValues, insertedValues);
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ const vector<Unigram> vChewingLM::unigramsForKey(const string& key)
|
|||
return allUnigrams;
|
||||
}
|
||||
|
||||
bool vChewingLM::hasUnigramsForKey(const string& key)
|
||||
bool LMInstantiator::hasUnigramsForKey(const std::string& key)
|
||||
{
|
||||
if (key == " ") {
|
||||
return true;
|
||||
|
@ -156,65 +156,65 @@ bool vChewingLM::hasUnigramsForKey(const string& key)
|
|||
return unigramsForKey(key).size() > 0;
|
||||
}
|
||||
|
||||
void vChewingLM::setPhraseReplacementEnabled(bool enabled)
|
||||
void LMInstantiator::setPhraseReplacementEnabled(bool enabled)
|
||||
{
|
||||
m_phraseReplacementEnabled = enabled;
|
||||
}
|
||||
|
||||
bool vChewingLM::phraseReplacementEnabled()
|
||||
bool LMInstantiator::phraseReplacementEnabled()
|
||||
{
|
||||
return m_phraseReplacementEnabled;
|
||||
}
|
||||
|
||||
void vChewingLM::setCNSEnabled(bool enabled)
|
||||
void LMInstantiator::setCNSEnabled(bool enabled)
|
||||
{
|
||||
m_cnsEnabled = enabled;
|
||||
}
|
||||
bool vChewingLM::cnsEnabled()
|
||||
bool LMInstantiator::cnsEnabled()
|
||||
{
|
||||
return m_cnsEnabled;
|
||||
}
|
||||
|
||||
void vChewingLM::setExternalConverterEnabled(bool enabled)
|
||||
void LMInstantiator::setExternalConverterEnabled(bool enabled)
|
||||
{
|
||||
m_externalConverterEnabled = enabled;
|
||||
}
|
||||
|
||||
bool vChewingLM::externalConverterEnabled()
|
||||
bool LMInstantiator::externalConverterEnabled()
|
||||
{
|
||||
return m_externalConverterEnabled;
|
||||
}
|
||||
|
||||
void vChewingLM::setExternalConverter(std::function<string(string)> externalConverter)
|
||||
void LMInstantiator::setExternalConverter(std::function<std::string(std::string)> externalConverter)
|
||||
{
|
||||
m_externalConverter = externalConverter;
|
||||
}
|
||||
|
||||
const vector<Unigram> vChewingLM::filterAndTransformUnigrams(const vector<Unigram> unigrams, const unordered_set<string>& excludedValues, unordered_set<string>& insertedValues)
|
||||
const std::vector<Taiyan::Gramambular::Unigram> LMInstantiator::filterAndTransformUnigrams(const std::vector<Taiyan::Gramambular::Unigram> unigrams, const std::unordered_set<std::string>& excludedValues, std::unordered_set<std::string>& insertedValues)
|
||||
{
|
||||
vector<Unigram> results;
|
||||
std::vector<Taiyan::Gramambular::Unigram> results;
|
||||
|
||||
for (auto&& unigram : unigrams) {
|
||||
// excludedValues filters out the unigrams with the original value.
|
||||
// insertedValues filters out the ones with the converted value
|
||||
string originalValue = unigram.keyValue.value;
|
||||
std::string originalValue = unigram.keyValue.value;
|
||||
if (excludedValues.find(originalValue) != excludedValues.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string value = originalValue;
|
||||
std::string value = originalValue;
|
||||
if (m_phraseReplacementEnabled) {
|
||||
string replacement = m_phraseReplacement.valueForKey(value);
|
||||
std::string replacement = m_phraseReplacement.valueForKey(value);
|
||||
if (replacement != "") {
|
||||
value = replacement;
|
||||
}
|
||||
}
|
||||
if (m_externalConverterEnabled && m_externalConverter) {
|
||||
string replacement = m_externalConverter(value);
|
||||
std::string replacement = m_externalConverter(value);
|
||||
value = replacement;
|
||||
}
|
||||
if (insertedValues.find(value) == insertedValues.end()) {
|
||||
Unigram g;
|
||||
Taiyan::Gramambular::Unigram g;
|
||||
g.keyValue.value = value;
|
||||
g.keyValue.key = unigram.keyValue.key;
|
||||
g.score = unigram.score;
|
||||
|
@ -225,12 +225,14 @@ const vector<Unigram> vChewingLM::filterAndTransformUnigrams(const vector<Unigra
|
|||
return results;
|
||||
}
|
||||
|
||||
const vector<std::string> vChewingLM::associatedPhrasesForKey(const string& key)
|
||||
const std::vector<std::string> LMInstantiator::associatedPhrasesForKey(const std::string& key)
|
||||
{
|
||||
return m_associatedPhrases.valuesForKey(key);
|
||||
}
|
||||
|
||||
bool vChewingLM::hasAssociatedPhrasesForKey(const string& key)
|
||||
bool LMInstantiator::hasAssociatedPhrasesForKey(const std::string& key)
|
||||
{
|
||||
return m_associatedPhrases.hasValuesForKey(key);
|
||||
}
|
||||
|
||||
} // namespace vChewing
|
|
@ -59,12 +59,7 @@ bool AssociatedPhrases::open(const char *path)
|
|||
}
|
||||
|
||||
LMConsolidator::FixEOF(path);
|
||||
|
||||
if (Preferences.shouldAutoSortAssociatedPhrasesOnLoad) {
|
||||
LMConsolidator::ConsolidateContent(path, true);
|
||||
} else {
|
||||
LMConsolidator::ConsolidateContent(path, false);
|
||||
}
|
||||
LMConsolidator::ConsolidateContent(path, Preferences.shouldAutoSortAssociatedPhrasesOnLoad, true);
|
||||
|
||||
fd = ::open(path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
|
|
|
@ -45,8 +45,8 @@ public:
|
|||
void close();
|
||||
void dump();
|
||||
|
||||
virtual const vector<Bigram> bigramsForKeys(const string& preceedingKey, const string& key);
|
||||
virtual const vector<Unigram> unigramsForKey(const string& key);
|
||||
virtual const std::vector<Taiyan::Gramambular::Bigram> bigramsForKeys(const string& preceedingKey, const string& key);
|
||||
virtual const std::vector<Taiyan::Gramambular::Unigram> unigramsForKey(const string& key);
|
||||
virtual bool hasUnigramsForKey(const string& key);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -281,14 +281,14 @@ void vChewing::CoreLM::dump()
|
|||
}
|
||||
}
|
||||
|
||||
const vector<Bigram> vChewing::CoreLM::bigramsForKeys(const string& preceedingKey, const string& key)
|
||||
const std::vector<Taiyan::Gramambular::Bigram> vChewing::CoreLM::bigramsForKeys(const string& preceedingKey, const string& key)
|
||||
{
|
||||
return vector<Bigram>();
|
||||
return std::vector<Taiyan::Gramambular::Bigram>();
|
||||
}
|
||||
|
||||
const vector<Unigram> vChewing::CoreLM::unigramsForKey(const string& key)
|
||||
const std::vector<Taiyan::Gramambular::Unigram> vChewing::CoreLM::unigramsForKey(const string& key)
|
||||
{
|
||||
vector<Unigram> v;
|
||||
std::vector<Taiyan::Gramambular::Unigram> v;
|
||||
map<const char *, vector<Row> >::const_iterator i = keyRowMap.find(key.c_str());
|
||||
|
||||
if (i != keyRowMap.end()) {
|
||||
|
|
|
@ -54,12 +54,7 @@ bool PhraseReplacementMap::open(const char *path)
|
|||
}
|
||||
|
||||
LMConsolidator::FixEOF(path);
|
||||
|
||||
if (Preferences.shouldAutoSortPhraseReplacementMapOnLoad) {
|
||||
LMConsolidator::ConsolidateContent(path, true);
|
||||
} else {
|
||||
LMConsolidator::ConsolidateContent(path, false);
|
||||
}
|
||||
LMConsolidator::ConsolidateContent(path, Preferences.shouldAutoSortPhraseReplacementMapOnLoad, true);
|
||||
|
||||
fd = ::open(path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
|
|
|
@ -23,7 +23,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
|
|||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
using namespace vChewing;
|
||||
namespace vChewing {
|
||||
|
||||
// About 20 generations.
|
||||
static const double DecayThreshould = 1.0 / 1048576.0;
|
||||
|
@ -33,8 +33,8 @@ static double Score(size_t eventCount,
|
|||
double eventTimestamp,
|
||||
double timestamp,
|
||||
double lambda);
|
||||
static bool IsEndingPunctuation(const string& value);
|
||||
static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
|
||||
static bool IsEndingPunctuation(const std::string& value);
|
||||
static std::string WalkedNodesToKey(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
|
||||
size_t cursorIndex);
|
||||
|
||||
UserOverrideModel::UserOverrideModel(size_t capacity, double decayConstant)
|
||||
|
@ -43,11 +43,11 @@ UserOverrideModel::UserOverrideModel(size_t capacity, double decayConstant)
|
|||
m_decayExponent = log(0.5) / decayConstant;
|
||||
}
|
||||
|
||||
void UserOverrideModel::observe(const std::vector<NodeAnchor>& walkedNodes,
|
||||
void UserOverrideModel::observe(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
|
||||
size_t cursorIndex,
|
||||
const string& candidate,
|
||||
const std::string& candidate,
|
||||
double timestamp) {
|
||||
string key = WalkedNodesToKey(walkedNodes, cursorIndex);
|
||||
std::string key = WalkedNodesToKey(walkedNodes, cursorIndex);
|
||||
auto mapIter = m_lruMap.find(key);
|
||||
if (mapIter == m_lruMap.end()) {
|
||||
auto keyValuePair = KeyObservationPair(key, Observation());
|
||||
|
@ -76,20 +76,20 @@ void UserOverrideModel::observe(const std::vector<NodeAnchor>& walkedNodes,
|
|||
}
|
||||
}
|
||||
|
||||
string UserOverrideModel::suggest(const std::vector<NodeAnchor>& walkedNodes,
|
||||
std::string UserOverrideModel::suggest(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
|
||||
size_t cursorIndex,
|
||||
double timestamp) {
|
||||
string key = WalkedNodesToKey(walkedNodes, cursorIndex);
|
||||
std::string key = WalkedNodesToKey(walkedNodes, cursorIndex);
|
||||
auto mapIter = m_lruMap.find(key);
|
||||
if (mapIter == m_lruMap.end()) {
|
||||
return string();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
auto listIter = mapIter->second;
|
||||
auto& keyValuePair = *listIter;
|
||||
const Observation& observation = keyValuePair.second;
|
||||
|
||||
string candidate;
|
||||
std::string candidate;
|
||||
double score = 0.0;
|
||||
for (auto i = observation.overrides.begin();
|
||||
i != observation.overrides.end();
|
||||
|
@ -112,7 +112,7 @@ string UserOverrideModel::suggest(const std::vector<NodeAnchor>& walkedNodes,
|
|||
return candidate;
|
||||
}
|
||||
|
||||
void UserOverrideModel::Observation::update(const string& candidate,
|
||||
void UserOverrideModel::Observation::update(const std::string& candidate,
|
||||
double timestamp) {
|
||||
count++;
|
||||
auto& o = overrides[candidate];
|
||||
|
@ -134,16 +134,16 @@ static double Score(size_t eventCount,
|
|||
return prob * decay;
|
||||
}
|
||||
|
||||
static bool IsEndingPunctuation(const string& value) {
|
||||
static bool IsEndingPunctuation(const std::string& value) {
|
||||
return value == "," || value == "。" || value== "!" || value == "?" ||
|
||||
value == "」" || value == "』" || value== "”" || value == "’";
|
||||
}
|
||||
static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
|
||||
static std::string WalkedNodesToKey(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
|
||||
size_t cursorIndex) {
|
||||
std::stringstream s;
|
||||
std::vector<NodeAnchor> n;
|
||||
std::vector<Taiyan::Gramambular::NodeAnchor> n;
|
||||
size_t ll = 0;
|
||||
for (std::vector<NodeAnchor>::const_iterator i = walkedNodes.begin();
|
||||
for (std::vector<Taiyan::Gramambular::NodeAnchor>::const_iterator i = walkedNodes.begin();
|
||||
i != walkedNodes.end();
|
||||
++i) {
|
||||
const auto& nn = *i;
|
||||
|
@ -154,19 +154,19 @@ static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<NodeAnchor>::const_reverse_iterator r = n.rbegin();
|
||||
std::vector<Taiyan::Gramambular::NodeAnchor>::const_reverse_iterator r = n.rbegin();
|
||||
|
||||
if (r == n.rend()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
string current = (*r).node->currentKeyValue().key;
|
||||
std::string current = (*r).node->currentKeyValue().key;
|
||||
++r;
|
||||
|
||||
s.clear();
|
||||
s.str(std::string());
|
||||
if (r != n.rend()) {
|
||||
string value = (*r).node->currentKeyValue().value;
|
||||
std::string value = (*r).node->currentKeyValue().value;
|
||||
if (IsEndingPunctuation(value)) {
|
||||
s << "()";
|
||||
r = n.rend();
|
||||
|
@ -181,12 +181,12 @@ static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
|
|||
} else {
|
||||
s << "()";
|
||||
}
|
||||
string prev = s.str();
|
||||
std::string prev = s.str();
|
||||
|
||||
s.clear();
|
||||
s.str(std::string());
|
||||
if (r != n.rend()) {
|
||||
string value = (*r).node->currentKeyValue().value;
|
||||
std::string value = (*r).node->currentKeyValue().value;
|
||||
if (IsEndingPunctuation(value)) {
|
||||
s << "()";
|
||||
r = n.rend();
|
||||
|
@ -201,7 +201,7 @@ static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
|
|||
} else {
|
||||
s << "()";
|
||||
}
|
||||
string anterior = s.str();
|
||||
std::string anterior = s.str();
|
||||
|
||||
s.clear();
|
||||
s.str(std::string());
|
||||
|
@ -209,3 +209,5 @@ static string WalkedNodesToKey(const std::vector<NodeAnchor>& walkedNodes,
|
|||
|
||||
return s.str();
|
||||
}
|
||||
|
||||
} // namespace vChewing
|
||||
|
|
|
@ -22,7 +22,6 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
|
|||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "Gramambular.h"
|
||||
|
||||
|
@ -34,12 +33,12 @@ class UserOverrideModel {
|
|||
public:
|
||||
UserOverrideModel(size_t capacity, double decayConstant);
|
||||
|
||||
void observe(const std::vector<NodeAnchor>& walkedNodes,
|
||||
void observe(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
|
||||
size_t cursorIndex,
|
||||
const string& candidate,
|
||||
const std::string& candidate,
|
||||
double timestamp);
|
||||
|
||||
string suggest(const std::vector<NodeAnchor>& walkedNodes,
|
||||
std::string suggest(const std::vector<Taiyan::Gramambular::NodeAnchor>& walkedNodes,
|
||||
size_t cursorIndex,
|
||||
double timestamp);
|
||||
|
||||
|
@ -56,7 +55,7 @@ private:
|
|||
std::map<std::string, Override> overrides;
|
||||
|
||||
Observation() : count(0) {}
|
||||
void update(const string& candidate, double timestamp);
|
||||
void update(const std::string& candidate, double timestamp);
|
||||
};
|
||||
|
||||
typedef std::pair<std::string, Observation> KeyObservationPair;
|
||||
|
@ -67,7 +66,7 @@ private:
|
|||
std::map<std::string, std::list<KeyObservationPair>::iterator> m_lruMap;
|
||||
};
|
||||
|
||||
}; // namespace vChewing
|
||||
}; // namespace vChewing
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -60,12 +60,7 @@ bool UserPhrasesLM::open(const char *path)
|
|||
}
|
||||
|
||||
LMConsolidator::FixEOF(path);
|
||||
|
||||
if (Preferences.shouldAutoSortUserPhrasesAndExclListOnLoad) {
|
||||
LMConsolidator::ConsolidateContent(path, true);
|
||||
} else {
|
||||
LMConsolidator::ConsolidateContent(path, false);
|
||||
}
|
||||
LMConsolidator::ConsolidateContent(path, Preferences.shouldAutoSortUserPhrasesAndExclListOnLoad, true);
|
||||
|
||||
fd = ::open(path, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
|
|
|
@ -32,8 +32,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
+ (BOOL)checkIfUserLanguageModelFilesExist;
|
||||
+ (BOOL)checkIfUserDataFolderExists;
|
||||
|
||||
+ (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase key:(NSString *)key NS_SWIFT_NAME(checkIfExist(userPhrase:key:));
|
||||
+ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode;
|
||||
+ (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase inputMode:(InputMode)mode key:(NSString *)key NS_SWIFT_NAME(checkIfUserPhraseExist(userPhrase:mode:key:));
|
||||
+ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode areWeDuplicating:(BOOL)areWeDuplicating;
|
||||
+ (void)setPhraseReplacementEnabled:(BOOL)phraseReplacementEnabled;
|
||||
+ (void)setCNSEnabled:(BOOL)cnsEnabled;
|
||||
+ (NSString *)userPhrasesDataPath:(InputMode)mode;
|
||||
|
|
|
@ -20,17 +20,15 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
|
|||
#import "mgrLangModel.h"
|
||||
#import "mgrLangModel_Privates.h"
|
||||
#import "vChewing-Swift.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace vChewing;
|
||||
#import "LMConsolidator.h"
|
||||
|
||||
static const int kUserOverrideModelCapacity = 500;
|
||||
static const double kObservedOverrideHalflife = 5400.0;
|
||||
|
||||
static vChewingLM gLangModelCHT;
|
||||
static vChewingLM gLangModelCHS;
|
||||
static UserOverrideModel gUserOverrideModelCHT(kUserOverrideModelCapacity, kObservedOverrideHalflife);
|
||||
static UserOverrideModel gUserOverrideModelCHS(kUserOverrideModelCapacity, kObservedOverrideHalflife);
|
||||
static vChewing::LMInstantiator gLangModelCHT;
|
||||
static vChewing::LMInstantiator gLangModelCHS;
|
||||
static vChewing::UserOverrideModel gUserOverrideModelCHT(kUserOverrideModelCapacity, kObservedOverrideHalflife);
|
||||
static vChewing::UserOverrideModel gUserOverrideModelCHS(kUserOverrideModelCapacity, kObservedOverrideHalflife);
|
||||
|
||||
static NSString *const kUserDataTemplateName = @"template-data";
|
||||
static NSString *const kUserAssDataTemplateName = @"template-data";
|
||||
|
@ -40,7 +38,7 @@ static NSString *const kTemplateExtension = @".txt";
|
|||
|
||||
@implementation mgrLangModel
|
||||
|
||||
static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewingLM &lm)
|
||||
static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing::LMInstantiator &lm)
|
||||
{
|
||||
Class cls = NSClassFromString(@"ctlInputMethod");
|
||||
NSString *dataPath = [[NSBundle bundleForClass:cls] pathForResource:filenameWithoutExtension ofType:@"txt"];
|
||||
|
@ -206,10 +204,10 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
|
|||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase key:(NSString *)key NS_SWIFT_NAME(checkIfExist(userPhrase:key:))
|
||||
+ (BOOL)checkIfUserPhraseExist:(NSString *)userPhrase inputMode:(InputMode)mode key:(NSString *)key NS_SWIFT_NAME(checkIfUserPhraseExist(userPhrase:mode:key:))
|
||||
{
|
||||
string unigramKey = string(key.UTF8String);
|
||||
vector<Unigram> unigrams = gLangModelCHT.unigramsForKey(unigramKey);
|
||||
vector<vChewing::Unigram> unigrams = [mode isEqualToString:imeModeCHT] ? gLangModelCHT.unigramsForKey(unigramKey): gLangModelCHS.unigramsForKey(unigramKey);
|
||||
string userPhraseString = string(userPhrase.UTF8String);
|
||||
for (auto unigram: unigrams) {
|
||||
if (unigram.keyValue.value == userPhraseString) {
|
||||
|
@ -219,7 +217,7 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
|
|||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode;
|
||||
+ (BOOL)writeUserPhrase:(NSString *)userPhrase inputMode:(InputMode)mode areWeDuplicating:(BOOL)areWeDuplicating
|
||||
{
|
||||
if (![self checkIfUserLanguageModelFilesExist]) {
|
||||
return NO;
|
||||
|
@ -251,6 +249,11 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
|
|||
// [currentMarkedPhrase appendString:@"\n"];
|
||||
// }
|
||||
[currentMarkedPhrase appendString:userPhrase];
|
||||
if (areWeDuplicating) {
|
||||
// Do not use ASCII characters to comment here.
|
||||
// Otherwise, it will be scrambled by HYPY2BPMF module shipped in the vChewing Phrase Editor.
|
||||
[currentMarkedPhrase appendString:@"\t#𝙾𝚟𝚎𝚛𝚛𝚒𝚍𝚎"];
|
||||
}
|
||||
[currentMarkedPhrase appendString:@"\n"];
|
||||
|
||||
NSFileHandle *writeFile = [NSFileHandle fileHandleForUpdatingAtPath:path];
|
||||
|
@ -262,9 +265,14 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
|
|||
[writeFile writeData:data];
|
||||
[writeFile closeFile];
|
||||
|
||||
// We use FSEventStream to monitor the change of the user phrase folder,
|
||||
// so we don't have to load data here.
|
||||
// [self loadUserPhrases];
|
||||
// We enforce the format consolidation here, since the pragma header will let the UserPhraseLM bypasses the consolidating process on load.
|
||||
vChewing::LMConsolidator::ConsolidateContent([path UTF8String], Preferences.shouldAutoSortUserPhrasesAndExclListOnLoad, false);
|
||||
|
||||
// We use FSEventStream to monitor the change of the user phrase folder,
|
||||
// so we don't have to load data here unless FSEventStream is disabled by user.
|
||||
if (!Preferences.shouldAutoReloadUserDataFiles) {
|
||||
[self loadUserPhrases];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
@ -306,12 +314,12 @@ static void LTLoadLanguageModelFile(NSString *filenameWithoutExtension, vChewing
|
|||
return [[NSBundle bundleForClass:cls] pathForResource:@"char-kanji-cns" ofType:@"txt"];
|
||||
}
|
||||
|
||||
+ (vChewingLM *)lmCHT
|
||||
+ (vChewing::LMInstantiator *)lmCHT
|
||||
{
|
||||
return &gLangModelCHT;
|
||||
}
|
||||
|
||||
+ (vChewingLM *)lmCHS
|
||||
+ (vChewing::LMInstantiator *)lmCHS
|
||||
{
|
||||
return &gLangModelCHS;
|
||||
}
|
||||
|
|
|
@ -19,13 +19,13 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR TH
|
|||
|
||||
#import "mgrLangModel.h"
|
||||
#import "UserOverrideModel.h"
|
||||
#import "vChewingLM.h"
|
||||
#import "LMInstantiator.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface mgrLangModel ()
|
||||
@property (class, readonly, nonatomic) vChewing::vChewingLM *lmCHT;
|
||||
@property (class, readonly, nonatomic) vChewing::vChewingLM *lmCHS;
|
||||
@property (class, readonly, nonatomic) vChewing::LMInstantiator *lmCHT;
|
||||
@property (class, readonly, nonatomic) vChewing::LMInstantiator *lmCHS;
|
||||
@property (class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHS;
|
||||
@property (class, readonly, nonatomic) vChewing::UserOverrideModel *userOverrideModelCHT;
|
||||
@end
|
||||
|
|
|
@ -17,82 +17,77 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef Bigram_h
|
||||
#define Bigram_h
|
||||
#ifndef BIGRAM_H_
|
||||
#define BIGRAM_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "KeyValuePair.h"
|
||||
|
||||
namespace Taiyan {
|
||||
namespace Gramambular {
|
||||
class Bigram {
|
||||
public:
|
||||
Bigram();
|
||||
|
||||
KeyValuePair preceedingKeyValue;
|
||||
KeyValuePair keyValue;
|
||||
double score;
|
||||
|
||||
bool operator==(const Bigram& inAnother) const;
|
||||
bool operator<(const Bigram& inAnother) const;
|
||||
};
|
||||
namespace Gramambular {
|
||||
class Bigram {
|
||||
public:
|
||||
Bigram();
|
||||
|
||||
KeyValuePair preceedingKeyValue;
|
||||
KeyValuePair keyValue;
|
||||
double score;
|
||||
|
||||
bool operator==(const Bigram& another) const;
|
||||
bool operator<(const Bigram& another) const;
|
||||
};
|
||||
|
||||
inline ostream& operator<<(ostream& inStream, const Bigram& inGram)
|
||||
{
|
||||
streamsize p = inStream.precision();
|
||||
inStream.precision(6);
|
||||
inStream << "(" << inGram.keyValue << "|" <<inGram.preceedingKeyValue << "," << inGram.score << ")";
|
||||
inStream.precision(p);
|
||||
return inStream;
|
||||
}
|
||||
|
||||
inline ostream& operator<<(ostream& inStream, const vector<Bigram>& inGrams)
|
||||
{
|
||||
inStream << "[" << inGrams.size() << "]=>{";
|
||||
|
||||
size_t index = 0;
|
||||
|
||||
for (vector<Bigram>::const_iterator gi = inGrams.begin() ; gi != inGrams.end() ; ++gi, ++index) {
|
||||
inStream << index << "=>";
|
||||
inStream << *gi;
|
||||
if (gi + 1 != inGrams.end()) {
|
||||
inStream << ",";
|
||||
}
|
||||
}
|
||||
|
||||
inStream << "}";
|
||||
return inStream;
|
||||
}
|
||||
|
||||
inline Bigram::Bigram()
|
||||
: score(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool Bigram::operator==(const Bigram& inAnother) const
|
||||
{
|
||||
return preceedingKeyValue == inAnother.preceedingKeyValue && keyValue == inAnother.keyValue && score == inAnother.score;
|
||||
}
|
||||
|
||||
inline bool Bigram::operator<(const Bigram& inAnother) const
|
||||
{
|
||||
if (preceedingKeyValue < inAnother.preceedingKeyValue) {
|
||||
return true;
|
||||
}
|
||||
else if (preceedingKeyValue == inAnother.preceedingKeyValue) {
|
||||
if (keyValue < inAnother.keyValue) {
|
||||
return true;
|
||||
}
|
||||
else if (keyValue == inAnother.keyValue) {
|
||||
return score < inAnother.score;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
inline std::ostream& operator<<(std::ostream& stream, const Bigram& gram) {
|
||||
std::streamsize p = stream.precision();
|
||||
stream.precision(6);
|
||||
stream << "(" << gram.keyValue << "|" << gram.preceedingKeyValue << ","
|
||||
<< gram.score << ")";
|
||||
stream.precision(p);
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& stream,
|
||||
const std::vector<Bigram>& grams) {
|
||||
stream << "[" << grams.size() << "]=>{";
|
||||
|
||||
size_t index = 0;
|
||||
|
||||
for (std::vector<Bigram>::const_iterator gi = grams.begin();
|
||||
gi != grams.end(); ++gi, ++index) {
|
||||
stream << index << "=>";
|
||||
stream << *gi;
|
||||
if (gi + 1 != grams.end()) {
|
||||
stream << ",";
|
||||
}
|
||||
}
|
||||
|
||||
stream << "}";
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline Bigram::Bigram() : score(0.0) {}
|
||||
|
||||
inline bool Bigram::operator==(const Bigram& another) const {
|
||||
return preceedingKeyValue == another.preceedingKeyValue &&
|
||||
keyValue == another.keyValue && score == another.score;
|
||||
}
|
||||
|
||||
inline bool Bigram::operator<(const Bigram& another) const {
|
||||
if (preceedingKeyValue < another.preceedingKeyValue) {
|
||||
return true;
|
||||
} else if (preceedingKeyValue == another.preceedingKeyValue) {
|
||||
if (keyValue < another.keyValue) {
|
||||
return true;
|
||||
} else if (keyValue == another.keyValue) {
|
||||
return score < another.score;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
} // namespace Gramambular
|
||||
} // namespace Taiyan
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,202 +17,190 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BlockReadingBuilder_h
|
||||
#define BlockReadingBuilder_h
|
||||
#ifndef BLOCKREADINGBUILDER_H_
|
||||
#define BLOCKREADINGBUILDER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Grid.h"
|
||||
#include "LanguageModel.h"
|
||||
|
||||
namespace Taiyan {
|
||||
namespace Gramambular {
|
||||
using namespace std;
|
||||
|
||||
class BlockReadingBuilder {
|
||||
public:
|
||||
BlockReadingBuilder(LanguageModel *inLM);
|
||||
void clear();
|
||||
|
||||
size_t length() const;
|
||||
size_t cursorIndex() const;
|
||||
void setCursorIndex(size_t inNewIndex);
|
||||
void insertReadingAtCursor(const string& inReading);
|
||||
bool deleteReadingBeforeCursor(); // backspace
|
||||
bool deleteReadingAfterCursor(); // delete
|
||||
|
||||
bool removeHeadReadings(size_t count);
|
||||
|
||||
void setJoinSeparator(const string& separator);
|
||||
const string joinSeparator() const;
|
||||
namespace Gramambular {
|
||||
|
||||
vector<string> readings() const;
|
||||
class BlockReadingBuilder {
|
||||
public:
|
||||
explicit BlockReadingBuilder(LanguageModel* lm);
|
||||
void clear();
|
||||
|
||||
size_t length() const;
|
||||
size_t cursorIndex() const;
|
||||
void setCursorIndex(size_t newIndex);
|
||||
void insertReadingAtCursor(const std::string& reading);
|
||||
bool deleteReadingBeforeCursor(); // backspace
|
||||
bool deleteReadingAfterCursor(); // delete
|
||||
|
||||
bool removeHeadReadings(size_t count);
|
||||
|
||||
void setJoinSeparator(const std::string& separator);
|
||||
const std::string joinSeparator() const;
|
||||
|
||||
std::vector<std::string> readings() const;
|
||||
|
||||
Grid& grid();
|
||||
|
||||
protected:
|
||||
void build();
|
||||
|
||||
static const std::string Join(std::vector<std::string>::const_iterator begin,
|
||||
std::vector<std::string>::const_iterator end,
|
||||
const std::string& separator);
|
||||
|
||||
// 最多使用六個字組成一個詞
|
||||
static const size_t MaximumBuildSpanLength = 6;
|
||||
|
||||
size_t m_cursorIndex;
|
||||
std::vector<std::string> m_readings;
|
||||
|
||||
Grid m_grid;
|
||||
LanguageModel* m_LM;
|
||||
std::string m_joinSeparator;
|
||||
};
|
||||
|
||||
Grid& grid();
|
||||
|
||||
protected:
|
||||
void build();
|
||||
|
||||
static const string Join(vector<string>::const_iterator begin, vector<string>::const_iterator end, const string& separator);
|
||||
|
||||
//最多使用六個字組成一個詞
|
||||
static const size_t MaximumBuildSpanLength = 6;
|
||||
|
||||
size_t m_cursorIndex;
|
||||
vector<string> m_readings;
|
||||
|
||||
Grid m_grid;
|
||||
LanguageModel *m_LM;
|
||||
string m_joinSeparator;
|
||||
};
|
||||
|
||||
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel *inLM)
|
||||
: m_LM(inLM)
|
||||
, m_cursorIndex(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline void BlockReadingBuilder::clear()
|
||||
{
|
||||
m_cursorIndex = 0;
|
||||
m_readings.clear();
|
||||
m_grid.clear();
|
||||
}
|
||||
|
||||
inline size_t BlockReadingBuilder::length() const
|
||||
{
|
||||
return m_readings.size();
|
||||
}
|
||||
|
||||
inline size_t BlockReadingBuilder::cursorIndex() const
|
||||
{
|
||||
return m_cursorIndex;
|
||||
}
|
||||
inline BlockReadingBuilder::BlockReadingBuilder(LanguageModel* lm)
|
||||
: m_LM(lm), m_cursorIndex(0) {}
|
||||
|
||||
inline void BlockReadingBuilder::setCursorIndex(size_t inNewIndex)
|
||||
{
|
||||
m_cursorIndex = inNewIndex > m_readings.size() ? m_readings.size() : inNewIndex;
|
||||
}
|
||||
|
||||
inline void BlockReadingBuilder::insertReadingAtCursor(const string& inReading)
|
||||
{
|
||||
m_readings.insert(m_readings.begin() + m_cursorIndex, inReading);
|
||||
|
||||
m_grid.expandGridByOneAtLocation(m_cursorIndex);
|
||||
build();
|
||||
m_cursorIndex++;
|
||||
}
|
||||
inline void BlockReadingBuilder::clear() {
|
||||
m_cursorIndex = 0;
|
||||
m_readings.clear();
|
||||
m_grid.clear();
|
||||
}
|
||||
|
||||
inline vector<string> BlockReadingBuilder::readings() const
|
||||
{
|
||||
return m_readings;
|
||||
}
|
||||
|
||||
inline bool BlockReadingBuilder::deleteReadingBeforeCursor()
|
||||
{
|
||||
if (!m_cursorIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_readings.erase(m_readings.begin() + m_cursorIndex - 1, m_readings.begin() + m_cursorIndex);
|
||||
inline size_t BlockReadingBuilder::length() const { return m_readings.size(); }
|
||||
|
||||
inline size_t BlockReadingBuilder::cursorIndex() const { return m_cursorIndex; }
|
||||
|
||||
inline void BlockReadingBuilder::setCursorIndex(size_t newIndex) {
|
||||
m_cursorIndex = newIndex > m_readings.size() ? m_readings.size() : newIndex;
|
||||
}
|
||||
|
||||
inline void BlockReadingBuilder::insertReadingAtCursor(
|
||||
const std::string& reading) {
|
||||
m_readings.insert(m_readings.begin() + m_cursorIndex, reading);
|
||||
|
||||
m_grid.expandGridByOneAtLocation(m_cursorIndex);
|
||||
build();
|
||||
m_cursorIndex++;
|
||||
}
|
||||
|
||||
inline std::vector<std::string> BlockReadingBuilder::readings() const {
|
||||
return m_readings;
|
||||
}
|
||||
|
||||
inline bool BlockReadingBuilder::deleteReadingBeforeCursor() {
|
||||
if (!m_cursorIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_readings.erase(m_readings.begin() + m_cursorIndex - 1,
|
||||
m_readings.begin() + m_cursorIndex);
|
||||
m_cursorIndex--;
|
||||
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
|
||||
build();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool BlockReadingBuilder::deleteReadingAfterCursor() {
|
||||
if (m_cursorIndex == m_readings.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_readings.erase(m_readings.begin() + m_cursorIndex,
|
||||
m_readings.begin() + m_cursorIndex + 1);
|
||||
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
|
||||
build();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool BlockReadingBuilder::removeHeadReadings(size_t count) {
|
||||
if (count > length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (m_cursorIndex) {
|
||||
m_cursorIndex--;
|
||||
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
|
||||
build();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool BlockReadingBuilder::deleteReadingAfterCursor()
|
||||
{
|
||||
if (m_cursorIndex == m_readings.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_readings.erase(m_readings.begin() + m_cursorIndex, m_readings.begin() + m_cursorIndex + 1);
|
||||
m_grid.shrinkGridByOneAtLocation(m_cursorIndex);
|
||||
build();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool BlockReadingBuilder::removeHeadReadings(size_t count)
|
||||
{
|
||||
if (count > length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (m_cursorIndex) {
|
||||
m_cursorIndex--;
|
||||
}
|
||||
m_readings.erase(m_readings.begin(), m_readings.begin() + 1);
|
||||
m_grid.shrinkGridByOneAtLocation(0);
|
||||
build();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void BlockReadingBuilder::setJoinSeparator(const string& separator)
|
||||
{
|
||||
m_joinSeparator = separator;
|
||||
}
|
||||
|
||||
inline const string BlockReadingBuilder::joinSeparator() const
|
||||
{
|
||||
return m_joinSeparator;
|
||||
}
|
||||
m_readings.erase(m_readings.begin(), m_readings.begin() + 1);
|
||||
m_grid.shrinkGridByOneAtLocation(0);
|
||||
build();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline Grid& BlockReadingBuilder::grid()
|
||||
{
|
||||
return m_grid;
|
||||
}
|
||||
inline void BlockReadingBuilder::setJoinSeparator(
|
||||
const std::string& separator) {
|
||||
m_joinSeparator = separator;
|
||||
}
|
||||
|
||||
inline void BlockReadingBuilder::build()
|
||||
{
|
||||
if (!m_LM) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t begin = 0;
|
||||
size_t end = m_cursorIndex + MaximumBuildSpanLength;
|
||||
|
||||
if (m_cursorIndex < MaximumBuildSpanLength) {
|
||||
begin = 0;
|
||||
}
|
||||
else {
|
||||
begin = m_cursorIndex - MaximumBuildSpanLength;
|
||||
}
|
||||
|
||||
if (end > m_readings.size()) {
|
||||
end = m_readings.size();
|
||||
}
|
||||
|
||||
for (size_t p = begin ; p < end ; p++) {
|
||||
for (size_t q = 1 ; q <= MaximumBuildSpanLength && p+q <= end ; q++) {
|
||||
string combinedReading = Join(m_readings.begin() + p, m_readings.begin() + p + q, m_joinSeparator);
|
||||
if (!m_grid.hasNodeAtLocationSpanningLengthMatchingKey(p, q, combinedReading)) {
|
||||
vector<Unigram> unigrams = m_LM->unigramsForKey(combinedReading);
|
||||
inline const std::string BlockReadingBuilder::joinSeparator() const {
|
||||
return m_joinSeparator;
|
||||
}
|
||||
|
||||
if (unigrams.size() > 0) {
|
||||
Node n(combinedReading, unigrams, vector<Bigram>());
|
||||
m_grid.insertNode(n, p, q);
|
||||
}
|
||||
}
|
||||
inline Grid& BlockReadingBuilder::grid() { return m_grid; }
|
||||
|
||||
inline void BlockReadingBuilder::build() {
|
||||
if (!m_LM) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t begin = 0;
|
||||
size_t end = m_cursorIndex + MaximumBuildSpanLength;
|
||||
|
||||
if (m_cursorIndex < MaximumBuildSpanLength) {
|
||||
begin = 0;
|
||||
} else {
|
||||
begin = m_cursorIndex - MaximumBuildSpanLength;
|
||||
}
|
||||
|
||||
if (end > m_readings.size()) {
|
||||
end = m_readings.size();
|
||||
}
|
||||
|
||||
for (size_t p = begin; p < end; p++) {
|
||||
for (size_t q = 1; q <= MaximumBuildSpanLength && p + q <= end; q++) {
|
||||
std::string combinedReading = Join(
|
||||
m_readings.begin() + p, m_readings.begin() + p + q, m_joinSeparator);
|
||||
if (!m_grid.hasNodeAtLocationSpanningLengthMatchingKey(p, q,
|
||||
combinedReading)) {
|
||||
std::vector<Unigram> unigrams = m_LM->unigramsForKey(combinedReading);
|
||||
|
||||
if (unigrams.size() > 0) {
|
||||
Node n(combinedReading, unigrams, std::vector<Bigram>());
|
||||
m_grid.insertNode(n, p, q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline const string BlockReadingBuilder::Join(vector<string>::const_iterator begin, vector<string>::const_iterator end, const string& separator)
|
||||
{
|
||||
string result;
|
||||
for (vector<string>::const_iterator iter = begin ; iter != end ; ) {
|
||||
result += *iter;
|
||||
++iter;
|
||||
if (iter != end) {
|
||||
result += separator;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline const std::string BlockReadingBuilder::Join(
|
||||
std::vector<std::string>::const_iterator begin,
|
||||
std::vector<std::string>::const_iterator end,
|
||||
const std::string& separator) {
|
||||
std::string result;
|
||||
for (std::vector<std::string>::const_iterator iter = begin; iter != end;) {
|
||||
result += *iter;
|
||||
++iter;
|
||||
if (iter != end) {
|
||||
result += separator;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace Gramambular
|
||||
} // namespace Taiyan
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,8 +17,8 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef Gramambular_h
|
||||
#define Gramambular_h
|
||||
#ifndef GRAMAMBULAR_H_
|
||||
#define GRAMAMBULAR_H_
|
||||
|
||||
#include "Bigram.h"
|
||||
#include "BlockReadingBuilder.h"
|
||||
|
|
|
@ -17,248 +17,207 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef Grid_h
|
||||
#define Grid_h
|
||||
#ifndef GRID_H_
|
||||
#define GRID_H_
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "NodeAnchor.h"
|
||||
#include "Span.h"
|
||||
|
||||
namespace Taiyan {
|
||||
namespace Gramambular {
|
||||
namespace Gramambular {
|
||||
|
||||
class Grid {
|
||||
public:
|
||||
void clear();
|
||||
void insertNode(const Node& node, size_t location, size_t spanningLength);
|
||||
bool hasNodeAtLocationSpanningLengthMatchingKey(size_t location,
|
||||
size_t spanningLength,
|
||||
const std::string& key);
|
||||
|
||||
void expandGridByOneAtLocation(size_t location);
|
||||
void shrinkGridByOneAtLocation(size_t location);
|
||||
|
||||
size_t width() const;
|
||||
std::vector<NodeAnchor> nodesEndingAt(size_t location);
|
||||
std::vector<NodeAnchor> nodesCrossingOrEndingAt(size_t location);
|
||||
|
||||
// "Freeze" the node with the unigram that represents the selected candidate
|
||||
// value. After this, the node that contains the unigram will always be
|
||||
// evaluated to that unigram, while all other overlapping nodes will be reset
|
||||
// to their initial state (that is, if any of those nodes were "frozen" or
|
||||
// fixed, they will be unfrozen.)
|
||||
NodeAnchor fixNodeSelectedCandidate(size_t location,
|
||||
const std::string& value);
|
||||
|
||||
// Similar to fixNodeSelectedCandidate, but instead of "freezing" the node,
|
||||
// only boost the unigram that represents the value with an overriding score.
|
||||
// This has the same side effect as fixNodeSelectedCandidate, which is that
|
||||
// all other overlapping nodes will be reset to their initial state.
|
||||
void overrideNodeScoreForSelectedCandidate(size_t location,
|
||||
const std::string& value,
|
||||
float overridingScore);
|
||||
|
||||
std::string dumpDOT();
|
||||
|
||||
protected:
|
||||
std::vector<Span> m_spans;
|
||||
};
|
||||
|
||||
inline void Grid::clear() { m_spans.clear(); }
|
||||
|
||||
inline void Grid::insertNode(const Node& node, size_t location,
|
||||
size_t spanningLength) {
|
||||
if (location >= m_spans.size()) {
|
||||
size_t diff = location - m_spans.size() + 1;
|
||||
|
||||
class Grid {
|
||||
public:
|
||||
void clear();
|
||||
void insertNode(const Node& inNode, size_t inLocation, size_t inSpanningLength);
|
||||
bool hasNodeAtLocationSpanningLengthMatchingKey(size_t inLocation, size_t inSpanningLength, const string& inKey);
|
||||
|
||||
void expandGridByOneAtLocation(size_t inLocation);
|
||||
void shrinkGridByOneAtLocation(size_t inLocation);
|
||||
|
||||
size_t width() const;
|
||||
vector<NodeAnchor> nodesEndingAt(size_t inLocation);
|
||||
vector<NodeAnchor> nodesCrossingOrEndingAt(size_t inLocation);
|
||||
|
||||
// "Freeze" the node with the unigram that represents the selected candidate value.
|
||||
// After this, the node that contains the unigram will always be evaluated to that
|
||||
// unigram, while all other overlapping nodes will be reset to their initial state
|
||||
// (that is, if any of those nodes were "frozen" or fixed, they will be unfrozen.)
|
||||
NodeAnchor fixNodeSelectedCandidate(size_t location, const string& value);
|
||||
|
||||
// Similar to fixNodeSelectedCandidate, but instead of "freezing" the node, only
|
||||
// boost the unigram that represents the value with an overriding score. This
|
||||
// has the same side effect as fixNodeSelectedCandidate, which is that all other
|
||||
// overlapping nodes will be reset to their initial state.
|
||||
void overrideNodeScoreForSelectedCandidate(size_t location, const string& value, float overridingScore);
|
||||
|
||||
const string dumpDOT();
|
||||
|
||||
protected:
|
||||
vector<Span> m_spans;
|
||||
};
|
||||
|
||||
inline void Grid::clear()
|
||||
{
|
||||
m_spans.clear();
|
||||
for (size_t i = 0; i < diff; i++) {
|
||||
m_spans.push_back(Span());
|
||||
}
|
||||
|
||||
inline void Grid::insertNode(const Node& inNode, size_t inLocation, size_t inSpanningLength)
|
||||
{
|
||||
if (inLocation >= m_spans.size()) {
|
||||
size_t diff = inLocation - m_spans.size() + 1;
|
||||
|
||||
for (size_t i = 0 ; i < diff ; i++) {
|
||||
m_spans.push_back(Span());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_spans[location].insertNodeOfLength(node, spanningLength);
|
||||
}
|
||||
|
||||
m_spans[inLocation].insertNodeOfLength(inNode, inSpanningLength);
|
||||
}
|
||||
inline bool Grid::hasNodeAtLocationSpanningLengthMatchingKey(
|
||||
size_t location, size_t spanningLength, const std::string& key) {
|
||||
if (location > m_spans.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Node* n = m_spans[location].nodeOfLength(spanningLength);
|
||||
if (!n) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return key == n->key();
|
||||
}
|
||||
|
||||
inline bool Grid::hasNodeAtLocationSpanningLengthMatchingKey(size_t inLocation, size_t inSpanningLength, const string& inKey)
|
||||
{
|
||||
if (inLocation > m_spans.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Node *n = m_spans[inLocation].nodeOfLength(inSpanningLength);
|
||||
if (!n) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return inKey == n->key();
|
||||
}
|
||||
|
||||
inline void Grid::expandGridByOneAtLocation(size_t inLocation)
|
||||
{
|
||||
if (!inLocation || inLocation == m_spans.size()) {
|
||||
m_spans.insert(m_spans.begin() + inLocation, Span());
|
||||
}
|
||||
else {
|
||||
m_spans.insert(m_spans.begin() + inLocation, Span());
|
||||
for (size_t i = 0 ; i < inLocation ; i++) {
|
||||
// zaps overlapping spans
|
||||
m_spans[i].removeNodeOfLengthGreaterThan(inLocation - i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void Grid::shrinkGridByOneAtLocation(size_t inLocation)
|
||||
{
|
||||
if (inLocation >= m_spans.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spans.erase(m_spans.begin() + inLocation);
|
||||
for (size_t i = 0 ; i < inLocation ; i++) {
|
||||
// zaps overlapping spans
|
||||
m_spans[i].removeNodeOfLengthGreaterThan(inLocation - i);
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t Grid::width() const
|
||||
{
|
||||
return m_spans.size();
|
||||
}
|
||||
|
||||
inline vector<NodeAnchor> Grid::nodesEndingAt(size_t inLocation)
|
||||
{
|
||||
vector<NodeAnchor> result;
|
||||
|
||||
if (m_spans.size() && inLocation <= m_spans.size()) {
|
||||
for (size_t i = 0 ; i < inLocation ; i++) {
|
||||
Span& span = m_spans[i];
|
||||
if (i + span.maximumLength() >= inLocation) {
|
||||
Node *np = span.nodeOfLength(inLocation - i);
|
||||
if (np) {
|
||||
NodeAnchor na;
|
||||
na.node = np;
|
||||
na.location = i;
|
||||
na.spanningLength = inLocation - i;
|
||||
|
||||
result.push_back(na);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline vector<NodeAnchor> Grid::nodesCrossingOrEndingAt(size_t inLocation)
|
||||
{
|
||||
vector<NodeAnchor> result;
|
||||
|
||||
if (m_spans.size() && inLocation <= m_spans.size()) {
|
||||
for (size_t i = 0 ; i < inLocation ; i++) {
|
||||
Span& span = m_spans[i];
|
||||
|
||||
if (i + span.maximumLength() >= inLocation) {
|
||||
|
||||
for (size_t j = 1, m = span.maximumLength(); j <= m ; j++) {
|
||||
|
||||
if (i + j < inLocation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Node *np = span.nodeOfLength(j);
|
||||
if (np) {
|
||||
NodeAnchor na;
|
||||
na.node = np;
|
||||
na.location = i;
|
||||
na.spanningLength = inLocation - i;
|
||||
|
||||
result.push_back(na);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// For nodes found at the location, fix their currently-selected candidate using the supplied string value.
|
||||
inline NodeAnchor Grid::fixNodeSelectedCandidate(size_t location, const string& value)
|
||||
{
|
||||
vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location);
|
||||
NodeAnchor node;
|
||||
for (auto nodeAnchor : nodes) {
|
||||
auto candidates = nodeAnchor.node->candidates();
|
||||
|
||||
// Reset the candidate-fixed state of every node at the location.
|
||||
const_cast<Node*>(nodeAnchor.node)->resetCandidate();
|
||||
|
||||
for (size_t i = 0, c = candidates.size(); i < c; ++i) {
|
||||
if (candidates[i].value == value) {
|
||||
const_cast<Node*>(nodeAnchor.node)->selectCandidateAtIndex(i);
|
||||
node = nodeAnchor;
|
||||
break;;
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
inline void Grid::overrideNodeScoreForSelectedCandidate(size_t location, const string& value, float overridingScore)
|
||||
{
|
||||
vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location);
|
||||
for (auto nodeAnchor : nodes) {
|
||||
auto candidates = nodeAnchor.node->candidates();
|
||||
|
||||
// Reset the candidate-fixed state of every node at the location.
|
||||
const_cast<Node*>(nodeAnchor.node)->resetCandidate();
|
||||
|
||||
for (size_t i = 0, c = candidates.size(); i < c; ++i) {
|
||||
if (candidates[i].value == value) {
|
||||
const_cast<Node*>(nodeAnchor.node)->selectFloatingCandidateAtIndex(i, overridingScore);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline const string Grid::dumpDOT()
|
||||
{
|
||||
stringstream sst;
|
||||
sst << "digraph {" << endl;
|
||||
sst << "graph [ rankdir=LR ];" << endl;
|
||||
sst << "BOS;" << endl;
|
||||
|
||||
for (size_t p = 0 ; p < m_spans.size() ; p++) {
|
||||
Span& span = m_spans[p];
|
||||
for (size_t ni = 0 ; ni <= span.maximumLength() ; ni++) {
|
||||
Node* np = span.nodeOfLength(ni);
|
||||
if (np) {
|
||||
if (!p) {
|
||||
sst << "BOS -> " << np->currentKeyValue().value << ";" << endl;
|
||||
}
|
||||
|
||||
sst << np->currentKeyValue().value << ";" << endl;
|
||||
|
||||
if (p + ni < m_spans.size()) {
|
||||
Span& dstSpan = m_spans[p+ni];
|
||||
for (size_t q = 0 ; q <= dstSpan.maximumLength() ; q++) {
|
||||
Node *dn = dstSpan.nodeOfLength(q);
|
||||
if (dn) {
|
||||
sst << np->currentKeyValue().value << " -> " << dn->currentKeyValue().value << ";" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p + ni == m_spans.size()) {
|
||||
sst << np->currentKeyValue().value << " -> " << "EOS;" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sst << "EOS;" << endl;
|
||||
sst << "}";
|
||||
return sst.str();
|
||||
inline void Grid::expandGridByOneAtLocation(size_t location) {
|
||||
if (!location || location == m_spans.size()) {
|
||||
m_spans.insert(m_spans.begin() + location, Span());
|
||||
} else {
|
||||
m_spans.insert(m_spans.begin() + location, Span());
|
||||
for (size_t i = 0; i < location; i++) {
|
||||
// zaps overlapping spans
|
||||
m_spans[i].removeNodeOfLengthGreaterThan(location - i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void Grid::shrinkGridByOneAtLocation(size_t location) {
|
||||
if (location >= m_spans.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_spans.erase(m_spans.begin() + location);
|
||||
for (size_t i = 0; i < location; i++) {
|
||||
// zaps overlapping spans
|
||||
m_spans[i].removeNodeOfLengthGreaterThan(location - i);
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t Grid::width() const { return m_spans.size(); }
|
||||
|
||||
inline std::vector<NodeAnchor> Grid::nodesEndingAt(size_t location) {
|
||||
std::vector<NodeAnchor> result;
|
||||
|
||||
if (m_spans.size() && location <= m_spans.size()) {
|
||||
for (size_t i = 0; i < location; i++) {
|
||||
Span& span = m_spans[i];
|
||||
if (i + span.maximumLength() >= location) {
|
||||
Node* np = span.nodeOfLength(location - i);
|
||||
if (np) {
|
||||
NodeAnchor na;
|
||||
na.node = np;
|
||||
na.location = i;
|
||||
na.spanningLength = location - i;
|
||||
|
||||
result.push_back(na);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline std::vector<NodeAnchor> Grid::nodesCrossingOrEndingAt(size_t location) {
|
||||
std::vector<NodeAnchor> result;
|
||||
|
||||
if (m_spans.size() && location <= m_spans.size()) {
|
||||
for (size_t i = 0; i < location; i++) {
|
||||
Span& span = m_spans[i];
|
||||
|
||||
if (i + span.maximumLength() >= location) {
|
||||
for (size_t j = 1, m = span.maximumLength(); j <= m; j++) {
|
||||
if (i + j < location) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Node* np = span.nodeOfLength(j);
|
||||
if (np) {
|
||||
NodeAnchor na;
|
||||
na.node = np;
|
||||
na.location = i;
|
||||
na.spanningLength = location - i;
|
||||
|
||||
result.push_back(na);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// For nodes found at the location, fix their currently-selected candidate using
|
||||
// the supplied string value.
|
||||
inline NodeAnchor Grid::fixNodeSelectedCandidate(size_t location,
|
||||
const std::string& value) {
|
||||
std::vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location);
|
||||
NodeAnchor node;
|
||||
for (auto nodeAnchor : nodes) {
|
||||
auto candidates = nodeAnchor.node->candidates();
|
||||
|
||||
// Reset the candidate-fixed state of every node at the location.
|
||||
const_cast<Node*>(nodeAnchor.node)->resetCandidate();
|
||||
|
||||
for (size_t i = 0, c = candidates.size(); i < c; ++i) {
|
||||
if (candidates[i].value == value) {
|
||||
const_cast<Node*>(nodeAnchor.node)->selectCandidateAtIndex(i);
|
||||
node = nodeAnchor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
inline void Grid::overrideNodeScoreForSelectedCandidate(
|
||||
size_t location, const std::string& value, float overridingScore) {
|
||||
std::vector<NodeAnchor> nodes = nodesCrossingOrEndingAt(location);
|
||||
for (auto nodeAnchor : nodes) {
|
||||
auto candidates = nodeAnchor.node->candidates();
|
||||
|
||||
// Reset the candidate-fixed state of every node at the location.
|
||||
const_cast<Node*>(nodeAnchor.node)->resetCandidate();
|
||||
|
||||
for (size_t i = 0, c = candidates.size(); i < c; ++i) {
|
||||
if (candidates[i].value == value) {
|
||||
const_cast<Node*>(nodeAnchor.node)
|
||||
->selectFloatingCandidateAtIndex(i, overridingScore);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Gramambular
|
||||
} // namespace Taiyan
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License).
|
||||
// All possible vChewing-specific modifications are (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
||||
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
1. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
2. No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor,
|
||||
except as required to fulfill notice requirements above.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "Grid.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace Taiyan {
|
||||
namespace Gramambular {
|
||||
|
||||
std::string Grid::dumpDOT() {
|
||||
std::stringstream sst;
|
||||
sst << "digraph {" << std::endl;
|
||||
sst << "graph [ rankdir=LR ];" << std::endl;
|
||||
sst << "BOS;" << std::endl;
|
||||
|
||||
for (size_t p = 0; p < m_spans.size(); p++) {
|
||||
Span& span = m_spans[p];
|
||||
for (size_t ni = 0; ni <= span.maximumLength(); ni++) {
|
||||
Node* np = span.nodeOfLength(ni);
|
||||
if (np) {
|
||||
if (!p) {
|
||||
sst << "BOS -> " << np->currentKeyValue().value << ";" << std::endl;
|
||||
}
|
||||
|
||||
sst << np->currentKeyValue().value << ";" << std::endl;
|
||||
|
||||
if (p + ni < m_spans.size()) {
|
||||
Span& dstSpan = m_spans[p + ni];
|
||||
for (size_t q = 0; q <= dstSpan.maximumLength(); q++) {
|
||||
Node* dn = dstSpan.nodeOfLength(q);
|
||||
if (dn) {
|
||||
sst << np->currentKeyValue().value << " -> "
|
||||
<< dn->currentKeyValue().value << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p + ni == m_spans.size()) {
|
||||
sst << np->currentKeyValue().value << " -> "
|
||||
<< "EOS;" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sst << "EOS;" << std::endl;
|
||||
sst << "}";
|
||||
return sst.str();
|
||||
}
|
||||
|
||||
} // namespace Gramambular
|
||||
} // namespace Taiyan
|
|
@ -17,47 +17,43 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef KeyValuePair_h
|
||||
#define KeyValuePair_h
|
||||
#ifndef KEYVALUEPAIR_H_
|
||||
#define KEYVALUEPAIR_H_
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace Taiyan {
|
||||
namespace Gramambular {
|
||||
using namespace std;
|
||||
|
||||
class KeyValuePair {
|
||||
public:
|
||||
string key;
|
||||
string value;
|
||||
namespace Gramambular {
|
||||
|
||||
bool operator==(const KeyValuePair& inAnother) const;
|
||||
bool operator<(const KeyValuePair& inAnother) const;
|
||||
};
|
||||
class KeyValuePair {
|
||||
public:
|
||||
std::string key;
|
||||
std::string value;
|
||||
|
||||
bool operator==(const KeyValuePair& another) const;
|
||||
bool operator<(const KeyValuePair& another) const;
|
||||
};
|
||||
|
||||
inline ostream& operator<<(ostream& inStream, const KeyValuePair& inPair)
|
||||
{
|
||||
inStream << "(" << inPair.key << "," << inPair.value << ")";
|
||||
return inStream;
|
||||
}
|
||||
|
||||
inline bool KeyValuePair::operator==(const KeyValuePair& inAnother) const
|
||||
{
|
||||
return key == inAnother.key && value == inAnother.value;
|
||||
}
|
||||
|
||||
inline bool KeyValuePair::operator<(const KeyValuePair& inAnother) const
|
||||
{
|
||||
if (key < inAnother.key) {
|
||||
return true;
|
||||
}
|
||||
else if (key == inAnother.key) {
|
||||
return value < inAnother.value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
inline std::ostream& operator<<(std::ostream& stream,
|
||||
const KeyValuePair& pair) {
|
||||
stream << "(" << pair.key << "," << pair.value << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline bool KeyValuePair::operator==(const KeyValuePair& another) const {
|
||||
return key == another.key && value == another.value;
|
||||
}
|
||||
|
||||
inline bool KeyValuePair::operator<(const KeyValuePair& another) const {
|
||||
if (key < another.key) {
|
||||
return true;
|
||||
} else if (key == another.key) {
|
||||
return value < another.value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace Gramambular
|
||||
} // namespace Taiyan
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,28 +17,28 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LanguageModel_h
|
||||
#define LanguageModel_h
|
||||
#ifndef LANGUAGEMODEL_H_
|
||||
#define LANGUAGEMODEL_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Bigram.h"
|
||||
#include "Unigram.h"
|
||||
|
||||
namespace Taiyan {
|
||||
namespace Gramambular {
|
||||
|
||||
using namespace std;
|
||||
|
||||
class LanguageModel {
|
||||
public:
|
||||
virtual ~LanguageModel() {}
|
||||
|
||||
virtual const vector<Bigram> bigramsForKeys(const string &preceedingKey, const string& key) = 0;
|
||||
virtual const vector<Unigram> unigramsForKey(const string &key) = 0;
|
||||
virtual bool hasUnigramsForKey(const string& key) = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
namespace Gramambular {
|
||||
|
||||
class LanguageModel {
|
||||
public:
|
||||
virtual ~LanguageModel() {}
|
||||
|
||||
virtual const std::vector<Bigram> bigramsForKeys(
|
||||
const std::string& preceedingKey, const std::string& key) = 0;
|
||||
virtual const std::vector<Unigram> unigramsForKey(const std::string& key) = 0;
|
||||
virtual bool hasUnigramsForKey(const std::string& key) = 0;
|
||||
};
|
||||
} // namespace Gramambular
|
||||
} // namespace Taiyan
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,208 +17,198 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef Node_h
|
||||
#define Node_h
|
||||
#ifndef NODE_H_
|
||||
#define NODE_H_
|
||||
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "LanguageModel.h"
|
||||
|
||||
namespace Taiyan {
|
||||
namespace Gramambular {
|
||||
using namespace std;
|
||||
namespace Gramambular {
|
||||
|
||||
class Node {
|
||||
public:
|
||||
Node();
|
||||
Node(const string& inKey, const vector<Unigram>& inUnigrams, const vector<Bigram>& inBigrams);
|
||||
|
||||
void primeNodeWithPreceedingKeyValues(const vector<KeyValuePair>& inKeyValues);
|
||||
|
||||
bool isCandidateFixed() const;
|
||||
const vector<KeyValuePair>& candidates() const;
|
||||
void selectCandidateAtIndex(size_t inIndex = 0, bool inFix = true);
|
||||
void resetCandidate();
|
||||
void selectFloatingCandidateAtIndex(size_t index, double score);
|
||||
|
||||
const string& key() const;
|
||||
double score() const;
|
||||
// double scoreForCandidate(string &candidate) const; // Prevents the override model to remember symbols with scode -X or lower.
|
||||
const KeyValuePair currentKeyValue() const;
|
||||
double highestUnigramScore() const;
|
||||
|
||||
protected:
|
||||
const LanguageModel* m_LM;
|
||||
|
||||
string m_key;
|
||||
double m_score;
|
||||
|
||||
vector<Unigram> m_unigrams;
|
||||
vector<KeyValuePair> m_candidates;
|
||||
map<string, size_t> m_valueUnigramIndexMap;
|
||||
map<KeyValuePair, vector<Bigram> > m_preceedingGramBigramMap;
|
||||
|
||||
bool m_candidateFixed;
|
||||
size_t m_selectedUnigramIndex;
|
||||
|
||||
friend ostream& operator<<(ostream& inStream, const Node& inNode);
|
||||
};
|
||||
class Node {
|
||||
public:
|
||||
Node();
|
||||
Node(const std::string& key, const std::vector<Unigram>& unigrams,
|
||||
const std::vector<Bigram>& bigrams);
|
||||
|
||||
void primeNodeWithPreceedingKeyValues(
|
||||
const std::vector<KeyValuePair>& keyValues);
|
||||
|
||||
bool isCandidateFixed() const;
|
||||
const std::vector<KeyValuePair>& candidates() const;
|
||||
void selectCandidateAtIndex(size_t index = 0, bool fix = true);
|
||||
void resetCandidate();
|
||||
void selectFloatingCandidateAtIndex(size_t index, double score);
|
||||
|
||||
const std::string& key() const;
|
||||
double score() const;
|
||||
double scoreForCandidate(const std::string& candidate) const;
|
||||
const KeyValuePair currentKeyValue() const;
|
||||
double highestUnigramScore() const;
|
||||
|
||||
protected:
|
||||
const LanguageModel* m_LM;
|
||||
|
||||
std::string m_key;
|
||||
double m_score;
|
||||
|
||||
std::vector<Unigram> m_unigrams;
|
||||
std::vector<KeyValuePair> m_candidates;
|
||||
std::map<std::string, size_t> m_valueUnigramIndexMap;
|
||||
std::map<KeyValuePair, std::vector<Bigram> > m_preceedingGramBigramMap;
|
||||
|
||||
bool m_candidateFixed;
|
||||
size_t m_selectedUnigramIndex;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& stream, const Node& node);
|
||||
};
|
||||
|
||||
inline ostream& operator<<(ostream& inStream, const Node& inNode)
|
||||
{
|
||||
inStream << "(node,key:" << inNode.m_key << ",fixed:" << (inNode.m_candidateFixed ? "true" : "false")
|
||||
<< ",selected:" << inNode.m_selectedUnigramIndex
|
||||
<< "," << inNode.m_unigrams << ")";
|
||||
return inStream;
|
||||
}
|
||||
inline std::ostream& operator<<(std::ostream& stream, const Node& node) {
|
||||
stream << "(node,key:" << node.m_key
|
||||
<< ",fixed:" << (node.m_candidateFixed ? "true" : "false")
|
||||
<< ",selected:" << node.m_selectedUnigramIndex << ","
|
||||
<< node.m_unigrams << ")";
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline Node::Node()
|
||||
: m_candidateFixed(false)
|
||||
, m_selectedUnigramIndex(0)
|
||||
, m_score(0.0)
|
||||
{
|
||||
}
|
||||
inline Node::Node()
|
||||
: m_candidateFixed(false), m_selectedUnigramIndex(0), m_score(0.0) {}
|
||||
|
||||
inline Node::Node(const string& inKey, const vector<Unigram>& inUnigrams, const vector<Bigram>& inBigrams)
|
||||
: m_key(inKey)
|
||||
, m_unigrams(inUnigrams)
|
||||
, m_candidateFixed(false)
|
||||
, m_selectedUnigramIndex(0)
|
||||
, m_score(0.0)
|
||||
{
|
||||
stable_sort(m_unigrams.begin(), m_unigrams.end(), Unigram::ScoreCompare);
|
||||
|
||||
if (m_unigrams.size()) {
|
||||
m_score = m_unigrams[0].score;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (vector<Unigram>::const_iterator ui = m_unigrams.begin() ; ui != m_unigrams.end() ; ++ui) {
|
||||
m_valueUnigramIndexMap[(*ui).keyValue.value] = i;
|
||||
i++;
|
||||
|
||||
m_candidates.push_back((*ui).keyValue);
|
||||
}
|
||||
|
||||
for (vector<Bigram>::const_iterator bi = inBigrams.begin() ; bi != inBigrams.end() ; ++bi) {
|
||||
m_preceedingGramBigramMap[(*bi).preceedingKeyValue].push_back(*bi);
|
||||
}
|
||||
}
|
||||
inline Node::Node(const std::string& key, const std::vector<Unigram>& unigrams,
|
||||
const std::vector<Bigram>& bigrams)
|
||||
: m_key(key),
|
||||
m_unigrams(unigrams),
|
||||
m_candidateFixed(false),
|
||||
m_selectedUnigramIndex(0),
|
||||
m_score(0.0) {
|
||||
stable_sort(m_unigrams.begin(), m_unigrams.end(), Unigram::ScoreCompare);
|
||||
|
||||
if (m_unigrams.size()) {
|
||||
m_score = m_unigrams[0].score;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (std::vector<Unigram>::const_iterator ui = m_unigrams.begin();
|
||||
ui != m_unigrams.end(); ++ui) {
|
||||
m_valueUnigramIndexMap[(*ui).keyValue.value] = i;
|
||||
i++;
|
||||
|
||||
inline void Node::primeNodeWithPreceedingKeyValues(const vector<KeyValuePair>& inKeyValues)
|
||||
{
|
||||
size_t newIndex = m_selectedUnigramIndex;
|
||||
double max = m_score;
|
||||
m_candidates.push_back((*ui).keyValue);
|
||||
}
|
||||
|
||||
for (std::vector<Bigram>::const_iterator bi = bigrams.begin();
|
||||
bi != bigrams.end(); ++bi) {
|
||||
m_preceedingGramBigramMap[(*bi).preceedingKeyValue].push_back(*bi);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isCandidateFixed()) {
|
||||
for (vector<KeyValuePair>::const_iterator kvi = inKeyValues.begin() ; kvi != inKeyValues.end() ; ++kvi) {
|
||||
map<KeyValuePair, vector<Bigram> >::const_iterator f = m_preceedingGramBigramMap.find(*kvi);
|
||||
if (f != m_preceedingGramBigramMap.end()) {
|
||||
const vector<Bigram>& bigrams = (*f).second;
|
||||
|
||||
for (vector<Bigram>::const_iterator bi = bigrams.begin() ; bi != bigrams.end() ; ++bi) {
|
||||
const Bigram& bigram = *bi;
|
||||
if (bigram.score > max) {
|
||||
map<string, size_t>::const_iterator uf = m_valueUnigramIndexMap.find((*bi).keyValue.value);
|
||||
if (uf != m_valueUnigramIndexMap.end()) {
|
||||
newIndex = (*uf).second;
|
||||
max = bigram.score;
|
||||
}
|
||||
}
|
||||
inline void Node::primeNodeWithPreceedingKeyValues(
|
||||
const std::vector<KeyValuePair>& keyValues) {
|
||||
size_t newIndex = m_selectedUnigramIndex;
|
||||
double max = m_score;
|
||||
|
||||
if (!isCandidateFixed()) {
|
||||
for (std::vector<KeyValuePair>::const_iterator kvi = keyValues.begin();
|
||||
kvi != keyValues.end(); ++kvi) {
|
||||
std::map<KeyValuePair, std::vector<Bigram> >::const_iterator f =
|
||||
m_preceedingGramBigramMap.find(*kvi);
|
||||
if (f != m_preceedingGramBigramMap.end()) {
|
||||
const std::vector<Bigram>& bigrams = (*f).second;
|
||||
|
||||
for (std::vector<Bigram>::const_iterator bi = bigrams.begin();
|
||||
bi != bigrams.end(); ++bi) {
|
||||
const Bigram& bigram = *bi;
|
||||
if (bigram.score > max) {
|
||||
std::map<std::string, size_t>::const_iterator uf =
|
||||
m_valueUnigramIndexMap.find((*bi).keyValue.value);
|
||||
if (uf != m_valueUnigramIndexMap.end()) {
|
||||
newIndex = (*uf).second;
|
||||
max = bigram.score;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_score != max) {
|
||||
m_score = max;
|
||||
}
|
||||
|
||||
if (newIndex != m_selectedUnigramIndex) {
|
||||
m_selectedUnigramIndex = newIndex;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool Node::isCandidateFixed() const
|
||||
{
|
||||
return m_candidateFixed;
|
||||
}
|
||||
|
||||
inline const vector<KeyValuePair>& Node::candidates() const
|
||||
{
|
||||
return m_candidates;
|
||||
}
|
||||
|
||||
inline void Node::selectCandidateAtIndex(size_t inIndex, bool inFix)
|
||||
{
|
||||
if (inIndex >= m_unigrams.size()) {
|
||||
m_selectedUnigramIndex = 0;
|
||||
}
|
||||
else {
|
||||
m_selectedUnigramIndex = inIndex;
|
||||
}
|
||||
|
||||
m_candidateFixed = inFix;
|
||||
m_score = 99;
|
||||
}
|
||||
|
||||
inline void Node::resetCandidate()
|
||||
{
|
||||
m_selectedUnigramIndex = 0;
|
||||
m_candidateFixed = 0;
|
||||
if (m_unigrams.size()) {
|
||||
m_score = m_unigrams[0].score;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Node::selectFloatingCandidateAtIndex(size_t index, double score) {
|
||||
if (index >= m_unigrams.size()) {
|
||||
m_selectedUnigramIndex = 0;
|
||||
} else {
|
||||
m_selectedUnigramIndex = index;
|
||||
}
|
||||
m_candidateFixed = false;
|
||||
m_score = score;
|
||||
}
|
||||
|
||||
inline const string& Node::key() const
|
||||
{
|
||||
return m_key;
|
||||
}
|
||||
|
||||
inline double Node::score() const
|
||||
{
|
||||
return m_score;
|
||||
}
|
||||
|
||||
// Prevents the override model to remember symbols with scode -X or lower.
|
||||
// inline double Node::scoreForCandidate(string &candidate) const
|
||||
// {
|
||||
// for (auto unigram : m_unigrams) {
|
||||
// if (unigram.keyValue.value == candidate) {
|
||||
// return unigram.score;
|
||||
// }
|
||||
// }
|
||||
// return 0.0;
|
||||
// }
|
||||
|
||||
inline double Node::highestUnigramScore() const {
|
||||
if (m_unigrams.empty()) {
|
||||
return 0.0;
|
||||
}
|
||||
return m_unigrams[0].score;
|
||||
}
|
||||
|
||||
inline const KeyValuePair Node::currentKeyValue() const
|
||||
{
|
||||
if(m_selectedUnigramIndex >= m_unigrams.size()) {
|
||||
return KeyValuePair();
|
||||
}
|
||||
else {
|
||||
return m_candidates[m_selectedUnigramIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_score != max) {
|
||||
m_score = max;
|
||||
}
|
||||
|
||||
if (newIndex != m_selectedUnigramIndex) {
|
||||
m_selectedUnigramIndex = newIndex;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool Node::isCandidateFixed() const { return m_candidateFixed; }
|
||||
|
||||
inline const std::vector<KeyValuePair>& Node::candidates() const {
|
||||
return m_candidates;
|
||||
}
|
||||
|
||||
inline void Node::selectCandidateAtIndex(size_t index, bool fix) {
|
||||
if (index >= m_unigrams.size()) {
|
||||
m_selectedUnigramIndex = 0;
|
||||
} else {
|
||||
m_selectedUnigramIndex = index;
|
||||
}
|
||||
|
||||
m_candidateFixed = fix;
|
||||
m_score = 99;
|
||||
}
|
||||
|
||||
inline void Node::resetCandidate() {
|
||||
m_selectedUnigramIndex = 0;
|
||||
m_candidateFixed = 0;
|
||||
if (m_unigrams.size()) {
|
||||
m_score = m_unigrams[0].score;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Node::selectFloatingCandidateAtIndex(size_t index, double score) {
|
||||
if (index >= m_unigrams.size()) {
|
||||
m_selectedUnigramIndex = 0;
|
||||
} else {
|
||||
m_selectedUnigramIndex = index;
|
||||
}
|
||||
m_candidateFixed = false;
|
||||
m_score = score;
|
||||
}
|
||||
|
||||
inline const std::string& Node::key() const { return m_key; }
|
||||
|
||||
inline double Node::score() const { return m_score; }
|
||||
|
||||
// Prevents the override model to remember symbols with scode -X or lower.
|
||||
//inline double Node::scoreForCandidate(const std::string& candidate) const {
|
||||
// for (auto unigram : m_unigrams) {
|
||||
// if (unigram.keyValue.value == candidate) {
|
||||
// return unigram.score;
|
||||
// }
|
||||
// }
|
||||
// return 0.0;
|
||||
//}
|
||||
|
||||
inline double Node::highestUnigramScore() const {
|
||||
if (m_unigrams.empty()) {
|
||||
return 0.0;
|
||||
}
|
||||
return m_unigrams[0].score;
|
||||
}
|
||||
|
||||
inline const KeyValuePair Node::currentKeyValue() const {
|
||||
if (m_selectedUnigramIndex >= m_unigrams.size()) {
|
||||
return KeyValuePair();
|
||||
} else {
|
||||
return m_candidates[m_selectedUnigramIndex];
|
||||
}
|
||||
}
|
||||
} // namespace Gramambular
|
||||
} // namespace Taiyan
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,55 +17,48 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef NodeAnchor_h
|
||||
#define NodeAnchor_h
|
||||
#ifndef NODEANCHOR_H_
|
||||
#define NODEANCHOR_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Node.h"
|
||||
|
||||
namespace Taiyan {
|
||||
namespace Gramambular {
|
||||
class NodeAnchor {
|
||||
public:
|
||||
NodeAnchor();
|
||||
const Node *node;
|
||||
size_t location;
|
||||
size_t spanningLength;
|
||||
double accumulatedScore;
|
||||
};
|
||||
|
||||
inline NodeAnchor::NodeAnchor()
|
||||
: node(0)
|
||||
, location(0)
|
||||
, spanningLength(0)
|
||||
, accumulatedScore(0.0)
|
||||
{
|
||||
}
|
||||
namespace Gramambular {
|
||||
|
||||
inline ostream& operator<<(ostream& inStream, const NodeAnchor& inAnchor)
|
||||
{
|
||||
inStream << "{@(" << inAnchor.location << "," << inAnchor.spanningLength << "),";
|
||||
if (inAnchor.node) {
|
||||
inStream << *(inAnchor.node);
|
||||
}
|
||||
else {
|
||||
inStream << "null";
|
||||
}
|
||||
inStream << "}";
|
||||
return inStream;
|
||||
}
|
||||
|
||||
inline ostream& operator<<(ostream& inStream, const vector<NodeAnchor>& inAnchor)
|
||||
{
|
||||
for (vector<NodeAnchor>::const_iterator i = inAnchor.begin() ; i != inAnchor.end() ; ++i) {
|
||||
inStream << *i;
|
||||
if (i + 1 != inAnchor.end()) {
|
||||
inStream << "<-";
|
||||
}
|
||||
}
|
||||
|
||||
return inStream;
|
||||
}
|
||||
struct NodeAnchor {
|
||||
const Node* node = nullptr;
|
||||
size_t location = 0;
|
||||
size_t spanningLength = 0;
|
||||
double accumulatedScore = 0.0;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& stream,
|
||||
const NodeAnchor& anchor) {
|
||||
stream << "{@(" << anchor.location << "," << anchor.spanningLength << "),";
|
||||
if (anchor.node) {
|
||||
stream << *(anchor.node);
|
||||
} else {
|
||||
stream << "null";
|
||||
}
|
||||
stream << "}";
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& stream,
|
||||
const std::vector<NodeAnchor>& anchor) {
|
||||
for (std::vector<NodeAnchor>::const_iterator i = anchor.begin();
|
||||
i != anchor.end(); ++i) {
|
||||
stream << *i;
|
||||
if (i + 1 != anchor.end()) {
|
||||
stream << "<-";
|
||||
}
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
} // namespace Gramambular
|
||||
} // namespace Taiyan
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,88 +17,77 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef Span_h
|
||||
#define Span_h
|
||||
#ifndef SPAN_H_
|
||||
#define SPAN_H_
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
#include "Node.h"
|
||||
|
||||
namespace Taiyan {
|
||||
namespace Gramambular {
|
||||
class Span {
|
||||
public:
|
||||
Span();
|
||||
namespace Gramambular {
|
||||
class Span {
|
||||
public:
|
||||
void clear();
|
||||
void insertNodeOfLength(const Node& node, size_t length);
|
||||
void removeNodeOfLengthGreaterThan(size_t length);
|
||||
|
||||
Node* nodeOfLength(size_t length);
|
||||
size_t maximumLength() const;
|
||||
|
||||
protected:
|
||||
std::map<size_t, Node> m_lengthNodeMap;
|
||||
size_t m_maximumLength = 0;
|
||||
};
|
||||
|
||||
void clear();
|
||||
void insertNodeOfLength(const Node& inNode, size_t inLength);
|
||||
void removeNodeOfLengthGreaterThan(size_t inLength);
|
||||
|
||||
Node* nodeOfLength(size_t inLength);
|
||||
size_t maximumLength() const;
|
||||
inline void Span::clear() {
|
||||
m_lengthNodeMap.clear();
|
||||
m_maximumLength = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
map<size_t, Node> m_lengthNodeMap;
|
||||
size_t m_maximumLength;
|
||||
};
|
||||
|
||||
inline Span::Span()
|
||||
: m_maximumLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline void Span::clear()
|
||||
{
|
||||
m_lengthNodeMap.clear();
|
||||
m_maximumLength = 0;
|
||||
}
|
||||
|
||||
inline void Span::insertNodeOfLength(const Node& inNode, size_t inLength)
|
||||
{
|
||||
m_lengthNodeMap[inLength] = inNode;
|
||||
if (inLength > m_maximumLength) {
|
||||
m_maximumLength = inLength;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Span::removeNodeOfLengthGreaterThan(size_t inLength)
|
||||
{
|
||||
if (inLength > m_maximumLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t max = 0;
|
||||
set<size_t> removeSet;
|
||||
for (map<size_t, Node>::iterator i = m_lengthNodeMap.begin(), e = m_lengthNodeMap.end() ; i != e ; ++i) {
|
||||
if ((*i).first > inLength) {
|
||||
removeSet.insert((*i).first);
|
||||
}
|
||||
else {
|
||||
if ((*i).first > max) {
|
||||
max = (*i).first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (set<size_t>::iterator i = removeSet.begin(), e = removeSet.end(); i != e; ++i) {
|
||||
m_lengthNodeMap.erase(*i);
|
||||
}
|
||||
|
||||
m_maximumLength = max;
|
||||
}
|
||||
|
||||
inline Node* Span::nodeOfLength(size_t inLength)
|
||||
{
|
||||
map<size_t, Node>::iterator f = m_lengthNodeMap.find(inLength);
|
||||
return f == m_lengthNodeMap.end() ? 0 : &(*f).second;
|
||||
}
|
||||
|
||||
inline size_t Span::maximumLength() const
|
||||
{
|
||||
return m_maximumLength;
|
||||
}
|
||||
inline void Span::insertNodeOfLength(const Node& node, size_t length) {
|
||||
m_lengthNodeMap[length] = node;
|
||||
if (length > m_maximumLength) {
|
||||
m_maximumLength = length;
|
||||
}
|
||||
}
|
||||
|
||||
inline void Span::removeNodeOfLengthGreaterThan(size_t length) {
|
||||
if (length > m_maximumLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t max = 0;
|
||||
std::set<size_t> removeSet;
|
||||
for (std::map<size_t, Node>::iterator i = m_lengthNodeMap.begin(),
|
||||
e = m_lengthNodeMap.end();
|
||||
i != e; ++i) {
|
||||
if ((*i).first > length) {
|
||||
removeSet.insert((*i).first);
|
||||
} else {
|
||||
if ((*i).first > max) {
|
||||
max = (*i).first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::set<size_t>::iterator i = removeSet.begin(), e = removeSet.end();
|
||||
i != e; ++i) {
|
||||
m_lengthNodeMap.erase(*i);
|
||||
}
|
||||
|
||||
m_maximumLength = max;
|
||||
}
|
||||
|
||||
inline Node* Span::nodeOfLength(size_t length) {
|
||||
std::map<size_t, Node>::iterator f = m_lengthNodeMap.find(length);
|
||||
return f == m_lengthNodeMap.end() ? 0 : &(*f).second;
|
||||
}
|
||||
|
||||
inline size_t Span::maximumLength() const { return m_maximumLength; }
|
||||
} // namespace Gramambular
|
||||
} // namespace Taiyan
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,80 +17,75 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef Unigram_h
|
||||
#define Unigram_h
|
||||
#ifndef UNIGRAM_H_
|
||||
#define UNIGRAM_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "KeyValuePair.h"
|
||||
|
||||
namespace Taiyan {
|
||||
namespace Gramambular {
|
||||
class Unigram {
|
||||
public:
|
||||
Unigram();
|
||||
namespace Gramambular {
|
||||
|
||||
KeyValuePair keyValue;
|
||||
double score;
|
||||
|
||||
bool operator==(const Unigram& inAnother) const;
|
||||
bool operator<(const Unigram& inAnother) const;
|
||||
|
||||
static bool ScoreCompare(const Unigram& a, const Unigram& b);
|
||||
};
|
||||
class Unigram {
|
||||
public:
|
||||
Unigram();
|
||||
|
||||
KeyValuePair keyValue;
|
||||
double score;
|
||||
|
||||
bool operator==(const Unigram& another) const;
|
||||
bool operator<(const Unigram& another) const;
|
||||
|
||||
static bool ScoreCompare(const Unigram& a, const Unigram& b);
|
||||
};
|
||||
|
||||
inline ostream& operator<<(ostream& inStream, const Unigram& inGram)
|
||||
{
|
||||
streamsize p = inStream.precision();
|
||||
inStream.precision(6);
|
||||
inStream << "(" << inGram.keyValue << "," << inGram.score << ")";
|
||||
inStream.precision(p);
|
||||
return inStream;
|
||||
}
|
||||
|
||||
inline ostream& operator<<(ostream& inStream, const vector<Unigram>& inGrams)
|
||||
{
|
||||
inStream << "[" << inGrams.size() << "]=>{";
|
||||
|
||||
size_t index = 0;
|
||||
|
||||
for (vector<Unigram>::const_iterator gi = inGrams.begin() ; gi != inGrams.end() ; ++gi, ++index) {
|
||||
inStream << index << "=>";
|
||||
inStream << *gi;
|
||||
if (gi + 1 != inGrams.end()) {
|
||||
inStream << ",";
|
||||
}
|
||||
}
|
||||
|
||||
inStream << "}";
|
||||
return inStream;
|
||||
}
|
||||
|
||||
inline Unigram::Unigram()
|
||||
: score(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool Unigram::operator==(const Unigram& inAnother) const
|
||||
{
|
||||
return keyValue == inAnother.keyValue && score == inAnother.score;
|
||||
}
|
||||
|
||||
inline bool Unigram::operator<(const Unigram& inAnother) const
|
||||
{
|
||||
if (keyValue < inAnother.keyValue) {
|
||||
return true;
|
||||
}
|
||||
else if (keyValue == inAnother.keyValue) {
|
||||
return score < inAnother.score;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Unigram::ScoreCompare(const Unigram& a, const Unigram& b)
|
||||
{
|
||||
return a.score > b.score;
|
||||
}
|
||||
}
|
||||
inline std::ostream& operator<<(std::ostream& stream, const Unigram& gram) {
|
||||
std::streamsize p = stream.precision();
|
||||
stream.precision(6);
|
||||
stream << "(" << gram.keyValue << "," << gram.score << ")";
|
||||
stream.precision(p);
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& stream,
|
||||
const std::vector<Unigram>& grams) {
|
||||
stream << "[" << grams.size() << "]=>{";
|
||||
|
||||
size_t index = 0;
|
||||
|
||||
for (std::vector<Unigram>::const_iterator gi = grams.begin();
|
||||
gi != grams.end(); ++gi, ++index) {
|
||||
stream << index << "=>";
|
||||
stream << *gi;
|
||||
if (gi + 1 != grams.end()) {
|
||||
stream << ",";
|
||||
}
|
||||
}
|
||||
|
||||
stream << "}";
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline Unigram::Unigram() : score(0.0) {}
|
||||
|
||||
inline bool Unigram::operator==(const Unigram& another) const {
|
||||
return keyValue == another.keyValue && score == another.score;
|
||||
}
|
||||
|
||||
inline bool Unigram::operator<(const Unigram& another) const {
|
||||
if (keyValue < another.keyValue) {
|
||||
return true;
|
||||
} else if (keyValue == another.keyValue) {
|
||||
return score < another.score;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Unigram::ScoreCompare(const Unigram& a, const Unigram& b) {
|
||||
return a.score > b.score;
|
||||
}
|
||||
} // namespace Gramambular
|
||||
} // namespace Taiyan
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,67 +17,69 @@ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABI
|
|||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef Walker_h
|
||||
#define Walker_h
|
||||
#ifndef WALKER_H_
|
||||
#define WALKER_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "Grid.h"
|
||||
|
||||
namespace Taiyan {
|
||||
namespace Gramambular {
|
||||
using namespace std;
|
||||
namespace Gramambular {
|
||||
|
||||
class Walker {
|
||||
public:
|
||||
Walker(Grid* inGrid);
|
||||
const vector<NodeAnchor> reverseWalk(size_t inLocation, double inAccumulatedScore = 0.0);
|
||||
|
||||
protected:
|
||||
Grid* m_grid;
|
||||
};
|
||||
|
||||
inline Walker::Walker(Grid* inGrid)
|
||||
: m_grid(inGrid)
|
||||
{
|
||||
class Walker {
|
||||
public:
|
||||
explicit Walker(Grid* inGrid);
|
||||
const std::vector<NodeAnchor> reverseWalk(size_t location,
|
||||
double accumulatedScore = 0.0);
|
||||
|
||||
protected:
|
||||
Grid* m_grid;
|
||||
};
|
||||
|
||||
inline Walker::Walker(Grid* inGrid) : m_grid(inGrid) {}
|
||||
|
||||
inline const std::vector<NodeAnchor> Walker::reverseWalk(
|
||||
size_t location, double accumulatedScore) {
|
||||
if (!location || location > m_grid->width()) {
|
||||
return std::vector<NodeAnchor>();
|
||||
}
|
||||
|
||||
std::vector<std::vector<NodeAnchor> > paths;
|
||||
|
||||
std::vector<NodeAnchor> nodes = m_grid->nodesEndingAt(location);
|
||||
|
||||
for (std::vector<NodeAnchor>::iterator ni = nodes.begin(); ni != nodes.end();
|
||||
++ni) {
|
||||
if (!(*ni).node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
inline const vector<NodeAnchor> Walker::reverseWalk(size_t inLocation, double inAccumulatedScore)
|
||||
{
|
||||
if (!inLocation || inLocation > m_grid->width()) {
|
||||
return vector<NodeAnchor>();
|
||||
}
|
||||
|
||||
vector<vector<NodeAnchor> > paths;
|
||||
|
||||
vector<NodeAnchor> nodes = m_grid->nodesEndingAt(inLocation);
|
||||
|
||||
for (vector<NodeAnchor>::iterator ni = nodes.begin() ; ni != nodes.end() ; ++ni) {
|
||||
if (!(*ni).node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(*ni).accumulatedScore = inAccumulatedScore + (*ni).node->score();
|
||||
|
||||
vector<NodeAnchor> path = reverseWalk(inLocation - (*ni).spanningLength, (*ni).accumulatedScore);
|
||||
path.insert(path.begin(), *ni);
|
||||
|
||||
paths.push_back(path);
|
||||
}
|
||||
|
||||
if (!paths.size()) {
|
||||
return vector<NodeAnchor>();
|
||||
}
|
||||
|
||||
vector<NodeAnchor>* result = &*(paths.begin());
|
||||
for (vector<vector<NodeAnchor> >::iterator pi = paths.begin() ; pi != paths.end() ; ++pi) {
|
||||
if ((*pi).back().accumulatedScore > result->back().accumulatedScore) {
|
||||
result = &*pi;
|
||||
}
|
||||
}
|
||||
|
||||
return *result;
|
||||
(*ni).accumulatedScore = accumulatedScore + (*ni).node->score();
|
||||
|
||||
std::vector<NodeAnchor> path =
|
||||
reverseWalk(location - (*ni).spanningLength, (*ni).accumulatedScore);
|
||||
path.insert(path.begin(), *ni);
|
||||
|
||||
paths.push_back(path);
|
||||
}
|
||||
|
||||
if (!paths.size()) {
|
||||
return std::vector<NodeAnchor>();
|
||||
}
|
||||
|
||||
std::vector<NodeAnchor>* result = &*(paths.begin());
|
||||
for (std::vector<std::vector<NodeAnchor> >::iterator pi = paths.begin();
|
||||
pi != paths.end(); ++pi) {
|
||||
if ((*pi).back().accumulatedScore > result->back().accumulatedScore) {
|
||||
result = &*pi;
|
||||
}
|
||||
}
|
||||
|
||||
return *result;
|
||||
}
|
||||
} // namespace Gramambular
|
||||
} // namespace Taiyan
|
||||
|
||||
#endif
|
||||
|
|
182
Source/README
182
Source/README
|
@ -1,182 +0,0 @@
|
|||
.
|
||||
├── AppDelegate.swift
|
||||
├── Base.lproj
|
||||
│ ├── Credits.rtf
|
||||
│ ├── InfoPlist.strings
|
||||
│ ├── Localizable.strings
|
||||
│ ├── MainMenu.xib
|
||||
│ ├── preferences.xib
|
||||
│ ├── template-data.txt
|
||||
│ ├── template-exclude-phrases-plain-bpmf.txt
|
||||
│ ├── template-exclude-phrases.txt
|
||||
│ └── template-phrases-replacement.txt
|
||||
├── Data
|
||||
│ ├── BPMFBase.txt
|
||||
│ ├── BPMFMappings.txt
|
||||
│ ├── BPMFPunctuations.txt
|
||||
│ ├── Makefile
|
||||
│ ├── PhraseFreq.txt
|
||||
│ ├── README
|
||||
│ ├── Symbols.txt
|
||||
│ ├── associated-phrases.cin
|
||||
│ ├── bin
|
||||
│ │ ├── C_Version
|
||||
│ │ │ ├── Makefile
|
||||
│ │ │ ├── count.bash
|
||||
│ │ │ └── count.occurrence.c
|
||||
│ │ ├── README
|
||||
│ │ ├── Sample_Prep
|
||||
│ │ │ ├── build.bash
|
||||
│ │ │ └── filter.bash
|
||||
│ │ ├── bpmfmap.py
|
||||
│ │ ├── buildFreq.py
|
||||
│ │ ├── cook-plain-bpmf.py
|
||||
│ │ ├── cook.py
|
||||
│ │ ├── cook_util.py
|
||||
│ │ ├── count.bash
|
||||
│ │ ├── count.occurrence.py
|
||||
│ │ ├── disabled
|
||||
│ │ │ ├── BIG5toUTF8.pl
|
||||
│ │ │ ├── bpmfmap_human.py
|
||||
│ │ │ ├── build4wlist.bash
|
||||
│ │ │ ├── buildFreq.bash
|
||||
│ │ │ ├── cook.rb
|
||||
│ │ │ ├── count.occurrence.pl
|
||||
│ │ │ ├── countphrase.bash
|
||||
│ │ │ ├── randomShuffle.bash
|
||||
│ │ │ ├── typocorrection.bash
|
||||
│ │ │ └── utf8length.pl
|
||||
│ │ ├── nonCJK_filter.py
|
||||
│ │ ├── self-score-test.py
|
||||
│ │ └── textpool.rc
|
||||
│ ├── data-plain-bpmf.txt
|
||||
│ ├── data.txt
|
||||
│ ├── exclusion.txt
|
||||
│ ├── heterophony1.list
|
||||
│ ├── heterophony2.list
|
||||
│ ├── heterophony3.list
|
||||
│ ├── memo
|
||||
│ │ ├── blacklist.txt
|
||||
│ │ ├── covered_by_others.txt
|
||||
│ │ ├── covered_by_singles.txt
|
||||
│ │ └── falsecount.txt
|
||||
│ └── phrase.occ
|
||||
├── Engine
|
||||
│ ├── AssociatedPhrases.cpp
|
||||
│ ├── AssociatedPhrases.h
|
||||
│ ├── CMakeLists.txt
|
||||
│ ├── Gramambular
|
||||
│ │ ├── Bigram.h
|
||||
│ │ ├── BlockReadingBuilder.h
|
||||
│ │ ├── Gramambular.h
|
||||
│ │ ├── Grid.h
|
||||
│ │ ├── KeyValuePair.h
|
||||
│ │ ├── LanguageModel.h
|
||||
│ │ ├── Node.h
|
||||
│ │ ├── NodeAnchor.h
|
||||
│ │ ├── Span.h
|
||||
│ │ ├── Unigram.h
|
||||
│ │ └── Walker.h
|
||||
│ ├── KeyValueBlobReader.cpp
|
||||
│ ├── KeyValueBlobReader.h
|
||||
│ ├── KeyValueBlobReaderTest.cpp
|
||||
│ ├── Mandarin
|
||||
│ │ ├── CMakeLists.txt
|
||||
│ │ ├── Mandarin.cpp
|
||||
│ │ ├── Mandarin.h
|
||||
│ │ └── MandarinTest.cpp
|
||||
│ ├── McBopomofoLM.cpp
|
||||
│ ├── McBopomofoLM.h
|
||||
│ ├── ParselessLM.cpp
|
||||
│ ├── ParselessLM.h
|
||||
│ ├── ParselessLMBenchmark.cpp
|
||||
│ ├── ParselessLMTest.cpp
|
||||
│ ├── ParselessPhraseDB.cpp
|
||||
│ ├── ParselessPhraseDB.h
|
||||
│ ├── ParselessPhraseDBTest.cpp
|
||||
│ ├── PhraseReplacementMap.cpp
|
||||
│ ├── PhraseReplacementMap.h
|
||||
│ ├── PhraseReplacementMapTest.cpp
|
||||
│ ├── UserOverrideModel.cpp
|
||||
│ ├── UserOverrideModel.h
|
||||
│ ├── UserPhrasesLM.cpp
|
||||
│ ├── UserPhrasesLM.h
|
||||
│ └── UserPhrasesLMTest.cpp
|
||||
├── Images
|
||||
│ ├── Bopomofo.tiff
|
||||
│ ├── Bopomofo@2x.tiff
|
||||
│ ├── Images.xcassets
|
||||
│ │ ├── AlertIcon.imageset
|
||||
│ │ │ ├── 128X128.png
|
||||
│ │ │ ├── 192x192.png
|
||||
│ │ │ ├── 64X64.png
|
||||
│ │ │ └── Contents.json
|
||||
│ │ ├── AppIcon.appiconset
|
||||
│ │ │ ├── 1024X1024.png
|
||||
│ │ │ ├── 128X128.png
|
||||
│ │ │ ├── 16X16.png
|
||||
│ │ │ ├── 256X256.png
|
||||
│ │ │ ├── 32X32.png
|
||||
│ │ │ ├── 512X512.png
|
||||
│ │ │ ├── 64X64.png
|
||||
│ │ │ └── Contents.json
|
||||
│ │ └── Contents.json
|
||||
│ ├── PlainBopomofo.tiff
|
||||
│ └── PlainBopomofo@2x.tiff
|
||||
├── InputMethodController.swift
|
||||
├── InputState.swift
|
||||
├── Installer
|
||||
│ ├── AppDelegate.swift
|
||||
│ ├── ArchiveUtil.swift
|
||||
│ ├── Base.lproj
|
||||
│ │ └── MainMenu.xib
|
||||
│ ├── BundleTranslocate.h
|
||||
│ ├── BundleTranslocate.m
|
||||
│ ├── Installer-Info.plist
|
||||
│ ├── Installer-Prefix.pch
|
||||
│ ├── McBopomofoInstaller-Bridging-Header.h
|
||||
│ ├── NotarizedArchives
|
||||
│ │ └── README.md
|
||||
│ ├── en.lproj
|
||||
│ │ ├── InfoPlist.strings
|
||||
│ │ ├── License.rtf
|
||||
│ │ └── Localizable.strings
|
||||
│ └── zh-Hant.lproj
|
||||
│ ├── InfoPlist.strings
|
||||
│ ├── License.rtf
|
||||
│ ├── Localizable.strings
|
||||
│ └── MainMenu.xib
|
||||
├── KeyHandler.h
|
||||
├── KeyHandler.mm
|
||||
├── KeyHandlerInput.swift
|
||||
├── LanguageModelManager+Privates.h
|
||||
├── LanguageModelManager.h
|
||||
├── LanguageModelManager.mm
|
||||
├── McBopomofo-Bridging-Header.h
|
||||
├── McBopomofo-Info.plist
|
||||
├── McBopomofo-Prefix.pch
|
||||
├── NonModalAlertWindowController.swift
|
||||
├── NonModalAlertWindowController.xib
|
||||
├── Preferences.swift
|
||||
├── PreferencesWindowController.swift
|
||||
├── README
|
||||
├── Tools
|
||||
│ ├── genRTF.py
|
||||
│ └── tistool.m
|
||||
├── en.lproj
|
||||
│ ├── Credits.rtf
|
||||
│ ├── InfoPlist.strings
|
||||
│ └── Localizable.strings
|
||||
├── main.swift
|
||||
└── zh-Hant.lproj
|
||||
├── Credits.rtf
|
||||
├── InfoPlist.strings
|
||||
├── Localizable.strings
|
||||
├── MainMenu.xib
|
||||
├── preferences.xib
|
||||
├── template-data.txt
|
||||
├── template-exclude-phrases-plain-bpmf.txt
|
||||
├── template-exclude-phrases.txt
|
||||
└── template-phrases-replacement.txt
|
||||
|
||||
22 directories, 157 files
|
|
@ -24,7 +24,7 @@
|
|||
"\"%@\" length must ≥ 2 for a user phrase." = "\"%@\" length must ≥ 2 for a user phrase.";
|
||||
"\"%@\" length should ≤ %d for a user phrase." = "\"%@\" length should ≤ %d for a user phrase.";
|
||||
"\"%@\" selected. ENTER to add user phrase." = "\"%@\" selected. ENTER to add user phrase.";
|
||||
"\"%@\" already exists." = "\"%@\" already exists.";
|
||||
"\"%@\" already exists, ENTER to boost its priority." = "\"%@\" already exists, ENTER to boost its priority.";
|
||||
"Edit Phrase Replacement Table…" = "Edit Phrase Replacement Table…";
|
||||
"Use Phrase Replacement" = "Use Phrase Replacement";
|
||||
"Candidates keys cannot be empty." = "Candidates keys cannot be empty.";
|
||||
|
|
Binary file not shown.
|
@ -24,7 +24,7 @@
|
|||
"\"%@\" length must ≥ 2 for a user phrase." = "\"%@\" length must ≥ 2 for a user phrase.";
|
||||
"\"%@\" length should ≤ %d for a user phrase." = "\"%@\" length should ≤ %d for a user phrase.";
|
||||
"\"%@\" selected. ENTER to add user phrase." = "\"%@\" selected. ENTER to add user phrase.";
|
||||
"\"%@\" already exists." = "\"%@\" already exists.";
|
||||
"\"%@\" already exists, ENTER to boost its priority." = "\"%@\" already exists, ENTER to boost its priority.";
|
||||
"Edit Phrase Replacement Table…" = "Edit Phrase Replacement Table…";
|
||||
"Use Phrase Replacement" = "Use Phrase Replacement";
|
||||
"Candidates keys cannot be empty." = "Candidates keys cannot be empty.";
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」もう1つ文字のお選びを。";
|
||||
"\"%@\" length should ≤ %d for a user phrase." = "「%@」文字数過剰で登録不可、%d 文字以内にして下さい。";
|
||||
"\"%@\" selected. ENTER to add user phrase." = "「%@」を ENTER で辞書に登録。";
|
||||
"\"%@\" already exists." = "「%@」は既存語彙である。";
|
||||
"\"%@\" already exists, ENTER to boost its priority." = "「%@」は既存語彙であり、ENTER で最優先にする。";
|
||||
"Edit Phrase Replacement Table…" = "言葉置換表を編集…";
|
||||
"Use Phrase Replacement" = "言葉置換機能";
|
||||
"Candidates keys cannot be empty." = "言選り用キー陣列に何かキーをご登録ください。";
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」字数不足以自订语汇。";
|
||||
"\"%@\" length should ≤ %d for a user phrase." = "「%@」字数超过 %d、无法自订。";
|
||||
"\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自订语汇。";
|
||||
"\"%@\" already exists." = "「%@」已存在。";
|
||||
"\"%@\" already exists, ENTER to boost its priority." = "「%@」已存在,敲 ENTER 以提升其权重。";
|
||||
"Edit Phrase Replacement Table…" = "编辑语汇置换表…";
|
||||
"Use Phrase Replacement" = "使用语汇置换";
|
||||
"Candidates keys cannot be empty." = "您必须指定选字键。";
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"\"%@\" length must ≥ 2 for a user phrase." = "「%@」字數不足以自訂語彙。";
|
||||
"\"%@\" length should ≤ %d for a user phrase." = "「%@」字數超過 %d、無法自訂。";
|
||||
"\"%@\" selected. ENTER to add user phrase." = "「%@」敲 Enter 添入自訂語彙。";
|
||||
"\"%@\" already exists." = "「%@」已存在。";
|
||||
"\"%@\" already exists, ENTER to boost its priority." = "「%@」已存在,敲 ENTER 以提升其權重。";
|
||||
"Edit Phrase Replacement Table…" = "編輯語彙置換表…";
|
||||
"Use Phrase Replacement" = "使用語彙置換";
|
||||
"Candidates keys cannot be empty." = "您必須指定選字鍵。";
|
||||
|
|
|
@ -86,7 +86,7 @@ extension RangeReplaceableCollection where Element: Hashable {
|
|||
|
||||
let menuItem_vChewingDachen = NSMenuItem()
|
||||
menuItem_vChewingDachen.title = String(format: NSLocalizedString("vChewing Dachen (Not Finished Yet)", comment: ""))
|
||||
menuItem_vChewingDachen.representedObject = String("org.atelierInmu.keyboardlayout.vChewingKeyLayout.zhuyindachen")
|
||||
menuItem_vChewingDachen.representedObject = String("org.atelierInmu.keyboardlayout.vChewingKeyLayout.vChewingDachen")
|
||||
basisKeyboardLayoutButton.menu?.addItem(menuItem_vChewingDachen)
|
||||
|
||||
let basisKeyboardLayoutID = Preferences.basisKeyboardLayout
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
<key>UpdateInfoSite</key>
|
||||
<string>https://gitee.com/vchewing/vChewing-macOS</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1922</string>
|
||||
<string>1923</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.3.3</string>
|
||||
<string>1.3.4</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */; };
|
||||
5B2DB16F27AF6891006D874E /* data-chs.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DB16D27AF6891006D874E /* data-chs.txt */; };
|
||||
5B2DB17027AF6891006D874E /* data-cht.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DB16E27AF6891006D874E /* data-cht.txt */; };
|
||||
5B30F11327BA568800484E24 /* vChewingKeyLayout.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */; };
|
||||
5B62A31727AE73A700A19448 /* unzip.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A30927AE73A700A19448 /* unzip.m */; };
|
||||
5B62A31827AE73A700A19448 /* zip.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A30A27AE73A700A19448 /* zip.m */; };
|
||||
5B62A31927AE73A700A19448 /* ioapi.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A30B27AE73A700A19448 /* ioapi.m */; };
|
||||
|
@ -50,6 +49,12 @@
|
|||
5BD05C6827B2BBEF004C4F1D /* Content.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD05C6327B2BBEF004C4F1D /* Content.swift */; };
|
||||
5BD05C6927B2BBEF004C4F1D /* WindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD05C6427B2BBEF004C4F1D /* WindowController.swift */; };
|
||||
5BD05C6A27B2BBEF004C4F1D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD05C6527B2BBEF004C4F1D /* ViewController.swift */; };
|
||||
5BDC5CAB27C2873D00E1CCE2 /* Grid.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC5CAA27C2873D00E1CCE2 /* Grid.mm */; };
|
||||
5BDC5CB327C28E8B00E1CCE2 /* icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 5BDC5CB227C28E8B00E1CCE2 /* icon.icns */; };
|
||||
5BDC5CB527C28E8B00E1CCE2 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC5CB427C28E8B00E1CCE2 /* ShareViewController.swift */; };
|
||||
5BDC5CB827C28E8B00E1CCE2 /* ShareViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BDC5CB627C28E8B00E1CCE2 /* ShareViewController.xib */; };
|
||||
5BDC5CBD27C28E8B00E1CCE2 /* KeyboardExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 5BDC5CB027C28E8B00E1CCE2 /* KeyboardExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
5BDC5CC227C2941F00E1CCE2 /* vChewingKeyLayout.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */; };
|
||||
5BDCBB2E27B4E67A00D0CC59 /* vChewingPhraseEditor.app in Resources */ = {isa = PBXBuildFile; fileRef = 5BD05BB827B2A429004C4F1D /* vChewingPhraseEditor.app */; };
|
||||
5BE78BD927B3775B005EA1BE /* ctlAboutWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BE78BD827B37750005EA1BE /* ctlAboutWindow.swift */; };
|
||||
5BE78BDD27B3776D005EA1BE /* frmAboutWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BE78BDA27B37764005EA1BE /* frmAboutWindow.xib */; };
|
||||
|
@ -68,7 +73,7 @@
|
|||
6ACC3D442793701600F1B140 /* ParselessPhraseDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6ACC3D402793701600F1B140 /* ParselessPhraseDB.cpp */; };
|
||||
6ACC3D452793701600F1B140 /* ParselessLM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6ACC3D422793701600F1B140 /* ParselessLM.cpp */; };
|
||||
D41355D8278D74B5005E5CBD /* mgrLangModel.mm in Sources */ = {isa = PBXBuildFile; fileRef = D41355D7278D7409005E5CBD /* mgrLangModel.mm */; };
|
||||
D41355DB278E6D17005E5CBD /* vChewingLM.mm in Sources */ = {isa = PBXBuildFile; fileRef = D41355D9278E6D17005E5CBD /* vChewingLM.mm */; };
|
||||
D41355DB278E6D17005E5CBD /* LMInstantiator.mm in Sources */ = {isa = PBXBuildFile; fileRef = D41355D9278E6D17005E5CBD /* LMInstantiator.mm */; };
|
||||
D41355DE278EA3ED005E5CBD /* UserPhrasesLM.mm in Sources */ = {isa = PBXBuildFile; fileRef = D41355DC278EA3ED005E5CBD /* UserPhrasesLM.mm */; };
|
||||
D427F76C278CA2B0004A2160 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D427F76B278CA1BA004A2160 /* AppDelegate.swift */; };
|
||||
D44FB74D2792189A003C80A6 /* PhraseReplacementMap.mm in Sources */ = {isa = PBXBuildFile; fileRef = D44FB74B2792189A003C80A6 /* PhraseReplacementMap.mm */; };
|
||||
|
@ -96,6 +101,13 @@
|
|||
remoteGlobalIDString = 5BD05BB727B2A429004C4F1D;
|
||||
remoteInfo = vChewingPhraseEditor;
|
||||
};
|
||||
5BDC5CBB27C28E8B00E1CCE2 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 6A0D4E9415FC0CFA00ABF4B3 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 5BDC5CAF27C28E8B00E1CCE2;
|
||||
remoteInfo = KeyboardExtension;
|
||||
};
|
||||
6A38BC2515FC131100A8A51F /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 6A0D4E9415FC0CFA00ABF4B3 /* Project object */;
|
||||
|
@ -112,6 +124,20 @@
|
|||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
5BDC5CBE27C28E8B00E1CCE2 /* Embed App Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 13;
|
||||
files = (
|
||||
5BDC5CBD27C28E8B00E1CCE2 /* KeyboardExtension.appex in Embed App Extensions */,
|
||||
);
|
||||
name = "Embed App Extensions";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
5B04305327B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
|
||||
5B04305427B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
|
@ -195,6 +221,13 @@
|
|||
5BD05C6327B2BBEF004C4F1D /* Content.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Content.swift; sourceTree = "<group>"; };
|
||||
5BD05C6427B2BBEF004C4F1D /* WindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WindowController.swift; sourceTree = "<group>"; };
|
||||
5BD05C6527B2BBEF004C4F1D /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
5BDC5CAA27C2873D00E1CCE2 /* Grid.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Grid.mm; sourceTree = "<group>"; };
|
||||
5BDC5CB027C28E8B00E1CCE2 /* KeyboardExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = KeyboardExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
5BDC5CB227C28E8B00E1CCE2 /* icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icon.icns; sourceTree = "<group>"; };
|
||||
5BDC5CB427C28E8B00E1CCE2 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = "<group>"; };
|
||||
5BDC5CB727C28E8B00E1CCE2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/ShareViewController.xib; sourceTree = "<group>"; };
|
||||
5BDC5CB927C28E8B00E1CCE2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
5BDC5CBA27C28E8B00E1CCE2 /* KeyboardExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = KeyboardExtension.entitlements; sourceTree = "<group>"; };
|
||||
5BDCBB4227B4F6C600D0CC59 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/MainMenu.strings"; sourceTree = "<group>"; };
|
||||
5BDCBB4327B4F6C600D0CC59 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/frmAboutWindow.strings"; sourceTree = "<group>"; };
|
||||
5BDCBB4527B4F6C600D0CC59 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings"; sourceTree = "<group>"; };
|
||||
|
@ -243,8 +276,8 @@
|
|||
6ACC3D432793701600F1B140 /* ParselessLM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParselessLM.h; sourceTree = "<group>"; };
|
||||
D41355D6278D7409005E5CBD /* mgrLangModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mgrLangModel.h; sourceTree = "<group>"; };
|
||||
D41355D7278D7409005E5CBD /* mgrLangModel.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = mgrLangModel.mm; sourceTree = "<group>"; };
|
||||
D41355D9278E6D17005E5CBD /* vChewingLM.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = vChewingLM.mm; sourceTree = "<group>"; };
|
||||
D41355DA278E6D17005E5CBD /* vChewingLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vChewingLM.h; sourceTree = "<group>"; };
|
||||
D41355D9278E6D17005E5CBD /* LMInstantiator.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = LMInstantiator.mm; sourceTree = "<group>"; };
|
||||
D41355DA278E6D17005E5CBD /* LMInstantiator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LMInstantiator.h; sourceTree = "<group>"; };
|
||||
D41355DC278EA3ED005E5CBD /* UserPhrasesLM.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UserPhrasesLM.mm; sourceTree = "<group>"; };
|
||||
D41355DD278EA3ED005E5CBD /* UserPhrasesLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UserPhrasesLM.h; sourceTree = "<group>"; };
|
||||
D427A9BF25ED28CC005D43E0 /* vChewing-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "vChewing-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
|
@ -280,6 +313,13 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
5BDC5CAD27C28E8B00E1CCE2 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6A0D4E9F15FC0D2D00ABF4B3 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -297,14 +337,6 @@
|
|||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
5B30F10727BA501900484E24 /* KeyLayouts */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */,
|
||||
);
|
||||
path = KeyLayouts;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5B62A30127AE732800A19448 /* 3rdParty */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -423,12 +455,12 @@
|
|||
5B62A32427AE757300A19448 /* LangModelRelated */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D41355D9278E6D17005E5CBD /* LMInstantiator.mm */,
|
||||
D41355DA278E6D17005E5CBD /* LMInstantiator.h */,
|
||||
D41355D6278D7409005E5CBD /* mgrLangModel.h */,
|
||||
D495583A27A5C6C4006ADE1C /* mgrLangModel_Privates.h */,
|
||||
D41355D7278D7409005E5CBD /* mgrLangModel.mm */,
|
||||
5B62A32527AE758000A19448 /* SubLanguageModels */,
|
||||
D41355D9278E6D17005E5CBD /* vChewingLM.mm */,
|
||||
D41355DA278E6D17005E5CBD /* vChewingLM.h */,
|
||||
);
|
||||
path = LangModelRelated;
|
||||
sourceTree = "<group>";
|
||||
|
@ -459,7 +491,6 @@
|
|||
5B62A33027AE78E500A19448 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B30F10727BA501900484E24 /* KeyLayouts */,
|
||||
6A0D4EEE15FC0DA600ABF4B3 /* Images */,
|
||||
5BBBB76E27AED70B0023B93A /* MenuIcons */,
|
||||
5BBBB75C27AED54C0023B93A /* SoundFiles */,
|
||||
|
@ -596,6 +627,19 @@
|
|||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5BDC5CB127C28E8B00E1CCE2 /* KeyboardExtension */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */,
|
||||
5BDC5CB227C28E8B00E1CCE2 /* icon.icns */,
|
||||
5BDC5CB427C28E8B00E1CCE2 /* ShareViewController.swift */,
|
||||
5BDC5CB627C28E8B00E1CCE2 /* ShareViewController.xib */,
|
||||
5BDC5CB927C28E8B00E1CCE2 /* Info.plist */,
|
||||
5BDC5CBA27C28E8B00E1CCE2 /* KeyboardExtension.entitlements */,
|
||||
);
|
||||
path = KeyboardExtension;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
6A0D4E9215FC0CFA00ABF4B3 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -603,6 +647,7 @@
|
|||
6ACA41E715FC1D9000935EF6 /* Installer */,
|
||||
6A0D4EC215FC0D3C00ABF4B3 /* Source */,
|
||||
5BD05BB927B2A429004C4F1D /* UserPhraseEditor */,
|
||||
5BDC5CB127C28E8B00E1CCE2 /* KeyboardExtension */,
|
||||
6A0D4EA315FC0D2D00ABF4B3 /* Products */,
|
||||
D47D73C127A7200500255A50 /* Frameworks */,
|
||||
);
|
||||
|
@ -614,6 +659,7 @@
|
|||
6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */,
|
||||
6ACA41CB15FC1D7500935EF6 /* vChewingInstaller.app */,
|
||||
5BD05BB827B2A429004C4F1D /* vChewingPhraseEditor.app */,
|
||||
5BDC5CB027C28E8B00E1CCE2 /* KeyboardExtension.appex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
@ -663,6 +709,7 @@
|
|||
6A0D4F1515FC0EB100ABF4B3 /* BlockReadingBuilder.h */,
|
||||
6A0D4F1615FC0EB100ABF4B3 /* Gramambular.h */,
|
||||
6A0D4F1715FC0EB100ABF4B3 /* Grid.h */,
|
||||
5BDC5CAA27C2873D00E1CCE2 /* Grid.mm */,
|
||||
6A0D4F1815FC0EB100ABF4B3 /* KeyValuePair.h */,
|
||||
6A0D4F1915FC0EB100ABF4B3 /* LanguageModel.h */,
|
||||
6A0D4F1A15FC0EB100ABF4B3 /* Node.h */,
|
||||
|
@ -734,6 +781,23 @@
|
|||
productReference = 5BD05BB827B2A429004C4F1D /* vChewingPhraseEditor.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
5BDC5CAF27C28E8B00E1CCE2 /* KeyboardExtension */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 5BDC5CC127C28E8B00E1CCE2 /* Build configuration list for PBXNativeTarget "KeyboardExtension" */;
|
||||
buildPhases = (
|
||||
5BDC5CAC27C28E8B00E1CCE2 /* Sources */,
|
||||
5BDC5CAD27C28E8B00E1CCE2 /* Frameworks */,
|
||||
5BDC5CAE27C28E8B00E1CCE2 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = KeyboardExtension;
|
||||
productName = KeyboardExtension;
|
||||
productReference = 5BDC5CB027C28E8B00E1CCE2 /* KeyboardExtension.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
6A0D4EA115FC0D2D00ABF4B3 /* vChewing */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 6A0D4EC015FC0D2E00ABF4B3 /* Build configuration list for PBXNativeTarget "vChewing" */;
|
||||
|
@ -741,12 +805,14 @@
|
|||
6A0D4E9E15FC0D2D00ABF4B3 /* Sources */,
|
||||
6A0D4E9F15FC0D2D00ABF4B3 /* Frameworks */,
|
||||
6A0D4EA015FC0D2D00ABF4B3 /* Resources */,
|
||||
5BDC5CBE27C28E8B00E1CCE2 /* Embed App Extensions */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
5B0AF8B327B2C4E20096FE54 /* PBXTargetDependency */,
|
||||
6A38BC2615FC131100A8A51F /* PBXTargetDependency */,
|
||||
5BDC5CBC27C28E8B00E1CCE2 /* PBXTargetDependency */,
|
||||
);
|
||||
name = vChewing;
|
||||
packageProductDependencies = (
|
||||
|
@ -790,6 +856,10 @@
|
|||
LastSwiftMigration = 1320;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
5BDC5CAF27C28E8B00E1CCE2 = {
|
||||
CreatedOnToolsVersion = 13.2;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
6A0D4EA115FC0D2D00ABF4B3 = {
|
||||
LastSwiftMigration = 1240;
|
||||
ProvisioningStyle = Automatic;
|
||||
|
@ -821,6 +891,7 @@
|
|||
6A0D4EA115FC0D2D00ABF4B3 /* vChewing */,
|
||||
6ACA41CA15FC1D7500935EF6 /* vChewingInstaller */,
|
||||
5BD05BB727B2A429004C4F1D /* vChewingPhraseEditor */,
|
||||
5BDC5CAF27C28E8B00E1CCE2 /* KeyboardExtension */,
|
||||
6A38BC2115FC12FD00A8A51F /* Data */,
|
||||
);
|
||||
};
|
||||
|
@ -838,6 +909,16 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
5BDC5CAE27C28E8B00E1CCE2 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
5BDC5CB827C28E8B00E1CCE2 /* ShareViewController.xib in Resources */,
|
||||
5BDC5CC227C2941F00E1CCE2 /* vChewingKeyLayout.bundle in Resources */,
|
||||
5BDC5CB327C28E8B00E1CCE2 /* icon.icns in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6A0D4EA015FC0D2D00ABF4B3 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -858,7 +939,6 @@
|
|||
5BBBB77627AED70B0023B93A /* MenuIcon-TCVIM.png in Resources */,
|
||||
6A187E2616004C5900466B2E /* MainMenu.xib in Resources */,
|
||||
5BBBB75F27AED54C0023B93A /* Beep.m4a in Resources */,
|
||||
5B30F11327BA568800484E24 /* vChewingKeyLayout.bundle in Resources */,
|
||||
5B2DB16F27AF6891006D874E /* data-chs.txt in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -913,6 +993,14 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
5BDC5CAC27C28E8B00E1CCE2 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
5BDC5CB527C28E8B00E1CCE2 /* ShareViewController.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
6A0D4E9E15FC0D2D00ABF4B3 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -937,12 +1025,13 @@
|
|||
5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */,
|
||||
5B62A31827AE73A700A19448 /* zip.m in Sources */,
|
||||
5B62A32E27AE78B000A19448 /* CNSLM.mm in Sources */,
|
||||
D41355DB278E6D17005E5CBD /* vChewingLM.mm in Sources */,
|
||||
D41355DB278E6D17005E5CBD /* LMInstantiator.mm in Sources */,
|
||||
5B62A31A27AE73A700A19448 /* mztools.m in Sources */,
|
||||
5B62A32927AE77D100A19448 /* FSEventStreamHelper.swift in Sources */,
|
||||
D47F7DD3278C1263002F9DD7 /* UserOverrideModel.cpp in Sources */,
|
||||
5B62A33627AE795800A19448 /* PreferencesModule.swift in Sources */,
|
||||
5B62A33827AE79CD00A19448 /* NSStringUtils.swift in Sources */,
|
||||
5BDC5CAB27C2873D00E1CCE2 /* Grid.mm in Sources */,
|
||||
5B62A33227AE792F00A19448 /* InputSourceHelper.swift in Sources */,
|
||||
5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */,
|
||||
6A0D4F4515FC0EB100ABF4B3 /* Mandarin.cpp in Sources */,
|
||||
|
@ -979,6 +1068,11 @@
|
|||
target = 5BD05BB727B2A429004C4F1D /* vChewingPhraseEditor */;
|
||||
targetProxy = 5B0AF8B227B2C4E20096FE54 /* PBXContainerItemProxy */;
|
||||
};
|
||||
5BDC5CBC27C28E8B00E1CCE2 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 5BDC5CAF27C28E8B00E1CCE2 /* KeyboardExtension */;
|
||||
targetProxy = 5BDC5CBB27C28E8B00E1CCE2 /* PBXContainerItemProxy */;
|
||||
};
|
||||
6A38BC2615FC131100A8A51F /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 6A38BC2115FC12FD00A8A51F /* Data */;
|
||||
|
@ -1046,6 +1140,14 @@
|
|||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5BDC5CB627C28E8B00E1CCE2 /* ShareViewController.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
5BDC5CB727C28E8B00E1CCE2 /* Base */,
|
||||
);
|
||||
name = ShareViewController.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5BE78BDA27B37764005EA1BE /* frmAboutWindow.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
|
@ -1147,7 +1249,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1922;
|
||||
CURRENT_PROJECT_VERSION = 1923;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
|
@ -1166,7 +1268,7 @@
|
|||
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
MARKETING_VERSION = 1.3.4;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
|
||||
|
@ -1199,7 +1301,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1922;
|
||||
CURRENT_PROJECT_VERSION = 1923;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
|
@ -1213,7 +1315,7 @@
|
|||
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
MARKETING_VERSION = 1.3.4;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
|
||||
|
@ -1225,6 +1327,102 @@
|
|||
};
|
||||
name = Release;
|
||||
};
|
||||
5BDC5CBF27C28E8B00E1CCE2 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = KeyboardExtension/KeyboardExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1923;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_ASSET_PATHS = KeyboardExtension/vChewingKeyLayout.bundle;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = KeyboardExtension/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = KeyboardExtension;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.1;
|
||||
MARKETING_VERSION = 1.3.4;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing.KeyboardExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
5BDC5CC027C28E8B00E1CCE2 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = KeyboardExtension/KeyboardExtension.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1923;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_ASSET_PATHS = KeyboardExtension/vChewingKeyLayout.bundle;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = KeyboardExtension/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = KeyboardExtension;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.1;
|
||||
MARKETING_VERSION = 1.3.4;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing.KeyboardExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
6A0D4E9915FC0CFA00ABF4B3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
@ -1311,6 +1509,7 @@
|
|||
6A0D4EBE15FC0D2E00ABF4B3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
|
@ -1327,8 +1526,8 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1922;
|
||||
DEVELOPMENT_ASSET_PATHS = Source/Resources/KeyLayouts/vChewingKeyLayout.bundle;
|
||||
CURRENT_PROJECT_VERSION = 1923;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
|
@ -1359,7 +1558,7 @@
|
|||
INFOPLIST_FILE = "Source/Resources/IME-Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
MARKETING_VERSION = 1.3.4;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -1375,6 +1574,7 @@
|
|||
6A0D4EBF15FC0D2E00ABF4B3 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
|
@ -1391,9 +1591,9 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1922;
|
||||
CURRENT_PROJECT_VERSION = 1923;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_ASSET_PATHS = Source/Resources/KeyLayouts/vChewingKeyLayout.bundle;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
|
@ -1417,7 +1617,7 @@
|
|||
INFOPLIST_FILE = "Source/Resources/IME-Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
MARKETING_VERSION = 1.3.4;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
@ -1500,7 +1700,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1922;
|
||||
CURRENT_PROJECT_VERSION = 1923;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
|
@ -1522,7 +1722,7 @@
|
|||
INFOPLIST_FILE = "Installer/Installer-Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
MARKETING_VERSION = 1.3.4;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -1550,7 +1750,7 @@
|
|||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1922;
|
||||
CURRENT_PROJECT_VERSION = 1923;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
|
@ -1566,7 +1766,7 @@
|
|||
INFOPLIST_FILE = "Installer/Installer-Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11.5;
|
||||
MARKETING_VERSION = 1.3.3;
|
||||
MARKETING_VERSION = 1.3.4;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
|
@ -1589,6 +1789,15 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
5BDC5CC127C28E8B00E1CCE2 /* Build configuration list for PBXNativeTarget "KeyboardExtension" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
5BDC5CBF27C28E8B00E1CCE2 /* Debug */,
|
||||
5BDC5CC027C28E8B00E1CCE2 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
6A0D4E9715FC0CFA00ABF4B3 /* Build configuration list for PBXProject "vChewing" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
Loading…
Reference in New Issue