佳木斯湛栽影视文化发展公司

主頁(yè) > 知識(shí)庫(kù) > Powershell ISE的抽象語(yǔ)法樹編程示例

Powershell ISE的抽象語(yǔ)法樹編程示例

熱門標(biāo)簽:Linux服務(wù)器 百度競(jìng)價(jià)排名 地方門戶網(wǎng)站 服務(wù)外包 鐵路電話系統(tǒng) 呼叫中心市場(chǎng)需求 網(wǎng)站排名優(yōu)化 AI電銷

有一個(gè)讓我非常喜歡Windows PowerShell ISE的理由,就是它將它的基礎(chǔ)腳本對(duì)象模型暴露給用戶,這樣就允許用戶按照自己的方式和需要去自定義腳本體驗(yàn)。
自定義ISE的核心是$psISE對(duì)象。$psISE對(duì)象允許用戶去控制ISE許多方面的功能。你可以從這里獲取關(guān)于$psISE的分層對(duì)象模型的介紹,和與這些對(duì)象相關(guān)聯(lián)的功能。

這篇文章會(huì)討論你怎樣利用PowerShell公開提供的解釋器接口,來結(jié)合ISE對(duì)象模型魅力,去創(chuàng)建腳本分析和快速定位的工具。

想象一下,你不得不分析一個(gè)相對(duì)龐大的PowerShell腳本。那這個(gè)腳本可能是別人寫的,也有可能是你自己幾個(gè)月前寫的,扔了好久了。PowerShell ISE已經(jīng)做了件非常棒的工作了,它提供了腳本環(huán)境。你可以通過添加Add-On(附加工具)來擴(kuò)充它的功能,讓你的腳本體驗(yàn)更好,更高效。從PowerShell 3.0開始,腳本的抽象語(yǔ)法樹(AST)就可以使用語(yǔ)法解釋器接口非常方便的獲取了。下面的腳本行會(huì)獲取當(dāng)前打開的ISE中的腳本的AST:

復(fù)制代碼 代碼如下:

$AbstractSyntaxTree = [System.Management.Automation.Language.Parser]::
ParseInput($psISE.CurrentFile.Editor.Text, [ref]$null, [ref]$null)

接下來讓我們查詢腳本中所有的函數(shù):

復(fù)制代碼 代碼如下:

$functionsInFile = $AbstractSyntaxTree.FindAll({$args[0] -is
 [System.Management.Automation.Language.FunctionDefinitionAst]}, $true)

撇開函數(shù)定位的定義,如果我們能回到光標(biāo)之前出現(xiàn)的位置,那將太漂亮了。實(shí)現(xiàn)這個(gè)也非常簡(jiǎn)單。我們所要做的只是存儲(chǔ)這些行號(hào),然后按照反轉(zhuǎn)順序反轉(zhuǎn)他們。(是否有人已經(jīng)知道了,“堆棧”)

下面的腳本塊展示了展示了Go-To Definition的實(shí)現(xiàn)。

復(fù)制代碼 代碼如下:

#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.Stack
 
#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]
 
{
 
}
 
}
 
}

補(bǔ)充一下,Go-To Definition 功能,如果當(dāng)前Powershell會(huì)話中存在的話,以上腳本會(huì)顯示選中文本的定義。(另外,上面的腳本只是一個(gè)簡(jiǎn)單的例子,假如你的“function”關(guān)鍵字和函數(shù)名出現(xiàn)在腳本的同一行。這在PowerShell中并不是必須的,所以如果你的腳本風(fēng)格不同,你可能需要微調(diào)一下邏輯。)

接下來應(yīng)當(dāng)是在Add-on(附加工具)菜單上添加這些腳本,并把它作為選中腳本的一個(gè)命令。下面兩行就可以做這件事。

復(fù)制代碼 代碼如下:

$global:__ISEGoToAddOnsb1 =
{ $global:__ISEGoToAddOnscriptBlockGoTo | Out-Null}
$null=$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add(
"Go do definition", $global:__ISEGoToAddOnsb1, "F12")

現(xiàn)在來看看我們?cè)鯓訉?shí)現(xiàn)Go-Back 功能,使用我們定義的全局堆棧,幾行代碼即可:

復(fù)制代碼 代碼如下:

$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")

就到這里了,只用了一些PowerShell代碼就實(shí)現(xiàn)了Visual Studio中的Go-To Definition (轉(zhuǎn)向定義)和Go-Back(返回)功能。

你還可以繼續(xù)擴(kuò)展這個(gè)腳本,讓它包含這些任務(wù):諸如顯示腳本中所有函數(shù),點(diǎn)擊函數(shù)轉(zhuǎn)到函數(shù)定義。作為大家進(jìn)一步擴(kuò)展功能的鼓勵(lì),我給你看下我的 ISE附加工具現(xiàn)在的樣子。

擴(kuò)展PowerShell ISE 中的 “附加工具”菜單

標(biāo)簽:銅川 湖南 衡水 崇左 黃山 仙桃 湘潭 蘭州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Powershell ISE的抽象語(yǔ)法樹編程示例》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    依兰县| 威信县| 天台县| 津市市| 梁平县| 施秉县| 龙陵县| 灵台县| 万源市| 祁阳县| 平山县| 河间市| 嘉禾县| 佛学| 平邑县| 苍南县| 霍邱县| 同心县| 孝昌县| 红桥区| 张家港市| 疏附县| 新巴尔虎左旗| 扶绥县| 澎湖县| 阿克苏市| 甘肃省| 奇台县| 铜梁县| 西峡县| 特克斯县| 张家界市| 泌阳县| 宜兰县| 大理市| 丰县| 铅山县| 綦江县| 公安县| 平邑县| 遂昌县|