Skip to content

Commit

Permalink
feat: 支持临时英文模式(在中文输入模式下,按;键可以开启临时英文模式,输入英文字符和半角符号)
Browse files Browse the repository at this point in the history
  • Loading branch information
qwertyyb committed Apr 22, 2023
1 parent a0e5e1a commit fe9df00
Show file tree
Hide file tree
Showing 13 changed files with 87 additions and 47 deletions.
32 changes: 22 additions & 10 deletions Fire/CandidatesView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct CandidateView: View {
var index: Int
var origin: String
var selected: Bool = false
var indexVisible = true

@Default(.themeConfig) private var themeConfig
@Default(.wubiCodeTip) private var wubiCodeTip
Expand All @@ -43,9 +44,11 @@ struct CandidateView: View {
: themeConfig[colorScheme].candidateCodeColor

return HStack(alignment: .center, spacing: 2) {
Text("\(index + 1).")
.foregroundColor(Color(indexColor))
Text(candidate.text)
if indexVisible {
Text("\(index + 1).")
.foregroundColor(Color(indexColor))
}
Text(candidate.label)
.foregroundColor(Color(textColor))
if wubiCodeTip {
Text(getShownCode(candidate: candidate, origin: origin))
Expand All @@ -69,7 +72,7 @@ struct CandidatesView: View {
static let candidateSelected = Notification.Name("CandidatesView.candidateSelected")
static let nextPageBtnTapped = Notification.Name("CandidatesView.nextPageBtnTapped")
static let prevPageBtnTapped = Notification.Name("CandidatesView.prevPageBtnTapped")

var candidates: [Candidate]
var origin: String
var hasPrev: Bool = false
Expand All @@ -86,12 +89,18 @@ struct CandidatesView: View {
candidate: candidate,
index: index,
origin: origin,
selected: index == 0
selected: index == 0,
indexVisible: candidates.count > 1
)
}
}

func getIndicatorIcon(imageName: String, direction: CandidatesDirection, disabled: Bool, eventName: Notification.Name) -> some View {
func getIndicatorIcon(
imageName: String,
direction: CandidatesDirection,
disabled: Bool,
eventName: Notification.Name
) -> some View {
return Image(imageName)
.renderingMode(.template)
.resizable()
Expand All @@ -111,6 +120,9 @@ struct CandidatesView: View {
}

var _indicator: some View {
if candidates.count <= 1 {
return AnyView(EmptyView())
}
let arrowUp = getIndicatorIcon(
imageName: "arrowUp",
direction: direction,
Expand Down Expand Up @@ -166,10 +178,10 @@ struct ContentView_Previews: PreviewProvider {
static var previews: some View {
CandidatesView(candidates: [
Candidate(code: "a", text: "", type: CandidateType.wb),
Candidate(code: "ab", text: "", type: CandidateType.wb),
Candidate(code: "abc", text: "", type: CandidateType.wb),
Candidate(code: "abcg", text: "", type: CandidateType.wb),
Candidate(code: "addd", text: "", type: CandidateType.wb)
Candidate(code: "ab", text: "", type: CandidateType.wb),
Candidate(code: "abc", text: "", type: CandidateType.wb),
Candidate(code: "abcg", text: "", type: CandidateType.wb),
Candidate(code: "addd", text: "", type: CandidateType.wb)
], origin: "a")
}
}
2 changes: 1 addition & 1 deletion Fire/CandidatesWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class CandidatesWindow: NSWindow, NSWindowDelegate {
self.orderFront(nil)
// NSApp.setActivationPolicy(.prohibited)
}

func bindEvents() {
let events: [NotificationObserver] = [
(CandidatesView.candidateSelected, { notification in
Expand Down
13 changes: 13 additions & 0 deletions Fire/DictManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class DictManager {
static let shared = DictManager()
static let userDictUpdated = Notification.Name("DictManager.userDictUpdated")

let tempEnTriggerPunctuation: Character = ";"
let userDictFilePath = NSSearchPathForDirectoriesInDomains(
.applicationSupportDirectory,
.userDomainMask, true).first! + "/" + Bundle.main.bundleIdentifier! + "/user-dict.txt"
Expand Down Expand Up @@ -129,10 +130,22 @@ class DictManager {
.replacingOccurrences(of: "z", with: "?")) + "*"
}

func punctuationCandidates(query: String) -> [Candidate] {
let text = query.count == 1 ? query : String(query.suffix(query.count - 1))
return [Candidate(
code: query,
text: text,
type: .placeholder,
label: "临时英文(空格输出半角符号,连敲;键两下输出全角符号)")]
}

func getCandidates(query: String = String(), page: Int = 1) -> (candidates: [Candidate], hasNext: Bool) {
if query.count <= 0 {
return ([], false)
}
if query.first == tempEnTriggerPunctuation {
return (candidates: punctuationCandidates(query: query), hasNext: false)
}
NSLog("[DictManager] getCandidates origin: \(query)")
let startTime = CFAbsoluteTimeGetCurrent()
let queryLike = getQueryLike(query)
Expand Down
2 changes: 1 addition & 1 deletion Fire/Fire.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Fire: NSObject {

var inputMode: InputMode = .zhhans

func transformPunctuation(_ origin: String)-> String? {
func transformPunctuation(_ origin: String) -> String? {
let isPunctuation = punctuation.keys.contains(origin)
if !isPunctuation {
return nil
Expand Down
49 changes: 24 additions & 25 deletions Fire/FireInputController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,6 @@ class FireInputController: IMKInputController {
monitorList: []
)

override init() {
super.init()
NSLog("[FireInputController] init without params")
}

override init!(server: IMKServer!, delegate: Any!, client inputClient: Any!) {
super.init(server: server, delegate: delegate, client: inputClient)
NSLog("[FireInputController] init with params")
}

deinit {
NSLog("[FireInputController] deinit")
clean()
Expand Down Expand Up @@ -198,23 +188,11 @@ class FireInputController: IMKInputController {
return nil
}

private func punctuationKeyHandler(event: NSEvent) -> Bool? {
// 获取输入的字符
let string = event.characters!

// 如果输入的字符是标点符号,转换标点符号为中文符号
if inputMode == .zhhans, let result = Fire.shared.transformPunctuation(string) {
insertText(result)
return true
}
return nil
}

private func charKeyHandler(event: NSEvent) -> Bool? {
// 获取输入的字符
let string = event.characters!

guard let reg = try? NSRegularExpression(pattern: "^[a-zA-Z]+$") else {
guard let reg = try? NSRegularExpression(pattern: "^[a-z]+$") else {
return nil
}
let match = reg.firstMatch(
Expand Down Expand Up @@ -286,6 +264,27 @@ class FireInputController: IMKInputController {
return nil
}

private func punctuationKeyHandler(event: NSEvent) -> Bool? {
// 获取输入的字符
let string = event.characters!
guard inputMode == .zhhans else { return nil }

if !Defaults[.disableTempEnMode]
&& _originalString.count <= 0 && string == String(DictManager.shared.tempEnTriggerPunctuation)
|| string != String(DictManager.shared.tempEnTriggerPunctuation)
&& _originalString.first == DictManager.shared.tempEnTriggerPunctuation {
_originalString += string
return true
}

// 如果输入的字符是标点符号,转换标点符号为中文符号
if inputMode == .zhhans, let result = Fire.shared.transformPunctuation(string) {
insertText(result)
return true
}
return nil
}

// ---- handlers end -------

override func recognizedEvents(_ sender: Any!) -> Int {
Expand All @@ -310,10 +309,10 @@ class FireInputController: IMKInputController {
deleteKeyHandler,
charKeyHandler,
numberKeyHandlder,
punctuationKeyHandler,
escKeyHandler,
enterKeyHandler,
spaceKeyHandler
spaceKeyHandler,
punctuationKeyHandler
])
return handler(event) ?? false
}
Expand Down
3 changes: 2 additions & 1 deletion Fire/FireInputServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,15 @@ extension FireInputController {
previousClientHandler()

CandidatesWindow.shared.inputController = self

if Defaults[.disableEnMode] {
return
}

activeCurrentClientInputMode()
}
override func deactivateServer(_ sender: Any!) {
clean()
NSLog("[FireInputController] deactivate server: \(client()?.bundleIdentifier() ?? "no client deactivate")")
}
}
3 changes: 2 additions & 1 deletion Fire/InputSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ class InputSource {
return nil
}

private func findInputSource(forUsage: InputSourceUsage = .enable) -> (inputSource: TISInputSource, sourceID: NSString)? {
private func findInputSource(forUsage: InputSourceUsage = .enable)
-> (inputSource: TISInputSource, sourceID: NSString)? {
let sourceList = TISCreateInputSourceList(nil, true).takeRetainedValue() as NSArray

for index in 0..<sourceList.count {
Expand Down
4 changes: 2 additions & 2 deletions Fire/Preferences/FirePreferencesController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class FirePreferencesController: NSObject, NSWindowDelegate {
var isVisible: Bool {
controller?.window?.isVisible ?? false
}

private func initController() {
if let controller = controller {
controller.show()
Expand Down Expand Up @@ -78,7 +78,7 @@ class FirePreferencesController: NSObject, NSWindowDelegate {
)
self.controller?.window?.delegate = self
}

func showPane(_ name: String) {
initController()
controller?.show(preferencePane: Preferences.PaneIdentifier(rawValue: name))
Expand Down
3 changes: 3 additions & 0 deletions Fire/Preferences/GeneralPane.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct GeneralPane: View {
@Default(.zKeyQuery) private var zKeyQuery
@Default(.toggleInputModeKey) private var toggleInputModeKey
@Default(.disableEnMode) private var disableEnMode
@Default(.disableTempEnMode) private var disableTempEnMode
@Default(.showInputModeStatus) private var showInputModeStatus

var body: some View {
Expand Down Expand Up @@ -82,6 +83,8 @@ struct GeneralPane: View {
}
HStack {
Toggle("禁止切换英文", isOn: $disableEnMode)
Spacer()
Toggle("禁用;键临时英文模式", isOn: $disableTempEnMode)
}
HStack {
Picker("快捷键", selection: $toggleInputModeKey) {
Expand Down
2 changes: 1 addition & 1 deletion Fire/Preferences/UserDictPane.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class UserDictTextModel: ObservableObject {

init() {
refresh()
NotificationCenter.default.publisher(for: DictManager.userDictUpdated).sink { notification in
NotificationCenter.default.publisher(for: DictManager.userDictUpdated).sink { _ in
self.refresh()
}
.store(in: &cancellable)
Expand Down
2 changes: 1 addition & 1 deletion Fire/StatusBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class StatusBar {
self.refreshTitle()
}
}

private func stopEventListener() {
inputSourceChangedSubscription?.cancel()
inputModeChangedSubscription?.cancel()
Expand Down
18 changes: 14 additions & 4 deletions Fire/types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ extension Defaults.Keys {
// 中英文切换配置
// 禁止切换英文
static let disableEnMode = Key<Bool>("diableEnMode", default: false)
// 禁止;键临时英文模式
static let disableTempEnMode = Key<Bool>("disableTempEnMode", default: false)
// 切换英文模式的按键
static let toggleInputModeKey = Key<ModifierKey>("toggleInputModeKey", default: ModifierKey.shift)
// 中英文切换提示弹窗位置
Expand Down Expand Up @@ -145,16 +147,24 @@ enum InputModeSetting: String, Codable {
}

enum CandidateType: String {
case wb = "wb" // 五笔
case py = "py" // 拼音
case user = "user" // 用户词库
case placeholder = "placeholder" // 运行时类型,无匹配时表示占位
case wb // 五笔
case py // 拼音
case user // 用户词库
case placeholder // 运行时类型,无匹配时表示占位
}

struct Candidate: Hashable {
let code: String
let text: String
let type: CandidateType
let label: String

init(code: String, text: String, type: CandidateType, label: String? = nil) {
self.code = code
self.text = text
self.type = type
self.label = label ?? text
}
}

enum CodeMode: Int, CaseIterable, Decodable, Encodable {
Expand Down
1 change: 1 addition & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
11. 支持自定义符号
12. 支持自定义主题
13. 支持数据统计
14. 支持临时英文模式(在中文输入模式下,按;键可以开启临时英文模式,输入英文字符和半角符号)


## 安装
Expand Down

0 comments on commit fe9df00

Please sign in to comment.