← XeFM English | 日本語 · crftwr/xefm on GitHub · craftware

ファイル拡張子の関連付け機能

English | 日本語

概要

ファイル拡張子の関連付け機能を使うと、XeFM がさまざまな種類のファイルを開く、表示する、編集するときに使うプログラムを、拡張子に基づいて設定できます。XeFM がいろいろなファイルの種類をどう扱うかを柔軟にカスタマイズできます。

クイックスタート

どんな機能か

ファイルの関連付けでは、XeFM がファイルの種類ごとに、開く・表示する・編集するのに使うプログラムを設定できます。たとえば、画像の表示にはプレビューを、編集には Photoshop を使う、といった設定ができます。

基本的な例

~/.xefm/config.py に次のように追加します。

FILE_ASSOCIATIONS = [
    # Images: Multiple patterns, Preview for viewing, Photoshop for editing
    {
        'pattern': ['*.jpg', '*.jpeg', '*.png', '*.gif'],
        'open|view': ['open', '-a', 'Preview'],  # Same for open and view
        'edit': ['open', '-a', 'Photoshop']
    },
    
    # Videos: QuickTime for viewing, Final Cut for editing
    {
        'pattern': ['*.mp4', '*.mov'],
        'open|view': ['open', '-a', 'QuickTime Player'],
        'edit': ['open', '-a', 'Final Cut Pro']
    },
    
    # PDFs: Preview for viewing, Acrobat for editing
    {
        'pattern': '*.pdf',
        'open|view': ['open', '-a', 'Preview'],
        'edit': ['open', '-a', 'Adobe Acrobat']
    }
]

設定

ファイルの関連付けは、~/.xefm/config.py ファイルの FILE_ASSOCIATIONS リストで設定します。

コンパクト形式の構造

FILE_ASSOCIATIONS = [
    {
        'pattern': '*.ext' or ['*.ext1', '*.ext2'],  # Single or multiple
        'open|view': ['command', 'args'],  # Combined actions
        'edit': ['command', 'args']        # Separate action
    }
]

主な特徴

  1. 複数のパターン:関連するパターンをリストにまとめられます
  2. アクションの結合:| を使って、同じコマンドを複数のアクションに割り当てられます
  3. 柔軟な形式:パターンが 1 つなら文字列、複数ならリストで書けます

アクション

ファイルのパターンごとに、最大 4 つのアクションを設定できます。

アクション 実行するもの 動作 値
enter open_item(Enter) 気軽に開く — XeFM の中で 処理 内蔵ハンドラーの名前
open open_with_os 意図して開く — 別のアプリに渡す コマンド
view view_file ファイルを表示 コマンド
edit edit_file ファイルを編集 コマンド

キーはキーマッププリセットによって異なります。キーマッププリセットを参照してください。

「開く」の 2 つの段階

open_item と open_with_os は、意図的に異なる操作になっています。

enter の段階は XeFM の中にとどまるので、その値には起動するプログラムではなく 内蔵ハンドラー の名前を書きます。

値 効果
'viewer' 内蔵のテキスト/Markdown ビューアーで開く
'navigate' ファイルをアーカイブとしてブラウズする(*.jar、*.whl に便利)
'list' ファイルを 1 行に 1 つのパスのファイルリストとして開く(*.m3u、*.m3u8 の既定)
None 何もしない
(ルールなし) XeFM の既定:ディレクトリとアーカイブには入り、ファイルは表示する
{
    'pattern': '*.csv',
    'enter': 'viewer',                    # Enter -> built-in viewer
    'open':  ['open', '-a', 'Numbers'],   # open_with_os -> Numbers
}

コマンドの形式

プログラムは 2 つの形式で指定できます。

  1. コマンドのリスト(推奨):
    'open': ['open', '-a', 'Preview']
    
  2. コマンドの文字列(自動的にリストに変換されます):
    'open': 'open -a Preview'
    
  3. None(アクションを使えなくする):
    'edit': None  # No editor configured for this file type
    

    view の場合、None はもっと具体的な意味になり、内蔵ビューアーを使う ことを表します。テキストファイルを参照してください。

ターミナルのプログラム

これを宣言する必要はありません。 XeFM が画面を明け渡すかどうかは、設定したプログラムではなく、実行しているバックエンドで決まります。

モード プログラムを起動したときの動作
ターミナル(--backend tui) XeFM は一時停止し、プログラムがターミナルを使います。プログラムが終了すると XeFM が復帰して再描画します
デスクトップモード 明け渡すターミナルがないので、プログラムは切り離して起動され、XeFM は操作できる状態のままです

そのため、'view': ['less'] はターミナルモードでそのまま動作します。フラグは要りません。

{
    'pattern': '*.log',
    'view': ['less'],      # terminal mode hands the display over and waits
    'edit': ['code'],      # a GUI editor in the same entry is fine
}

実際の帰結は TEXT_EDITOR と同じで、実行するモードに合ったプログラムを選んでください。 デスクトップモードで実行中に設定したターミナルプログラムは描画するターミナルがないので表示されません。ターミナルモードで GUI のランチャーを使うと動作し、XeFM が復帰するときに短い再描画が入ります。

この機能の初期の案では、エントリごとに 'terminal': True フラグがありました。これは削除されました。XeFM がすでに判断できることと重複しており、ターミナルのビューアーと GUI のエディターを混ぜた 1 つのエントリを表現できず、しかも失敗したときに安全ではなかったためです。less に付け忘れるとターミナルが壊れました。手書きの設定に残った terminal キーは無視されます。

コンパクト形式の機能

1. 複数のパターン

関連するファイルのパターンをまとめます。

{
    'pattern': ['*.jpg', '*.jpeg', '*.png', '*.gif']
}

拡張子ごとに同じ設定を繰り返す必要がありません。

2. アクションの結合

パイプ | 演算子を使って、同じコマンドを複数のアクションに割り当てます。

{
    'open|view': ['open', '-a', 'Preview']
}

open と view が同じプログラムを使うことがはっきりわかり、意図が明確になります。

3. 柔軟なパターンの形式

パターンが 1 つなら文字列で:

'pattern': '*.pdf'

複数ならリストで:

'pattern': ['*.mp4', '*.mov', '*.avi']

形式の比較

旧形式(冗長):

FILE_ASSOCIATIONS = {
    '*.jpg': {
        'open': ['open', '-a', 'Preview'],
        'view': ['open', '-a', 'Preview'],
        'edit': ['open', '-a', 'Photoshop']
    },
    '*.jpeg': {
        'open': ['open', '-a', 'Preview'],
        'view': ['open', '-a', 'Preview'],
        'edit': ['open', '-a', 'Photoshop']
    },
    # ... repeat for each extension
}

新形式(コンパクト):

FILE_ASSOCIATIONS = [
    {
        'pattern': ['*.jpg', '*.jpeg', '*.png', '*.gif'],
        'open|view': ['open', '-a', 'Preview'],
        'edit': ['open', '-a', 'Photoshop']
    }
]

削減効果:行数が 75% 減ります。

優先順位による照合

FILE_ASSOCIATIONS のエントリは、上から下へ順に調べられます。そのため、一般的なルールの前に特定のルールを書いておけば、ファイルの扱いを細かく制御できます。

仕組み

XeFM があるファイルとアクションに対応するプログラムを探すときは、次のようにします。

  1. FILE_ASSOCIATIONS の 各エントリを上から下へ調べます
  2. エントリごとに:
    • ファイル名がパターンに一致するかを調べます
    • パターンが一致したら、そのエントリにアクションがあるかを調べます
    • アクションがあれば、そのコマンドを使います(None であっても)
    • アクションがなければ、次のエントリに進みます
  3. パターンとアクションの両方が見つかった 最初のエントリで止まります

基本原則

最初に一致したエントリが優先されます。ただし、そのエントリにアクションがある場合に限ります。

優先順位の例

例 1:一般的なものより特定のものを先に

FILE_ASSOCIATIONS = [
    # Specific: Test files
    {
        'pattern': 'test_*.py',
        'open': ['pytest', '-v'],
        'edit': ['vim']
    },
    # General: All Python files
    {
        'pattern': '*.py',
        'open': ['python3'],
        'view': ['less'],
        'edit': ['vim']
    }
]

動作:

例 2:README ファイル

FILE_ASSOCIATIONS = [
    # Specific: README files with special viewer
    {
        'pattern': 'README*',
        'view': ['glow']  # Markdown renderer
    },
    # General: All markdown files
    {
        'pattern': '*.md',
        'open': ['typora'],
        'view': ['less'],
        'edit': ['vim']
    }
]

動作:

優先順位のベストプラクティス

  1. 特定のパターンを先に:より特定的なパターンは、常に一般的なパターンより前に置いてください
  2. 意図を書き残す:エントリをその順序にした理由をコメントで説明してください
  3. 設定を確かめる:ファイルが想定どおりのパターンに一致するか確認してください

XeFM での使い方

設定すると、XeFM は次の場面でこれらの関連付けを使います。

  1. ファイルを選んでアクション(open、view、edit)を選んだとき
  2. ファイル操作のキーボードショートカットを使ったとき
  3. ファイルのコンテキストメニューを使ったとき

キーバインド

Enter - XeFM の中で開く

Enter は enter アクションを使います。外部プログラムを起動することはありません。

動作:

  1. ディレクトリには入り、認識できるアーカイブはブラウズします。これは常にそうで、設定では変えられません。構造上、Enter はこういう意味だからです
  2. 通常のファイルでは、関連付けに ‘enter’ ハンドラーがあるかを調べます
  3. 'viewer' は内蔵ビューアーで開き、'navigate' はファイルをアーカイブとしてブラウズし、'list' はファイルリストとして開き、None は何もしません
  4. ルールがなければ、内蔵ビューアーで開きます
  5. ただし、XeFM にそのファイルを表示する内蔵の手段がない場合(たとえば PNG)は、表示できない内容をビューアーで開く代わりに、open_with_os に割り当てたキーを示す警告をログに出します

現在、画像で *“No built-in viewer for photo.png — press to open it in an external program"* と表示されるのは手順 5 のためです。メッセージには `open_with_os` に割り当てられているキーが示されるので、設定に従います。そのようなパターンに `'enter': 'viewer'` を設定するとこの動作が上書きされ、とにかくビューアーで開きます。その場合はバイナリ用のプレースホルダーが表示されます。

open_with_os - 外部で開く

open_with_os は open アクションを使います。

動作:

  1. 関連付けに ‘open’ コマンドがあるかを調べます
  2. 見つかればそれを起動します。ターミナルモードでは先に画面を明け渡し、デスクトップモードでは切り離して起動します(ターミナルのプログラムを参照)
  3. 明示的に None なら何も起動しません(あるファイルの種類を OS に決して渡さないようにするにはこうします)
  4. それ以外は OS の既定のアプリ(open / xdg-open / start)を使います

view_file - ファイルを表示

ファイルの上で view_file(File → View File)を実行すると、XeFM はファイルの関連付けの view アクションを使います。

動作:

  1. ファイルの関連付けに ‘view’ アクションがあるかを調べます
  2. 見つかれば、設定したビューアーを起動します
  3. 明示的に None なら、内蔵のテキストビューアーで開きます
  4. 見つからなければ、内蔵のテキストビューアーで開きます(バイナリはプレースホルダーを表示します)

リモートのファイルとアーカイブ内のファイルは、常に内蔵ビューアーを使います。外部プログラムが開けるディスク上のパスがないためです。

edit_file - ファイルを編集

edit_file(File → Edit File)を実行すると、XeFM はファイルの関連付けの edit アクションを使って、選択したファイル(何も選択していなければフォーカスのあるファイル)を編集します。

動作(ファイルごと):

  1. ファイルの関連付けに ‘edit’ アクションがあるかを調べます
  2. 見つかれば、設定したエディターを起動します
  3. 明示的に None なら、エディターが設定されていないことを伝えて止まります
  4. 見つからなければ、設定項目 TEXT_EDITOR を使います

同じプログラムになるファイルは 1 回の起動でまとめて渡される(vim a.txt b.txt)ので、複数ファイルの編集は 1 つのエディターのセッションになります。いろいろなファイルが混ざった選択では、エディターごとに 1 回ずつ起動されることもあります。

ローカルのファイルだけが対象です。リモートのパスとアーカイブ内のパスはスキップされます(混ざった選択では個別にスキップされ、それぞれログに 1 行出ます)。

使用例

画像 - ビューアーは同じ、エディターは別

{
    'pattern': ['*.jpg', '*.png'],
    'open|view': ['open', '-a', 'Preview'],  # Same for both
    'edit': ['open', '-a', 'Photoshop']      # Different editor
}

使い方:

動画 - ビューアーのみ

{
    'pattern': '*.avi',
    'open|view': ['open', '-a', 'VLC'],
    'edit': None  # No editor configured
}

使い方:

テキストファイル - View アクションに内蔵ビューアー

{
    'pattern': '*.txt',
    'open': ['open', '-e'],      # TextEdit
    'edit': ['vim']              # Terminal editor
    # 'view' omitted - will use built-in text viewer
}

使い方:

注:view アクションを省略すると、XeFM はテキストファイルに内蔵のテキストビューアーを使えます。内蔵ビューアーはシンタックスハイライトを備え、コードやテキストファイルの閲覧に最適化されています。

フォールバックの動作

ファイルに関連付けが設定されていない場合:

  1. Enter キー:テキストファイルでは内蔵ビューアーを使います。XeFM に表示する内蔵の手段がないファイル(たとえば画像)では、意味のない文字を表示する代わりに、ファイルを外部で開くキーを示す警告をログに出します
  2. view_file:内蔵のテキストビューアーで開きます。ビューアーはバイト列を読み、テキストはシンタックスハイライト付きで表示し、バイナリはプレースホルダーを表示します
  3. edit_file:設定項目 TEXT_EDITOR を使います

XeFM がテキストファイルと判定する方法

XeFM は拡張子ではなく、バイト列を読んでテキストかどうかを判定します。 XeFM には「テキストの拡張子」の一覧は意図的にどこにもありません。そのような一覧は、拡張子のないファイル(Makefile、README)、未知の拡張子、紛らわしい拡張子では間違えますが、内容を調べればこの 3 つとも労せず正しく判定できます。

内蔵ビューアーは次のように判定します。

  1. ファイルを utf-8、次に latin-1、次に cp1252 として デコードしてみます
  2. どれでもデコードできなければ、生のバイト列を読み、最初の 1024 バイトに NUL バイトがあるかを調べます。NUL があればバイナリとみなし、[Binary file — cannot display as text] と表示します
  3. それ以外の場合 は、置換文字を使って latin-1 で表示します

XeFM 全体での目安は 能力はバイト列から判定し、好みは拡張子で設定する です。拡張子が決めるのは どのアプリケーションを使いたいか であって、ファイルがテキストとして読めるかどうかではありません。

View アクション:コマンド、None、ルールなし

view アクションには 3 つの場合があり、そのうち 2 つは同じ結果になります。

view の値 効果
コマンド(例:['less']) その外部ビューアーを起動する
None 内蔵ビューアーを使う(テキストは表示、バイナリはプレースホルダー)
(一致するルールなし) None と同じ — フォールバックで内蔵ビューアー

つまり view では、None と「ルールがまったくない」ことは同じです。この違いが意味を持つのは open と edit だけで、そこでは None は「このファイルの種類ではこのアクションを使えない」ことを意味し、フォールバックを止めます。'view': None を明示的に設定するのは、後にあるより一般的なエントリがコマンドを指定するかもしれない場合に、内蔵ビューアーを 確実に 使いたいときだけです。

アクションのフォールバック早見表

アクション 関連付けあり 関連付けなし — テキスト 関連付けなし — バイナリ
Enter 内蔵ハンドラーまたは設定した open 内蔵ビューアー 外部で開くキーを使うよう警告
View(view_file) 設定したビューアー(None なら内蔵) 内蔵ビューアー 内蔵ビューアーがプレースホルダーを表示
Edit(edit_file) 設定したエディター 設定項目 TEXT_EDITOR 設定項目 TEXT_EDITOR

外部で開く・ファイルマネージャーで表示

上の設定できるアクションのほかに、XeFM にはファイルを OS に渡す固定の操作が 2 つあります。

外部で開く — OS の既定のアプリ

アクション:open_with_os。open アクションと同じキーです。

これは open_with_os で説明した、意図して開く段階です。XeFM はまず関連付けの中から open コマンドを探し、なければ(明示的に None でもなければ)OS の既定のアプリケーションを使います。macOS では open、Linux では xdg-open、Windows では start です。選択したファイルを開き、何も選択していなければフォーカスのあるファイルを開きます。この受け渡しは open コマンドのようにファイルごとに設定することは できません。その種類のファイルに OS が登録しているものが使われます。

ファイルマネージャーで表示

アクション:reveal_in_os。

OS のファイルマネージャーを、その項目を選択した状態で開きます。

このアクションは選択項目ではなく、常に フォーカスのある 項目を使います。フォーカスのある項目がディレクトリの場合は、中身を表示するために開くのではなく、その親の中で(選択された項目として)表示します。OS 側に出てドラッグ&ドロップをしたり、ネイティブのコンテキストメニューを使ったりするのに便利です。

OS の既定のアプリではなく自分で設定したツールを実行するには、X で外部プログラムのメニューを開きます(外部プログラムを参照)。

例

画像ファイル

複数の画像の拡張子をまとめ、開くのと表示するのに同じプログラムを使います。

{
    'pattern': ['*.jpg', '*.jpeg', '*.png', '*.gif'],
    'open|view': ['open', '-a', 'Preview'],
    'edit': ['open', '-a', 'Photoshop']
}

動画ファイル

{
    'pattern': ['*.mp4', '*.mov'],
    'open|view': ['open', '-a', 'QuickTime Player'],
    'edit': ['open', '-a', 'Final Cut Pro']
},
{
    'pattern': '*.avi',
    'open|view': ['open', '-a', 'VLC'],
    'edit': None  # No editor configured
}

PDF ファイル

{
    'pattern': '*.pdf',
    'open|view': ['open', '-a', 'Preview'],
    'edit': ['open', '-a', 'Adobe Acrobat']
}

テキストファイルとコードファイル

{
    'pattern': '*.txt',
    'open': ['open', '-e'],  # TextEdit on macOS
    'edit': ['vim']
    # 'view' omitted - uses built-in text viewer
},
{
    'pattern': ['*.py', '*.js'],
    'open': ['open', '-a', 'Visual Studio Code'],
    'edit': ['vim']
    # 'view' omitted - uses built-in text viewer with syntax highlighting
}

パターンの照合

ファイルの関連付けは、ワイルドカードのパターンで照合します。

パターンの照合では大文字と小文字を区別しないので、*.PDF と *.pdf は同じものとして扱われます。

プラットフォームごとの設定

プラットフォームごとに異なるプログラムを設定できます。

import platform

FILE_ASSOCIATIONS = []

if platform.system() == 'Darwin':  # macOS
    FILE_ASSOCIATIONS.append({
        'pattern': ['*.jpg', '*.png'],
        'open|view': ['open', '-a', 'Preview'],
        'edit': ['open', '-a', 'Photoshop']
    })
elif platform.system() == 'Linux':
    FILE_ASSOCIATIONS.append({
        'pattern': ['*.jpg', '*.png'],
        'open': ['xdg-open'],
        'view': ['eog'],  # Eye of GNOME
        'edit': ['gimp']
    })

既定の関連付け

XeFM には、よく使われるファイルの種類に対する既定の関連付けが用意されています。

これらの既定は、設定ファイルでどれでも上書きできます。

ヒントとベストプラクティス

  1. 複数のアクションに同じプログラム:特にメディアファイルでは、’open’ と ‘view’ の両方に同じプログラムを使うのが一般的です。

  2. 専用のエディター:閲覧用のアプリケーションとは別の、編集専用のソフトウェアには ‘edit’ アクションを使ってください。

  3. アクションを使えなくする:あるファイルの種類であるアクションを使えなくしたい場合は、そのアクションを None に設定してください。

  4. コマンドを試す:設定に追加する前に、コマンドがターミナルから動作することを確認してください。

  5. 絶対パスを使う:プログラムが PATH にない場合は、実行ファイルの絶対パスを使ってください。

  6. 特定のパターンを先に:設定では、より特定的なパターンを常に一般的なパターンより前に置いてください。

  7. 意図を書き残す:エントリをその順序にした理由をコメントで説明してください。

トラブルシューティング

プログラムが見つからない

XeFM がプログラムを見つけられない場合:

違うプログラムが開く

違うプログラムが開く場合:

アクションが使えない

アクションが表示されない場合:

パターンが一致しない

ファイルが想定したパターンに一致しない場合:

設定のテスト

テストを実行して、すべてが動作することを確認します。

python3 test/test_file_associations.py

関連ドキュメント