ロゴテキスト ロゴ

    AlfredのワークフローをNodeで作成する

    AlfredのワークフローをNodeで作成する

    AlfredのワークフローをNode.jsを使って作成します。


    AlfredのワークフローはデフォルトでNodeをサポートしていないため、

    NodeでAlfredのワークフローを開発出来るようにする Alfy というパッケージを使います

    sindresorhus/alfy: Create Alfred workflows with ease



    Alfy

    2020/11/10現在 バージョンが 0.10.0 と1.0.0以下なのが気になりますが、スター数も1k超えていて使いやすいパッケージになってます!


    Alfy を使うことでAlfredのワークフローをNodeで作ることができます

    またGitでの管理もしやすく出来るようなかゆいところに手が届く工夫がされています!(素晴らしい。。😭)





    作成の手順や Alfy を使った際の仕組みで理解が難しい部分があったため細かく書いていきます。

    また、作成したものをGitで管理したいのでその手順も合わせて記載します。

    検証した環境

    1 yarn 1.22.4
    2 node 14.13.1
    3 Alfy 0.10.0

    作成手順

    先に大まかな作成手順を

    • 1.GitHubのリポジトリ作成(Git管理しない場合はスキップ)
    • 2.ダミーのワークフローを作成
      • ワークフローの核となる info.plist を作成するため
    • 3.リポジトリのフォルダでAlfy導入
      • 合わせて2.で作った info.plist を移動
    • 4.index.jsに処理を追加
    • 5.alfy-initを実行してワークフローを管理するフォルダにシンボリックリンクを貼る


    理解しづらいのが2と5かな、と思います。

    Alfredはワークフローを「info.plist」というもので管理していて、


    2でinfo.plistを作る

    3でinfo.plistをGit管理するフォルダに移動

    5でAlfredのワークフローを管理するフォルダ内にシンボリックリンクを貼ってinfo.plistを戻す


    という流れになります。

    今回作るもの

    今回はこのようなものを作ります

    今回作るもの

    まず一般的なAlfredのワークフローようにキーワードを入力し起動させ、
    jsで処理(Alfyを使用)を実行
    処理した内容を画面に出力します

    1.GitHubのリポジトリ作成

    Git管理しない人はスキップして下さい。


    本題とそれるので簡単に。

    先にリポジトリの作成とクローンをしておきます。

    空白のワークフローを作成

    この段階でREADME.mdを作ってfirst commitしておくとブランチ切ることも出来るようになるのでおすすめ

    2.ダミーのワークフローを作成

    ダミーのワークフローを作成します。


    なぜダミーを作るかというと、Alfredの全ての設定が書かれているinfo.plistを手にいれるため。

    空白のワークフローを作成

    左下の「+」ボタンから Blank Workflow を選択して空白のワークフローを作成します

    空白のワークフローを作成

    Node.jsを使用する、というのを分かりやすくするためにNode.jsのアイコンを拝借してみました。


    Bundle Idが必須になります、設定しないと以下のようなエラーが出るためです。

    This script must be called from Alfred, $alfred_workflow_cache is missing. Make sure a Bundle ID is set.


    Workflowの流れを作成

    作成したワークフローで 右クリック → Inputs → Script Filter を選択し、

    Script Filterを選択



    以下のように入力

    • Keyword・・alfredのアクションを起こすための好きな文字列(ここでは hoge で起動)
    • Placeholder Title・・Keyword(この場合hoge)入力後に表示されるテキスト、必須
      • なくても大丈夫やろ、と思ったらないと表示されません、注意
    • Language・・ /bin/bash
    • Script・・./node_modules/.bin/run-node index.js "$1"
      • AlfyでNodeを実行する際の定型文、と思って下さい
    Script Filterを選択



    またjsで処理した値をテキスト表示したいため Outputs → Large Type を選択しScript Filterとつなげます。

    Script FilterとLarge Typeをつなげる

    Large Typeの内容はシンプルにScript Filterで選択した内容を表示するだけでいきます。

    Large Typeの内容

    info.plistの確認

    作成したワークフローを選択し「Open in Finder」で該当ワークフローのフォルダを開くと「info.plist」が作成されています。
    (アイコンを設定したため、 icon も一緒に存在しています)

    info.plistが出来ている

    info.plistをのぞいてみるとワークフローがどのように処理され作られているか、イメージがつきやすいです。

    3.リポジトリのフォルダでAlfy導入

    いよいよAlfredの処理の部分をNodeで書ける環境を作っていきます!

    info.plistをリポジトリフォルダにコピー

    Gitで管理するリポジトリフォルダにinfo.plistをコピーします

    info.plistを移動

    私のようにアイコンなど何かしら追加のファイルがある人はそのファイルも含めてコピーします

    alfred-workflow-node-sample/
      icon
      info.plist
      README.md

    ダミーのワークフローを削除

    先程Alfredで作ったダミーのワークフローを削除します!!

    後々$ alfy-init というコマンドを叩いて復活するのでいったん今は削除!

    ダミーのワークフローを削除

    Alfyの導入

    肝心のAlfyを導入します!



    Git管理するリポジトリフォルダで yarn initnpm init を実行

    $ yarn init -y

    Alfyをインストール

    $ yarn add alfy


    パッケージを追加したので「node_modules」フォルダが作られます。
    git管理したくないので「.gitignore」を作成しGit管理対象から外します

    .gitignore
    node_modules/

    ここまででフォルダ構成はこのようになってます

    alfred-workflow-node-sample/
      icon
      info.plist
      node_modules/
      package.json
      README.md
      yarn.lock

    4.index.jsに処理を追加

    Prettier導入(お好みで)

    Prettierを使うと自動フォーマットしてくれてコーディングで考えることが減るので、jsを書く前のこのタイミングでの導入がおすすめ!



    本題とそれるので簡単に。

    Prettierをインストール

    $ yarn add -D prettier

    設定をpackage.jsonに追記(設定内容はお好みで)

    package.json
    {
      "name": "alfred-workflow-node-sample",
      ・・・
      "prettier": {
        "singleQuote": true,
        "semi": false,
        "arrowParens": "avoid"
      }
    }

    index.jsを追加

    ここまでくれば後一息!

    Alfredの核となる処理の部分を「index.js」に書いていきます。


    簡単なリスト表示するコードです

    index.js
    const alfy = require('alfy')
     
    const items = [
      { title: 'hello, Alfred', subtitle: 'alfred subtitle', arg: 'alfred' },
      { title: 'hello, Node', subtitle: 'node subtitle', arg: 'node' },
    ]
     
    alfy.output(items)

    最終的な成果物を実行した際のイメージを見ると、コードで何をやっているか分かりやすいです

    リスト表示される


    「hoge a」と謎な a が付いているのは、ワークフローを作る際に「Argument Required」で設定したからですな。😎笑

    Argument Requiredを設定したためkeywordが必須


    arg は次のアクションに渡される値です。

    例えば、argにURLを設定して次のアクションとして「Open URL」を設定すれば、Webページを開く、ということが出来ます。

    Alfyのコードについて

    公式GitHubのREADME.mdが充実しているので1度目を通すのがおすすめ!
    sindresorhus/alfy: Create Alfred workflows with ease




    alfy.output() の引数に渡した値が一覧で表示されます。


    outputは以下のように定義されていて

    output(list, options?)

    listにはオブジェクトの配列を渡す必要があります。



    listに渡すオブジェクトで定義出来るものはAlfred公式ページに書かれています
    Script Filter JSON Format - Workflow Input Objects - Alfred Help and Support

    {"items": [
        {
            "uid": "desktop",
            "type": "file",
            "title": "Desktop",
            "subtitle": "~/Desktop",
            "arg": "~/Desktop",
            "autocomplete": "Desktop",
            "icon": {
                "type": "fileicon",
                "path": "~/Desktop"
            }
        }
    ]}


    最低限 title があれば成り立つため以下のコードでも動作します

    index.js
    const alfy = require('alfy')
     
    const items = [{ title: 'hello, Alfred' }, { title: 'hello, Node' }]
    alfy.output(items)

    5.alfy-initを実行

    Alfyのパッケージの中には alfy-init というコマンドが含まれています。

    alfy-initはAlfredのワークフローを管理するためのフォルダにシンボリックリンクを貼ってくれる、というもの。

    node_modules/.bin/alfy-init
    #!/usr/bin/env node
    'use strict';
    const execa = require('execa');
     
    (async () => {
    	try {
    		await execa('alfred-link', {
    			preferLocal: true,
    			localDir: __dirname
    		});
    	} catch (error) {
    		console.error(error);
    		process.exit(1);
    	}
    })();

    exaca というライブラリでシンボリックリンクを貼ってくれてそうですね



    実行してみると、

    $ npx alfy-init
    シンボリックリンクが貼られている

    ワークフローのフォルダにシンボリックリンクが作られてます。



    この状態でAlfredを見てみると、

    削除したワークフローが復活している

    !!
    削除したワークフローが復活してる。。


    つまり、Alfredは workflows/<ワークフローのフォルダ>/info.plist でワークフローの管理をしてるんですね。

    Alfredを実行する

    いよいよ実行してみます

    できた!😍

    文字でかいなw

    プロフィールの背景画像 プロフィール画像
    Yuki Takara
    都内でフリーランスのエンジニアをやってます。フロントとアプリ開発メインに幅広くやってます。