讓 Alfred 支持拼音搜索[轉(zhuǎn)]

最近筆者在網(wǎng)路上發(fā)現(xiàn)一篇特別有實(shí)際應(yīng)用意義的文章,大家都知道?Alfred 默認(rèn)是不支持拼音搜索的,但萬能的國人卻有辦法讓她具備這種能力,方法有些小眾,需要你的 Mac 具備 Python 環(huán)境,不過還是先看教程,也許并沒有你想象的那么難。

Alfred 是個好東西,不過檢索程序的時候不支持拼音搜索;我在論壇看到有人給作者反饋過,無奈作者說支持中文,他不知道拼音是什么,于是就不了了之了。舉個例子:我想打開網(wǎng)易云音樂,可是當(dāng)我輸入wangyiyunyinyue的時候卻是這樣的結(jié)果:

要么我知道這個App的名字叫做NeteaseMusic,要么我就需要用中文輸入網(wǎng)易云音樂打開了;如果恰巧輸入法是英文輸入狀態(tài),那么就會遇到上圖的情況;這時候再把已經(jīng)輸入的刪除然后切換輸入法打開,效率無疑大大折扣。

就算這里搜索這個App可以使用英文名字解決,可是對于某些系統(tǒng)程序比如郵件可能還知道是Mail,那么備忘錄呢?便簽?zāi)兀窟€有一些別的中文程序沒有英文名的比如馬克飛象?如果Alfred能支持拼音搜索,這些問題全部都沒了!而且,Alfred可以強(qiáng)制使用英文輸入,直接使用字母檢索,不用切換輸入法了。

原理

經(jīng)過簡單的觀察之后,發(fā)現(xiàn)Alfred檢索程序不僅僅是檢索名字,還收集了一些額外的信息;在Alfred作者的幫助下,知道它利用了Mac文件系統(tǒng)的一個拓展信息的字段;如果你發(fā)現(xiàn)某些目錄后面有@那么就是有拓展信息了:

  1. drwxr-xr-x+ 3 root wheel 102 9 10 2014 Stickies.app/
  2. drwxr-xr-x@ 3 weishu admin 102 3 26 2015 Sublime Text.app/

可以借助命令行工具xattr進(jìn)行操作;具體使用可以man xattr.

所以,我們可以通過把拼音信息添加到文件的拓展信息里面去,這樣Alfred就能借助這些信息幫助拼音檢索了。

實(shí)現(xiàn)

獲取程序名

程序名不僅僅是一個文件名這么簡單,Mac軟件有一個叫做localization的概念,大致就是國際化吧;程序結(jié)構(gòu)把國際化的字段存放在不同的文件里面,在程序本地化之后自動load.

我們要使用的那個字段是CFBundleName存放在/<App>/Contents/Resources/<language>/InfoPlist.strings這個文件里面;我們把這個名字讀取出來即可。

嘗試過使用objc的接口NSBundle.localizedInfoDiction來獲取本地化的字段,無奈拿到的永遠(yuǎn)是英文字段;只好手工解析中文字段了(不會Objc ?);使用的命令行工具plutil:

  1. def _get_localized_name(abs_path):
  2. ”’get the localized name of given app”’
  3. bundle = NSBundle.new()
  4. bundle.initWithPath_(abs_path)
  5. localizations = bundle.localizations()
  6. chinese = (‘zh_CN’, ‘zh_Hans’)
  7. b = any(map(lambda x: x in localizations, chinese))
  8. if not b: return
  9. for ch in chinese:
  10. path = bundle.pathForResource_ofType_inDirectory_forLanguage_(‘InfoPlist’, ‘strings’, None, ch)
  11. if not path: continue
  12. # the path must surround with “”, there may be space characters
  13. json_str = subprocess.check_output(u’plutil -convert json -o – “%s”‘ % path, shell=True)
  14. # print json_str
  15. json_res = json.loads(json_str, encoding=’utf8′)
  16. name = json_res.get(‘CFBundleName’)
  17. if name: return name

轉(zhuǎn)換為拼音

可以直接使用python的拼音轉(zhuǎn)換庫pypinyin,借助這個工具,一行代碼搞定:

  1. def _get_app_pinyin_name(app_name):
  2. reduce(lambda x, y: x + y, lazy_pinyin(app_name, errors=’ignore’))

添加拼音信息

拼音信息被添加到文件的拓展信息里面,直接使用xattr添加即可:

  1. def _add_meta_data(app_pinyin_name, app_path):
  2. ”’ add meta data(comments) to the app, which can help Alfred or SpotLight find it”’
  3. subprocess.check_call(‘xattr -w com.apple.metadata:kMDItemFinderComment %s %s’ % (app_pinyin_name, app_path), shell=True)

好了,把這些代碼整合起來,就能得到最終的結(jié)果了,完整的代碼在這里。

  1. def main():
  2. pattern = re.compile(r’^[\w\s.]+$’)
  3. workspace = NSWorkspace.sharedWorkspace()
  4. for app_dir in APP_DIRECTORYS:
  5. if not os.path.exists(app_dir): continue
  6. for root, dirs, files in os.walk(app_dir, topdown=True):
  7. remove_list = []
  8. for directory in dirs:
  9. # print type(directory), root, directory
  10. full_path = os.path.join(root, directory)
  11. if not _is_application(workspace, full_path): continue
  12. remove_list.append(directory)
  13. localized_name = _get_localized_name(full_path)
  14. app_name = localized_name if localized_name else directory.rsplit(r’.’)[0]
  15. if pattern.match(app_name):
  16. continue
  17. _add_meta_data(_get_app_pinyin_name(app_name), full_path)
  18. # if this directory is already a Application # do not traverse this; some app may be very large # and there won’t be any other app inside it
  19. dirs[:] = [d for d in dirs if d not in remove_list]

最后,我們執(zhí)行這一段腳本即可sudo python main.py。之所以需要sudo是因?yàn)槟承┫到y(tǒng)程序(比如家計(jì)算器),直接使用是沒有權(quán)限的。

來看一段動圖演示:

 

感謝原文作者為我們分享如此棒的 Alfred 技巧,原文地址《讓 Alfred 支持拼音搜索》。

評論 3 條
  • ElderDog

    不需要改文件名,直接寫個注釋不就行了么

    2016-01-13 13:28 回復(fù)

  • nothing

    alfred不是支持拼音么?難道我用的是假的?

    2016-01-06 19:56 回復(fù)

  • mykk2002

    道理我都懂,但為什么不改個文件名呢。 完全按照自己的使用習(xí)慣自定義了啊。幾秒鐘的事情。。。

    2016-01-06 11:20 回復(fù)