この章では、第 2 章「サンプル・スクリプト」で説明したものよりも、さらに複雑なスクリプトについて説明します。非常に長いので、スクリプト全体の一覧は付録 C 「script_find スクリプト」 に掲載します。このマニュアルは、Korn シェル・プログラミングのチュートリアルではありませんので注意してください。Korn シェル・プログラミングに慣れていない方は、『Korn シェル・プログラミング』のマニュアルを取り寄せて、参照してください。
スクリプト script_find は、dtksh を使用して find コマンドに対するグラフィカル・インタフェースを提供する方法について図示します。script_find は、find コマンドのパラメータを指定できるウィンドウを作成します。スクリプトに関して完全に理解するには、find コマンドをよく理解し、マニュアル・ページを使用可能にしておく必要があります。script_find によって作成されたウィンドウにある多数のトグル・ボタン・メニュー選択には、find コマンドについての知識が多少必要です。
スクリプトのウィンドウで、検索ディレクトリとファイル名を指定できます。他のオプションを使用すると、検索用のファイル・システムの型とそれに一致するファイル型を制限できます。図 4-1 は、スクリプトのウィンドウを示します。
探したい検索ディレクトリとファイル名をウィンドウの上部のテキスト・フィールドに入力します。さらに、5 個のトグル・ボタンから適用可能な選択を選びます。オプション・メニュー内で検索をさらに制限できます。必要な選択をすべて行なってから、[了解] をクリックします。すべてうまくいった場合は、その後すぐにウィンドウが表示され、find 処理の結果を表示します。検索ディレクトリやファイル名を指定しない場合、または指定された検索ディレクトリが無効な場合は、エラー・ダイアログが表示されます。たとえば、two_letter_calls という名前のファイルが、ディレクトリ /users/dlm の下のどこにあるのか見つけようとします。[検索ディレクトリ] テキスト・フィールドにディレクトリを入力するときに、/users/dlm の代わりに誤って /users/dln と入力したとします。[了解] または [適用] をクリックすると、script_find はディレクトリ /users/dln を見つけることができないので、エラー・ダイアログを作成してユーザに通知します。
ミスを訂正すると、script_find はその後適切に実行され、ファイルが見つかった場合に要求したファイルの絶対パスを表示する dtterm ウィンドウを作成します。
script_find が指定のディレクトリにファイルを見つけることができなかった場合は、dtterm ウィンドウには何も表示されません。
script_find の構造は、C プログラムに似ています。つまり、いくつかの関数とコールバックが最初に表示され、次にメイン・スクリプトが表示されます。
スクリプトの最初の 2 行が重要で、全ての dtksh スクリプトに取り込む必要があります。
#! /usr/dt/bin/dtksh . /usr/dt/lib/dtksh/DtFunc.dtsh
1 行目は dtksh システムを実行し、2 行目は dtksh 簡易関数をロードします。2 行目は、第 2 章「サンプル・スクリプト」で説明しているスクリプトでは使用されていません。これは、それらのスクリプトでは dtksh 簡易関数を使用しないためです。
script_find には、次のような関数とコールバックがあります。
PostErrorDialog()
OkCallback()
LoadStickyValues()
EvalCmd()
RetrieveAndSaveCurrentValues()
この関数は、ユーザが無効なディレクトリを入力するなどのエラー検出時に呼び出されます。この関数は簡易関数 DtkshDisplayErrorDialog() を呼び出しますが、この簡易関数はタイトルが [検索エラー] で、呼び出し位置から渡される変数 $1 にメッセージが格納されるダイアログ・ボックスを表示します。
dialogPostErrorDialog() { DtDisplayErrorDialog "Find Error" "$1" ¥ DIALOG_PRIMARY_APPLICATION_MODAL }
最後のパラメータ DIALOG_PRIMARY_APPLICATION_MODAL は、他の対話が発生する前に応答しなければならないダイアログを作成するように dtksh に通知します。
OkCallback()は、script_find メイン・ウィンドウの [了解] か [適用] ボタンが押されたときに呼び出されます。[了解] ボタンが押されると、script_find ウィンドウは管理から除外されます。[適用] か [了解] のどちらかに対して、入力検索ディレクトリは妥当性検査をされます。無効な場合は、OkCallback() は PostErrorDialog() を呼び出します。有効な場合は、script_find ウィンドウのトグル・ボタンのステータスについて検査が行われ、そのステータスに対応した調整が変数 $CMD に対して行われます。この変数には、最後に実行されるコマンド全体が含まれています。
この関数は、ウィンドウが作成され管理されるようになった後でメイン・プログラムから呼び出されます。スクリプトの最新の実行結果からすべての値をロードします。これらの値は、関数 RetrieveAndSaveCurrentValues() によって Find.sticky と呼ばれるファイルに保存されます。
EvalCmd() は LoadStickyValues() によって使用され、dtksh コマンドとして Find.sticdky にある各行の評価をします。Find.sticky ファイルの内容を次に示します。
XmTextSetString $SD "/users/dlm" XmTextFieldSetInsertionPosition $SD 10 XmTextSetString $FNP "two_letter_calls" XmTextFieldSetInsertionPosition $FNP 16 XtSetValues $FSTYPE menuHistory:$NODIR XtSetValues $FILETYPE menuHistory:$NOTYPE XmToggleButtonSetState $T2 true false XmToggleButtonSetState $T4 true false
RetrieveAndSaveCurrentValues() は script_find ウィンドウにあるウィジェットの現在の設定と値を検索し、それらをファイル Find.sticky に保存します。Find.sticky は、スクリプトが実行された後に引き続き LoadStickyValues()によって使用されます。
スクリプトの残りは、C プログラムの Main() と同等なものです。Xt イントリンシクスを初期化し、script_find ウィンドウで使用されているすべてのウィジェットを作成します。1 行目にある set -f は、パス名にあるワイルドカード文字の拡張を禁止するように dtksh に通知します。これは、find コマンドがこの拡張を実行できるようにするために必要です。
script_find ウィンドウ (図 4-4 参照) は、4 つの領域から成る Form ウィジェットです。領域は Separator ウィジェットによってマークされ、各領域にはいくつかのウィジェットがあり、それらはすべて Form の子になります。
ウィジェットは、上部から下部に順番に領域ごとに作成されます。
初期化は、次のように Xt イントリンシクス関数 XtInitialize によって行われます。
XtInitialize TOPLEVEL find Dtksh $0 "${@:-}"
これにより、次に作成される Form ウィジェットの親として機能するトップレベルのシェルを作成します。
Form ウィジェットは、メインの親ウィジェットとして使用されます。Form は、ユーザがその子に制約を課することができるようにする Manager ウィジェットです。script_find メイン・ウィンドウにあるほとんどのウィジェットは、Form の子です。ウィジェットの残りの部分の作成についての記述は、ウィンドウの 4 つの領域 (図 4-4 参照) ごとに分かれています。
1 番目の領域は、2 つの Label ウィジェットと 2 つの TextField ウィジェット、および1 番目と 2 番目の領域を分割する Separator ウィジェットから成ります。
次のコード・セグメントは、1 番目の Label ウィジェットを作成してから位置付け、DtkshAnchorTop 簡易関数と DtkshAnchorLeft 簡易関数を使用して Form 内にそのウィジェットを位置付けます。
XtCreateManagedWidget SDLABEL sdlabel XmLabel $FORM ¥ labelString:"Search Directory:" ¥ $(DtkshAnchorTop 12) ¥ $(DtkshAnchorLeft 10)
次のコード・セグメントは、1 番目の TextField ウィジェットを作成してから位置付けます。このウィジェットは、Form ウィジェットと Label ウィジェットの両方に関連のある場所に位置付けられるので注意してください。
XtCreateManagedWidget SD sd XmText $FORM ¥ columns:30 ¥ value:"." ¥ $(DtkshAnchorTop 6) ¥ $(DtkshRightOf $SDLABEL 10) ¥ $(DtkshAnchorRight 10) ¥ navigationType:EXCLUSIVE_TAB_GROUP XmTextFieldSetInsertionPosition $SD 1
残りの Label ウィジェットと TextField ウィジェットも同じ方法で作成されます。
Separator ウィジェットは、Form ウィジェットの子として作成され、2 番目の TextField ウィジェットの下に位置付けられます。
XtCreateManagedWidget SEP sep XmSeparator $FORM ¥ separatorType:SINGLE_DASHED_LINE ¥ $(DtkshUnder $FNP 10) ¥ $(DtkshSpanWidth)
2 番目の領域は、RowColumn ウィジェットと 5 つの ToggleButton ウィジェット、および 1 番目のとは別の Separator ウィジェットから成ります。
ガジェットは、その属性の多くをその親に依存するウィジェットなので、メモリ・リソースを節約できます。
RowColumn ウィジェットは、Form ウィジェットの子として作成され、1 番目の領域で作成された Separator ウィジェットの直下に位置付けられます。
XtCreateManagedWidget RC rc XmRowColumn $FORM ¥ orientation:HORIZONTAL ¥ numColumns:3 ¥ packing:PACK_COLUMN ¥ $(DtkshUnder $SEP 10) ¥ $(DtkshSpanWidth 10 10) ¥ navigationType:EXCLUSIVE_TAB_GROUP
5 つの ToggleButton ガジェットは、次のように簡易関数 DtkshAddButtons を使用して RowColumn の子として作成されます。
DtkshAddButtons -w $RC XmToggleButtonGadget ¥ T1 "Cross Mount Points" ""¥ T2 "Print Matching Filenames" ""¥ T3 "Search Hidden Subdirectories" ""¥ T4 "Follow Symbolic Links" ""¥ T5 "Descend Subdirectories First" ""
1 番目とは別の Separator が次に作成され、2 番目と 3 番目の領域を分割します。この Separator ウィジェット ID は SEP2 と呼ばれていますので注意してください。
XtCreateManagedWidget SEP2 sep XmSeparator $FORM ¥ separatorType:SINGLE_DASHED_LINE ¥ $(DtkshUnder $RC 10) ¥ $(DtkshSpanWidth)
3 番目の領域は、2 つのオプション・メニューともう一つの Separator ウィジェットから成ります。
オプション・メニューは、プルダウン・メニューです。オプション・メニュー・ボタンをクリックすると、多数の選択肢のあるメニュー区画が表示されます。適切な選択肢へポインタをドラッグし、マウス・ボタンを離してください。メニュー区画が消え、オプション・メニュー・ボタン・ラベルが新規の選択肢を表示します。
最初のオプション・メニューのメニュー区画は、多数のプッシュ・ボタン・ガジェットから成り、find コマンドに強制するさまざまな制限を表示します。
XmCreatePulldownMenu PANE $FORM pane DtkshAddButtons -w $PANE XmPushButtonGadget ¥ NODIR "no restrictions" ""¥ NFS "nfs" ""¥ CDFS "cdfs" ""¥ HFS "hfs" "" Next, the Option Menu button itself is created and managed, with the menu pane just created ($PANE) identified as a subMenuId: XmCreateOptionMenu FSTYPE $FORM fstype ¥ labelString:"Restrict Search To File System Type:" ¥ menuHistory:$NODIR ¥ subMenuId:$PANE ¥ $(DtkshUnder $SEP2 20) ¥ $(DtkshSpanWidth 10 10) ¥ navigationType:EXCLUSIVE_TAB_GROUP XtManageChild $FSTYPE
2 番目のオプション・メニュー・ボタンも同じ方法で作成されます。このボタンは find コマンドにさらに制限を加えます。
3 番目のセパレータは、他のセパレータと同じ方法で作成されます。
4 番目の領域は、Form ウィジェットの子である 4 つのプッシュ・ボタンから成ります。
4 つのプッシュ・ボタンは次のように使用されます。
[了解] は、script_find ウィンドウに入力されたパラメータで find コマンドを実行し、script_find ウィンドウを削除します。
[適用] は、script_find ウィンドウに入力されたパラメータで find コマンドを実行しますが、script_find ウィンドウは削除しません。
[閉じる] は、find コマンドを実行しないで script_find を終了します。
[ヘルプ] は、script_find の使用に関する情報が入っているダイアログ・ボックスを作成します。
プッシュ・ボタンは、それぞれ別にラベル付けされますが、他のウィジェットのボタンとほとんど同じ方法で作成され、位置付けられます。次のコード・セグメントは [了解] プッシュ・ボタンの作成方法を示します。
XtCreateManagedWidget OK ok XmPushButton $FORM ¥ labelString:"Ok" ¥ $(DtkshUnder $SEP3 10) ¥ $(DtkshFloatLeft 4) ¥ $(DtkshFloatRight 24) ¥ $(DtkshAnchorBottom 10) XtAddCallback $OK activateCallback "OkCallback"
XtSetValues は、最初のオペレーティング・パラメータのいくつかを設定するために使用されます。
XtSetValues $FORM ¥ initialFocus:$SD ¥ defaultButton:$OK ¥ cancelButton:$CLOSE ¥ navigationType:EXCLUSIVE_TAB_GROUP
初期のフォーカスは、1 番目の領域の最初の TextField ウィジェットに設定されます。
デフォルトのボタンには、4 番目の領域の [了解] プッシュ・ボタンが設定されます。
取消しのボタンには、4 番目の領域の [閉じる] ボタンが設定されます。
ナビゲーション型には、EXCLUSIVE_TAB_GROUP が設定されます。
次の行は、リターン・キーを押しても Form 内のデフォルト・ボタンを起動しないように TextField ウィジェットを構成しています。その使用の詳細は、付録 B 「dtksh 簡易関数」 の EXCLUSIVE_TAB_GROUP についての説明を参照してください。
DtkshSetReturnKeyControls $SD $FNP $FORM $OK
スクリプトの最後の 3 行は、script_find ウィンドウの前の値をロードし、トップレベルのウィジェットを認識し、次にユーザ入力を待っているループに入ります。
LoadStickyValues XtRealizeWidget $TOPLEVEL XtMainLoop