让 Alfred 支持拼音

效果图在这里

最终结果就是像这样

解决办法

首先 你要有以下几个工具或者库

  • python 安装方法 brew install python(brew怎么没这个命令…没有的同学请自行百度)ps:其实mac自带的python足够用了 我们只运行一个脚本而已
  • pypinyin 安装方法 pip install pypinyin
  • pyobjc 安装方法 pip install pyobjc

准备好环境之后 创建以下脚本

#! /usr/bin/python
# -*- coding: utf-8 -*-

# @author weishu @2015/12/7

import subprocess
import os
import re
import json

from AppKit import NSWorkspace, NSBundle
from pypinyin import lazy_pinyin

# copy from Alfred 2 preferences, if you have applications installed at other place, add it here.
APP_DIRECTORYS = [
    u'/Applications',
    u'/Applications/Xcode.app/Contents/Applications',
    u'/Developer/Applications',
    u'/Library/PreferencePannes',
    u'/opt/homebrew-cask/Caskroom',
    u'/System/Library/PreferencePannes',
    u'/usr/local/Cellar',
    u'~/Library/Caches/Metadata',
    u'~/Library/Mobile Documents',
    u'~/Library/PreferencePannes'
]

def _is_application(workspace, abspath):
    ''' is a `abspath` stand for a mac app'''
    return workspace.isFilePackageAtPath_(abspath)

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

def _add_meta_data(app_pinyin_name, app_path):
    ''' add meta data(comments) to the app, which can help Alfred or SpotLight find it'''
    print "processing %s" % app_path
    try:
        subprocess.check_call('xattr -w com.apple.metadata:kMDItemFinderComment %s "%s"' % (app_pinyin_name, app_path), shell=True)
    except:
        print "process %s failed, ignore." % app_path
        
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', 'zh-Hans', 'zh-CN')

    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

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:
                full_path = os.path.join(root, directory)
                # print full_path
                if not _is_application(workspace, full_path): continue

                remove_list.append(directory)
                try:
                    localized_name =  _get_localized_name(full_path)
                except:
                    print "get localized name for %s failed. ignore" % full_path
                    # continue
                
                # print "localized_name:", localized_name if localized_name else None
                app_name = localized_name if localized_name else directory.rsplit(r'.')[0]

                if pattern.match(app_name):
                    # print "app_name: %s not match" % app_name
                    continue
                try:
                    _add_meta_data(_get_app_pinyin_name(app_name), full_path)
                except:
                    # may be empty, just ignore
                    print "add meta for %s failed" % 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]

if __name__ == '__main__':
    main()

执行脚本

sudo python alfred-pinyin.py

that’s all

原理

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]

git 地址:https://gist.github.com/tiann/35fb758c18036d7f8640
参考文章:http://www.jianshu.com/p/dee4d6a0ed4f

Alfred是一款屡获殊荣的macOS应用程序,可通过热键,关键字,文本扩展等功能提高您的效率。搜索Mac和网络,并通过自定义操作来控制Mac来提高生产力。 启动应用程序并在Mac或Web上查找文件。阿尔弗雷德(Alfred)了解如何使用Mac并优先考虑结果。 通过使用热键,关键字并自定义搜索Mac和活动历史记录的方式,可以节省大量时间。 进入并浏览,预览文件并对其进行操作,而无需用手指离开键盘。 使用Alfred的剪贴板历史记录和代码片段功能,无需一遍又一遍地键入相同的URL或响应。 使用剪贴板历史记录可以找到您先前复制的任何文本,图像或文件,然后再次粘贴。 创建您自己的代码片段,然后键入一个简短的缩写,以将其自动扩展为全文代码片段,从长远来看,您可以节省数小时的输入时间! 借助Alfred的Powerpack,可使用功能强大的工作流程来更高效地执行任务,并减少重复的手动任务。 将热键,关键字和操作链接在一起以创建自己的工作流程;无需编写任何代码即可创建工作流。来自我们创建者社区共享的成千上万个导入工作流。 你是老板通过使用Alfred与macOS的深度集成来控制Mac,从而提高工作效率。迅速对文件和联系人采取措施,控制音乐播放器并调度系统命令。 为您的一天增添些乐趣;借助适用于iOS的Alfred Remote,将iPhone或iPad变成Mac的命令中心。 另外,看看其他音乐服务(例如Spotify)的许多工作流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值