モチベーション

自分でGFMに対応したLinkフォーマットに合わせるのが煩わしい

作ったAlfred workflow

URL craftというworkflowを作った。これをインストールすれば、Alfredを開いてug 加工したいURLと入力するだけでクリップボードにGithub Flavored MarkdownのLinkフォーマットに従ったテキストが保存される。

20150428_url_craft

アプローチ

URLをGFMのLinkフォーマットに従い変更したものをクリップボードに保存する(以降GFM Link化と呼ぶ)にはいくつかのアプローチが有る。例えば、

  • ブラウザプラグインを利用して、現在開いているブラウザのアクティブなウィンドウのurlとタイトルを自動加工する
  • Alfred workflowを利用してurlをコピーして引数として渡しスクリプトフィルタで自動加工する

前者に関しては、ブラウザプラグインを利用しているので現在閲覧中のWebサイトのURLとタイトルを簡単に習得できる。しかし、特定のブラウザでしか利用出来ないし、全てのブラウザのプラグインを作成するのは面倒である。それに比べて、後者はMacのアプリケーションAlfredを利用するものなので特定のブラウザという制約は受けない。Alfredを利用する場合、どのブラウザのどのタブのものをGFM Link化するか判定するロジックを組むのは色々と煩わしいが、workflowの引数としてGFM Link化したいURL情報をプログラムに渡す方法はシンプルで実装も簡単そうだ。よって、今回のAlfred workflowのスクリプトフィルタの引数に加工したURL情報を渡す方法を採用する。また、GFM Link化するURLが持つタイトル情報などは以下のように取得する。

Webページのタイトル

htmlの<head><title>XXXX</title></head>の中にあるXXXXが目的のWebページのタイトルになる。

Webページのurl

htmlの<link rel='canonical' href='YYYY/>にあるYYYYが目的のURLになる

<link rel='canonical' href='http://blog.takanabe.tokyo/?p=335' />

しかし、今回はworkflowの引数としてGFM化したいURLを入力するのでその情報を利用することとする。ホットキーで一発で現在開いているWebページのURLを持ってきたいときには使いたいと思う。

workflowの作成手順

workflowはpythonのAlfredライブラリの使い勝手が良さそうなのでpythonで実装した。以下はメモ書き程度のworkflowの作成手順である。実装はアプローチに則り行った。

1. workflowの設定

  • Bundle ID:一意に決まるものが良い。まあでも自分の運用しているWebサイトのFQDNとかを使ってもいいだろう。
  • Created By: 自分の名前
  • Web Page:自分の運用しているWebサイト

2. Python Alfred workflow moduleのインストール

インストール方法はInstallation :Alfred-Workflow 1.11.1 documentationに従った。

  1. githubから最新のalfred-workflow-X.X.X.zipをダウンロードする
  2. ダウンロードしたファイルを解凍して、workflowディレクトリを取り出す
  3. 1.で作成したディレクトリに2.で取り出したworkflowディレクトリを以下のように格納する(作成したworkflowを右クリックすると該当のディレクトリを開くことができる)

    Your Workflow/
    info.plist
    icon.png
    workflow/
        __init__.py
        background.py
        update.py
        version
        web.py
        workflow.py
    yourscript.py
    etc.
    
    

3. スクリプトフィルタブロックの作成

pythonのAlfred Workflowモジュールを使うと簡単に実装できる。

import sys
from workflow import Workflow,web

def main(wf):
    # Get args from Workflow, already in normalised Unicode

    query = None  # Ensure `query` is initialised
    # Set `query` if a value was passed (it may be an empty string)
    if len(wf.args):
       query = wf.args[0]

    url = query

    #=========================================================#
    # title: it shows a big sentence in result
    # subtitle : it shows a small sentence in result
    # valid : valid = True tells Alfred that the item is actionable
    # arg : the value it will pass to the next action
    #=========================================================#

    wf.add_item(title = 'Craft URL as GFM style',subtitle = url, valid = True, arg = url,icon = 'icon.png')
    wf.send_feedback()

if __name__ == '__main__':
    wf = Workflow()
    sys.exit(wf.run(main))

ポイントは、wf.add_itemargで次のブロックに渡す値を格納して、valid = TrueでAlfredからEnterキーで実行可能にする。このプログラムはスクリプトフィルタブロックのScriptのフォームに直接記述することも可能だが、それをするとinfo.plistにプログラムが保存されてしまう。管理の面を考えると外部のプログラムを呼び出す形の方が良さ気である。従って僕は以下のようにした、

20150428_scriptfilter_block

4. Run scriptブロックの作成

スクリプトフィルタで動的に生成したargの値をRun scriptに渡す。渡された引数をwf.args[0]で参照している。

import re
import urllib2
from workflow import Workflow

def main(wf):
    # Get args from Workflow, already in normalised Unicode
    query = None  # Ensure `query` is initialised
    # Set `query` if a value was passed (it may be an empty string)
    if len(wf.args):
       query = wf.args[0]

    url = query

    res = urllib2.urlopen(url)
    pattern_title = re.compile('<title>(.*?)</title>')
    m = pattern_title.search(res.read())
    title = m.group(1)

    print "[{title}]({url})".format(title = title, url = url)

if __name__ == '__main__':
    wf = Workflow()
    sys.exit(wf.run(main))

20150428_run_script_block

5. Notificationブロックの作成

MacのNotification Centerに通知を表示するブロックを作成する。TitleやTextの値は好きなものに変化すれば良い。

20150428_notification_block

6. Copy Clipboardブロックの作成

Run scriptブロックの結果をクリップボードに保存するブロックを作成する。特に難しいことはないが、直前のブロックの処理内容を参照するために{query}マクロを利用する。

20150428_copy_clipboard_block

7 完成!

最終的にはこんな感じのworkflowブロックが出来る。

20150428_workflow_blocks

作ったworkflowの共有

作ったworkflowは他の人も使いたいかもしれないから共有しよう。共有方法はPackalというサービスを使うのが主流のようだ。僕は、Packalに作ったworkflowを預け、Github、Alfred Forum、このサイトにはPackalへのリンクを貼ることにした。

まとめ

最低限のプログラムしか書いていないが、一応自分の目的とするworkflowの作成をすることができた。今まで手動でしてきたGFM Linkの作成から解放されると思うと清々しくなる。今回は、ブラウザのプラグインで作成するのも選択肢としてはあったが、それだとブラウザを変えた瞬間使えなくなってしまうのでMacを使っている限り使えるもので作成した。作成したURL Craftは、現在はGFM Link化にしか対応していないが、URLの短縮とかURLに纏わる便利機能などにも対応させようと思う。

参考

Official site

Tutorial

Python Alfred workflow module

workflowを共有する