Powershell ISE 抽象構文木 プログラミング例
Windows PowerShell ISEで私が気に入っていることの1つは、その基礎となるスクリプト・オブジェクト・モデルをユーザーに公開していることで、ユーザーは自分のやり方で、自分の思うようにスクリプト体験をカスタマイズすることができます。
ISEのカスタマイズの中心となるのは、$psISEオブジェクトです。psISE オブジェクトを使用すると、ISE の機能の多くの側面を制御することができます。を開始することができます。
ここで
の階層的なオブジェクト・モデル、およびこれらのオブジェクトに関連する機能の紹介をご覧ください。
この記事では、PowerShellの一般公開されているインタプリタインターフェイスを使って、ISEオブジェクトモデルのチャームを組み込み、スクリプト解析やクイックロケーションのためのツールを作成する方法について説明します。
比較的大きなPowerShellスクリプトを解析する必要があると想像してください。PowerShell ISE はすでにスクリプト環境を提供する素晴らしい仕事をしています。アドオンツールを追加することで機能を拡張し、スクリプトをより良く、より効率的に使用することができます。PowerShell 3.0 からは、スクリプトの抽象構文木 (AST) に構文インタプリタインタフェースを使用して簡単にアクセスできるようになりました。次のスクリプト行は、ISE で現在開いているスクリプトの AST をフェッチします。
$AbstractSyntaxTree = [System.Management.Automation.Language.Parser]::
ParseInput($psISE.CurrentFile.Editor.Text, [ref]$null, [ref]$null)
次に、スクリプト内のすべての関数を照会してみましょう。
$functionsInFile = $AbstractSyntaxTree.FindAll({$args[0] -is
[System.Management.Automation.Language.FunctionDefinitionAst]}, $true)
ファンクションポジショニングの定義はさておき、カーソルが以前現れた場所に戻ることができれば、とても素敵です。これも実装は非常に簡単だ。行番号を記憶しておいて、それを逆順にすればいいだけだ。(既にご存知の方もいらっしゃるかと思いますが、"stack")
以下のスクリプトブロックは、Go-To Definitionの実装を示すものである。
#Define some useful global variables
$global:__ISEGoToAddOncurrLine=1
$global:__ISEGoToAddOncurrcol=1
$global:__ISEGoToAddOnlineToGoTo=1
$global:__ISEGoToAddOncolToGoTo=1
#We need two stacks - one each for line and column
$global:__ISEGoToAddOnstackOfLine = New-Object System.Collections.Stack
$global:__ISEGoToAddOnstackOfCol = New-Object System.Collections.
#This script block has the logic for the implementation of the Go-To definition functionality
$global:__ISEGoToAddOnscriptBlockGoTo =
{
$AbstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($psISE.CurrentFile.Editor.Text, [ref]$null, [ref]$ null)
$functionsInFile = $AbstractSyntaxTree.FindAll(
{$args[0] -is[System.Management.Automation.Language.FunctionDefinitionAst]}, $true)
#Get the text of the line where we have the cursor
$str = $psISE.CurrentFile.Editor.CaretLineText
#Store them on the stack for later use
$global:__ISEGoToAddOnstackOfLine.Push($psISE.CurrentFile.Editor.CaretLine)
$global:__ISEGoToAddOnstackOfCol.Push($psISE.CurrentFile.Editor.CaretColumn)
$global:__ISEGoToAddOncurrLine = $global:__ISEGoToAddOnstackOfLine.Peek()
$global:__ISEGoToAddOncurrcol = $global:__ISEGoToAddOnstackOfCol.Peek()
#Get the selected text so that it can be used for searching existing functions
$selectedFunction = $psISE.CurrentFile.Editor.SelectedText
#Ensure that the cursor is somewhere between the word boundaries of the function
$functionsInFile | %{if(($str.Contains($_.name)) `
-and ($global:__ISEGoToAddOncurrcol -ge
$str.IndexOf($_.name)) `
-and ($global:__ISEGoToAddOncurrcol -le
($str.IndexOf($_.name)+$_.name.length))
)
{$selectedFunction = $_.name}
}
if($selectedFunction -ne "")
{
#See if the selected function exists in the current open file
$functionToGoTo = $functionsInFile | ? {$_.name -eq "$selectedFunction"}
$global:__ISEGoToAddOnlineToGoTo = $functionToGoTo.Extent.StartLineNumber
$global:__ISEGoToAddOncolToGoTo = $functionToGoTo.Extent.StartColumnNumber
}
if($functionToGoTo -eq $null)
{
try
{
$comm = Get-Command -Name "$selectedFunction" -ErrorAction SilentlyContinue
$comm.Definition | Out-GridView
}
catch [System.Exception]
{
}
}
else
{
#Select the function definition, assuming the function name immediately follows the keyword 'function'
try
{
$psise.CurrentFile.Editor.Select($global:__ISEGoToAddOnlineToGoTo,
($global:__ISEGoToAddOncolToGoTo+9),
$global:__ISEGoToAddOnlineToGoTo,
($global:__ISEGoToAddOncolToGoTo+8+$selectedFunction.length+1))
}
catch [System.Exception]
{
}
}
}
余談ですが、Go-To Definition関数が現在のPowershellセッションに存在する場合、上記のスクリプトで選択したテキストの定義が表示されます。(また、上記のスクリプトは、"function" キーワードと関数名がスクリプトの同じ行に表示される場合の簡単な例に過ぎません。PowerShellでは必須ではありませんので、スクリプトのスタイルが異なる場合はロジックを微調整する必要があるかもしれません)
次のステップでは、これらのスクリプトをアドオンメニューに追加して、選択したスクリプトのコマンドにする必要があります。次の2行でこれを行います。
$global:__ISEGoToAddOnsb1 =
{& $global:__ISEGoToAddOnscriptBlockGoTo | Out-Null}
$null=$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add(
"Go do definition", $global:__ISEGoToAddOnsb1, "F12")
では、定義したグローバルスタックを使って、Go-Back 機能をどのように実装するか、数行のコードで見てみましょう。
$global:__ISEGoToAddOnscriptBlockGoBack =
{
try
{
#Pop the line and column numbers from the stack to do a reverse traversal
$global:__ISEGoToAddOncurrLine =
$global:__ISEGoToAddOnstackOfLine.Pop()
$global:__ISEGoToAddOncurrcol =
$global:__ISEGoToAddOnstackOfCol.Pop()
$psISE.CurrentFile.Editor.SetCaretPosition(
$global:__ISEGoToAddOncurrLine, $global:__ISEGoToAddOncurrcol)
$psISE.CurrentFile.Editor.SelectCaretLine();
}
catch [System.Exception]
{
}
}
$global:__ISEGoToAddOnsb2 = {& $global:__ISEGoToAddOnscriptBlockGoBack | Out-Null}
$null=$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Go Back",$global:__ISEGoToAddOnsb2, "Shift+F12")
Visual StudioでGo-To DefinitionとGo-Back機能を実装するためのPowerShellのコードは以上です。
このスクリプトを拡張して、スクリプト内のすべての関数を表示したり、関数をクリックして関数定義に移動したりといった作業を継続的に行うことができます。さらに機能を拡張する動機付けとして、私のISEアドオンツールがどのように見えるかをお見せしましょう。
PowerShell ISE の "追加ツール" メニューを拡張する。
関連
-
PowerShell スクリプト ランダムパスワードジェネレータ (ps random password generator)
-
PowerShell 4.0の新コマンドを簡単に紹介します。
-
Win Server 2008 R2のためのPowerShellマネジメント
-
PowerShellでWin-Serverのパフォーマンスを詳細に監視する方法
-
ADユーザーのパスワード属性を一括で変更するPowerShellコード
-
PowerShellを使用して、現在のホストメモリ使用量と合計を取得する方法
-
PowerShell は、現在のスクリプトランタイムによって消費されるメモリの動的フェッチを実装しています。
-
PowerShellで文字列を別行動で表示する2つの方法
-
PowerShell で iso8601 形式の日付と DateTime オブジェクトを交換する例
-
PowerShellで複数ファイルからキーワードを取得する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Powershellを選択すべき10の理由(cmdを捨てるべき)
-
Ubuntu PowerShell詳解(初心者必見チュートリアル)
-
What-ifのためのPowershellエラー処理
-
Powershellディレクトリフォルダ管理権限継承・割り当て方法
-
PowerShellのエスケープ文字とは何ですか?
-
Powershellで定数を定義する方法
-
PowershellでWebServicesをリクエストし、結果をJSON形式で出力する
-
PowerShellでWAVオーディオファイルを再生する
-
Powershellは、ローカルレジストリからすべてのソフトウェア関連付けの拡張子を読み取ります。
-
ネットワーク上のホストの種類を検出するPowerShellスクリプト