## 経緯
[[Windows]]で[[Flow Launcher]]を使っていたときは、入力した文字列を[[Base64エンコード]]/[[Base64デコード]]したり、[[URLエンコード]]/[[URLデコード]]したりする機能を使っていた。[[Raycast]]でもこれを実現したい。
[[Raycast Extension]]をインストールしてくれば解決できそうだが、せっかくなので自力で整備してみる。
## Script Commands
[[Raycast]]には[[Script Commands (Raycast)|Script Commands]]という機能があり、[[Raycast]]からの入力を受け取って処理した結果を色々な方法で出力する機能がある。今回は文字列を入力し、文字列を出力+クリップボード保存したいだけなので用途に合いそう。
## shellスクリプト作成
[[URLエンコード]]/[[URLデコード]]には[[Python]]を利用するが、以下の理由から[[Script Commands (Raycast)|Script Commands]]としては[[Bash]]で登録する。
- ワンライナーで書ける
- 標準出力とクリップボードどちらにも出力する
`base64-encode.sh`
```bash
#!/bin/bash
# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Base64 Encode
# @raycast.mode compact
# @raycast.icon https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png
# @raycast.argument1 { "type": "text", "placeholder": "text", "optional": true }
set -o pipefail
echo "${1:-$(pbpaste)}" | base64 | tee >(pbcopy)
```
`base64-decode.sh`
```bash
#!/bin/bash
# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Base64 Decode
# @raycast.mode compact
# @raycast.icon https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png
# @raycast.argument1 { "type": "text", "placeholder": "text", "optional": true }
set -o pipefail
echo "${1:-$(pbpaste)}" | base64 -d | tee >(pbcopy)
```
`url-encode.sh`
```bash
#!/bin/bash
# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title URL Encode
# @raycast.mode compact
# @raycast.icon https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png
# @raycast.argument1 { "type": "text", "placeholder": "text", "optional": true }
set -o pipefail
python3 -c "import urllib.parse; print(urllib.parse.quote('${1:-$(pbpaste)}'))" | tee >(pbcopy)
```
`url-decode.sh`
```bash
#!/bin/bash
# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title URL Decode
# @raycast.mode compact
# @raycast.icon https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png
# @raycast.argument1 { "type": "text", "placeholder": "text", "optional": true }
set -o pipefail
python3 -c "import urllib.parse; print(urllib.parse.unquote('${1:-$(pbpaste)}'))" | tee >(pbcopy)
```
ポイントは以下で説明。
### set -o pipefail
[[パイプの途中で失敗した場合はステータスを失敗に (Bash)|パイプの途中で失敗した場合はステータスを失敗に]]するため必要。これをつけないと、[[tee]]の前にコマンドが失敗しても、[[tee]]で必ず成功(0)になってしまうためエラーが起こっていることに気づきにくくなる。
### `tee >(pbcopy)`
前段のコマンドで標準出力に出力された結果を標準入力として受けとり、**標準出力** および [[pbcopy]]の標準入力に渡す書き方。端的に言うと以下2つを同時に実現するため。
- [[Raycast]]に結果の文字列を表示する
- クリップボードに結果の文字列をコピーする
### エンコード/デコードのロジック
以下を利用。
- [[ターミナルでURLエンコード]]
- [[ターミナルでURLデコード]]
- [[ターミナルでBase64エンコード]]
- [[ターミナルでBase64デコード]]
### 入力がない場合の制御
今回のコマンドは `@raycast.argument1` に `"optional: true"` を設定しているので、いずれも入力を省略可能。
```bash
# @raycast.argument1 { "type": "text", "placeholder": "text", "optional": true }
```
入力が省略された場合はクリップボードのテキストを入力として扱う。[[pbpaste]]の実行結果を利用。
```bash
${1:-$(pbpaste)}
```
## 成果物
[[Base64エンコード]]と[[Base64デコード]]の実演。結果は左下に表示される。
![[20250614_13_35_12.mp4]]