12
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Espanso

Espanso とは、オープンソースかつ無料で使用できる、クロスプラットフォーム(Windows、macOS、Linux)のスニペットアプリです。Espanso を使用すると、短いキーワードを入力するだけで、長いテキストを瞬時に入力できます。これにより、繰り返し入力する必要のあるテキストを簡単に入力できるようになります。Mac 標準のテキスト辞書よりも高速で、多機能です。さらに、Shell script を呼び出すことができるので、ただのスニペットアプリとしてだけでなく、アプリやファイルを開いたり、APIを呼び出すことができるなど、非常に拡張性が高いです。例えば、クリップボードにコピーしたテキストを LLM の API で即時翻訳させることができ、作業中のアプリから離れる必要もなくなります。

image.png

ezgif-1-5219cff875.gif

ezgif-1-6d58091dfc.gif

インストール

インストールしたら、アプリを開きます。そして、ターミナルを開き、コマンドで espanso status を実行して動いているか確認しましょう。

設定

Espanso の設定は主に2つのファイルで行います。

espanso/
├── config/
│   └── default.yml
└── match/
    └── base.yml

espanso のディレクトリの場所は OS によって異なり、コマンド espanso path によって確かめることができます。

  • Linux: $XDG_CONFIG_HOME/espanso (e.g. /home/user/.config/espanso)
  • MacOS: $HOME/Library/Application Support/espanso (e.g. /Users/user/Library/Application Support/espanso)
  • Windows: {FOLDERID_RoamingAppData}\espanso (e.g. C:\Users\user\AppData\Roaming\espanso)

config/default.yml ファイルは、初めは特に設定することはないです。
もし、メニューバーのアイコンを非表示にたい場合は、show_icon: false と書き込むと良いです。

使い方

スニペットの設定は match/base.yml ファイルに書き込みます。

基本的には次のような文法で書きます。

matches: 
  - trigger: ":hello"
    replace: "world"

# 複数行
  - trigger: ":hello"
    replace: "line1\nline2"

# 複数行
  - trigger: ":include newlines"
    replace: |
              exactly as you see
              will appear these three
              lines of poetry

# 改行なし
  - trigger: ":fold newlines"
    replace: >
              this is really a
              single line of text
              despite appearances

match/base.yml を変更したら、それを反映させるためにメニューバーで Reload をするか、コマンドで espanso restart を実行しましょう。

望まないスニペットの作動を防ぐために、:; などの普段は使わない記号を接頭辞に用いると良いです。

:a を登録すると :as:ad といったトリガーは使えなくなります。なぜなら、:a を入力した段階で別のテキストに置換されるからです。このようなことを防ぐために、短すぎるトリガーの設定は避けた方が良いです。

match ディレクトリにある全ての .yml ファイルは読み込まれるので、用途に応じてファイルを細かく分割することもできます。

動的マッチ

次の設定では、:now と入力すると It's 11:29 のように現在時刻に変換します。

  - trigger: ":now"
    replace: It's {{mytime}}
    vars:
      - name: mytime
        type: date
        params:
          format: "%H:%M"

単語マッチ

基本的な triggermatch の設定方法では、変換して欲しくない場面で変換が起こる可能性があります。例えば、トリガー ther によって there としたいとき、other と入力しても変換が実行され othere となってしまいます。これを防ぐためには、以下のように word: true のオプションをつけます。

  - trigger: "ther"
    replace: there
    word: true

カーソルヒント

テキストを変換した後に、カーソルが来る位置を $|$ で決めることができます。

  - trigger: ":div"
    replace: <div>$|$</div>

一つのトリガーに複数の変換

  - trigger: ":quote"
    replace: "Every moment is a fresh beginning."
  - trigger: ":quote"
    replace: "Everything you can imagine is real."
  - trigger: ":quote"
    replace: "Whatever you do, do it well."

複数のトリガーに一つの変換

  - triggers: [":hello", ":hi"]
    replace: "world"

複数のトリガーに複数の変換

  - triggers: [":ok",":emoji"]
    replace: "👍"
  - triggers: [":ok",":emoji"]
    replace: "✅"
  - triggers: [":up",":emoji"]
    replace: "⬆️"
  - triggers: [":down",":emoji"]
    replace: "⬇️"

画像のマッチ

  - trigger: ":cat"
    image_path: "$CONFIG/images/cat.png"

グローバル変数

match に共通してよく使う変数がある場合はグローバル変数として設定すると、変更する際に便利です。

global_vars:
  - name: myname
    type: echo
    params:
      echo: "John"
# It can also be defined as follows:
#  - name: myname
#    type: shell
#    params:
#      cmd: "echo John"

matches:
  - trigger: ":greet"
    replace: "Hello {{myname}}"

  - trigger: ":sig"
    replace: "Best regards, {{myname}}"

espanso のディレクトリを GitHub などで管理したいが、一部プライベートな情報を含むような場合は、それをparams.yml にグローバル変数として入れておき、params.yml.gitignore に追加する方法があります。match ディレクトリにある *.yml ファイルは全て読み込まれます。それ以外の場合は、直接パスを指定して import することもできます。

espanso/
├── config/
│   └── default.yml
└── match/
    ├── base.yml
    ├── params.yml
    ...
# match/params.yml 
# このファイルを .gitignore に追加しておくと安全です
global_vars:
  - name: MY_API
    type: echo
    params:
      echo: "EmitDqIhb7Rzu5GheVtiwL452"
# base.yml
imports:
  # YML file outside of espanso/match/
  - "paths/to/your.yml"

matches:
  - trigger: ":myapi"
    replace: "{{MY_API}}"

Clipboard Extension

変換後の中身にクリップボードの内容を含めて出力することができます。これで、貼り付け作業が必要なくなります。

例えば、直前にコピーしたリンクを用いて、HTML の <a> タグを作成したい時、以下のようにトリガーを定義します。

  - trigger: ":aref"
    replace: "<a href='{{clip}}' />$|$</a>"
    vars:
      - name: "clip"
        type: "clipboard"

マークダウンのトリガー例:

  - trigger: ";mdlink"
    replace: "[$|$]({{clip}})"
    vars:
      - name: "clip"
        type: "clipboard"

  - trigger: ";mdcode"
    replace: |
          ```
          {{clip}}
          ```
    vars:
      - name: "clip"
        type: "clipboard"

各トリガーにクリップボード変数を定義するのが面倒な方は、global_vars に定義しておくと良いです。

Shell Exntension

シェルコマンドを実行して、その結果を出力することもできます。

  - trigger: ":shell"
    replace: "{{output}}"
    vars:
      - name: output
        type: shell
        params:
          cmd: "echo 'Hello from your shell'"

以下の例は、ipify からパブリック IP を取得するトリガーです。

  - trigger: ":ip"
    replace: "{{output}}"
    vars:
      - name: output
        type: shell
        params:
          cmd: "curl 'https://api.ipify.org'"

以下の例は、UUID(Universally Unique Identifier)を生成するトリガーです。

  - trigger: ";uuid"
    replace: "{{output}}"
    vars:
    - name: output
      type: shell
      params:
        # macOS,Linux:
        cmd: "uuidgen"
        # Windows (requires PowerShell):
        # cmd: "powershell -command \"[guid]::NewGuid().ToString()\""

以下の複数の例は、本来のアプリの趣旨とは異なりますが、アプリやWebサイト、ファイルを開くためのトリガーです。

まずは、ターミナルや特定のフォルダを開くトリガー。

  - trigger: ";term"
    replace: "{{output}}"
    vars:
      - name: output
        type: shell
        params:
          cmd: "open -a Terminal.app"

  - trigger: ";dotfile"
    replace: "{{output}}"
    vars:
      - name: output
        type: shell
        params:
          cmd: "open ~/github/dotfiles/"

ターミナルを経由し、VScode で espanso ディレクトリを開くトリガー。ターミナルが開き、code ~/github/dotfiles/espanso/ が実行されます。\n がエンターの役割を果たします。

  - trigger: ";espanso"
    replace: "{{output}}\n"
    vars:
      - name: output
        type: shell
        params:
          cmd: "open -a Terminal.app; echo 'code ~/github/dotfiles/espanso/'"

以下のように、直接呼び出す書き方もできますが、最初に開かれているファイルの一部が消される可能性があります。

  - trigger: ";espanso"
    replace: "{{output}}"
    vars:
      - name: output
        type: shell
        params:
          cmd: "code ~/github/dotfiles/espanso/"

新しいファイルを作成し、開くトリガー。

  - trigger: ";newfile"
    replace: "{{output}}"
    vars:
      - name: uuid
        type: shell
        params:
          cmd: "uuidgen"
      - name: output
        type: shell
        params:
          cmd: "cd ~/Desktop; touch {{uuid}}.md; open /Applications/CotEditor.app {{uuid}}.md"

Youtube を開くトリガー。デフォルトのブラウザで開きます。

  - trigger: ";you"
    replace: "{{output}}"
    vars:
      - name: output
        type: shell
        params:
          cmd: "open 'https://www.youtube.com/'"

クリップボードにコピーした内容を検索するトリガー。

  - trigger: ";ggl"
    replace: "{{output}}"
    vars:
      - name: "clip"
        type: "clipboard"
      - name: output
        type: shell
        params:
          cmd: "open 'https://www.google.com/search?q={{clip}}'"

これがEspansoの真骨頂です。 クリップボードにテキストをコピーし、;transen と入力するだけで、カーソル位置に Google Gemini による英語訳が挿入されます。global_varsGEMINI_API_KEY を定義した上で使用してください。

  - trigger: ";transen"
    replace: "{{translation}}"
    vars:
      - name: "clip"
        type: "clipboard"
      - name: translation
        type: shell
        params:
          cmd: >
            curl -s \
              "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={{GEMINI_API_KEY}}" \
              -H 'Content-Type: application/json' \
              -X POST \
              -d '{
                    "contents": [{
                      "parts": [{"text": "Translate the following to English. Provide ONLY the translated text, no explanations or markdown: {{clip}}"}]
                    }]
                  }' \
            | jq -r '.candidates[0].content.parts[0].text | split("\n")[0]'

jq コマンドが必要です: brew install jq。APIからのJSONレスポンスを解析するために使用します。指示(プロンプト)を変更すれば、翻訳だけでなく、文章の校正、要約、リファクタリングなど、あらゆる種類のトリガーを自作できます。

Script Exntension

外部ファイルを実行してその結果を受け取ることもできます。

script.py

print("Hello from python")

base.yml

  - trigger: ":pyscript"
    replace: "{{output}}"
    vars:
      - name: output
        type: script
        params:
          args:
            - python
            - /path/to/your/script.py

Form Extension (対話的なスニペット)

トリガーからフォームを生成し、定型文にそって文章を作成することもできます。

  - trigger: ":greet"
    form: |
      Hey [[name]],
      Happy Birthday!

screenshot.png

上のフォームは以下のように表現することもできます。

# The above is equivalent to the following
  - trigger: ";_greet"
    replace: |
        Hey {{form.name}},
        Happy Birthday!
    vars:
      - name: "form"
        type: form
        params:
          layout: |
            Hey [[name]],
            Happy Birthday!

variableform を同じトリガー内で使用するような複雑な場合には、こちらの記法出ないと作動しないようです。

メールの定型文フォームから文章を作成

matches:
  - trigger: ";reply"
    form: |
        Hi, [[name]]
        
        Thank you for your email and for bringing this to our attention.
        I am sorry that you're disappointed with our product.
        
        [[choices]]

        Looking forward to hearing from you
        
        All the best,
        ABC Support Team
    form_fields:
      choices:
        type: choice
        values:
          - Could you please let me know what specific issues you've encountered?
          - sentence 2
          - sentence 3
          - sentence 4

screenshot.png

Todo アイテムを作成

  - trigger: ";todo"
    replace: "Task: {{form1.task}}, Due Date: {{form1.day}} {{form1.time}}"
    vars:
      - name: "day0"
        type: date
        params:
          format: "%Y/%m/%d"
      - name: "day1"
        type: shell
        params:
          cmd: "date -v+1d '+%Y/%m/%d'"
      - name: "day2"
        type: shell
        params:
          cmd: "date -v+2d '+%Y/%m/%d'"
      - name: "day3"
        type: shell
        params:
          cmd: "date -v+3d '+%Y/%m/%d'"
      - name: "day4"
        type: shell
        params:
          cmd: "date -v+4d '+%Y/%m/%d'"
      - name: "day5"
        type: shell
        params:
          cmd: "date -v+5d '+%Y/%m/%d'"
      - name: "day6"
        type: shell
        params:
          cmd: "date -v+6d '+%Y/%m/%d'"
      - name: "form1"
        type: form
        params:
          layout: "Task: [[task]], Due Date: [[day]] [[time]]"
          fields:
            day:
              type: choice
              values: |
                      {{day0}}
                      {{day1}}
                      {{day2}}
                      {{day3}}
                      {{day4}}
                      {{day5}}
                      {{day6}}
            time:
              type: choice
              values:
                - "9:00"
                - "10:00"
                - "11:00"
                - "12:00"
                - "13:00"
                - "14:00"
                - "15:00"
                - "16:00"
                - "17:00"
                - "18:00"
                - "19:00"
                - "20:00"

SCR-20240618-qyki.png

テキストのケーススタイル変換

フォームとシェルスクリプトを組み合わせた強力な例です。クリップボードのテキストを、フォームで選択した形式(キャメルケース、スネークケースなど)に変換します。

# text.yml
matches:
  - trigger: ";case"
    replace: "{{output}}"
    vars:
      - name: form
        type: form
        params:
          layout: "Convert clipboard to: [[style]]"
          fields:
            style:
              type: choice
              values: ["UPPERCASE", "lowercase", "PascalCase", "camelCase", "Title Case", "kebab-case", "snake_case"]
      - name: output
        type: shell
        params:
          cmd: |
            text="{{clipboard}}"
            case "{{form.style}}" in
              "UPPERCASE")  echo "$text" | tr '[:lower:]' '[:upper:]';;
              "lowercase")  echo "$text" | tr '[:upper:]' '[:lower:]';;
              "PascalCase") echo "$text" | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2));}1' | tr -d ' ';;
              "camelCase")  echo "$text" | awk '{out=tolower($1); for(i=2;i<=NF;i++){out=out toupper(substr($i,1,1)) tolower(substr($i,2))}; print out}';;
              "Title Case") echo "$text" | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2));}1';;
              "kebab-case") echo "$text" | sed -E 's/[^a-zA-Z0-9 ]+//g' | tr '[:upper:]' '[:lower:]' | tr -s ' ' '-';;
              "snake_case") echo "$text" | sed -E 's/[^a-zA-Z0-9 ]+//g' | tr '[:upper:]' '[:lower:]' | tr -s ' ' '_';;
            esac

まとめ

Espansoは、単純なテキスト置換ツールに留まらず、シェルスクリプト、外部API、対話フォームを駆使することで、日々のPC作業を劇的に効率化する強力なパーソナル自動化ツールです。

この記事で紹介した例はほんの一部です。ぜひあなた自身の定型業務や面倒な作業を見つけ出し、Espansoで自動化してみてください。

参考リンク

ここでは書ききれなかったトリガーの例は以下のレポジトリにあります。

あるいは、次のサイトも参考になります。

また、Espanso Hubでは他のユーザーが作成したパッケージを簡単に追加できます。

12
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?