落格输入法 macOS 是如何处理 ascii 0x01 的兼容问题的-macOS 输入法如何正确设置 buffer

2018-01-22 10:42:35来源:https://www.logcg.com/archives/2959.html作者:落格博客人点击

分享

最近更新:21st 一月, 2018


早在去年,落格输入法的用户就有报告说落格输入法 macOS 在 有道云笔记 的 MarkDown 模式下无法正常键入中文,经过测试证明确实如此,体现为打中文字的时候,buffer的刷新会奇怪的删除掉光标前的一个字符——对,不多不少,就删一个。


捣鼓了很久未果,最后我没招了打印出了所有内容,发现了谜团:


当我把输入法获取到的光标左边的文字打印出来后,我发现文字的后边被追加了一个奇怪的字符:





奇怪的红色问号,表示这个字符无法表达。


你可能看不见,它实际上也是一个无法表达的字符,一般来说文本编辑器都用来表示一个坏掉的字符。不过,经过字符编码转换后,我还是找到了它的原本,这是一个 ASCII 字符,编码是 0x01 ……嗯,无法表达的字符——那么答案就明显了,显然是在系统在设定 buffer 的时候判断到了这个字符的数量(也就是1),但在替换的时候这个字符没了,于是把末尾的字给替换了。


于是,我就根据有道云笔记的 BundleID 进行判断,一旦找到这个字符,那说明就是在它的 MarkDown 模式里,然后在键入 buffer 之前,手动把这个字符给它补回去——好吧它至少真的管用:


//修复有道云笔记 MD 模式的奇葩问题
if let id = self.bundleIdentifier(), id == "com.youdao.note.YoudaoNoteMac" {
if self.selectedRange().length == 1 {
if self.attributedSubstring(from: self.selectedRange()).string == "/u{01}" {
self.insert(text: "/u{01}")
}
}
}
//补丁结束

不过好景不长,时隔半年,在另一个 app, Quiver 中又遇到了这个问题,这次就没那么容易解决了,同样的办法会导致无限递归……好吧,是时候使用真正的技术了。


经过询问大佬(是的是问出来的……),macOS 的 InputMethodKit 中 public func setMarkedText ( _ string : Any ! , selectionRange : NSRange , replacementRange : NSRange ) 这个方法,虽然在 Swift 中声明的是接收 Any 类型,也就是说不论是 String 还是 NSAttributedString 均可(声明中也是如此说明),但实际上它需要的是后者,很简单,生成一个 NSAttributedString 再写入 buffer ,问题解决。


同时,细心的我还发现了一个有趣的问题,落格输入法的 buffer 下划线总是比系统的下划线要粗那么一点(这里我用 QIM 做比较):





落格输入法的 buffer 下划线很粗





QIM 的下划线就比较细,和系统的一样。


原来, IMKInputController 中是有这么一个方法的:


func mark(forStyle style: Int, at range: NSRange) -> [AnyHashable : Any]!

它可以返回一个包含富文本标签的字典,这个字典可以标记某条 buffer,从而让系统认识这个 buffer。


那么大概用法是这样:


let attr = mark(forStyle: kTSMHiliteConvertedText, at: NSMakeRange(NSNotFound,0))

然后把这个属性附加到设置 buffer 时生成的 NSAttributedString 即可,这才是 macOS 输入法正确设置 buffer 的姿势:


let att = NSAttributedString(string: t, attributes: attr)
setMarkedText(att, selectionRange: NSMakeRange(NSNotFound, NSNotFound), replacementRange: NSMakeRange(NSNotFound, NSNotFound))

这样,输入法的 buffer 区域就和系统的一模一样了:





落格输入法 macOS 改正后的 buffer 下划线很细


最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台