Alfred 编写 workflow

Alfred 的一个亮点功能就是workflow。通过workflow用户可以很容易的扩展alfred的功能,
而开源的优秀的workflow也有很多,不过如果找不到自己满意的workflow,可以自己动手编写workflow。自己动手,丰衣足食!
之所以重复造轮子的原因的是因为这个datetie-format-converter 转换的时间是按照UTC-GMT时间来算的,所以对于中国来说,属于东八区,所以就写了一个php版本的自己使用。
这里只是简单记录下自己开发的一个Unix时间戳转换的workflow的过程,详细教程请自行google或者参考 这篇教程.

一些基本概念

workflow可以使用脚本语言来编写,包括但不限于bashphppythonruby等。workflow中的triggersinputsactionsouputs等基本概念就不解释了,详细了解的可以自己一个个的试一试,反正总共加起来也不多。

Alfred XML格式数据

Alfred中要求ouputs最后输出特定SchemaXML内容。其实这一点我不太理解为什么,个人一直不喜欢XML格式的数据,重复臃肿、层级难于管理,就数据交换格式而言,个人比较倾向简单清晰易读的JSONAlfred不支持返回JSON数据结果,不知道是不是由于MacOS的原因,没有深究。
Alfred要求输出的内容以下:

1
2
3
4
5
6
7
<items>
<item autocomplete = "autocompletex" uid = "123321" arg = "argsx" >
<title >title</title>
<subtitle >subtitle</subtitle>
<icon >icon</icon>
</item>
</items>

根节点为items 其中包括任意多个item节点,每一个item节点代表本次查询结果的一行。 每一个item节点包括若干parameter与childnode,其含义为: uid: 每一个item要有一个独立的uid,不可重复 valid:值为yes 或者 no, 若为no,该行结果不可被选择 autocomplete : 自动补全的值, 使用tab可以令alfred自动补全为 autocompelete属性的值. arg:作为下一个模块的参数传递

该行item的标题,也是主要显示的位置。 <subtitle> 该行字标题位置,会被显示为灰色小字 <icon> 该行图标的文件名,其大小为64X64 pixels</icon></subtitle>

接受参数

Alfred可以通过query字段来获取数据的内容。

逻辑处理&格式输出

获取query的内容后,使用熟悉的脚本语言进行一些处理后组成转符合上面SchemaXML数据格式直接输出即可。

调试

Alfred很人性化的为开发者提供了调试工具,在workflow开发界面的右上角Toggle debuggind mode即可在下方打开一个debug窗口输出一些调试信息,方便开发。

说明

以下是开发的一个简单的时间戳转换workflow,代码没有做严格的输入检查,只是简单的将输入的内容通过phpdate函数转换成人类可读的Y-m-d H:i:s格式.

1
2
3
4
5
6
date_default_timezone_set('Asia/Shanghai');
require_once ('workflows.php');
$query = "{query}";
$wf = new Workflows ();
$wf->result ( time (), $query, date('Y-m-d H:i:s',$query), '', 'icon.png', 'yes' );
echo $wf->toxml();

其中worklows.php 中就只用到了 输出 XML 的方法,这个方法就是将resutl()中传递的参数组装成特定XML数据。

后续

后来研究了下datetime-format-converter的源码,做了简单的修改,已经支持北京时间的转换,其实就是在作者的python代码中时间转换的时候加上了时区的设置,手动将时区设置为Asia/Shanghai即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def parse_query_value(query_str):
""" Return value for the query string """
try:
query_str = str(query_str).strip('"\' ')
if query_str == 'now':
d = utcnow().shift('Asia/Shanghai')
else:
# Parse datetime string or timestamp
try:
d = epoch(float(query_str)).shift("Asia/Shanghai")
except ValueError:
d = parse(str(query_str)).shift('Asia/Shanghai')
except (TypeError, ValueError):
d = None
return d

将第61012行中时间转换加上了shift('Asia/Shanghai')

1
d = epoch(float(query_str))

改为

1
d = epoch(float(query_str)).shift("Asia/Shanghai")

即可。其实更好的做法是自动检测系统信息推断出用户所使用的时区并转换。

参考资料

0%