├── LICENSE.txt ├── PSColors.format.ps1xml ├── PSColors.psd1 ├── PSColors.psm1 └── README.md /LICENSE.txt: -------------------------------------------------------------------------------- 1 | License 2 | 3 | Eduardo Sousa 4 | 5 | MIT License 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the ""Software""), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /PSColors.format.ps1xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | FileSystemTypes 6 | 7 | System.IO.DirectoryInfo 8 | System.IO.FileInfo 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | FileSystemTypes-GroupingFormat 17 | 18 | 19 | 20 | 21 | 22 | 4 23 | 24 | 25 | 26 | 27 | $_.PSParentPath.Replace("Microsoft.PowerShell.Core\FileSystem::", "") 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | children 45 | 46 | FileSystemTypes 47 | 48 | 49 | PSParentPath 50 | FileSystemTypes-GroupingFormat 51 | 52 | 53 | 54 | 55 | 56 | 7 57 | left 58 | 59 | 60 | 61 | 25 62 | right 63 | 64 | 65 | 66 | 10 67 | right 68 | 69 | 70 | 71 | Left 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | Mode 80 | 81 | 82 | 83 | [String]::Format("{0,10} {1,8}", $_.LastWriteTime.ToString("d"), $_.LastWriteTime.ToString("t")) 84 | 85 | 86 | 87 | Length 88 | 89 | 90 | 91 | $name = $_.Name 92 | 93 | 94 | if($global:PSColorsUseAnsi) { 95 | $regexOptions = ([System.Text.RegularExpressions.RegexOptions]::IgnoreCase) 96 | 97 | $executables = @('exe', 'bat', 'cmd', 'py', 'pl', 'ps1', 'psm1', 'vbs', 'rb', 'reg', 'fsx') 98 | $compresseds = @('zip', 'tar', 'gz', '[rjw]ar', 'arj', 'tgz', 'gz') 99 | $texts = @('txt', 'cfg', 'conf', 'ini', 'csv', 'log', 'xml', 'java', 'c(pp)?', 'fs', 'html?') 100 | 101 | $executableRegex = New-Object regex("\.($([string]::Join('|', $executables)))`$", $regexOptions) 102 | $compressedRegex = New-Object regex("\.($([string]::Join('|', $compresseds)))`$", $regexOptions) 103 | $textRegex = New-Object regex("\.($([string]::Join('|', $texts)))`$", $regexOptions) 104 | 105 | $symlinkColor = "$([char](27))[36;1m" 106 | $directoryColor = "$([char](27))[34;1m" 107 | $executableColor = "$([char](27))[32;1m" 108 | $compressedColor = "$([char](27))[31;1m" 109 | $textColor = "$([char](27))[33;1m" 110 | $resetColor = "$([char](27))[0m" 111 | 112 | if ($_.Target) { 113 | $name = "$symlinkColor$name$resetColor -> $(Resolve-Path -Relative $_.Target)" 114 | } 115 | elseif ($_ -is [System.IO.DirectoryInfo]) { 116 | $name = "$directoryColor$name/$resetColor" 117 | } 118 | elseif ($compressedRegex.IsMatch($_.Name)) { 119 | $name = "$compressedColor$name$resetColor" 120 | } 121 | elseif ($executableRegex.IsMatch($_.Name)) { 122 | $name = "$executableColor$name*$resetColor" 123 | } 124 | elseif ($textRegex.IsMatch($_.Name)) { 125 | $name = "$textColor$name$resetColor" 126 | } 127 | } 128 | 129 | 130 | $name 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /PSColors.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | RootModule = 'PSColors.psm1' 3 | ModuleVersion = '1.3.0' 4 | GUID = 'a049cbc8-595a-41a0-b9f6-ae0098fcc15e' 5 | Author = 'Eduardo Sousa' 6 | Description = 'Nice prompt coloring for PowerShell' 7 | PowerShellVersion = '3.0' 8 | DotNetFrameworkVersion = '4.0' 9 | CLRVersion = '4.0' 10 | FunctionsToExport = @('prompt', 'Get-ChildItem') 11 | AliasesToExport = @('') 12 | HelpInfoURI = 'https://github.com/ecsousa/PSColors' 13 | PrivateData = @{ 14 | Tags='Prompt Coloring' 15 | ProjectUri='https://github.com/ecsousa/PSColors' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /PSColors.psm1: -------------------------------------------------------------------------------- 1 |  2 | # Function to check wheter current Console support ANSI codes 3 | function Test-Ansi { 4 | 5 | # Powershell ISE don't support ANSI, and this test will print ugly chars there 6 | if($host.PrivateData.ToString() -eq 'Microsoft.PowerShell.Host.ISE.ISEOptions') { 7 | return $false; 8 | } 9 | 10 | # To test is console supports ANSI, we will print an ANSI code 11 | # and check if cursor postion has changed. If it has, ANSI is not 12 | # supported 13 | $oldPos = $host.UI.RawUI.CursorPosition.X 14 | 15 | Write-Host -NoNewline "$([char](27))[0m" -ForegroundColor ($host.UI.RawUI.BackgroundColor); 16 | 17 | $pos = $host.UI.RawUI.CursorPosition.X 18 | 19 | if($pos -eq $oldPos) { 20 | return $true; 21 | } 22 | else { 23 | # If ANSI is not supported, let's clean up ugly ANSI escapes 24 | Write-Host -NoNewLine ("`b" * 4) 25 | return $false 26 | } 27 | } 28 | 29 | $Script:HasAnsi = Test-Ansi 30 | 31 | if($Script:HasAnsi) { 32 | # If ANSI is supported, save current console mode, so we can restore it latter. 33 | # Some programs, like cygwin's git disables ANSI support in windows Console. 34 | # This it will bad side effetcts from GIT. 35 | 36 | $sig = ''; 37 | $sig = $sig + '[DllImport("kernel32.dll", SetLastError = true)] public static extern bool SetConsoleMode(IntPtr hConsoleHandle, int dwMode);'; 38 | $sig = $sig + '[DllImport("kernel32.dll", SetLastError = true)] public static extern bool GetConsoleMode(IntPtr hConsoleHandle, ref int nCmdShow);'; 39 | $sig = $sig + '[DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr GetStdHandle(int nStdHandle);'; 40 | Add-Type -MemberDefinition $sig -name PSColorsNativeMethods -namespace Win32; 41 | 42 | $Script:ConsoleHandle = [Win32.PSColorsNativeMethods]::GetStdHandle(-11); 43 | $Script:ConsoleMode = 0; 44 | [Win32.PSColorsNativeMethods]::GetConsoleMode($Script:ConsoleHandle, [ref] $Script:ConsoleMode); 45 | } 46 | 47 | function Test-Git { 48 | param([IO.DirectoryInfo] $dir) 49 | # Function to check wheter directory is in a git repository 50 | 51 | # If have .git dir, it's a git repo 52 | if(Test-Path (Join-Path $dir.FullName '.git')) { 53 | return $true; 54 | } 55 | 56 | # If reached root dir, we are not in a git repository 57 | if(($dir.Parent -eq $null) -or ($dir -eq $dir.Parent)) { 58 | return $false; 59 | } 60 | 61 | # Check parent dir. Let's hope PowerShell supports tail recursion 62 | return Test-Git ($dir.Parent.FullName) 63 | } 64 | 65 | # Overriding PowerShell's default prompt function! 66 | function prompt { 67 | if($Script:HasAnsi) { 68 | # Making sure we are restoing original Console Mode in case someone (e.g. GIT) has changed it 69 | [Win32.PSColorsNativeMethods]::SetConsoleMode($Script:ConsoleHandle, $Script:ConsoleMode) | Out-Null 70 | } 71 | 72 | if($global:FSFormatDefaultColor) { 73 | [Console]::ForegroundColor = $global:FSFormatDefaultColor 74 | } 75 | 76 | $isFS = (Get-Item .).PSProvider.Name -eq 'FileSystem'; 77 | 78 | if($isFS) { 79 | # PowerShell don't change CurrentDirectory when you navigate throught File Sytem 80 | # which causes problem when executing external programs providing relative paths 81 | # This will fix the issue, syncing PowerShell current localtion to Windows Environment 82 | [system.Environment]::CurrentDirectory = (Convert-Path "."); 83 | } 84 | 85 | 86 | #Check if current user has admin privilges so we can use a different color 87 | $user = [Security.Principal.WindowsIdentity]::GetCurrent(); 88 | $admin = (New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) 89 | 90 | $branch = $null; 91 | 92 | # Legancy functionality to display git branch. Recommend to use posh-git, as it has better info 93 | # PSColors will not use its own branching displaying if it dectects posh-git is present 94 | if(-not(Get-Command Write-VcsStatus -ErrorAction SilentlyContinue)) { 95 | if( $isFS -and (Test-Git (Convert-Path .)) -and (Get-Command git)) { 96 | $branch = (git branch 2>$null) | %{ ([regex] '\* (.*)').match($_) } | ? { $_.Success } | %{ $_.Groups[1].Value } | Select-Object -First 1 97 | } 98 | } 99 | 100 | $drive = (Get-Location).Drive 101 | 102 | if($drive.Root -eq "$($drive.Name):\") { 103 | $title = $executionContext.SessionState.Path.CurrentLocation 104 | 105 | if($branch) { 106 | $title = "[$branch] $title"; 107 | } 108 | } 109 | else { 110 | $title = $drive.Name 111 | 112 | if($branch) { 113 | $title = "$title@$branch"; 114 | } 115 | } 116 | 117 | $host.UI.RawUI.WindowTitle = $title 118 | 119 | 120 | # Choosing color based on admin's privileges 121 | if($admin) { 122 | $color = 'Yellow'; 123 | } 124 | else { 125 | $color = 'Green'; 126 | } 127 | 128 | Write-Host ([System.Char](10)) -NoNewLine; 129 | 130 | # Print git branch, if posh-git is not present 131 | if($branch) { 132 | Write-Host "[" -NoNewLine -ForegroundColor Yellow 133 | Write-Host "$branch" -NoNewLine -ForegroundColor Cyan 134 | Write-Host "] " -NoNewLine -ForegroundColor Yellow 135 | } 136 | 137 | # If we have posh-git, use it 138 | if(Get-Command Write-VcsStatus -ErrorAction SilentlyContinue) { 139 | Write-VcsStatus; 140 | } 141 | 142 | # Write prompt info 143 | Write-Host $executionContext.SessionState.Path.CurrentLocation -NoNewLine -ForegroundColor $color; 144 | Write-Host ('>' * ($nestedPromptLevel + 1)) -NoNewLine -ForegroundColor $color; 145 | 146 | # Prevents PowerShell default prompt printing 147 | if($host.Name -like 'StudioShell*') { 148 | return " "; 149 | } 150 | else { 151 | return " `b"; 152 | } 153 | 154 | 155 | } 156 | 157 | # Wrapper for Get-ChildItem, that will aid PSColors.format.ps1xml detect if it's outputing to console, 158 | # and hence use ANSI code for coloring different file types 159 | 160 | function Get-ChildItem { 161 | <# 162 | .ForwardHelpTargetName Get-ChildItem 163 | .ForwardHelpCategory Cmdlet 164 | #> 165 | [CmdletBinding(DefaultParameterSetName='Items', SupportsTransactions=$true, HelpUri='https://go.microsoft.com/fwlink/?LinkID=113308')] 166 | param( 167 | [Parameter(ParameterSetName='Items', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] 168 | [string[]] 169 | ${Path}, 170 | 171 | [Parameter(ParameterSetName='LiteralItems', Mandatory=$true, ValueFromPipelineByPropertyName=$true)] 172 | [Alias('PSPath')] 173 | [string[]] 174 | ${LiteralPath}, 175 | 176 | [Parameter(Position=1)] 177 | [string] 178 | ${Filter}, 179 | 180 | [string[]] 181 | ${Include}, 182 | 183 | [string[]] 184 | ${Exclude}, 185 | 186 | [Alias('s')] 187 | [switch] 188 | ${Recurse}, 189 | 190 | [uint32] 191 | ${Depth}, 192 | 193 | [switch] 194 | ${Force}, 195 | 196 | [System.IO.FileAttributes] 197 | ${Attributes}, 198 | 199 | [switch] 200 | ${Directory}, 201 | 202 | [switch] 203 | ${File}, 204 | 205 | [switch] 206 | ${Hidden}, 207 | 208 | [switch] 209 | ${ReadOnly}, 210 | 211 | [switch] 212 | ${System}, 213 | 214 | [switch] 215 | ${Name}) 216 | 217 | dynamicparam 218 | { 219 | try { 220 | # Set global variable to indicates PSColors.format.ps1xml should output ANSI colors 221 | $global:PSColorsUseAnsi = $Script:HasAnsi -and ($MyInvocation.PipelineLength -eq $MyInvocation.PipelinePosition); 222 | 223 | $targetCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Management\Get-ChildItem', [System.Management.Automation.CommandTypes]::Cmdlet, $PSBoundParameters) 224 | $dynamicParams = @($targetCmd.Parameters.GetEnumerator() | Microsoft.PowerShell.Core\Where-Object { $_.Value.IsDynamic }) 225 | if ($dynamicParams.Length -gt 0) 226 | { 227 | $paramDictionary = [Management.Automation.RuntimeDefinedParameterDictionary]::new() 228 | foreach ($param in $dynamicParams) 229 | { 230 | $param = $param.Value 231 | 232 | if(-not $MyInvocation.MyCommand.Parameters.ContainsKey($param.Name)) 233 | { 234 | $dynParam = [Management.Automation.RuntimeDefinedParameter]::new($param.Name, $param.ParameterType, $param.Attributes) 235 | $paramDictionary.Add($param.Name, $dynParam) 236 | } 237 | } 238 | return $paramDictionary 239 | } 240 | } catch { 241 | throw 242 | } 243 | } 244 | 245 | begin 246 | { 247 | try { 248 | $outBuffer = $null 249 | if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) 250 | { 251 | $PSBoundParameters['OutBuffer'] = 1 252 | } 253 | $showDotFiles = -not $env:PSCOLORS_HIDE_DOTFILE -or $env:PSCOLORS_HIDE_DOTFILE.ToLower() -ne 'true' 254 | $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Management\Get-ChildItem', [System.Management.Automation.CommandTypes]::Cmdlet) 255 | 256 | $scriptCmd = { 257 | & $wrappedCmd @PSBoundParameters ` 258 | | ? { $Force -or $showDotFiles -or ($_.Name -eq $null) -or -not $_.Name.StartsWith('.') } 259 | } 260 | 261 | 262 | $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) 263 | $steppablePipeline.Begin($PSCmdlet) 264 | } catch { 265 | throw 266 | } 267 | } 268 | 269 | process 270 | { 271 | try { 272 | $steppablePipeline.Process($_) 273 | } catch { 274 | throw 275 | } 276 | } 277 | 278 | end 279 | { 280 | try { 281 | # Get-ChildItem has ended. PSColors.format.ps1xml will not longer append ANSI codes 282 | $global:PSColorsUseAnsi = $false; 283 | $steppablePipeline.End() 284 | } catch { 285 | throw 286 | } 287 | } 288 | } 289 | 290 | if($Script:HasAnsi) { 291 | # If ANSI is active, use custom PSColors.format.ps1xml for output coloring 292 | Update-FormatData -Prepend (Join-Path $PSScriptRoot PSColors.format.ps1xml) 293 | } 294 | 295 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PSColors 2 | 3 | This PowerShell provides no functions to be used. Instead it will provide some coloring for PowerShell: 4 | 5 | * Forces background color to black 6 | * Green prompt, without changing the actual foreground color 7 | * If used in a ANSI console (like [ConEmu](https://github.com/Maximus5/ConEmu)), it will also provide coloring for files output 8 | 9 | ## Extra features 10 | 11 | ### Hiding _dot files_ 12 | 13 | By setting environment variable PSCOLORS\_HIDE\_DOTFILE to **true**, 14 | PSColors will prevent `Get-ChildItem` Cmdlet from outputting files whose 15 | names start with a dot, unless `-Force` is used. 16 | 17 | This will make PowerShell behave similar to Unix's `ls` command. 18 | 19 | ## Installing 20 | 21 | Windows 10 users: 22 | 23 | Install-Module PSColors -Scope CurrentUser -AllowClobber 24 | 25 | ***NOTE**: `AllowClobber` is only required after Aniversary Update* 26 | 27 | Otherwise, if you have [PsGet](http://psget.net/) installed: 28 | 29 | Install-Module PSColors 30 | 31 | Or you can install it manually copying `PSColors.psm1` to your modules folder (e.g. ` $Env:USERPROFILE\Documents\WindowsPowerShell\Modules\PSColors\`) 32 | 33 | After installed, you will also need to explicitly load this module: 34 | 35 | Import-Module PSColors 36 | 37 | It's recommended that you this command to your profile file (`$PROFILE`) in order for the prompt function to take effect. 38 | --------------------------------------------------------------------------------