Last active
November 9, 2025 17:05
-
-
Save drandarov-io/ec6a51a1d4e256c322f496cb47ab704a to your computer and use it in GitHub Desktop.
Personal PowerShell $PROFILE (drandarov-io)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # https://gist.github.com/drandarov-io/ec6a51a1d4e256c322f496cb47ab704a | |
| ######################### | |
| # Modules | |
| ######################### | |
| # Delayed loading of some modules and completions for startup speed | |
| Register-EngineEvent -SourceIdentifier 'PowerShell.OnIdle' -MaxTriggerCount 1 -Action { | |
| Import-Module Terminal-Icons | |
| Import-Module Microsoft.WinGet.CommandNotFound | |
| Import-Module npm-completion | |
| Import-Module yarn-completion | |
| # if (Get-Command git -ErrorAction SilentlyContinue) { Import-Module posh-git } | |
| # if (Get-Command helm -ErrorAction SilentlyContinue) { helm completion powershell | Out-String | Invoke-Expression } | |
| # if (Get-Command docker -ErrorAction SilentlyContinue) { docker completion powershell | Out-String | Invoke-Expression } | |
| # if (Get-Command podman -ErrorAction SilentlyContinue) { podman completion powershell | Out-String | Invoke-Expression } | |
| # if (Get-Command kubectl -ErrorAction SilentlyContinue) { kubectl completion powershell | Out-String | Invoke-Expression } | |
| # if (Get-Command minikube -ErrorAction SilentlyContinue) { minikube completion powershell | Out-String | Invoke-Expression } | |
| } | Out-Null | |
| Import-Module z | |
| Import-Module UsefulArgumentCompleters | |
| ######################### | |
| # Proxy Functions | |
| ######################### | |
| # My wishful idea would be to have something that could be used as follows: New-ProxyFunction -Name helf -Command Get-Help -DefaultParameters '-Full' (similar to New-Alias syntax), | |
| # which would create the appropriate proxy function with $PSBoundParameters['Full'] = $true in its begin block or even a String concatination. | |
| # The only idea I'd have, would be to use String manipulation to do this with the resulting String from [Management.Automation.ProxyCommand]::Create(...) | |
| # Forwarding function with autocomplete | |
| # https://stackoverflow.com/questions/78674503/powershell-how-to-do-autocompletion-for-proxy-functions | |
| # https://devblogs.microsoft.com/scripting/proxy-functions-spice-up-your-powershell-core-cmdlets/ | |
| # https://www.reddit.com/r/PowerShell/comments/7ht0dk/passthrough_parameters_in_scripts_and_functions/ | |
| # https://livebook.manning.com/book/powershell-in-depth/chapter-37/ | |
| # https://devblogs.microsoft.com/powershell/extending-andor-modifing-commands-with-proxies/ | |
| # TODO Move to POWERFUNCTIONS | |
| # MAKE A PROXY FUNCTIONLIBRARY | |
| # TODO Make compatible with pipelines (?? or Select-Or) | |
| # TODO Check whether it makes sence to create proxy functions with proper names like Get-HelpFull and then as an additional parameter create an alias like helf | |
| # Create method for `Compare-Object -ReferenceObject $allItemsMeasure -DifferenceObject $filteredItemsMeasure -Property ($allItemsMeasure | Get-Member -MemberType Property | Select Name)` | |
| # Fix for Set-Location if z is installed | |
| Set-Alias Set-LocationZ ((Test-Path Function:cdX) ? "cdX" : "Set-Location") | |
| function c { $args ? (code @args) : (code './') } | |
| function c. { Set-LocationZ .. @args } | |
| function c+ { Set-LocationZ + @args } | |
| function c_ { Set-LocationZ - @args } | |
| function cdf { Set-LocationZ (Split-Path $args[0]) } # Change Directory to file parent | |
| function id { $args ? (Invoke-Item @args) : (Invoke-Item ./) } # Invoke Directory # TODO pipelines | |
| function idf { Invoke-Item (Split-Path $args[0]) } # Invoke Directory of file # TODO pipelines | |
| function idc { Write-Host (Get-Command $args[0]).Source; Invoke-Item (Split-Path(Get-Command $args[0]).Source) } | |
| function wtd { wt -d . @args } | |
| function helf { Get-Help -Full @args } | |
| function lr { Get-ChildItem -Recurse @args } | |
| function ll { Get-ChildItem -Force @args } | |
| function lf { Get-ChildItem -File @args } | |
| function lfr { Get-ChildItem -File -Recurse @args } | |
| function co { gh copilot @args } | |
| function coe { gh copilot explain @args } | |
| function cos { gh copilot suggest @args } | |
| function gtc { git clone @args } | |
| function gtp { git pull @args } | |
| function sds { $input | Out-String -Stream | Select-String @args } # grep style | |
| function selext { $input | Select-Object -ExpandProperty @args } | |
| function tablew { $input | Format-Table -Wrap @args } | |
| function sudops { sudo.exe pwsh -e ([Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($args))) } | |
| # Filters | |
| filter md5 { Select-Or $_ $args[0] | Get-FileHash -Algorithm MD5 } | |
| filter sha1 { Select-Or $_ $args[0] | Get-FileHash -Algorithm SHA1 } | |
| filter sha256 { Select-Or $_ $args[0] | Get-FileHash -Algorithm SHA256 } | |
| filter crc32 { 7z h -scrcCRC32 @args } | |
| filter crc64 { 7z h -scrcCRC64 @args } | |
| # Good Test for Pipelines vs Direct | |
| # - s* ABC -> Select-Object -InputObject (gcm Parallel-Transcode) -Property * | |
| # - ABC | s* -> ABC | Select-Object -Property * | |
| filter s* { ($_ ? ($_ | Select-Object * @args) : (Select-Object * @args)) } # Example for Alias for Filters | |
| filter suffix { ($_ ? $_ : $args[0]) -replace '\.[^.]+$', "$($_ ? $args[0] : $args[1])$&" } | |
| filter ext { [IO.Path]::ChangeExtension($_ ? $_ : $args[0], $_ ? $args[0] : $args[1]) } | |
| filter head { $_ ? ($_ | Get-Content -Head ($args[0] ? $args[0] : 10)) : (Get-Content -Head ($args[1] ? $args[1] : 10) $args[0]) } | |
| filter tail { $_ ? ($_ | Get-Content -Tail ($args[0] ? $args[0] : 10)) : (Get-Content -Tail ($args[1] ? $args[1] : 10) $args[0]) } | |
| filter Test-Empty { param([System.Collections.IEnumerable]$InputObject) ($InputObject.Count -eq 0) -or ($InputObject.Length -eq 0) } | |
| filter Test-Blank { param([string]$InputObject) (Test-Empty ($InputObject.Trim())) } | |
| filter Test-Null { Select-InputOrArgs | ForEach-Object { $_ -ne $null } } | |
| ######################### | |
| # Alias / Paths | |
| ######################### | |
| $UserPaths = @{ | |
| dev = "X:/" | |
| tools = "F:/Tools" | |
| res = "F:/Res" | |
| backup = "D:/Backup" | |
| create = "D:/Create" | |
| tmp = "D:/Temp" | |
| img = "P:/Dev/Images" | |
| media = "W:/Media" | |
| lnk = "F:/Tools/.lnk" | |
| dl = "$HOME/Downloads" | |
| config = "$HOME/.d7v" | |
| } | |
| # Winget separated for autocomplete | |
| $WingetFunctions = @{ | |
| wu = { winget upgrade @args } | |
| wui = { winget upgrade -i @args } | |
| wuiu = { winget upgrade --include-unknown @args } | |
| wi = { winget install @args } | |
| wii = { winget install -i @args } | |
| wr = { winget uninstall @args } | |
| wri = { winget uninstall -i @args } | |
| ws = { winget search @args } | |
| wsho = { winget show @args } | |
| wl = { winget list @args } | |
| } | |
| $UserPaths.Keys | ForEach-Object { Set-Variable -Scope Global -Name $_ -Value $UserPaths.$_ } | |
| $UserPaths.Keys | ForEach-Object { Set-Item "Function:\global:$_" -Value ([ScriptBlock]::Create("Set-LocationZ $($UserPaths.$_) @args")) } | |
| $WingetFunctions.Keys | ForEach-Object { Set-Item "Function:\global:$_" -Value $WingetFunctions.$_ } | |
| ######################### | |
| # Autocompletion | |
| ######################### | |
| # TODO Simplify | |
| Register-ArgumentCompleter -Native -CommandName @($WingetFunctions.Keys; 'winget'; 'winget.exe') -ScriptBlock { | |
| param($wordToComplete, $commandAst, $cursorPosition) | |
| Write-StringList (Get-VariableRaw $wordToComplete $commandAst $cursorPosition) | |
| $word = $wordToComplete.Replace('"', '""') | |
| $ast = $commandAst.ToString().Replace('"', '""') | |
| $new_ast = $ast -replace '^[a-z]*', { | |
| if ($WingetFunctions.ContainsKey($_.Value)) { | |
| return $WingetFunctions[$_.Value].ToString().Replace("@args", "").Trim() | |
| } | |
| return $_.Value | |
| } | |
| if ($ast -ne $new_ast) { $cursorPosition += $new_ast.Length - $ast.Length} | |
| winget complete --word="$word" --commandline "$new_ast" --position $cursorPosition | ForEach-Object { | |
| [Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) | |
| } | |
| } | |
| # function UserPathCompleter { | |
| # param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) | |
| # # Check if the variable $media exists and is a string | |
| # if ($global:media -and ($global:media -is [string])) { | |
| # # Add a trailing slash if not present | |
| # $completion = if ($global:media[-1] -ne '\') { "$global:media\" } else { $global:media } | |
| # # Return completion result | |
| # $completion | |
| # } | |
| # } | |
| # Register-ArgumentCompleter -CommandName Get-ChildItem -ParameterName Path -ScriptBlock $function:UserPathCompleter | |
| # Register-ArgumentCompleter -CommandName * -ParameterName * -ScriptBlock { | |
| # param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) | |
| # $proj = "W:/Media" | |
| # [Management.Automation.CompletionResult]::new("~proj", "~proj", 'Variable', "Custom variable for projects directory") | |
| # } | |
| function Add-KeyboardShortcut { | |
| param($shortcut, $text, $description="", [switch]$beep) | |
| Set-PSReadLineKeyHandler $shortcut -Description $description { | |
| [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine() | |
| [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine() # Once doesn't always work 🙄 | |
| [Microsoft.PowerShell.PSConsoleReadLine]::Insert($text) | |
| [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() | |
| if ($beep) { [Microsoft.PowerShell.PSConsoleReadLine]::Ding() } | |
| }.GetNewClosure() | |
| } | |
| ######################### | |
| # Aliases | |
| ######################### | |
| # General | |
| Set-Alias e Write-Output | |
| Set-Alias l Get-ChildItem | |
| Set-Alias json> ConvertFrom-Json | |
| Set-Alias json< ConvertTo-Json | |
| Set-Alias fromjson ConvertFrom-Json | |
| Set-Alias tojson ConvertTo-Json | |
| Set-Alias table Format-Table | |
| Set-Alias list Format-List | |
| Set-Alias s Select-Object | |
| # Diagnostic | |
| Set-Alias sysinfo Get-ComputerInfo | |
| Set-Alias psd Get-PSDrive | |
| # My functions | |
| Set-Alias ?or Select-Or | |
| Set-Alias ?and Select-And | |
| Set-Alias osl Out-StringList | |
| Set-Alias cop Edit-Profile | |
| # Third party tools | |
| Set-Alias wfe winfetch | |
| Set-Alias wcr wingetcreate | |
| Set-Alias ig ImageGlass | |
| Set-Alias nixgui mkvtoolnix-gui | |
| Set-Alias ai Start-AIShell | |
| ################################### | |
| # Prompt | |
| ################################### | |
| $env:WINFETCH_CONFIG_PATH = "$($UserPaths.config)/winfetch_config.ps1" | |
| $env:POSH_THEME = "$($UserPaths.config)/d7v.io.omp.json" | |
| $env:CW = Get-Date -UFormat %V | |
| function composh { $env:POSH_COMPACT = if ($env:POSH_COMPACT) { "" } else { "1" }; setx POSH_COMPACT $env:POSH_COMPACT >$null 2>&1 } | |
| oh-my-posh init pwsh --config "$env:POSH_THEME" | Invoke-Expression | |
| # Configuration | |
| Set-PSReadLineOption -PredictionSource HistoryAndPlugin | |
| Set-PSReadLineOption -PredictionViewStyle ListView | |
| Set-PSReadLineOption -MaximumHistoryCount 10000 | |
| Set-PSReadLineOption -BellStyle Audible -DingTone 300 -DingDuration 50 | |
| Set-PSReadLineOption -ContinuationPrompt "" | |
| Set-PSReadlineKeyHandler Tab MenuComplete | |
| # Shortcuts | |
| Add-KeyboardShortcut Ctrl+Alt+Shift+C -Beep 'Clear-Host' 'Clear the console' | |
| Add-KeyboardShortcut Ctrl+Alt+Shift+R -Beep '. $PROFILE' 'Reload the Powershell profile' | |
| Add-KeyboardShortcut Ctrl+Alt+Shift+F 'composh' 'Switch between POSH compact and full prompt' | |
| Add-KeyboardShortcut Ctrl+UpArrow 'cd ..' 'Navigate to the directory above' | |
| Add-KeyboardShortcut Ctrl+Shift+Z 'cd -' 'Navigate back in directory history' | |
| Add-KeyboardShortcut Ctrl+Shift+X 'cd +' 'Navigate forward in directory history' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment