กลับมาเยี่ยมชมปฏิทิน PowerShell แล้ว
เมื่อต้นสัปดาห์ที่ผ่านมา ฉันพบตัวอย่างโค้ดเก่าในโฟลเดอร์สคริปต์ของฉัน ซึ่งเผยแพร่ครั้งแรกโดย Lee Holmes เป็นสคริปต์เก่าตั้งแต่ปี 2008 ที่ใช้ PowerShell เพื่อแสดงปฏิทินโดยไม่มีข้อมูลการลางาน ดูเหมือนฉันจะจำได้ว่าฉันพยายามทำสิ่งที่คล้ายกัน — แสดงปฏิทินรายเดือนในคอนโซล เมื่อฉันเจอวิธีแก้ปัญหาที่ดีกว่ามากของ Lee ฉันตัดสินใจที่จะรื้อฟื้นสคริปต์ของเขาและอัปเดต เวอร์ชันใหม่มีฟังก์ชันที่แสดงปฏิทินในคอนโซลของคุณ
สคริปต์ต้นฉบับให้คุณระบุวันที่เริ่มต้นและสิ้นสุดของเดือนที่จะแสดง คุณยังระบุวันที่จะเน้นด้วยเครื่องหมายดอกจันหรือวงเล็บเหลี่ยมได้ด้วย ฉันตัดสินใจลดความซับซ้อนและเก็บเฉพาะโค้ดเพื่อเน้นบางวันด้วยเครื่องหมายดอกจันเท่านั้น ฉันยังตัดสินใจเปลี่ยนโค้ดต้นฉบับซึ่งเป็นสคริปต์ให้เป็นฟังก์ชันขั้นสูงด้วย ไปที่ฟังก์ชัน ทำให้ใช้งานได้ง่ายขึ้น และให้ฉันใช้ประโยชน์จากคุณลักษณะฟังก์ชันขั้นสูง เช่น ชุดพารามิเตอร์ ใช่ ฉันรู้ว่าคุณสามารถใช้คุณสมบัติเหล่านี้มากมายในไฟล์สคริปต์ได้ แต่ฟังก์ชันนี้ทำให้ทุกอย่างง่ายขึ้นมาก ที่จริงแล้ว ตอนนี้เมื่อฉันคิดถึงโค้ดที่ฉันเขียนแล้ว ให้เวลาฉันสักครู่ ฉันจะกลับมา.
ฉันรู้ว่าฉันต้องนำโค้ดมาแปลงเป็นโมดูลที่เหมาะสม ขณะนี้ได้รับการเผยแพร่ไปยัง PowerShell Gallery แล้ว
Install-Module PSCalendar
โมดูลควรทำงานบน PowerShell Core กับทั้งแพลตฟอร์ม Windows และ Linux ฉันไม่มี Mac ให้ทดสอบ สามารถดูซอร์สโค้ดได้ที่ https://github.com/jdhitsolutions/PSCalendar แม้ว่าฉันจะอธิบายบางสิ่งที่นี่
คำสั่งหลักคือ Get-Calendar พฤติกรรมเริ่มต้นคือการแสดงเดือนปัจจุบันและเน้นวันที่ปัจจุบัน
คุณยังสามารถระบุช่วงเดือนได้
ฉันต้องการที่จะระบุเดือนได้ แต่ฉันก็ต้องการคุณค่าเพื่อที่จะคำนึงถึงวัฒนธรรมด้วย ฉันไม่ต้องการฮาร์ดโค้ดแอตทริบิวต์ ValidateSet เพราะนั่นจะบังคับให้ฉันใช้ค่า US ฉันเริ่มต้นเส้นทางการใช้พารามิเตอร์ไดนามิก แต่สิ่งเหล่านี้ไม่เป็นมิตรต่อผู้ใช้มากนัก ดังนั้นฉันจึงเพิ่มตัวเติมข้อความอัตโนมัติให้กับโมดูล
ขณะนี้ PowerShell มีคำสั่งที่เรียกว่า Register-AutoCompleter คำสั่งนี้ช่วยให้คุณสามารถกำหนดโค้ดที่จะช่วยให้คุณเติมค่าพารามิเตอร์ได้อัตโนมัติ คุณอาจเคยเห็นว่าเมื่อคุณพิมพ์ Get-Service ตามด้วยช่องว่างแล้วตามด้วยแท็บ PowerShell จะเติมค่าที่เป็นไปได้โดยอัตโนมัติ คุณสามารถเพิ่มฟังก์ชันเดียวกันนี้ให้กับโค้ดของคุณได้
Register-ArgumentCompleter -CommandName Get-Calendar, Show-Calendar -ParameterName Month -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
#get month names, filtering out blanks
(Get-Culture).DateTimeFormat.MonthNames | Where-object {$_ -match "\w+" -and $_ -match "$WordToComplete"} |
ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_.Trim(), $_.Trim(), 'ParameterValue', $_)
}
}
รหัสนี้คล้ายกับสิ่งที่คุณเห็นมากเมื่อดูวิธีใช้สำหรับ Register-AutoCompleter ในกรณีของฉัน ฉันกำลังกำหนดตัวเติมข้อความอัตโนมัติสำหรับคำสั่ง Get-Calendar และ Show-Calendar (เพิ่มเติมเกี่ยวกับเรื่องนี้ในภายหลัง) ซึ่งทั้งคู่มีชื่อพารามิเตอร์เป็น Month scriptblock นั้นเป็นฟังก์ชันที่จะถูกดำเนินการเป็นหลัก เท่าที่ฉันสามารถบอกได้ให้ใช้พารามิเตอร์กับ scriptblock อย่างที่ฉันมีที่นี่ มีเอกสารประกอบน้อยมากเกี่ยวกับคำสั่งนี้ ดังนั้นฉันจึงทำงานจากตัวอย่าง ส่วนแรกของ scriptblock คือการรับชื่อเดือนเฉพาะวัฒนธรรม ในคอมพิวเตอร์ของฉัน ฉันมีช่องว่างอยู่บ้าง ดังนั้นฉันจึงกรองไปที่ Where-Object เพื่อเก็บเฉพาะค่าที่มีอักขระคำเท่านั้น ฉันยังใช้ตัวแปร/พารามิเตอร์ $WordToComplete ด้วย เมื่อฉันเรียกใช้ Get-Calendar -Month และเริ่มกด Tab PowerShell จะเริ่มต้นด้วยรายการแรกในรายการ มกราคม แต่ถ้าฉันพิมพ์ “ju” แล้วกดแท็บ PowerShell จะข้ามไปที่ “มิถุนายน” “ju” จะกลายเป็นค่าของ $WordToComplete ชื่อเดือนแต่ละเดือนจะถูกเพิ่มเป็นผลสำเร็จ พารามิเตอร์ ได้แก่ CompletionText, ListItemText,ResultType (ซึ่งเป็นค่าพารามิเตอร์) และ ToolTip
ฉันทำสิ่งที่คล้ายกับพารามิเตอร์ -Year เพื่อแสดงปีปัจจุบันบวกอีก 5 ปีถัดไป
Register-ArgumentCompleter -CommandName Get-Calendar, Show-Calendar -ParameterName Year -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
$first = (Get-Date).Year
$last = (Get-Date).AddYears(5).Year
$first..$last |
ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}
นี่คือสิ่งที่ดูเหมือน:
ในปัจจุบัน ไม่มีอะไรขัดขวางผู้ใช้จากการเข้าสู่เดือนที่ไม่ถูกต้อง แต่ฉันคิดว่าการเติมข้อความอัตโนมัติจะให้คำแนะนำ ถึงกระนั้น ฉันจะย้อนกลับไปในบางจุดและเพิ่มการจัดการข้อผิดพลาดเพิ่มเติมสำหรับเดือนที่ไม่ถูกต้อง
โอ้และคำสั่งยังให้คุณเน้นวันที่หนึ่งวันขึ้นไป
แต่ฉันรักสี ดังนั้นฉันจึงเขียนฟังก์ชัน "wrapper" ที่เรียกว่า Show-Calendar ซึ่งใช้พารามิเตอร์เดียวกัน แต่ใช้ Write-Host เพื่อเขียนเวอร์ชันที่มีสีลงในคอนโซล
Get-Calendar เขียนสตริงไปยังไปป์ไลน์ ดังนั้นความท้าทายที่ฉันมีคือการเปลี่ยนสตริงให้เป็นอาร์เรย์ของสตริงและเขียนแต่ละบรรทัดกลับโดยใช้ Write-Host ส่วนที่ยากที่สุดคือการระบุวันที่มีเครื่องหมายดอกจันเพื่อที่ฉันจะได้แสดงวันเหล่านั้นเป็นสีไฮไลต์ได้ สิ่งนี้ต้องใช้เวทย์มนตร์การแสดงออกปกติเล็กน้อย
$cal = Get-Calendar @PSBoundParameters
#turn the calendar into an array of strings
$calarray = $cal.split("`n")
# a regular expression pattern to match on highlighted days
[regex]$m = "(\*)?[\s|\*]\d{1,2}(\*)?"
foreach ($line in $calarray) {
if ($line -match "\d{4}") {
write-Host $line -ForegroundColor Yellow
}
elseif ($line -match "\w{3}|-{3}") {
Write-Host $line -ForegroundColor cyan
}
elseif ($line -match "\*") {
#write-host $line -foregroundcolor Magenta
$week = $line
$m.Matches($week).Value| foreach-object {
$day = "$_"
if ($day -match "\*") {
write-host "$($day.replace('*','').padleft(3," ")) " -NoNewline -ForegroundColor $HighlightColor
}
else {
write-host "$($day.PadLeft(3," ")) " -nonewline
}
}
write-host ""
}
else {
Write-host $line
}
}
แต่ตอนนี้ฉันสามารถใช้มันได้ดังนี้:
ฉันใช้ Show-Calendar ในสคริปต์โปรไฟล์ PowerShell ของฉันพร้อมกับโค้ดอื่นๆ เพื่อเน้นวันสำคัญที่กำลังจะมาถึง
ฉันหวังว่านี่จะแสดงให้คุณเห็นว่าโค้ดเก่ายังคงสามารถตอบสนองวัตถุประสงค์ได้ ลองใช้โมดูลนี้แล้วแจ้งให้เราทราบว่าคุณคิดอย่างไร ใช้ repo Github เพื่อรายงานปัญหาใดๆ
สนุก!
อัปเดต: ฉันกังวลว่าอาจมีปัญหากับรหัสนี้ในวัฒนธรรมอื่นและดูเหมือนว่าจะเป็นเช่นนั้น ถือเป็นการทดสอบและพัฒนากับวัฒนธรรมอื่นๆ ที่ท้าทาย แต่ฉันได้แจ้งปัญหากับตัวเองแล้วและจะตรวจสอบเพิ่มเติม
อัปเดต #2: ฉันได้ผลัก v1.2.0 ไปที่ PowerShell Gallery แล้ว ฉันกำลังพิจารณาการตัดสินใจทางวัฒนธรรมจำนวนหนึ่งตามคุณค่าทางวัฒนธรรมจาก [system.threading.thread]::CurrentThread สำหรับเพื่อนที่ไม่ใช่ชาวอเมริกัน โปรดแจ้งให้เราทราบว่าวิธีนี้ใช้ได้ผลสำหรับคุณอย่างไร