Alfred workflow 开发指南
小帽子alfred是mac上最為傳奇的效率作品, 今天,我們一起來探索alfred workflow 的世界吧!
1. alfred 簡介
小帽子是 Mac 平臺上最為傳奇的效率作品,譽為神兵利器毫不為過。
由于中文網絡上尚無系統的alfred workflow 開發教程,便有了寫一個教程的心思,以期拋磚引玉,為alfred吸引更多的開發者加入。
2.alfred 插件開發
2.1 alfred 插件開發概述
Workflow 是alfred2.0推出的最激動人心的特性,通過與腳本語言的交互,workflow可以支持任意操作,把您日常的重復性事務封裝在腳本中,大大的提高工作效率。
Workflow 支持php、bash、perl、ruby以及python作為腳本語言,并內置腳本語言解釋器,并通過stdio的形式在各個腳本模塊中傳遞參數。
在代碼中插入 {query}塊可以接收上一個腳本輸出的內容。形成完整的控制鏈條。 最后由alfred輸出至 Output 模塊, 在Output模塊中, 我們可以啟動瀏覽器、將內容復制到剪切板、 啟動通知中心、甚至執行bash腳本。
在日常的使用中,我們通常通過關鍵字來調用某一模塊,例如“find xxx” 即是調用find內建模塊 query內容為xxx。 在workflow的開發中, 開發者可以自定義自己編寫模塊的關鍵字,只要不與其他模塊沖突即可。
在workflow的結構中,數據流通過alfred的控制線進行傳遞,每一個腳本模塊的STDIO輸出會被alfred替換到 下一個腳本的{query}塊中。
如下圖所示:
?
其中,我們使用『拖動』的方式,控制數據在workflow的流向:
?
以上的 有道翻譯workflow的數據流向是這樣的。
通過yd作為關鍵字啟動workflow, 如果直接回車,使用OpenURL,啟動youdao網站。如果使用Cmd+回車的方式, 則執行Run Scirpt 并將其輸出到剪切板,并用Post Notification的方式,在通知中心顯示。
2.2 Alfred的XML格式概述
在Alfred腳本執行的最后一部中, 所有數據要被封裝到XML格式中被alfred調用,其格式為 <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:作為下一個模塊的參數傳遞
<title> 該行item的標題,也是主要顯示的位置。 <subtitle> 該行字標題位置,會被顯示為灰色小字 <icon> 該行圖標的文件名,其大小為64X64 pixels
2.3 {query} 與 stdio
alfred模塊間數據是如何傳遞的,曾經困擾我很久。
其數據流是這樣的, 你在關鍵字之后的文字會作為第一個模塊的query, 由alfred替換代碼中{query}的位置, 該模塊print到stdio的數據會像第一個模塊一樣,去替換第二個模塊的{query}位置,直到最后生成XML文件, 只有最后一步是不一樣的,也就是xml文件輸出之后, 用戶在不同的條目上按回車, alfred將把該條目對應的item的arg屬性的值傳遞給下一個模塊。
2.4 python 開發示例
下面,我將用開發一個百度詞典為例,詳細講解開發alred插件中的每一個步驟。
###2.4.1 Script Filter Script Filter 的作用是提供一個Alfred workflow的起始點,可以通過點擊右上角的加號,從Inputs中選擇。
它的界面如下圖所示:
?
在上圖中可以看出, 輸入 “bdc hello” 之后, alfred會啟動一個python解釋器,并運行Scirpt欄中的代碼。
Script中的{query}會被alfred自動的取代為「hello」.
也就是,此時 實際運行的代碼是
import bddict bddict.query('hello')其中 , bddict.py 的代碼如下:
# -*- coding: utf_8 -*- # author xiaogo import sys import hashlib import time import math import base64 import urllib2 import urllib import re import json import alfredxmlclient_id = '1xML4eLvqG8runr4uHcDPU6f'def is_cn_char(i):return 0x4e00<=ord(i)<0x9fa6def bdDict(From,To,Q):resp = urllib2.urlopen("http://openapi.baidu.com/public/2.0/translate/dict/simple?client_id=%s&q=%s&from=%s&to=%s"%(client_id,Q,From,To)).read()js = json.loads(resp,encoding = 'utf-8')return js# alfred 的入口函數. def query(query): # 對query 作防御if(len(query)==0):rowList = [{'uid':'1','arg':'','autocomplete':'','icon':'icon.png','subtitle':'Please Input','title':'Please Input'}]element = alfredxml.genAlfredXML(rowList)print(element)return # 判斷是否為中文字符,若是 漢譯英 若否 英譯漢if(is_cn_char(unicode(query,"utf-8")[0] )):resp = bdDict("zh","en",query)else:resp = bdDict("en","zh",query)if(resp[u'errno'] == 0): # 通過bdDict() 函數 ,調用百度詞典HTTP接口.if(len(resp[u'data'])==0):returnrowList = []subtitle = ''k = resp['data']['symbols'][0] # 解析JSON.uid = 1for i in k.keys():if(i.startswith("ph_")):subtitle +=i[3:]+'['+ resp['data']['symbols'][0][i] + ']'# 解析JSON, 生成rowListrowList.append({'uid':uid,'arg':query,'autocomplete':query,'icon':'icon.png','subtitle':subtitle.encode("utf-8"),'title':'發音'})uid +=1for i in resp['data']['symbols'][0]['parts']:if(len(i['part'])>0):subtitle = reduce(lambda x,y:x+","+y, i['part'])else:subtitle = ''title = reduce(lambda x,y:x+","+y, i['means'])rowList.append({'uid':uid,'arg':query,'autocomplete':query,'icon':'icon.png','subtitle':subtitle.encode("utf-8"),'title':title.encode("utf-8")})uid +=1else:print("err")pass#print(rowList)# 生成XML文件.print(alfredxml.genAlfredXML(rowList))其中, 生成XML的代碼如下 alfredxml.py :
# 生成XML文件 def genElement(lists):assert(len(lists)%3==0)name = lists[0] # 節點名params = lists[1] # 節點屬性listcontent = lists[2] # 節點內容 , 可能是String 或者是包含其他Element.string = ''string +="<%s"%name + “ “ # 以下為解析XML List的過程for k,v in params.items(): # 枚舉屬性string+='%s = "%s" '%(k,v)if(isinstance(content, str)): # 通過遞歸 解析子節點text = contentelse:text = genElement(content)string +=">" + text + "</%s>\n"%nameif(len(lists)<=3): # 通過遞歸, 解析同級節點return stringelse:return string + genElement(lists[3:])def genAlfredXML(rowList): # 生成alfred所需要的XML String.item = []for row in rowList:tsi = ['title',{},row['title'],'subtitle',{},row['subtitle'],'icon',{},row['icon']]item.extend(['item',{'uid':row['uid'],'arg':row['arg'],'autocomplete':row['autocomplete']},tsi])items = ['items',{},item]return genElement(items)if __name__=='__main__':rowList = [{'uid':'123321','arg':'argsx','autocomplete':'autocompletex','icon':'icon','subtitle':'subtitle','title':'title'}]element = genAlfredXML(rowList)print(element)###2.4.2 Output
output 是 alfred 中的『執行器』。
通過Script Filter, 我們已經得到了一個alfred 的結果列表, 通過點按回車鍵,我們可以執行相應的命令。 以百度詞典這個workflow為例,我們打開了百度詞典的網站。
執行的時候,我們打開了http://dict.baidu.com/s?wd={query}
注意,這里又出現了一個{query}
這個{query} 將承接 Scirpt Filter 中,被點擊回車的那條XML 節點中的 arg參數 。
?
實際上,我們不僅可以使用URL Open 作為 結果,也可以使用Terminal Command 作為結果執行。
使用Terminal ,可以令你更加隨心所欲的控制你的MAC. 實現諸如Wifi切換、更改DNS服務器、啟動某個服務端、甚至可以控制你家的空調或者咖啡機, 這以前只有emacs才能做到 ;)
#3.參考文獻
1.Alfred - workflow python dev lib
2.Tutorial on alfred workflow with python
來源:?http://myg0u.com/python/2015/05/23/tutorial-alfred-workflow.html
總結
以上是生活随笔為你收集整理的Alfred workflow 开发指南的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nios烧写到EPCS的问题处理
- 下一篇: 天津计算机三加二学校有哪些,天津3+2学