RaycastからObsidianのMap Viewプラグインで読み込める位置情報を生成する

Raycastはランチャーに分類されることが多く、さまざまなアプリを簡単に起動できます。
そして、さまざまな便利な機能を追加できます。
今回は「Script Commands」を活用して、ObsidianのMap Viewプラグインで読み込める「位置情報」を生成する方法について紹介します。

この記事は[Raycast Advent Calendar 2024](https://qiita.com/advent-calendar/2024/raycast)に参加しています。

昨日は @masuipeo による「[RaycastのScript Commandsでちょっとした便利な処理を実行する](https://qiita.com/masuipeo/items/31d0a27b40da72b129fa)」でした。

# ObsidianのMap Viewプラグインとは

[Obsidian](https://obsidian.md)はノートアプリであり、PKM（Personal Knowledge Management）ツールでもあります。
Markdown形式でローカルにファイルを保存できることから、便利に使っているITエンジニアは多いでしょう。

そして、さまざまなプラグイン（拡張）が用意されており、導入するだけでさらに便利になります。
その中でも、個人的によく使うのが「Map View」プラグインです。

https://github.com/esm7/obsidian-map-view

これを使うと、ノート内に位置情報を記述するだけで、そのノートに書いた場所を地図として表現できます。
詳しくは、私が書いた以下のページなどを参考にしてください。

https://note.com/masuipeo/n/ne4fcfb5443c5

# 位置情報の記述

上記では「ノート内に位置情報を記述する」と書きました。
また、上記のnoteでは、以下のような記法で書いていました。

```txt
---
location: [40.6892494, -74.0466891]
---
```

このような書き方もできましたが、現在は公式サイトでも以下のように書くことを推奨されています。

```txt
---
location: "40.6892494,-74.0466891"
---
```

そこで、このような位置情報を取得することを考えます。

# 位置情報の取得

この位置情報を取得するとき、手軽なのは、Googleマップを使う方法です。
Googleマップでお店や場所などをクリックして、右クリックすると、その位置情報を取得できます。

![東京タワー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309006/3ae37f34-77ee-c534-2ffa-d60b05380f3c.png)

この緯度と経度が表示されている部分をクリックするとクリップボードに以下のような値が入ります。

```txt
35.6586065962376, 139.7454650873197
```

これを使うのでも十分なのですが、店名や施設名などがわかっているときに、わざわざGoogleマップを開いて場所を検索し、それをコピーしなければなりません。
これは数が少ないと大した手間ではありませんが、何度も使うときには不便です。

そこで、効率よく取得することを考えます。

# 位置情報を取得できるAPI

プログラムから位置情報を取得することを考えたとき、さまざまなAPIが提供されています。
GoogleマップにもAPIがあります。

https://developers.google.com/maps?hl=ja

月に200$の無料利用枠があるため、個人的に使うだけであれば十分でしょう。

しかし、もっと手軽に使えるものとして、Geocoding APIがあります。

https://www.geocoding.jp/api/

登録も不要で、それほど負荷をかけなければ便利に使えそうです。

たとえば、次のURLにアクセスすると、XML形式のデータが返ってきます。

https://www.geocoding.jp/api/?q=東京タワー

今回はこれを使うことにします。

# 位置情報をシェルスクリプトから取得する

手軽に呼び出せるようにするために、シェルスクリプトを作ります。
今回は、bashから`curl`コマンドを使ってXML形式のデータを読み込み、`xmllint`で取り出すことにします。
また、日本語で入力したキーワードからURLエンコードするために、`nkf`を使うことにします。`nkf`はHomebrewなどでインストールしておきましょう。

```sh
$ brew install nkf
```

たとえば、次のようなコードが考えられます。

```geo.sh
function urlencode {
    echo "$1" | nkf -WwMQ | sed 's/=$//g' | tr = % | tr -d '\n'
}

param=$(urlencode "$1")
xml=$(curl -s "https://www.geocoding.jp/api/?q=$param")

if [ $? -eq 0 ]; then
    lat=$(echo "$xml" | xmllint --xpath "/result/coordinate/lat/text()" -)
    lng=$(echo "$xml" | xmllint --xpath "/result/coordinate/lng/text()" -)
    echo "\"$lat,$lng\""
else
    echo "\"\""
fi
```

このコマンドに引数として店名や場所を渡すと、位置情報が出力されます。

```sh
$ ./geo.sh "東京タワー"
"35.658581,139.745433"
```

# Raycastから呼び出す

そして、このコマンドを手軽に実行するためにRaycastを使います。
昨日の記事でも書いたように、Raycastには「Script Commands」という機能があります。

https://qiita.com/masuipeo/items/31d0a27b40da72b129fa

これを使うと、bashやApple Script、Python、Ruby、node.jsなどのスクリプトを簡単に呼び出せます。

このため、上記のスクリプトも簡単に実行できます。
Raycastから「Create Script Command」を実行し、`mode`として`compact`を指定します。
また、「With argument」にチェックを入れておきます。
そして、できたファイルに、上記のプログラムを記述し、引数（`@raycast.argument1`）を設定します。

たとえば、次のような感じでしょうか。

```sh
#!/bin/bash

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Geo
# @raycast.mode compact

# Optional parameters:
# @raycast.icon 📍

# Documentation:
# @raycast.description Get geolocation.
# @raycast.author masuipeo
# @raycast.argument1 { "type": "text", "placeholder": "住所または施設名", "optional": false }

function urlencode {
    echo "$1" | nkf -WwMQ | sed 's/=$//g' | tr = % | tr -d '\n'
}

param=$(urlencode "$1")
xml=$(curl -s "https://www.geocoding.jp/api/?q=$param")

if [ $? -eq 0 ]; then
    lat=$(echo "$xml" | xmllint --xpath "/result/coordinate/lat/text()" -)
    lng=$(echo "$xml" | xmllint --xpath "/result/coordinate/lng/text()" -)
    echo "\"$lat,$lng\""
else
    echo "\"\""
fi
```

このように、引数を指定すると、Raycastからは次のような入力欄が表示されます。

![geo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309006/e2c49972-2b23-faac-e8cc-6c9001c67cbb.png)

そして、ここに「東京タワー」などと入力すると、それが引数として指定され、プログラムが実行されます。

# 実行結果

今回は`mode`に`compact`を指定していますので、位置情報がRaycastの画面に表示されます。
これを「Command + T」でコピーして、Obsidianに貼り付けるだけです。

![tokyotower2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309006/b6e2d20d-c45d-7d52-40e5-c84240fe435b.png)

一度作ってしまえば便利なので、ぜひ使ってみてください。