#Requires -Version 7 | |
# Version 1.2.13 | |
# check if newer version | |
$gistUrl = "https://api.github.com/gists/a208d2bd924691bae7ec7904cab0bd8e" | |
$latestVersionFile = [System.IO.Path]::Combine("$HOME",'.latest_profile_version') | |
$versionRegEx = "# Version (?<version>\d+\.\d+\.\d+)" | |
if ([System.IO.File]::Exists($latestVersionFile)) { | |
$latestVersion = [System.IO.File]::ReadAllText($latestVersionFile) | |
$currentProfile = [System.IO.File]::ReadAllText($profile) | |
[version]$currentVersion = "0.0.0" | |
if ($currentProfile -match $versionRegEx) { | |
$currentVersion = $matches.Version | |
} | |
if ([version]$latestVersion -gt $currentVersion) { | |
Write-Verbose "Your version: $currentVersion" -Verbose | |
Write-Verbose "New version: $latestVersion" -Verbose | |
$choice = Read-Host -Prompt "Found newer profile, install? (Y)" | |
if ($choice -eq "Y" -or $choice -eq "") { | |
try { | |
$gist = Invoke-RestMethod $gistUrl -ErrorAction Stop | |
$gistProfile = $gist.Files."profile.ps1".Content | |
Set-Content -Path $profile -Value $gistProfile | |
Write-Verbose "Installed newer version of profile" -Verbose | |
. $profile | |
return | |
} | |
catch { | |
# we can hit rate limit issue with GitHub since we're using anonymous | |
Write-Verbose -Verbose "Was not able to access gist, try again next time" | |
} | |
} | |
} | |
} | |
$global:profile_initialized = $false | |
function prompt { | |
function Initialize-Profile { | |
$null = Start-ThreadJob -Name "Get version of `$profile from gist" -ArgumentList $gistUrl, $latestVersionFile, $versionRegEx -ScriptBlock { | |
param ($gistUrl, $latestVersionFile, $versionRegEx) | |
try { | |
$gist = Invoke-RestMethod $gistUrl -ErrorAction Stop | |
$gistProfile = $gist.Files."profile.ps1".Content | |
[version]$gistVersion = "0.0.0" | |
if ($gistProfile -match $versionRegEx) { | |
$gistVersion = $matches.Version | |
Set-Content -Path $latestVersionFile -Value $gistVersion | |
} | |
} | |
catch { | |
# we can hit rate limit issue with GitHub since we're using anonymous | |
Write-Verbose -Verbose "Was not able to access gist to check for newer version" | |
} | |
} | |
if ((Get-Module PSReadLine).Version -lt 2.2) { | |
throw "Profile requires PSReadLine 2.2+" | |
} | |
# setup psdrives | |
if ([System.IO.File]::Exists([System.IO.Path]::Combine("$HOME",'test'))) { | |
New-PSDrive -Root ~/test -Name Test -PSProvider FileSystem -ErrorAction Ignore > $Null | |
} | |
if (!(Test-Path repos:)) { | |
if (Test-Path ([System.IO.Path]::Combine("$HOME",'git'))) { | |
New-PSDrive -Root ~/repos -Name git -PSProvider FileSystem > $Null | |
} | |
elseif (Test-Path "d:\PowerShell") { | |
New-PSDrive -Root D:\ -Name git -PSProvider FileSystem > $Null | |
} | |
} | |
Set-PSReadLineOption -Colors @{ Selection = "`e[92;7m"; InLinePrediction = "`e[2m" } -PredictionSource HistoryAndPlugin | |
Set-PSReadLineKeyHandler -Chord Shift+Tab -Function MenuComplete | |
Set-PSReadLineKeyHandler -Chord Ctrl+b -Function BackwardWord | |
Set-PSReadLineKeyHandler -Chord Ctrl+f -Function ForwardWord | |
Set-PSReadLineKeyHandler -Chord F2 -Function SwitchPredictionView | |
if ($IsWindows) { | |
Set-PSReadLineOption -EditMode Emacs -ShowToolTips | |
Set-PSReadLineKeyHandler -Chord Ctrl+Shift+c -Function Copy | |
Set-PSReadLineKeyHandler -Chord Ctrl+Shift+v -Function Paste | |
} | |
else { | |
try { | |
Import-PSUnixTabCompletion | |
} | |
catch [System.Management.Automation.CommandNotFoundException] | |
{ | |
Install-Module Microsoft.PowerShell.UnixTabCompletion -Repository PSGallery -AcceptLicense -Force | |
Import-PSUnixTabCompletion | |
} | |
} | |
# add path to dotnet global tools | |
$env:PATH += [System.IO.Path]::PathSeparator + [System.IO.Path]::Combine("$HOME",'.dotnet','tools') | |
# ensure dotnet cli is in path | |
$dotnet = Get-Command dotnet -CommandType Application -ErrorAction Ignore | |
if ($null -eq $dotnet) { | |
if ([System.IO.File]::Exists("$HOME/.dotnet/dotnet")){ | |
$env:PATH += [System.IO.Path]::PathSeparator+ [System.IO.Path]::Combine("$HOME",'.dotnet') | |
} | |
} | |
} | |
if ($global:profile_initialized -ne $true) { | |
$global:profile_initialized = $true | |
Initialize-Profile | |
} | |
$currentLastExitCode = $LASTEXITCODE | |
$lastSuccess = $? | |
$color = @{ | |
Reset = "`e[0m" | |
Red = "`e[31;1m" | |
Green = "`e[32;1m" | |
Yellow = "`e[33;1m" | |
Grey = "`e[37;0m" | |
White = "`e[37;1m" | |
Invert = "`e[7m" | |
RedBackground = "`e[41m" | |
} | |
# set color of PS based on success of last execution | |
if ($lastSuccess -eq $false) { | |
$lastExit = $color.Red | |
} else { | |
$lastExit = $color.Green | |
} | |
# get the execution time of the last command | |
$lastCmdTime = "" | |
$lastCmd = Get-History -Count 1 | |
if ($null -ne $lastCmd) { | |
$cmdTime = $lastCmd.Duration.TotalMilliseconds | |
$units = "ms" | |
$timeColor = $color.Green | |
if ($cmdTime -gt 250 -and $cmdTime -lt 1000) { | |
$timeColor = $color.Yellow | |
} elseif ($cmdTime -ge 1000) { | |
$timeColor = $color.Red | |
$units = "s" | |
$cmdTime = $lastCmd.Duration.TotalSeconds | |
if ($cmdTime -ge 60) { | |
$units = "m" | |
$cmdTIme = $lastCmd.Duration.TotalMinutes | |
} | |
} | |
$lastCmdTime = "$($color.Grey)[$timeColor$($cmdTime.ToString("#.##"))$units$($color.Grey)]$($color.Reset) " | |
} | |
# get git branch information if in a git folder or subfolder | |
$gitBranch = "" | |
$path = Get-Location | |
while ($path -ne "") { | |
if (Test-Path ([System.IO.Path]::Combine($path,'.git'))) { | |
# need to do this so the stderr doesn't show up in $error | |
$ErrorActionPreferenceOld = $ErrorActionPreference | |
$ErrorActionPreference = 'Ignore' | |
$branch = git rev-parse --abbrev-ref --symbolic-full-name '@{u}' | |
$ErrorActionPreference = $ErrorActionPreferenceOld | |
# handle case where branch is local | |
if ($lastexitcode -ne 0 -or $null -eq $branch) { | |
$branch = git rev-parse --abbrev-ref HEAD | |
} | |
$branchColor = $color.Green | |
if ($branch -match "/master") { | |
$branchColor = $color.Red | |
} | |
$gitBranch = " $($color.Grey)[$branchColor$branch$($color.Grey)]$($color.Reset)" | |
break | |
} | |
$path = Split-Path -Path $path -Parent | |
} | |
# truncate the current location if too long | |
$currentDirectory = $executionContext.SessionState.Path.CurrentLocation.Path | |
$consoleWidth = [Console]::WindowWidth | |
$maxPath = [int]($consoleWidth / 2) | |
if ($currentDirectory.Length -gt $maxPath) { | |
$currentDirectory = "`u{2026}" + $currentDirectory.SubString($currentDirectory.Length - $maxPath) | |
} | |
# check if running dev built pwsh | |
$devBuild = '' | |
if ($PSHOME.Contains("publish")) { | |
$devBuild = " $($color.White)$($color.RedBackground)DevPwsh$($color.Reset)" | |
} | |
"${lastCmdTime}${currentDirectory}${gitBranch}${devBuild}`n${lastExit}PS$($color.Reset)$('>' * ($nestedPromptLevel + 1)) " | |
# set window title | |
try { | |
$prefix = '' | |
if ($isWindows) { | |
$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent() | |
$windowsPrincipal = [Security.Principal.WindowsPrincipal]::new($identity) | |
if ($windowsPrincipal.IsInRole("Administrators") -eq 1) { | |
$prefix = "Admin:" | |
} | |
} | |
$Host.ui.RawUI.WindowTitle = "$prefix$PWD" | |
} catch { | |
# do nothing if can't be set | |
} | |
$global:LASTEXITCODE = $currentLastExitCode | |
} |
why you decided to use gists and the manual handling for this instead of using using git.
@danstur, not trying to speak for Steve here, but I had the same thought. I'm thinking the reasoning is you don't need to install git to do it this way. That being said, being on a public GitHub project would allow the same thing... Would also allow extra niceties like a license file, and perhaps the version check is pulling down a small file with the version instead of the whole script 🤷♂️
@SteveL-MSFT i try to implement powerline with the following line
Import-Module posh-git
Import-Module oh-my-posh
Set-PoshPrompt -Theme paradox
but i cant seem to find out how or where to correctly implement it with this script
@BigHoss , did you ever figure it out?
You would just add those options to the top of the script. The potential issue is that oh-my-posh modifies the function:\prompt
so your theme would be overridden with the next declaration of function
. You would have to put the code from Steve's prompt' function in the
Set-PoshContext` function.
@BigHoss I would recommend you delete the first part of the code and create ur own profile
to delete :
check if newer version
$gistUrl = "https://api.github.com/gists/a208d2bd924691bae7ec7904cab0bd8e"
$latestVersionFile = [System.IO.Path]::Combine("$HOME",'.latest_profile_version')
$versionRegEx = "# Version (?\d+.\d+.\d+)"
to create own profile(open with ur edit code):
exemple with vscode
. code $PROFILE.CurrentUserCurrentHost
and add inside:
. $env:USERPROFILE\FOLDERYOUDIRECTORYOFUSER\YOUPROFILE.ps1
ex:
. $env:USERPROFILE\.config\user_profile.ps1
and in your "YOUPROFILE.ps1" add the rest of the code, without the part I said not to put with "Module" and "theme", remembering that it is necessary to install the modules first.
my github with code:
Did this work for you without adding -Scope Global?
New-PSDrive -Root ~/repos -Name git -PSProvider FileSystem
In my setup, I had to change the scope in order to see the mapped PSDrives.
@SteveL-MSFT I'm curious why you decided to use gists and the manual handling for this instead of using using git. That's how I sync my profile (although admittedly I update manually to avoid the performance hit of explicitly checking at startup)
I "borrowed" the idea of setting up custom PSDrives for common folders though. I feel stupid for never making that connection - that sounds like it should be very useful.