Author: 颖奇L’Amore
Blog: www.gem-love.com
MacOS高效使用文章合集:here
前言 在前篇 中我们介绍了Alfred的内置feature,这篇文章介绍Alfred的终极技能:Workflow
注意,未激活的Alfred不支持workflow功能,所以你需要先购买powerpack激活码
初识workflow workflow是由用户开发的工作流程,只要你懂得任何一门编程语言基本上都可以来编写自己的workflow,可以通过以下几个渠道获取别人分享的workflow:
https://www.alfredapp.com/workflows/
http://www.packal.org/workflow-list
https://github.com/zenorocha/alfred-workflows
https://github.com/alfred-workflows/awesome-alfred-workflows
https://github.com/ctwise/alfred-workflows
https://pacmax.org/
https://github.com/vitorgalvao/alfred-workflows/
https://www.alfredforum.com/forum/3-share-your-workflows/
其中8是论坛,大家可以自由分享自己写的workflow;其他是精选workflow合集,上面第3个里有相应的效果图,可以先去点进去看一下workflow的使用效果,然后下载自己需要的workflow
Debug 有时候我们发现导入了别人的workflow,然后自己用不了,这时候就需要调试了 这里我以我自己的环境为例,实际操作一下debug and fix的流程
举例1:encode / decode 下载:https://github.com/willfarrell/alfred-encode-decode-workflow 这是它的使用效果: 但是我却用不了:
此时我们进入该workflow,点击右上角的🕷打开debug页面,可以发现错误原因是/bin/bash: php: command not found
那么我们双击encode和decode的script filter打开,发现它的代码实际上是直接用bash去执行了php 这可能是PATH中找不到php的路径,所以我们直接将其改为自己的php的绝对路径 改完之后就能用了:
举例2:DevDocs 下载:https://github.com/yannickglt/alfred-devdocs 这是它的使用效果: 同样我本地用不了: 报错显示找不到所使用的的编程语言,进入workflow双击打开,可以发现它使用的是/usr/bin/php而我们的php不在这个目录 首先考虑用软链接把php链接过来,但奈何/usr/bin目录在当前macos版本已经不可写了 这时候只能用bash去调用php了
首先我们先看一个run script,是不用传参的 使用的语言改成/bin/bash,同时代码改成:
/Applications/MxSrvs/bin/php/bin/php -r '$query = "nuke";require_once("scripts/conf.php");'
然后我们看node这个script filter,原本使用的/usr/bin/php时的代码如下:
$query = "{query}" ;$documentation = 'node' ;require_once ("scripts/devdocs.php" );
这个是要接收参数的,有点麻烦,我们先右键open in finder进入该workflow的目录 新建一个node.php,代码写成:
<?php $query = $argv [1 ];$documentation = 'node' ;require_once ("scripts/devdocs.php" );
然后使用的语言改成/bin/bash,同时代码改成:
query="{query}" /Applications/MxSrvs/bin/php/bin/php node.php $query
此时就解决了/usr/bin/php未安装的问题,尽管此时还不能用,debug显示报错为网页访问不了(但这不是我们workflow的问题了,是对方的文档请求不了了,node命令是直接去这个远程文档去搜索的):
Warning: file_get_contents(http://m axcdn-docs.devdocs.io/node/i ndex.json): failed to open stream: php_network_getaddresses: getaddrinfo failed: nodename nor servname provided, or not known in /Users/ amortang/Library/ Application Support/Alfred/ Alfred.alfredpreferences/workflows/u ser.workflow.9 CE45714-7860 -4 A74-B002-78 AA58F3BC8E/scripts/ devdocs.php on line 73
同样的方法把其他的script filter给处理了,依然不能用,看debug的php报错信息:
Deprecated : Array and string offset access syntax with curly braces is deprecated in /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/vendor/rodneyrehm/plist/classes/CFPropertyList/CFBinaryPropertyList.php on line 787 Call Stack: 0 .0002 395432 1 . {main}() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/cdocadd.php:0 0 .0008 443448 2 . require_once('/Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php') /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/cdocadd.php:4 0 .0017 549832 3 . CFPropertyList\DevDocsConf->__construct() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php:253 0 .1059 550896 4 . CFPropertyList\DevDocsConf->openPlist() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php:40 0 .1059 550896 5 . spl_autoload_call() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php:51 0 .1059 550952 6 . Composer\Autoload\ClassLoader->loadClass() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php:51 0 .1059 551208 7 . Composer\Autoload\includeFile() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/vendor/composer/ClassLoader.php:274 0 .1063 625656 8 . include('/Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/vendor/rodneyrehm/plist/classes/CFPropertyList/CFPropertyList.php') /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/vendor/composer/ClassLoader.php:382 Deprecated : Array and string offset access syntax with curly braces is deprecated in /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/vendor/rodneyrehm/plist/classes/CFPropertyList/CFBinaryPropertyList.php on line 810 Call Stack: 0 .0002 395432 1 . {main}() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/cdocadd.php:0 0 .0008 443448 2 . require_once('/Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php') /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/cdocadd.php:4 0 .0017 549832 3 . CFPropertyList\DevDocsConf->__construct() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php:253 0 .1059 550896 4 . CFPropertyList\DevDocsConf->openPlist() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php:40 0 .1059 550896 5 . spl_autoload_call() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php:51 0 .1059 550952 6 . Composer\Autoload\ClassLoader->loadClass() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php:51 0 .1059 551208 7 . Composer\Autoload\includeFile() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/vendor/composer/ClassLoader.php:274 0 .1063 625656 8 . include('/Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/vendor/rodneyrehm/plist/classes/CFPropertyList/CFPropertyList.php') /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/vendor/composer/ClassLoader.php:382 Warning : Invalid argument supplied for foreach() in /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php on line 107 Call Stack: 0 .0002 395432 1 . {main}() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/cdocadd.php:0 0 .0008 443448 2 . require_once('/Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php') /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/cdocadd.php:4 0 .0017 549832 3 . CFPropertyList\DevDocsConf->__construct() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php:253 0 .1118 916104 4 . CFPropertyList\DevDocsConf->setDocumentations() /Users/amortang/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.9 CE45714 -7860 -4 A74 -B002 -78 AA58 F3 BC8 E/scripts/conf.php:41
这是因为7.4的php的数组不支持用大括号寻址了
根据php的报错修改一下源码的对应源码,可以用了:
编写workflow 类型 我们右键可以发现,Alfred支持的东西太多了,比如打开文件、弹个通知、打开浏览器等等
这里面有一些东西是用来控制执行流程之类的东西的,但是最核心的东西其实还是运行脚本,脚本里写的才是我们最核心的操作,你会发现有两种脚本运行:Run Script和Script Filter
简单来讲,想让一个脚本后台自己的去跑一个脚本,没有反馈,这种用run script,例如:
如果想通过一个脚本进行相应操作,不用回车,直接得到单个或多个结果,则需要Script Filter,例如:
写一个Run Script 我这个电脑的AntSword有个bug,没法退出,每次都得kill进程才能退出,所以我们就以这个为需求来写一个kill蚁剑进程的东西 新建workflow选空白即可,他也给我们提供了一些流程模板 对workflow写一些基本信息 添加一个keywords,用klat
来触发,并选择不需要参数: 后面跟上一个Run Script,不用输入信息,执行固定的语句,语言选择/bin/bash
ps -ef | grep AntSword | grep -v grep | awk '{print $2}' | xargs kill -9
效果如下(蚁剑被kill掉退出了): 当然这个workflow就比较简单(但是也达到了提升工作效率的目的,这就是Alfred的初衷),其他复杂的功能大家自行探索吧,方法就是这样的。
写一个Script Filter 这里我们就来简单写一个货币转换的workflow吧,可以在我的github 下载这个workflow
使用方法可以看github的说明,转100美元到欧元效果如下:
整个项目就一个script filter,将用户输入传给了run.py这个python文件:
在看具体文件代码之前,我们需要先来看Alfred的官方文档
这个文档告诉我们,想要使用script filter让结果显示出来,脚本的输出是有固定的json格式的,例如:
{"items" : [ { "uid" : "desktop" , "type" : "file" , "title" : "Desktop" , "subtitle" : "~/Desktop" , "arg" : "~/Desktop" , "autocomplete" : "Desktop" , "icon" : { "type" : "fileicon" , "path" : "~/Desktop" } } ]}
items
是一个数组,里面的每一个元素是一个对象,一个对象就是一个输出结果,具体的参数的意思大家把上面文档读一读就明白了。
接着我们就来写转换货币的具体代码,主要的思路就是获取用户的输入,然后判断是否合法,如果符合要求,就去https://api.getgeoapi.com/v2/currency/convert
这个货币兑换的api进行货币转换。最后的输出一定是要符合它要求的json格式,所以使用了json.dumps
import requestsimport reimport os import sys import warningsimport jsonwarnings.filterwarnings('ignore' ) def mysplit (s ): if not re.match(r"^[\d.]+[a-zA-Z]+$" , s): sys.exit(0 ) cnt = 0 while cnt < len (s): if s[cnt].isalpha(): break cnt += 1 return [s[:cnt], s[cnt:]] if len (sys.argv) < 2 or not re.match(r"^[\d.]+[a-zA-Z]+\ [a-zA-Z]+$" , sys.argv[1 ]): sys.exit(0 ) api = os.getenv('api' ) amonut_from = sys.argv[1 ].split(' ' )[0 ] to = sys.argv[1 ].split(' ' )[1 ] amonut_from_split = mysplit(amonut_from) baseurl = "https://api.getgeoapi.com/v2/currency/convert" url = "%s?api_key=%s&from=%s&to=%s&amount=%s&format=json" % (baseurl, api, amonut_from_split[1 ], to, amonut_from_split[0 ]) r = requests.get(url) res = r.json() if res['status' ] != 'success' : print (json.dumps({"items" :[{"title" : "Error" , "subtitle" : "something wrong" , "arg" : "please check your input" }]})) sys.exit(0 ) result = {} try : result = res['rates' ][list (res['rates' ].keys())[0 ]] except : print (json.dumps({"items" :[{"title" : "Error" , "subtitle" : "something wrong" , "arg" : "please check your input" }]})) sys.exit(0 ) items = {"items" : [ { "subtitle" : "currency name" , "title" : result['currency_name' ], "arg" : result['currency_name' ] }, { "subtitle" : "rate" , "title" : result['rate' ], "arg" : result['rate' ] }, { "subtitle" : "Total value of currency after conversion" , "title" : result['rate_for_amount' ], "arg" : result['rate_for_amount' ] }] } print (json.dumps(items))
但是这里面我们使用了一个api接口,这个api接口需要有API Key才可以,我们不能把这个API Key写死在代码里,因为我们希望能让用户自己去注册去申请它自己的API Key,而又不用编写源代码文件就可以把API Key导入进去,这时我们可以设置Alfred当前workflow的环境变量。点击这个[x]
左边是项目的描述,右边就是环境变量的键和值,勾上Do not export的话导出时就不会把值给导出了 这样在代码里就可以通过获取环境变量的方法os.getenv('api')
来取到了。 在share中可以导出workflow,相当于生成release版本,这里可以对项目信息进行一些配置之类的,然后就可以分享给你的小伙伴了,或者分享到Alfred论坛