mirror of
https://github.com/tw93/Mole.git
synced 2026-03-24 02:05:07 +00:00
fix(windows): harden visual lookups in logger
This commit is contained in:
@@ -12,41 +12,48 @@ $script:MOLE_BASE_LOADED = $true
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Color Definitions (ANSI escape codes for modern terminals)
|
# Color Definitions (ANSI escape codes for modern terminals)
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
$script:ESC = [char]27
|
function Get-MoleDefaultColors {
|
||||||
$script:DefaultColors = @{
|
$esc = [char]27
|
||||||
Green = "$ESC[0;32m"
|
return @{
|
||||||
Blue = "$ESC[0;34m"
|
Green = "$esc[0;32m"
|
||||||
Cyan = "$ESC[0;36m"
|
Blue = "$esc[0;34m"
|
||||||
Yellow = "$ESC[0;33m"
|
Cyan = "$esc[0;36m"
|
||||||
Purple = "$ESC[0;35m"
|
Yellow = "$esc[0;33m"
|
||||||
PurpleBold = "$ESC[1;35m"
|
Purple = "$esc[0;35m"
|
||||||
Red = "$ESC[0;31m"
|
PurpleBold = "$esc[1;35m"
|
||||||
Gray = "$ESC[0;90m"
|
Red = "$esc[0;31m"
|
||||||
White = "$ESC[0;37m"
|
Gray = "$esc[0;90m"
|
||||||
NC = "$ESC[0m" # No Color / Reset
|
White = "$esc[0;37m"
|
||||||
|
NC = "$esc[0m" # No Color / Reset
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Icon Definitions
|
# Icon Definitions
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
$script:DefaultIcons = @{
|
function Get-MoleDefaultIcons {
|
||||||
Confirm = [char]0x25CE # ◎
|
return @{
|
||||||
Admin = [char]0x2699 # ⚙
|
Confirm = [char]0x25CE # ◎
|
||||||
Success = [char]0x2713 # ✓
|
Admin = [char]0x2699 # ⚙
|
||||||
Error = [char]0x263B # ☻
|
Success = [char]0x2713 # ✓
|
||||||
Warning = [char]0x25CF # ●
|
Error = [char]0x263B # ☻
|
||||||
Empty = [char]0x25CB # ○
|
Warning = [char]0x25CF # ●
|
||||||
Solid = [char]0x25CF # ●
|
Empty = [char]0x25CB # ○
|
||||||
List = [char]0x2022 # •
|
Solid = [char]0x25CF # ●
|
||||||
Arrow = [char]0x27A4 # ➤
|
List = [char]0x2022 # •
|
||||||
DryRun = [char]0x2192 # →
|
Arrow = [char]0x27A4 # ➤
|
||||||
NavUp = [char]0x2191 # ↑
|
DryRun = [char]0x2192 # →
|
||||||
NavDown = [char]0x2193 # ↓
|
NavUp = [char]0x2191 # ↑
|
||||||
Folder = [char]0x25A0 # ■ (folder substitute)
|
NavDown = [char]0x2193 # ↓
|
||||||
File = [char]0x25A1 # □ (file substitute)
|
Folder = [char]0x25A0 # ■ (folder substitute)
|
||||||
Trash = [char]0x2718 # ✘ (trash substitute)
|
File = [char]0x25A1 # □ (file substitute)
|
||||||
|
Trash = [char]0x2718 # ✘ (trash substitute)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$script:DefaultColors = Get-MoleDefaultColors
|
||||||
|
$script:DefaultIcons = Get-MoleDefaultIcons
|
||||||
|
|
||||||
function Get-OrCreateScriptHashtable {
|
function Get-OrCreateScriptHashtable {
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
@@ -63,24 +70,79 @@ function Get-OrCreateScriptHashtable {
|
|||||||
return $table
|
return $table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Get-MoleDefaultHashtable {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[ValidateSet('Colors', 'Icons')]
|
||||||
|
[string]$Name
|
||||||
|
)
|
||||||
|
|
||||||
|
$defaultVariable = Get-Variable -Name "Default$Name" -Scope Script -ErrorAction SilentlyContinue
|
||||||
|
if ($defaultVariable -and $defaultVariable.Value -is [hashtable]) {
|
||||||
|
return $defaultVariable.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($Name) {
|
||||||
|
'Colors' { return Get-MoleDefaultColors }
|
||||||
|
'Icons' { return Get-MoleDefaultIcons }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Initialize-MoleVisualDefaults {
|
function Initialize-MoleVisualDefaults {
|
||||||
|
$defaultColors = Get-MoleDefaultHashtable -Name "Colors"
|
||||||
$colors = Get-OrCreateScriptHashtable -Name "Colors"
|
$colors = Get-OrCreateScriptHashtable -Name "Colors"
|
||||||
|
|
||||||
foreach ($entry in $script:DefaultColors.GetEnumerator()) {
|
foreach ($entry in $defaultColors.GetEnumerator()) {
|
||||||
if (-not $colors.ContainsKey($entry.Key)) {
|
if (-not $colors.ContainsKey($entry.Key)) {
|
||||||
$colors[$entry.Key] = $entry.Value
|
$colors[$entry.Key] = $entry.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$defaultIcons = Get-MoleDefaultHashtable -Name "Icons"
|
||||||
$icons = Get-OrCreateScriptHashtable -Name "Icons"
|
$icons = Get-OrCreateScriptHashtable -Name "Icons"
|
||||||
|
|
||||||
foreach ($entry in $script:DefaultIcons.GetEnumerator()) {
|
foreach ($entry in $defaultIcons.GetEnumerator()) {
|
||||||
if (-not $icons.ContainsKey($entry.Key)) {
|
if (-not $icons.ContainsKey($entry.Key)) {
|
||||||
$icons[$entry.Key] = $entry.Value
|
$icons[$entry.Key] = $entry.Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Get-MoleVisualValue {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[ValidateSet('Colors', 'Icons')]
|
||||||
|
[string]$TableName,
|
||||||
|
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[string]$Key
|
||||||
|
)
|
||||||
|
|
||||||
|
$table = Get-OrCreateScriptHashtable -Name $TableName
|
||||||
|
if (-not $table.ContainsKey($Key)) {
|
||||||
|
$defaults = Get-MoleDefaultHashtable -Name $TableName
|
||||||
|
if ($defaults.ContainsKey($Key)) {
|
||||||
|
$table[$Key] = $defaults[$Key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($table.ContainsKey($Key)) {
|
||||||
|
return $table[$Key]
|
||||||
|
}
|
||||||
|
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-MoleColor {
|
||||||
|
param([Parameter(Mandatory)][string]$Name)
|
||||||
|
return Get-MoleVisualValue -TableName "Colors" -Key $Name
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-MoleIcon {
|
||||||
|
param([Parameter(Mandatory)][string]$Name)
|
||||||
|
return Get-MoleVisualValue -TableName "Icons" -Key $Name
|
||||||
|
}
|
||||||
|
|
||||||
Initialize-MoleVisualDefaults
|
Initialize-MoleVisualDefaults
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ function Write-LogMessage {
|
|||||||
)
|
)
|
||||||
|
|
||||||
$timestamp = Get-Date -Format "HH:mm:ss"
|
$timestamp = Get-Date -Format "HH:mm:ss"
|
||||||
$colorCode = $script:Colors[$Color]
|
$colorCode = Get-MoleColor -Name $Color
|
||||||
$nc = $script:Colors.NC
|
$nc = Get-MoleColor -Name "NC"
|
||||||
|
|
||||||
$formattedIcon = if ($Icon) { "$Icon " } else { "" }
|
$formattedIcon = if ($Icon) { "$Icon " } else { "" }
|
||||||
$output = " ${colorCode}${formattedIcon}${nc}${Message}"
|
$output = " ${colorCode}${formattedIcon}${nc}${Message}"
|
||||||
@@ -60,7 +60,7 @@ function Write-Info {
|
|||||||
Write an informational message
|
Write an informational message
|
||||||
#>
|
#>
|
||||||
param([string]$Message)
|
param([string]$Message)
|
||||||
Write-LogMessage -Message $Message -Level "INFO" -Color "Cyan" -Icon $script:Icons.List
|
Write-LogMessage -Message $Message -Level "INFO" -Color "Cyan" -Icon (Get-MoleIcon -Name "List")
|
||||||
}
|
}
|
||||||
|
|
||||||
function Write-Success {
|
function Write-Success {
|
||||||
@@ -69,7 +69,7 @@ function Write-Success {
|
|||||||
Write a success message
|
Write a success message
|
||||||
#>
|
#>
|
||||||
param([string]$Message)
|
param([string]$Message)
|
||||||
Write-LogMessage -Message $Message -Level "SUCCESS" -Color "Green" -Icon $script:Icons.Success
|
Write-LogMessage -Message $Message -Level "SUCCESS" -Color "Green" -Icon (Get-MoleIcon -Name "Success")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ function Write-MoleWarning {
|
|||||||
Write a warning message
|
Write a warning message
|
||||||
#>
|
#>
|
||||||
param([string]$Message)
|
param([string]$Message)
|
||||||
Write-LogMessage -Message $Message -Level "WARN" -Color "Yellow" -Icon $script:Icons.Warning
|
Write-LogMessage -Message $Message -Level "WARN" -Color "Yellow" -Icon (Get-MoleIcon -Name "Warning")
|
||||||
}
|
}
|
||||||
|
|
||||||
function Write-MoleError {
|
function Write-MoleError {
|
||||||
@@ -88,7 +88,7 @@ function Write-MoleError {
|
|||||||
Write an error message
|
Write an error message
|
||||||
#>
|
#>
|
||||||
param([string]$Message)
|
param([string]$Message)
|
||||||
Write-LogMessage -Message $Message -Level "ERROR" -Color "Red" -Icon $script:Icons.Error
|
Write-LogMessage -Message $Message -Level "ERROR" -Color "Red" -Icon (Get-MoleIcon -Name "Error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -100,8 +100,8 @@ function Write-Debug {
|
|||||||
param([string]$Message)
|
param([string]$Message)
|
||||||
|
|
||||||
if ($script:LogConfig.DebugEnabled) {
|
if ($script:LogConfig.DebugEnabled) {
|
||||||
$gray = $script:Colors.Gray
|
$gray = Get-MoleColor -Name "Gray"
|
||||||
$nc = $script:Colors.NC
|
$nc = Get-MoleColor -Name "NC"
|
||||||
Write-Host " ${gray}[DEBUG] $Message${nc}"
|
Write-Host " ${gray}[DEBUG] $Message${nc}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ function Write-DryRun {
|
|||||||
Write a dry-run message (action that would be taken)
|
Write a dry-run message (action that would be taken)
|
||||||
#>
|
#>
|
||||||
param([string]$Message)
|
param([string]$Message)
|
||||||
Write-LogMessage -Message $Message -Level "DRYRUN" -Color "Yellow" -Icon $script:Icons.DryRun
|
Write-LogMessage -Message $Message -Level "DRYRUN" -Color "Yellow" -Icon (Get-MoleIcon -Name "DryRun")
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -136,9 +136,9 @@ function Start-Section {
|
|||||||
$script:CurrentSection.Activity = $false
|
$script:CurrentSection.Activity = $false
|
||||||
$script:CurrentSection.Name = $Title
|
$script:CurrentSection.Name = $Title
|
||||||
|
|
||||||
$purple = $script:Colors.PurpleBold
|
$purple = Get-MoleColor -Name "PurpleBold"
|
||||||
$nc = $script:Colors.NC
|
$nc = Get-MoleColor -Name "NC"
|
||||||
$arrow = $script:Icons.Arrow
|
$arrow = Get-MoleIcon -Name "Arrow"
|
||||||
|
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "${purple}${arrow} ${Title}${nc}"
|
Write-Host "${purple}${arrow} ${Title}${nc}"
|
||||||
@@ -181,8 +181,8 @@ function Start-Spinner {
|
|||||||
param([string]$Message = "Working...")
|
param([string]$Message = "Working...")
|
||||||
|
|
||||||
$script:SpinnerIndex = 0
|
$script:SpinnerIndex = 0
|
||||||
$gray = $script:Colors.Gray
|
$gray = Get-MoleColor -Name "Gray"
|
||||||
$nc = $script:Colors.NC
|
$nc = Get-MoleColor -Name "NC"
|
||||||
|
|
||||||
Write-Host -NoNewline " ${gray}$($script:SpinnerFrames[0]) $Message${nc}"
|
Write-Host -NoNewline " ${gray}$($script:SpinnerFrames[0]) $Message${nc}"
|
||||||
}
|
}
|
||||||
@@ -196,8 +196,8 @@ function Update-Spinner {
|
|||||||
|
|
||||||
$script:SpinnerIndex = ($script:SpinnerIndex + 1) % $script:SpinnerFrames.Count
|
$script:SpinnerIndex = ($script:SpinnerIndex + 1) % $script:SpinnerFrames.Count
|
||||||
$frame = $script:SpinnerFrames[$script:SpinnerIndex]
|
$frame = $script:SpinnerFrames[$script:SpinnerIndex]
|
||||||
$gray = $script:Colors.Gray
|
$gray = Get-MoleColor -Name "Gray"
|
||||||
$nc = $script:Colors.NC
|
$nc = Get-MoleColor -Name "NC"
|
||||||
|
|
||||||
# Move cursor to beginning of line and clear
|
# Move cursor to beginning of line and clear
|
||||||
Write-Host -NoNewline "`r ${gray}$frame $Message${nc} "
|
Write-Host -NoNewline "`r ${gray}$frame $Message${nc} "
|
||||||
@@ -232,8 +232,8 @@ function Write-Progress {
|
|||||||
$empty = $Width - $filled
|
$empty = $Width - $filled
|
||||||
|
|
||||||
$bar = ("[" + ("=" * $filled) + (" " * $empty) + "]")
|
$bar = ("[" + ("=" * $filled) + (" " * $empty) + "]")
|
||||||
$cyan = $script:Colors.Cyan
|
$cyan = Get-MoleColor -Name "Cyan"
|
||||||
$nc = $script:Colors.NC
|
$nc = Get-MoleColor -Name "NC"
|
||||||
|
|
||||||
Write-Host -NoNewline "`r ${cyan}$bar${nc} ${percent}% $Message "
|
Write-Host -NoNewline "`r ${cyan}$bar${nc} ${percent}% $Message "
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ BeforeAll {
|
|||||||
$script:WindowsDir = Split-Path -Parent $PSScriptRoot
|
$script:WindowsDir = Split-Path -Parent $PSScriptRoot
|
||||||
$script:BinDir = Join-Path $script:WindowsDir "bin"
|
$script:BinDir = Join-Path $script:WindowsDir "bin"
|
||||||
$script:InstallScript = Join-Path $script:WindowsDir "install.ps1"
|
$script:InstallScript = Join-Path $script:WindowsDir "install.ps1"
|
||||||
$script:VisualDefaultsErrorPattern = 'property ''Solid'' cannot be found|找不到属性.?Solid|VariableIsUndefined|\$script:Colors'
|
$script:VisualDefaultsErrorPattern = 'property ''(Solid|Error)'' cannot be found|找不到属性.?(Solid|Error)|VariableIsUndefined|\$script:Colors'
|
||||||
}
|
}
|
||||||
|
|
||||||
Describe "Clean Command" {
|
Describe "Clean Command" {
|
||||||
|
|||||||
@@ -70,6 +70,14 @@ Describe "Base Module" {
|
|||||||
$script:Icons.Solid | Should -Be "*"
|
$script:Icons.Solid | Should -Be "*"
|
||||||
$script:Icons.Admin | Should -Not -BeNullOrEmpty
|
$script:Icons.Admin | Should -Not -BeNullOrEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
It "Should restore missing icon entries on demand" {
|
||||||
|
$script:Icons = @{ Solid = "*" }
|
||||||
|
|
||||||
|
(Get-MoleIcon -Name "Error") | Should -Not -BeNullOrEmpty
|
||||||
|
$script:Icons.Error | Should -Not -BeNullOrEmpty
|
||||||
|
$script:Icons.Solid | Should -Be "*"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context "Test-IsAdmin" {
|
Context "Test-IsAdmin" {
|
||||||
@@ -242,6 +250,19 @@ Describe "Logging Module" {
|
|||||||
# Note: The actual function is Write-MoleError
|
# Note: The actual function is Write-MoleError
|
||||||
{ Write-MoleError "Test message" } | Should -Not -Throw
|
{ Write-MoleError "Test message" } | Should -Not -Throw
|
||||||
}
|
}
|
||||||
|
|
||||||
|
It "Should log errors even when the icon table is partial" {
|
||||||
|
$originalIcons = $script:Icons.Clone()
|
||||||
|
|
||||||
|
try {
|
||||||
|
$script:Icons = @{ Solid = "*" }
|
||||||
|
{ Write-MoleError "Test message" } | Should -Not -Throw
|
||||||
|
$script:Icons.Error | Should -Not -BeNullOrEmpty
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$script:Icons = $originalIcons
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context "Section Functions" {
|
Context "Section Functions" {
|
||||||
|
|||||||
Reference in New Issue
Block a user