詩と創作・思索のひろば

ドキドキギュンギュンダイアリーです!!!

Fork me on GitHub

Alfredの代替としてRaycastを使っている

新春ツール入れ替えシリーズです。macOS における Spotlight 的なランチャーツールとして Alfred を長いこと使ってきたが、最近 Raycast を使ってみてこれがよかったので、以来ずっと使い続けている。

Raycast - Supercharged productivity

開発者のための便利ツールという売り文句のようで、そういう点がまさに気に入った。

カレンダーの次の予定が表示される

まずこれがいい。これだけで十分使える。ランチャーを起動したときにカレンダーの次の予定を表示してくれる。Enter でそのまま Meet や Zoom を開いてくれるのでキーボードから手を離す必要がない。

f:id:motemen:20220128231151p:plain

もともとカレンダーの確認には Dato を使っていたし今も使ってるが、これでミーティングへのアクセスがかなりよくなった。

コミュニティベースの Store で機能を追加できる

https://www.raycast.com/store にいろんな extension がアップロードされているし、この検索やインストールも Raycast 上で行える。Extension ってのは補完候補を増やしたり、Raycast 上から何らかのアクションを起こせるようにするやつだ。

自分の場合以下のような extension をインストールして、いろんな作業の起点を Raycast にできている。

  • Google Workspace
    • Google ドライブのファイルの検索ができる。これめっちゃ助かる。
  • Google Chrome
    • Chrome のタブを操作したり選択したりできるらしい。が複数ウィンドウ開いてるとあまりちゃんと動いてくれないことがある……。
  • TickTick
    • 以前のエントリで紹介した TickTick のタスクもここから確認できて便利。

Extension は TypeScript/React で書ける!!!

これ、なるほど便利だなーとなった。Raycast の追加機能は TypeScript/React で書くことになっている。

以下のサイトに詳しく書かれているのでエッセンスのみ紹介する。

Introduction - Raycast API

  • コマンドは React コンポーネントとして実装する。@raycast/api<List><ActionPanel> などを使うことで、候補アクションや取れるサブアクションをユーザに提示できる。
  • Node のランタイムが提供されるので、fetch() とかが普通に使える。
  • 手元で開発するときは @raycast/api 同梱のコマンドを使って ray develop すると、自動リロードしつつ手元の Raycast に反映してくれる。
  • API キーなど、Extension に設定項目が必要な場合は package.json に書いとくと自動的に UI を提供してくれる。

自分で extension を作ってみる

とまあ非常に楽を追究していて、スムーズに開発できるのがよい。そういうわけで1つ作ってみた。ウェブ API でなにかの一覧を提供してるものがほしかったので、手近な Mackerel のアラートを一覧するようなもの。

GitHub - motemen/raycast-extension-mackerel-alerts

API を利用するのに API キーが必要なので、package.json に書いておく。"required": true とすることで、この extension を使う初回に勝手にダイアログを出してくれるので便利。

  "preferences": [
    {
      "name": "apiKey",
      "type": "password",
      "required": true,
      "title": "API key",
      "description": "Mackerel API key",
      "placeholder": "Visit https://mackerel.io/my?tab=apikeys to obtain one"
    }
  ],

中身は swr と axios でごくごく普通に作る。選択したときのアクションはブラウザを開く、とし、アラートの重大度に合わせて色もつけてみる。

export default function Command() {
  const apiKey = preferences.apiKey?.value as string | undefined;

  const { data, error } = useSWR(apiKey, async (apiKey) => {
    ...
  });

  ...

  return (
    <List isLoading={!data && !error}>
      {data?.alerts.map((alert) => (
        <AlertListItem key={alert.id} orgName={data.orgName} alert={alert} />
      ))}
    </List>
}
const AlertListItem = ({ orgName, alert }: { orgName: string; alert: AlertResponseItem }) => (
  <List.Item
    title={`${alert.type}: ${alert.message || alert.hostId || alert.value}`}
    ...
    // アイテムに対するアクションは actions で設定する
    actions={
      <ActionPanel>
        <OpenInBrowserAction url={`https://mackerel.io/orgs/${orgName}/alerts/${alert.id}`}></OpenInBrowserAction>
      </ActionPanel>
    }
    // なんかいい感じのアイコンが提供されている
    icon={{
      source: Icon.Circle,
      ...
    }}
  ></List.Item>
);

こんな感じに動きます。簡単だった。なんかいいやつ作ったら教えてくれ!

f:id:motemen:20220128231541g:plain

ちなみに同様なもので Command E ってのもあるらしいが、Dropbox に買収されてからなりを潜めていそう。再浮上に期待。ランディングページにインストールへの導線がなくて笑った。

はてなで一緒に働きませんか?