让Alfred支持拼音搜索

Alfred是个好东西,不过检索程序的时候不支持拼音搜索;我在论坛看到有人给作者反馈过,无奈作者说支持中文,他不知道拼音是什么,于是就不了了之了。举个例子:我想打开网易云音乐,可是当我输入wangyiyunyinyue的时候却是这样的结果:

要么我知道这个App的名字叫做NeteaseMusic,要么我就需要用中文输入网易云音乐打开了;如果恰巧输入法是英文输入状态,那么就会遇到上图的情况;这时候再把已经输入的删除然后切换输入法打开,效率无疑大大折扣。

就算这里搜索这个App可以使用英文名字解决,可是对于某些系统程序比如邮件可能还知道是Mail,那么备忘录呢?便签呢?还有一些别的中文程序没有英文名的比如马克飞象?如果Alfred能支持拼音搜索,这些问题全部都没了!而且,Alfred可以强制使用英文输入,直接使用字母检索,不用切换输入法了。

原理

经过简单的观察之后,发现Alfred检索程序不仅仅是检索名字,还收集了一些额外的信息;在Alfred作者的帮助下,知道它利用了Mac文件系统的一个拓展信息的字段;如果你发现某些目录后面有@那么就是有拓展信息了:

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

可以借助命令行工具xattr进行操作;具体使用可以man xattr.

所以,我们可以通过把拼音信息添加到文件的拓展信息里面去,这样Alfred就能借助这些信息帮助拼音检索了。

实现

获取程序名

程序名不仅仅是一个文件名这么简单,Mac软件有一个叫做localization的概念,大致就是国际化吧;程序结构把国际化的字段存放在不同的文件里面,在程序本地化之后自动load.

我们要使用的那个字段是CFBundleName存放在/<App>/Contents/Resources/<language>/InfoPlist.strings这个文件里面;我们把这个名字读取出来即可。

尝试过使用objc的接口NSBundle.localizedInfoDiction来获取本地化的字段,无奈拿到的永远是英文字段;只好手工解析中文字段了(不会Objc ?);使用的命令行工具plutil:

def _get_localized_name(abs_path):
    '''get the localized name of given app'''
    bundle = NSBundle.new()
    bundle.initWithPath_(abs_path)
    localizations = bundle.localizations()
    chinese = ('zh_CN', 'zh_Hans')

    b = any(map(lambda x: x in localizations, chinese))
    if not b: return 

    for ch in chinese:
        path = bundle.pathForResource_ofType_inDirectory_forLanguage_('InfoPlist', 'strings', None, ch)
        if not path: continue
        # the path must surround with "", there may be space characters
        json_str = subprocess.check_output(u'plutil -convert json -o - "%s"' % path, shell=True)
        # print json_str
        json_res = json.loads(json_str, encoding='utf8')
        name = json_res.get('CFBundleName')
        if name: return name

转换为拼音

可以直接使用python的拼音转换库pypinyin,借助这个工具,一行代码搞定:

def _get_app_pinyin_name(app_name):
    reduce(lambda x, y: x + y, lazy_pinyin(app_name, errors='ignore'))

添加拼音信息

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

def_add_meta_data(app_pinyin_name, app_path):
''' add meta data(comments) to the app, which can help Alfred or SpotLight find it'''
    subprocess.check_call('xattr -w com.apple.metadata:kMDItemFinderComment %s %s' % (app_pinyin_name, app_path), shell=True)

好了,把这些代码整合起来,就能得到最终的结果了,完整的代码在这里

def main():
    pattern = re.compile(r'^[\w\s.]+$')

    workspace = NSWorkspace.sharedWorkspace()

    for app_dir in APP_DIRECTORYS:
        if not os.path.exists(app_dir): continue

        for root, dirs, files in os.walk(app_dir, topdown=True):
            remove_list = []
            for directory in dirs:
                # print type(directory), root, directory
                full_path = os.path.join(root, directory)
                if not _is_application(workspace, full_path): continue

                remove_list.append(directory)
                
                localized_name =  _get_localized_name(full_path)
                app_name = localized_name if localized_name else directory.rsplit(r'.')[0]

                if pattern.match(app_name): 
                    continue
                
                _add_meta_data(_get_app_pinyin_name(app_name), full_path)

            # 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
            dirs[:] = [d for d in dirs if d not in remove_list]

最后,我们执行这一段脚本即可sudo python main.py。之所以需要sudo是因为某些系统程序(比如家计算器),直接使用是没有权限的。

最后看效果:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏信安之路

SeLoadDriverPrivilege 在提权中的应用

我本想翻译学习一下,结果发现安全客已经有人翻译了,我也就没必要翻译了,就复现学习一下吧,顺便算是稍微补充下原文的内容,验证下提权风险。希望能对大家有所帮助。

1780
来自专栏程序员的碎碎念

如何解决Python包依赖问题

以简洁高效(指编程较为高效, 而不是运行速度)出名的Python, 在包依赖问题上有时候让人挠头.

1962
来自专栏自由而无用的灵魂的碎碎念

实战解决使用ghost安装系统出现的各种问题

昨天使用ghost给人安装系统时,把另一个分区的数据都搞没了,安装完也只剩下一个分区,相信了解的同志们知道是什么原因。

1473
来自专栏吾真本

从“CI搭建兽”到“流水线即代码”操练目的准备工作CI搭建兽的辛苦手工工作10行代码搞定“CI搭建兽”的全部手工工作部署流水线与单件流

本文是2017年3月13日晚9点在“AHA面对面”线上分享的“单件流的力量-伍斌_Ben面对面”的操练步骤,这里是报名链接。

1132
来自专栏用户2442861的专栏

python项目打包部署

作者:张博 链接:https://www.zhihu.com/question/38081354/answer/81829426 来源:知乎 著作权归作者...

3.9K1
来自专栏雨过天晴

转 树莓派无显示器安装系统

1772
来自专栏python学习之旅

Python+Selenium笔记(二):配置谷歌+IE环境

#有的时候可能要访问外国的网站下载资料或工具,这时可能出现各种问题,例如谷歌人机验证显示不了、网站打不开等,建议使用一个FQ软件 下载免费版的就行了,土豪请随...

46311
来自专栏编程

年底总结一下Python WEB最好用的几个框架,让你有一个系统的了解

2017年就要过完了,我们来总结一下2017年最好用的17个Python Web框架 群内不定时分享干货,包括2017最新的python企业案例学习资料和零基础...

8728
来自专栏沃趣科技

ASM 翻译系列第二十七弹:ASM INTERNAL ASM METADATA BLOCK

原作者:Bane Radulovic 译者: 邱大龙 审核: 魏兴华 DBGeeK社群联合出品 ASM METADATA BLOCK ASM的元数据...

3708
来自专栏FreeBuf

记我的一次账号劫持和BLIND XSS漏洞发现过程

我发现的第一个漏洞就是不安全对象引用漏洞(IDOR),利用该漏洞我能在每个账户中创建一个 element x元素,经过和朋友的交流,他建议我可以试试在其中注入一...

1750

扫码关注云+社区

领取腾讯云代金券