ค้นหาเว็บไซต์

กลับมาเยี่ยมชมปฏิทิน 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 สำหรับเพื่อนที่ไม่ใช่ชาวอเมริกัน โปรดแจ้งให้เราทราบว่าวิธีนี้ใช้ได้ผลสำหรับคุณอย่างไร

บทความที่เกี่ยวข้อง