Iniedit.py 技術ドキュメント

プログラムの動作

iniedit.py は、INIファイルやTOMLファイルなどの設定ファイルを編集するためのGUIベースのテキストエディタです。主に以下の機能を提供し、設定ファイルの管理と編集を効率化します。

  • 基本的なファイル操作: 新規作成、ファイルを開く、上書き保存、名前を付けて保存。

  • 文字コードの自動判別と手動指定: chardet ライブラリを使用してファイルの文字コードを自動判別し、UTF-8、Shift_JIS、CP932、EUC-JP、ISO2022-JPなどの手動指定も可能です。

  • テキスト編集機能:

    • 検索と置換: 正規表現および大文字小文字の区別に対応しています。

    • 元に戻す (Undo) とやり直し (Redo)。

    • カーソル位置の行と桁の表示。

    • 文書の先頭、末尾、または指定した行番号へのジャンプ。

  • GUIのカスタマイズと状態保存:

    • ウィンドウのサイズ、位置、フォント設定を iniedit.ini に保存し、次回起動時に復元します。

    • 検索・置換ダイアログやセクションダイアログのサイズと位置も保存されます。

  • 定型文の挿入機能: text.ini に定義されたキーと値のペアをコンテキストメニューから簡単に挿入できます。複数行のテキストもサポートします。

  • シンタックスハイライト: color.ini に定義された正規表現パターンに基づいて、テキストに色やスタイルを適用し、視認性を高めます。

  • セクションジャンプ機能: INI/TOML形式のセクション(例: [section])を一覧表示し、クリックで該当する行にジャンプできます。正規表現によるセクションフィルタリングも可能です。

  • ドラッグ&ドロップ: エディタにファイルをドラッグ&ドロップすることで、ファイルを直接開くことができます。

  • 外部コマンド実行: iniedit.ini に設定された外部コマンドをメニューから実行でき、編集中のファイルパスを変数として渡すことが可能です。

  • ファイル場所の操作: 編集中のファイルが存在するディレクトリをOSのファイルエクスプローラー/ファインダーで開いたり、ターミナルを開いたりする機能を提供します。

原理

iniedit.py は、Pythonの標準GUIライブラリである tkinter を中心に構築されています。以下に主な機能の原理を説明します。

  1. GUI構築:

    • メインウィンドウ、メニューバー、ツールバー、テキスト編集エリア (scrolledtext.ScrolledText)、ステータスバーは tkinter ウィジェットで構成されます。

    • ファイルのドラッグ&ドロップ機能は tkinterdnd2 ライブラリを利用して実現されています。

  2. INIファイル解析:

    • read_ini(filepath): シンプルな key=value 形式のINIファイルを解析します。行頭が # の行はコメントとして無視されます。

    • parse_multiline_ini(filepath): read_ini と同様に key=value 形式を解析しますが、値が 「3重引用符」 (""") で囲まれている場合に複数行の値をサポートします。キーにバックスラッシュ (\) を含むことで、コンテキストメニュー上で階層構造として表示されるように処理されます。

  3. 文字コード検出とファイルI/O:

    • ファイルを開く際、chardet.detect() 関数を使用してバイナリデータから文字コードを自動検出します。検出された文字コードまたはユーザーが指定した文字コードでファイルをデコード(読み込み時)またはエンコード(書き込み時)します。

    • ファイルの読み書きはPythonの組み込み open() 関数を使用し、encoding 引数と errors='ignore' で文字コード関連のエラーを適切に処理します。

  4. 簡易TOML/INIパーサー (SimpleTomlParser):

    • このクラスは、厳密なTOML仕様ではなく、[section]key=value の形式に特化した簡易パーサーです。

    • テキストエリアの内容を行ごとに走査し、正規表現 ^\s*\[ でセクション行を識別します。

    • セクション名とそれが現れる行番号を記録し、セクションジャンプ機能で利用できるようにします。

  5. シンタックスハイライト:

    • color.ini から 正規表現=スタイル:色 の形式でハイライトルールを読み込みます。

    • _setup_highlighting() メソッドで、各ルールに対して tkinter.Text ウィジェットの tag_configure() を使用してフォントスタイル(太字、斜体)と前景色を設定したタグを定義します。

    • _apply_highlighting() メソッドで、re.compile() で正規表現パターンをコンパイルし、pattern.finditer(content) でテキスト内のすべてのマッチを検索します。見つかったマッチの開始位置と終了位置を tkinter.Text のインデックス形式に変換し、tag_add() で対応するタグを適用します。

  6. 検索と置換:

    • tkinter.Text ウィジェットの search() メソッドを利用して、テキスト内の文字列を検索します。正規表現検索は regexp=True を、大文字小文字の区別なし検索は nocase=True を設定することで行います。

    • 置換は、tkinter.Textdelete()insert() メソッドを組み合わせて行います。全て置換の場合には、re.subn() を使用して一度に全ての置換を実行し、テキストエリアの内容を更新します。

  7. 外部コマンド実行:

    • subprocess.Popen() 関数を使用して外部プログラムを実行します。

    • iniedit.ini で定義されたコマンド文字列内の {{file_path}} などのプレースホルダは、_substitute_variables() メソッドによって現在のファイルパスやエディタ設定値で置換されます。

    • cwd (current working directory) を指定することで、特定のディレクトリでコマンドを実行できます。

必要な非標準ライブラリとインストール方法

iniedit.py の実行には、以下の非標準ライブラリが必要です。

  1. chardet: ファイルの文字コードを自動検出するために使用されます。

    pip install chardet
    
  2. tkinterdnd2: Tkinterアプリケーションでドラッグ&ドロップ機能を実現するために使用されます。

    pip install tkinterdnd2
    
  3. Pillow (PIL): ツールバーアイコンの画像ファイルを読み込み、リサイズするために使用されます。

    pip install Pillow
    

必要な入力ファイル

iniedit.py は、以下の種類の入力ファイルを読み込み、設定や機能を提供します。

  1. 編集対象ファイル:

    • ファイル名: 任意のINI/TOML/テキストファイル(例: settings.ini, config.toml, data.txt など)。

    • 形式: 基本的には [section]key=value の構造を持つテキストファイルです。プログラムはこれらの構造を簡易的に解析し、セクションジャンプ機能などに利用します。

    • 文字コード: 自動判別を試みますが、手動で指定することも可能です。

  2. iniedit.ini:

    • ファイル名: iniedit.ini

    • 配置場所: iniedit.py と同じディレクトリ。

    • 形式: シンプルな key=value 形式のINIファイルです。

    • 内容:

      • main_width, main_height, main_pos_x, main_pos_y: メインウィンドウのサイズと位置。

      • find_dialog_width, find_dialog_height: 検索ダイアログのサイズ。

      • replace_dialog_width, replace_dialog_height: 置換ダイアログのサイズ。

      • section_dialog_width, section_dialog_height: セクションダイアログのサイズ。

      • font_family, font_size: テキストエディタのフォント設定。

      • external_cmdN_name, external_cmdN_path (Nは1から9): 外部コマンドの名前と実行パス。実行パスには {{file_path}} で現在開いているファイルのパスを、{{VAR_NAME}}iniedit.ini に定義された他のキーの値や環境変数を埋め込むことができます。

  3. text.ini:

    • ファイル名: text.ini

    • 配置場所: iniedit.py と同じディレクトリ。

    • 形式: key=value 形式のINIファイルですが、値は複数行をサポートします。複数行の値は、値全体を 「3重引用符」 (""") で囲みます。

      • 例1: greeting=Hello, World!

      • 例2: long_text="3重引用符"これは\n複数行にわたる\nテキストです。"3重引用符"

    • 内容: コンテキストメニューから挿入できる定型文やコードスニペットを定義します。キーに \ を含めることで、メニュー内でサブメニューとして表示される階層構造を作成できます (例: Python\Import\Os=import os)。

  4. color.ini:

    • ファイル名: color.ini

    • 配置場所: iniedit.py と同じディレクトリ。

    • 形式: 正規表現パターン=スタイル:色 のINIファイルです。

    • 内容: テキストエリアのシンタックスハイライトルールを定義します。

      • 正規表現パターン: Pythonの re モジュールが解釈できる正規表現です。

      • スタイル: bold (太字) または italic (斜体) を指定します。

      • : HTMLカラーコード (例: #FF0000) または色の名前 (例: blue) を指定します。

      • 例: ^\[.*?\]=bold:blue (セクション名を青の太字でハイライト)

  5. icons/ ディレクトリ:

    • 配置場所: iniedit.py と同じディレクトリ。

    • 内容: ツールバーで使用されるアイコン画像ファイル(例: new.png, open.png, save.png など)を格納します。

生成される出力ファイル

iniedit.py は、主に以下のファイルを出力または変更します。

  1. 編集対象ファイル:

    • 現在開いているファイル(self.current_file)がある場合は、そのファイルに上書き保存されます。

    • 「名前を付けて保存...」機能を使用した場合、指定されたパスに新規ファイルとして保存されます。

    • 内容: テキストエディタのテキストエリアに表示されている内容が、選択された文字コードで保存されます。行末はOSの標準的な改行コード(WindowsではCRLF、Unix系ではLF)に変換されます。

  2. iniedit.ini:

    • ファイル名: iniedit.ini

    • 配置場所: iniedit.py と同じディレクトリ。

    • 内容: エディタの終了時、メインウィンドウの現在のサイズと位置 (main_width, main_height, main_pos_x, main_pos_y)、および各ダイアログのサイズ (find_dialog_width, find_dialog_height など) が自動的に更新され、保存されます。これにより、次回起動時に同じレイアウトが復元されます。

コマンドラインでの使用例 (Usage)

iniedit.py は、ファイルパスやジャンプ先の行・列をコマンドライン引数で指定して起動できます。

python iniedit.py [input_file] [--line LINE] [--col COL]
  • [input_file]: (オプション) 編集したいINI/TOMLファイルのパスを指定します。指定しない場合、エディタは「無題」の新規ファイルとして起動します。

  • --line LINE: (オプション) エディタ起動時にカーソルを移動させる行番号を指定します。デフォルトは1です。

  • --col COL: (オプション) エディタ起動時にカーソルを移動させる桁番号を指定します。デフォルトは0です。

コマンドラインでの具体的な使用例

例1: 特定のINIファイルを開く

example.ini というファイルを直接開きます。

実行コマンド:

python iniedit.py example.ini

実行結果の説明: iniedit.py のGUIウィンドウが起動し、example.ini の内容がテキストエリアに読み込まれて表示されます。ウィンドウのタイトルバーには「Inifile Editor - example.ini」と表示されます。カーソルはファイルの先頭(1行目、0桁目)に配置されます。

例2: 特定のファイルを開き、指定した行と桁にジャンプする

config.toml というファイルを開き、カーソルを10行目の5桁目(文字のインデックスは4)に移動させます。

実行コマンド:

python iniedit.py config.toml --line 10 --col 5

実行結果の説明: iniedit.py のGUIウィンドウが起動し、config.toml の内容がテキストエリアに読み込まれて表示されます。ウィンドウのタイトルバーには「Inifile Editor - config.toml」と表示され、テキストエリアのカーソルは自動的に10行目の5桁目(行頭から数えて5文字目の直後)に移動し、その位置がビューポートの中央に表示されるようにスクロールされます。ステータスバーには「行: 10, 桁: 5」と表示されます。

例3: ファイルを指定せずにエディタを起動する

引数を何も指定せずにエディタを起動します。

実行コマンド:

python iniedit.py

実行結果の説明: iniedit.py のGUIウィンドウが起動し、空のテキストエリアが表示されます。ウィンドウのタイトルバーには「Inifile Editor - 無題」と表示されます。新規ファイルとしてすぐに編集を開始できます。