如何編寫你的 Alfred Workflow

前言

每當有人問到有什麼 macOS 上的提高效率的神器,Alfred 都是我腦海裏第一個蹦出來的答案。Alfred with Powerpack 更是強上增強。 幾乎 mac 裏的一切均可以經過簡單的 ⌘ + space(個人 Alfred 快捷鍵)獲取到。php

Alfred 的 workflows 是一個使我很是興奮的功能。它能充分知足程序員自給自足的樂趣。git

今天咱們不介紹 Alfred 的那些優秀的功能。只來學習下如何開發本身的 workflow。程序員

這是成品 alfred-gitmoji-workflow。效果以下:github

alt

Gitmoji 是一個標準化和解釋在GitHub提交消息上使用emojis的計劃。能夠理解爲用來規範 git commit message 中 emoji 的使用的。shell

經過在 Alfred 中鍵入 gitmoji 就會列出全部的 gitmoji,能夠經過 gitmoji 官網中提供的 emoji 名稱和釋義來搜索。按下回車就複製到了粘貼板,而且粘貼到你當前 focus 的窗口的輸入框。json

搭建工做環境

在 Alfred 打開時,鍵入 ⌘ + , 就會進入到偏好頁。在 Alfred偏好頁 -> Workflows 左側 workflow 列表的最下方點擊加號新建一個空白的 workflow。緩存

abc

在建立 workflow 的彈窗,填寫好基本信息,須要注意的是 Bundle Id 是你這個 workflow 的簽名。須要填寫的獨特一些。服務器

alt

在空白的 workflow 界面,右鍵。根據咱們此次須要開發的 wolkflow 的特性選擇 Inputs 爲 Script Filter。數據結構

alt

而後填寫關鍵詞的一些描述信息,包括輸入關鍵詞的標題,副標題,和 Loading 時的佔位詞等等一些設置。app

固然最重要的就是設置獲得用戶輸入以後,對這個輸入進行處理而後輸出的腳本。

alt

Alfred 提供了幾種腳本語言的運行時。

languages

一開始以爲這種插件的開發應該是 JS 的天下。沒想到在 Github 上用來開發 workflow 的最多的語言竟然是 PHP。我也隨大流的選擇了 PHP 來進行此次開發。

腳本輸入框內就是最關鍵的兩行代碼,咱們的腳本入口:

$query = urlencode( "{query}" );
require_once("gitmoji.php");
複製代碼

在 Alfred 中。輸入gitmoji, 這個關鍵字後面輸入的文字就做爲 {query} 做爲咱們腳本的輸入。也就是上面咱們把這個輸入 urlencode 以後賦給了變量 $query。咱們而後引用了 gitmoji.php。咱們作的搜索邏輯就是在這個 php 文件中完成的。

在列表中右鍵這個 workflow, 選擇在 Finder 中打開,咱們就能夠看到兩個文件。info.plist, icon.pnginfo.plist 就包含了咱們剛剛填寫的全部基本信息和設置選項的 xml 文件。你能夠雙擊打開查看。 因此再建立一個 gitmoji.php 就完成了一個 workflow 的開發了。

alt

剛剛打開的路徑是/Users/xxxx/Library/Application\ Support/Alfred\3/Alfred.alfredpreferences/workflows/user.workflow.xxxxx/

咱們通常不會選擇直接在上面這個路徑咱們的開發目錄,由於這根本不是咱們的開發地盤。

因此在本身經常使用的開發目錄下新建一個目錄,將上面獲得的兩個文件拷貝過來。咱們新建一個空白的 workflow 的目的就是先獲得這兩個文件。

咱們不在 Alfred 存放 workflow 的目錄開發,那咱們怎麼將咱們源碼放置到 workflow 指定的目錄呢?

其實 Alfred 的 workflow 的文件擴展是相似 gitmoji.workflow 的一個壓縮文件。雙擊這個壓縮文件 Alfred 就會安裝這個插件到上面的路徑。

因此咱們就須要一個腳本幫咱們完成這個壓縮(打包)的工做。

這裏借鑑(copy)的是 alfred-github-workflow 的打包腳本。

#!/usr/bin/env php
<?php
// Forked from https://github.com/gharlan/alfred-github-workflow/blob/master/bin/build

$dir = dirname(__DIR__);
$VERSION = "1.0.0";
require $dir.'/workflows.php';

$plist = $dir.'/info.plist';

exec(sprintf('/usr/libexec/PlistBuddy -c "Set :version %s" %s', $VERSION, escapeshellarg($plist)));

// $changelog = file_get_contents($dir.'/CHANGELOG.md');
// $changelog = str_replace("\n", '\n', $changelog);
// exec(sprintf('/usr/libexec/PlistBuddy -c "Set :readme \"%s\"" %s', escapeshellcmd($changelog), escapeshellarg($plist)));

$zipFile = $dir.'/github.zip';
if (file_exists($zipFile)) {
    unlink($zipFile);
}

$zip = new PharData($zipFile);

$files = array(
    'icon.png',
    'info.plist',
    'gitmoji.php',
    'README.md',
    'workflows.php',
);

foreach ($files as $file) {
    $zip->addFile($dir.'/'.$file, $file);
}
foreach (glob($dir.'/icons/*.png') as $path) {
    $zip->addFile($path, 'icons/'.basename($path));
}

$zip->compressFiles(Phar::GZ);

$workflow = $dir.'/gitmoji.alfredworkflow';
if (file_exists($workflow)) {
    unlink($workflow);
}
rename($zipFile, $workflow);
複製代碼

它所作的事情就是將源碼(workflow 須要的幾個文件)經過 php 的 PharData 類將生成一個壓縮包。雙擊就能被 Alfred 安裝。安裝也就是解壓縮以後複製到 workflow 的工做目錄。

寫腳本

<?php
require_once('workflows.php');
$w = new Workflows();
$query = urldecode(strtolower(trim($query)));

<!-- 一週更新一次 -->
if (filemtime("data.json") <= (time() - 86400 * 7)) {
    $dataUrl = 'https://raw.githubusercontent.com/carloscuesta/gitmoji/master/src/data/gitmojis.json';
    $gitmojis = $w->request($dataUrl);
    if (isset(json_decode($gitmojis)->gitmojis)) {
        file_put_contents("data.json", $gitmojis);
    }
}

<!-- 將 gitmoji 的數據設置成 Alfred 可讀的數據結構  -->
function setResult($gitmojis) {
    global $w;
    foreach ($gitmojis as $key => $value) {
        $id = $value->name;
        $arg = $value->code;
        $emoji = $value->emoji;
        $title = $emoji." ".$value->description;
        $subTitle = "Copy ".$arg." to clipboard";
        $w->result($id, $arg, $title, $subTitle, ' ');
    }
}

<!-- 經過搜索詞過濾出結果 -->
function filter($var) {
    global $query;
    $description = strtolower($var->description);
    $name = strtolower($var->name);
    return strpos($description,$query) !== false || strpos($name,$query) !== false;
}
$gitmojis = json_decode(file_get_contents('data.json'))->gitmojis;
$data = $gitmojis;

<!-- 沒有關鍵詞就顯示全部 gitmoji -->
if (strlen($query) != 0) {
    $data = array_filter($gitmojis, "filter");
}

<!-- 獲得的搜索,設置到緩衝區 -->
setResult($data);

<!-- 將結果輸出成 Alfred 可讀的 xml -->
echo $w->toxml();
複製代碼

腳本只有短短的42行。能這麼短的緣由是社區有已經封裝好的很好用的 workflow util

咱們用到的這個 util 的方法只有resulttoxml

result方法就是把數據推到一個緩衝區,而且設置了 Alfred 最終顯示的每一行的數據結構。這個結構包括$uid, $arg, $title, $sub, $icon。依次對應惟一ID、結果(複製到粘貼板的字符串)、標題、副標題、icon。注意這裏的 icon 只能是本地資源,不能是服務器資源。

toxml方法就是把緩衝區的數據轉成 Alfred 可讀的 xml 格式。

我作的事情就是獲取 gitmoji 託管在 github 上的 json 數據,緩存到本地。根據關鍵詞經過字符串匹配名字和釋義。將過濾以後獲得的數據轉成 Alfred 須要的數據格式,而後轉成 xml。

而後再終端運行 ./bin/build。就獲得了一個 Alfred workflow: gitmoji.workflow。:tada::tada:

雙擊gitmoji.workflow安裝,就能夠在 Alfred 中和 gitmoji 盡情玩耍了。

TODO

其實能夠作到事情還有

  • 根據不一樣的語言來搜索 gitmoji。惋惜 gitmoji 的維護者說還沒有找到好的方法維護多語言翻譯。
  • 爲了保持和 gitmoji 源碼數據的同步,沒有使用 emoji 圖片做爲 icon。由於這樣每次 gitmoji 數據一更新,這個 workflow 也須要更新。
  • 增長 update 命令:當即同步 github 數據。
相關文章
相關標籤/搜索