Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,32 @@ Get-ChildItem | Format-List
Get-ChildItem | Format-Wide
```

## PowerShell Remoting Support

Terminal-Icons now supports displaying icons for file and folder objects returned from remote PowerShell sessions. When you use `Invoke-Command` or `Enter-PSSession` to retrieve directory listings from remote machines, the objects are automatically deserialized during transmission. Terminal-Icons handles these deserialized objects seamlessly.

### Examples

Display files from a remote server:
```powershell
Invoke-Command -ComputerName Server01 -ScriptBlock { Get-ChildItem C:\Logs }
```

Use with Format-TerminalIcons directly:
```powershell
Invoke-Command -ComputerName Server01 -ScriptBlock { Get-ChildItem } | Format-TerminalIcons
```

Interactive remote session:
```powershell
Enter-PSSession -ComputerName Server01
Get-ChildItem # Icons will display automatically
```

### How It Works

PowerShell remoting serializes objects when sending them across the network. FileSystemInfo objects (DirectoryInfo and FileInfo) become `Deserialized.System.IO.DirectoryInfo` and `Deserialized.System.IO.FileInfo` objects. Terminal-Icons automatically detects and handles these deserialized objects, ensuring icons display correctly regardless of whether the files are local or remote.

## Commands

| Command | Description
Expand Down
2 changes: 2 additions & 0 deletions Terminal-Icons/Data/colorThemes/devblackops.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Name = 'devblackops'
Types = @{
Directories = @{
'' = '4682B4' # Default directory color (steel blue)
symlink = '7373ff'
junction = '7373ff'
WellKnown = @{
Expand Down Expand Up @@ -53,6 +54,7 @@
}
}
Files = @{
'' = 'D3D3D3' # Default file color (light gray)
symlink = '7373ff'
junction = '7373ff'
WellKnown = @{
Expand Down
15 changes: 15 additions & 0 deletions Terminal-Icons/Private/ConvertTo-ColorSequence.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@ function ConvertTo-ColorSequence {
if ($ColorData.Types.Directories['junction']) {
$cs.Types.Directories['junction'] = ConvertFrom-RGBColor -RGB $ColorData.Types.Directories['junction']
}
# Process WellKnown directory names
$ColorData.Types.Directories.WellKnown.GetEnumerator().ForEach({
$cs.Types.Directories[$_.Name] = ConvertFrom-RGBColor -RGB $_.Value
})
# Process default directory color if present
if ($ColorData.Types.Directories.ContainsKey('') -and $ColorData.Types.Directories['']) {
$defaultColor = $ColorData.Types.Directories['']
if ($defaultColor -is [string] -and $defaultColor -match '^[0-9A-Fa-f]{6}$') {
$cs.Types.Directories[''] = ConvertFrom-RGBColor -RGB $defaultColor
}
}

# Wellknown files
if ($ColorData.Types.Files['symlink']) {
Expand All @@ -35,6 +43,13 @@ function ConvertTo-ColorSequence {
$ColorData.Types.Files.GetEnumerator().Where({$_.Name -ne 'WellKnown' -and $_.Name -ne ''}).ForEach({
$cs.Types.Files[$_.Name] = ConvertFrom-RGBColor -RGB $_.Value
})
# Process default file color if present
if ($ColorData.Types.Files.ContainsKey('') -and $ColorData.Types.Files['']) {
$defaultColor = $ColorData.Types.Files['']
if ($defaultColor -is [string] -and $defaultColor -match '^[0-9A-Fa-f]{6}$') {
$cs.Types.Files[''] = ConvertFrom-RGBColor -RGB $defaultColor
}
}

$cs
}
Expand Down
97 changes: 74 additions & 23 deletions Terminal-Icons/Private/Resolve-Icon.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@ function Resolve-Icon {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[IO.FileSystemInfo]$FileInfo,
[ValidateScript({
# Accept both local FileSystemInfo objects and deserialized objects from remoting
if ($_ -is [IO.FileSystemInfo]) {
return $true
}
# Check TypeNames array for deserialized objects
$matches = $_.PSObject.TypeNames -match '^Deserialized\.System\.IO\.(DirectoryInfo|FileInfo)$'
return ($null -ne $matches -and $matches.Count -gt 0)
})]
[PSObject]$FileInfo,

[string]$IconTheme = $script:userThemeData.CurrentIconTheme,

Expand All @@ -22,13 +31,40 @@ function Resolve-Icon {
Target = ''
}

if ($FileInfo.PSIsContainer) {
# Safe property access for both local and deserialized objects
$isContainer = if ($FileInfo.PSObject.Properties['PSIsContainer']) {
$FileInfo.PSIsContainer
} else {
$false
}
$linkType = if ($FileInfo.PSObject.Properties['LinkType']) {
$FileInfo.LinkType
} else {
$null
}
$target = if ($FileInfo.PSObject.Properties['Target']) {
$FileInfo.Target
} else {
$null
}
$name = if ($FileInfo.PSObject.Properties['Name']) {
$FileInfo.Name
} else {
''
}
$extension = if ($FileInfo.PSObject.Properties['Extension']) {
$FileInfo.Extension
} else {
''
}

if ($isContainer) {
$type = 'Directories'
} else {
$type = 'Files'
}

switch ($FileInfo.LinkType) {
switch ($linkType) {
# Determine symlink or junction icon and color
'Junction' {
if ($icons) {
Expand All @@ -41,7 +77,9 @@ function Resolve-Icon {
} else {
$colorSet = $script:colorReset
}
$displayInfo['Target'] = ' ' + $glyphs['nf-md-arrow_right_thick'] + ' ' + $FileInfo.Target
if ($target) {
$displayInfo['Target'] = ' ' + $glyphs['nf-md-arrow_right_thick'] + ' ' + $target
}
break
}
'SymbolicLink' {
Expand All @@ -55,23 +93,25 @@ function Resolve-Icon {
} else {
$colorSet = $script:colorReset
}
$displayInfo['Target'] = ' ' + $glyphs['nf-md-arrow_right_thick'] + ' ' + $FileInfo.Target
if ($target) {
$displayInfo['Target'] = ' ' + $glyphs['nf-md-arrow_right_thick'] + ' ' + $target
}
break
} default {
if ($icons) {
# Determine normal directory icon and color
$iconName = $icons.Types.$type.WellKnown[$FileInfo.Name]
$iconName = $icons.Types.$type.WellKnown[$name]
if (-not $iconName) {
if ($FileInfo.PSIsContainer) {
$iconName = $icons.Types.$type[$FileInfo.Name]
} elseif ($icons.Types.$type.ContainsKey($FileInfo.Extension)) {
$iconName = $icons.Types.$type[$FileInfo.Extension]
if ($isContainer) {
$iconName = $icons.Types.$type[$name]
} elseif ($icons.Types.$type.ContainsKey($extension)) {
$iconName = $icons.Types.$type[$extension]
} else {
# File probably has multiple extensions
# Fallback to computing the full extension
$firstDot = $FileInfo.Name.IndexOf('.')
$firstDot = $name.IndexOf('.')
if ($firstDot -ne -1) {
$fullExtension = $FileInfo.Name.Substring($firstDot)
$fullExtension = $name.Substring($firstDot)
$iconName = $icons.Types.$type[$fullExtension]
}
}
Expand All @@ -81,7 +121,7 @@ function Resolve-Icon {

# Fallback if everything has gone horribly wrong
if (-not $iconName) {
if ($FileInfo.PSIsContainer) {
if ($isContainer) {
$iconName = 'nf-oct-file_directory'
} else {
$iconName = 'nf-fa-file'
Expand All @@ -92,32 +132,43 @@ function Resolve-Icon {
$iconName = $null
}
if ($colors) {
$colorSeq = $colors.Types.$type.WellKnown[$FileInfo.Name]
$colorSeq = $colors.Types.$type.WellKnown[$name]
if (-not $colorSeq) {
if ($FileInfo.PSIsContainer) {
$colorSeq = $colors.Types.$type[$FileInfo.Name]
} elseif ($colors.Types.$type.ContainsKey($FileInfo.Extension)) {
$colorSeq = $colors.Types.$type[$FileInfo.Extension]
if ($isContainer) {
$colorSeq = $colors.Types.$type[$name]
} elseif ($colors.Types.$type.ContainsKey($extension)) {
$colorSeq = $colors.Types.$type[$extension]
} else {
# File probably has multiple extensions
# Fallback to computing the full extension
$firstDot = $FileInfo.Name.IndexOf('.')
$firstDot = $name.IndexOf('.')
if ($firstDot -ne -1) {
$fullExtension = $FileInfo.Name.Substring($firstDot)
$fullExtension = $name.Substring($firstDot)
$colorSeq = $colors.Types.$type[$fullExtension]
}
}
if (-not $colorSeq) {
$colorSeq = $colors.Types.$type['']
}

# Fallback if everything has gone horribly wrong
# Final fallback: use hardcoded default colors
if (-not $colorSeq) {
$colorSeq = $script:colorReset
if ($isContainer) {
# Default directory color: steel blue
$colorSeq = "${script:escape}[38;2;70;130;180m"
} else {
# Default file color: light gray
$colorSeq = "${script:escape}[38;2;211;211;211m"
}
}
}
} else {
$colorSeq = $script:colorReset
# No theme colors available: use default colors
if ($isContainer) {
$colorSeq = "${script:escape}[38;2;70;130;180m"
} else {
$colorSeq = "${script:escape}[38;2;211;211;211m"
}
}
}
}
Expand Down
32 changes: 32 additions & 0 deletions Terminal-Icons/Private/Test-DeserializedFileSystemInfo.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
function Test-DeserializedFileSystemInfo {
<#
.SYNOPSIS
Tests if an object is a deserialized FileSystemInfo object from PowerShell remoting.
.DESCRIPTION
When FileSystemInfo objects (DirectoryInfo/FileInfo) are passed through PowerShell remoting,
they are deserialized and their type names are prefixed with "Deserialized.".
This function detects such objects to enable special handling.
.PARAMETER InputObject
The object to test for deserialization.
.OUTPUTS
System.Boolean
Returns $true if the object is a deserialized FileSystemInfo object, $false otherwise.
.EXAMPLE
Test-DeserializedFileSystemInfo $fileObject
Returns $true if $fileObject came from a remote session.
#>
[OutputType([bool])]
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[PSObject]$InputObject
)

process {
$typeNames = $InputObject.PSObject.TypeNames
# -match on an array returns matching items, not a boolean
# We need to explicitly check and return a boolean
$matches = $typeNames -match '^Deserialized\.System\.IO\.(DirectoryInfo|FileInfo)$'
return ($null -ne $matches -and $matches.Count -gt 0)
}
}
14 changes: 12 additions & 2 deletions Terminal-Icons/Public/Format-TerminalIcons.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ function Format-TerminalIcons {
.INPUTS
System.IO.FileSystemInfo

You can pipe an objects that derive from System.IO.FileSystemInfo (System.IO.DIrectoryInfo and System.IO.FileInfo) to 'Format-TerminalIcons'.
You can pipe objects that derive from System.IO.FileSystemInfo (System.IO.DirectoryInfo and System.IO.FileInfo) to 'Format-TerminalIcons'.
Also supports deserialized FileSystemInfo objects from PowerShell remoting sessions.
.OUTPUTS
System.String

Expand All @@ -28,7 +29,16 @@ function Format-TerminalIcons {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[IO.FileSystemInfo]$FileInfo
[ValidateScript({
# Accept both local FileSystemInfo objects and deserialized objects from remoting
if ($_ -is [IO.FileSystemInfo]) {
return $true
}
# Check TypeNames array for deserialized objects
$matches = $_.PSObject.TypeNames -match '^Deserialized\.System\.IO\.(DirectoryInfo|FileInfo)$'
return ($null -ne $matches -and $matches.Count -gt 0)
})]
[PSObject]$FileInfo
)

process {
Expand Down
2 changes: 2 additions & 0 deletions Terminal-Icons/Terminal-Icons.format.ps1xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ https://github.com/DHowett/DirColors -->
<Types>
<TypeName>System.IO.DirectoryInfo</TypeName>
<TypeName>System.IO.FileInfo</TypeName>
<TypeName>Deserialized.System.IO.DirectoryInfo</TypeName>
<TypeName>Deserialized.System.IO.FileInfo</TypeName>
</Types>
</SelectionSet>
</SelectionSets>
Expand Down
21 changes: 19 additions & 2 deletions docs/en-US/Add-TerminalIconsColorTheme.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ Add a Terminal-Icons color theme for the current user.

### Path (Default)
```
Add-TerminalIconsColorTheme [-Path] <String[]> [-Force] [-WhatIf] [-Confirm] [<CommonParameters>]
Add-TerminalIconsColorTheme [-Path] <String[]> [-Force] [-ProgressAction <ActionPreference>] [-WhatIf]
[-Confirm] [<CommonParameters>]
```

### LiteralPath
```
Add-TerminalIconsColorTheme [-LiteralPath] <String[]> [-Force] [-WhatIf] [-Confirm] [<CommonParameters>]
Add-TerminalIconsColorTheme [-LiteralPath] <String[]> [-Force] [-ProgressAction <ActionPreference>] [-WhatIf]
[-Confirm] [<CommonParameters>]
```

## DESCRIPTION
Expand Down Expand Up @@ -122,6 +124,21 @@ Accept pipeline input: False
Accept wildcard characters: False
```

### -ProgressAction
{{ Fill ProgressAction Description }}

```yaml
Type: ActionPreference
Parameter Sets: (All)
Aliases: proga

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).

Expand Down
21 changes: 19 additions & 2 deletions docs/en-US/Add-TerminalIconsIconTheme.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ Add a Terminal-Icons icon theme for the current user.

### Path (Default)
```
Add-TerminalIconsIconTheme [-Path] <String[]> [-Force] [-WhatIf] [-Confirm] [<CommonParameters>]
Add-TerminalIconsIconTheme [-Path] <String[]> [-Force] [-ProgressAction <ActionPreference>] [-WhatIf]
[-Confirm] [<CommonParameters>]
```

### LiteralPath
```
Add-TerminalIconsIconTheme [-LiteralPath] <String[]> [-Force] [-WhatIf] [-Confirm] [<CommonParameters>]
Add-TerminalIconsIconTheme [-LiteralPath] <String[]> [-Force] [-ProgressAction <ActionPreference>] [-WhatIf]
[-Confirm] [<CommonParameters>]
```

## DESCRIPTION
Expand Down Expand Up @@ -122,6 +124,21 @@ Accept pipeline input: False
Accept wildcard characters: False
```

### -ProgressAction
{{ Fill ProgressAction Description }}

```yaml
Type: ActionPreference
Parameter Sets: (All)
Aliases: proga

Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```

### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).

Expand Down
Loading