シーン 2
Delphi のソースコードの uses 部に、特定のモジュール参照を追加する必要があります。しかも、プロジェクト内の全てのソースに対して…。
プロジェクトの規模は、サブシステムが 7つ。機能数は 173機能で、ソースファイルの数でいうと… なんと 861 本。
さて、どうしたものか…。
背景(本題とは少々脱線しています)
開発言語 Delphi を 2007 から XE4 にバージョンアップする案件。
このバージョンアップでは、内部で扱う文字コードが ShiftJIS から Unicode に変更になったため、文字列を扱う関数群の互換性がなくなっているみたいで、影・響・大!
非互換な関数を使用している箇所は膨大で、すべて修正するのは非現実的だし、そもそもやりたくない。
そこで、非互換を吸収するモジュール Compat2007 を作って、すべてのソースで uses してやるだけで、ソース内の関数を個別に修正することなく、互換性を維持することになったのです。
どうしたい?
Delphi のソースは、次のようになっています。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Mask, ComCtrls;
implementation
:
interface 部の uses に Compat2007 を追加したいのです。
つまり、次のようになってほしいのです。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Mask, ComCtrls, Compat2007; // Compat2007 を追加しています
implementation
:
注意しておきたいのは…
- uses に書かれているモジュールの種類や数は、ソースファイル毎に異なる
- interface 部の中には、uses 以外のブロックも存在し得る
ということです。
これを、全てのソースファイル 861本 の uses 部に対して、追加することになります。
どうやって
一度に思考は働きません。順を追って考えていきましょう。
まず、1つのソースファイルから
最初に、モジュールを追加したい箇所にマッチする正規表現を考えてみましょう。
/\vinterface\s*\n(.*\n){-}\s*uses\s*\n*(.*\n){-}.*\zs;\ze
簡単に補足すると…
-
\v
で very magic を指定して、( ) や { } をエスケープ無しで入力しやすくしています。 -
interface
以降に出てくる最初のuses
から;
までを検索します。 - 最後の
;
だけを置換対象にするために、\zs
と\ze
で囲みます。 -
(.*\n)
で任意の行にマッチさせています。 -
{-}
で最短マッチを指定しています。
これで、interface
部の uses
にある最後の ;
が置換対象としてマッチされることになります。
次に、このマッチした箇所に Compat2007
が追加されるように、置換を実行します。
:%s//, Compat2007;/
- 直前に使用した正規表現をそのまま置換条件とするので、省略しています。
- マッチした
;
を, Compat2007;
に置換します。
これで、1つのソースファイルに対して、Compat2007 を追加できたことになります。
(以降の一括置換処理で二重に追加されてしまわないように、ここで実行した置換処理については、u
で undo しておいてください)
さあ、全てのソースファイルへ
いよいよ、全てのソースファイルへ適用する準備が整いました。
処理対象にしたいファイルを読み込みましょう。
:args **/*.pas
バックグラウンドで更新できるように、hidden
を設定しておきます。
:set hidden
1つのファイルに対して実行した置換処理を、読み込んだファイル郡に対して、一括で実行します。(直前の置換処理を使用するので、省略できます)
:argdo %s
しばらく待っているだけで、全てのソースファイルに Compat2007 が追加されていきます。これは圧巻!
処理の経過が1行ずつ表示されて、1画面いっぱいになると処理が一時停止されます。
最後まで停止せずに処理を継続したい場合には、一時停止の状態でG
を押してください。
あとは、ファイルの更新内容を確認して、問題なければ、一括保存しましょう。
:argdo w
まとめ
複数行に渡る正規表現のマッチ&置換処理と、args
, argdo
による一括処理で、退屈なソース修正作業から開放 されるだけでなく、大幅に修正工数を削減 することができました。
勿論、このソース修正を実行するスクリプト言語などを書いて対応する方法もあるでしょう。
しかし、コードを書くことなく、これだけの仕事を捌ききることができて、しかも試行錯誤しやすい環境を提供してくれる Vim には、やはり惚れてしまいますね。