Skip to content

Instantly share code, notes, and snippets.

@drandarov-io
Last active July 2, 2024 10:09
Show Gist options
  • Save drandarov-io/ec6a51a1d4e256c322f496cb47ab704a to your computer and use it in GitHub Desktop.
Save drandarov-io/ec6a51a1d4e256c322f496cb47ab704a to your computer and use it in GitHub Desktop.
Personal PowerShell $PROFILE (drandarov-io)
# https://gist.github.com/drandarov-io/ec6a51a1d4e256c322f496cb47ab704a
#########################
# Modules
#########################
# General
Import-Module z
Import-Module Terminal-Icons
Import-Module Microsoft.WinGet.CommandNotFound
# Autocompleters
Import-Module UsefulArgumentCompleters
# Third party autocompleters (call ". cmp" to load)
function cmp {
Import-Module npm-completion -Global
Import-Module yarn-completion -Global
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 kubectl -ErrorAction SilentlyContinue) { kubectl completion powershell | Out-String | Invoke-Expression }
Write-Host "Autocomplete modules loaded"
}
# Fix for Set-Location if z is installed
Set-Alias Set-LocationZ ((Test-Path Function:cdX) ? "cdX" : "Set-Location")
#########################
# Variables
#########################
$Global:USERPATHS = @{
dev = "Y:/Dev"
ydev = "Y:/Dev"
xdev = "X:/Dev"
tools = "X:/Tools"
res = "X:/Res"
backup = "D:/Backup"
create = "D:/Create"
temp = "D:/Temp"
img = "P:/Dev/Images"
media = "W:/Media"
dl = "$env:USERPROFILE/Downloads"
config = "$env:USERPROFILE/.dmi3"
}
# Use [scriptblock]::Create() to avoid assigning a temporary variable in the prompt scope, since $_ is not accessible inside a scriptblock (It's about the principle)
$USERPATHS.Keys | ForEach-Object { Set-Item function:$_ -Value ([scriptblock]::Create("Set-LocationZ `$USERPATHS.$_ @args")) }
$USERPATHS.Keys | ForEach-Object { Set-Variable -Name $_ -Value $USERPATHS.$_ }
$Global:WALLPAPER = "$env:APPDATA/Microsoft/Windows/Themes/TranscodedWallpaper"
$Global:HOSTSPROFILE = $PROFILE.CurrentUserAllHosts
$Global:USERSCRIPTS = "$(Split-Path $PROFILE)/Scripts"
#########################
# Functions
#########################
# TODO Make compatible with pipelines
# TODO Create somthing like $input ?? $args[0] | ForEach-Object { ... }
function Edit-Profile { code $PROFILE @args }
function Get-PublicIP { param([switch]$IP6) $IP6 ? (curl -s -6 ipconfig.io) : (curl -s -4 ipconfig.io) }
function Get-Wallpaper { "$([Text.Encoding]::Unicode.GetString((Get-ItemProperty 'HKCU:\Control Panel\Desktop' TranscodedImageCache -ErrorAction Stop).TranscodedImageCache) -replace '(.+)([A-Z]:[0-9a-zA-Z\\])+','$2')" }
function Get-AdminStatus { ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) }
function Get-LocalGroupsAll { Get-LocalGroup | ForEach-Object { $group = $_.Name; Get-LocalGroupMember $group | Select-Object @{Name='GroupName';Expression={$group}}, * } }
function Select-And { $args[0] ? $args[0] : $args[1] }
function Select-Or { $args[0] ? $args[0] : $args[1] }
function Get-VariableRaw { Select-Zip $MyInvocation.Statement.Replace('Get-VariableRaw ', '').Split(' '), $MyInvocation.UnboundArguments | ForEach-Object { [PSCustomObject]@{Name = $_[0]; Value = $_[1]} } }
function Out-StringList { param([switch]$Stream) $args | Format-List * | Out-String -Stream:$Stream }
function Out-StringTable { param([switch]$Stream) $args | Format-Table * | Out-String -Stream:$Stream }
function Out-StringVariables { Out-StringTable (Get-VariableRaw $args) }
function Write-StringList { Write-Host (Out-StringList @args) }
function Write-StringTable { Write-Host (Out-StringTable @args) }
function Write-HLine { param([switch]$NoPadding=$false) Write-Host $("=" * [Console]::WindowWidth) ($NoPadding ? "" : "`n") }
function Get-Colors { [enum]::GetValues([ConsoleColor]) | Select-Object @{N='ColorObject';E={$_}}, @{N='ColorName'; E={ If ($_.ToString().substring(0,3) -eq 'Dar' ){ $_.ToString().Substring(4) + 'DARK' } else { $_.ToString() } } } | Sort-Object Colorname }
function Write-Colormap { $colors = Get-Colors; foreach ($bgcolor in $colors.ColorObject) { foreach ($fgcolor in $colors.ColorObject) { Write-Host "$fgcolor■" -ForegroundColor $fgcolor -BackgroundColor $bgcolor -NoNewLine; Write-Host " " -NoNewline } Write-Host " on $bgcolor" } }
function Get-LatestGitRelease { param($RepoName, $PatternWord) (Invoke-WebRequest "https://api.github.com/repos/$RepoName/releases/latest").Content | Select-String "(https:\/\/github\.com\/[^\/]+\/[^\/]+\/releases\/download\/[^\/]+\/[^\/]*$PatternWord[^\/]*\.zip)" | ForEach-Object { $_.Matches.Value } }
function Expand-WebArchive { param($Uri, $Path) $tempFile = New-TemporaryFile; Invoke-WebRequest $uri -OutFile $tempFile; Expand-Archive $tempFile $path; Remove-Item $tempFile }
function Add-DirToPath { param($Path=$PWD, [switch]$System) if (-not (Get-AdminStatus) -and $System) { "'-System' requires admin priviledges." } else { [Environment]::SetEnvironmentVariable('Path', "$env:Path;$(($Path | Resolve-Path) -join ';');", $System ? 'Machine' : 'User') } }
function Invoke-ParameterTest { process {Get-VariableRaw $params $PSBoundParamters $($input) $_ $args @args } }
function Invoke-ParameterTest2 { Get-VariableRaw $params $PSBoundParamters $($input) $_ $args @args }
function Invoke-CopyTranscodeIdf { ff copytranscode @args; idf $args[0] }
function Update-GitRecurse { Get-ChildItem -Directory -Force -Recurse *.git | ForEach-Object { Set-Location $_.Parent.FullName; Write-Host $_.Parent.FullName; git pull; Write-HLine }; Set-Location .. } # Recusively Update Git Repos
#########################
# Proxy Functions
#########################
# TODO Make compatible with pipelines
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
function idf { Invoke-Item (Split-Path $args[0]) } # Invoke Directory of file
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 mergeobj { $obj1, $prop1, $obj2, $prop2 = $args; $obj1 | ForEach-Object { $p = $_; $obj2 | Where-Object { $p.$prop1 -eq $_.$prop2 } } }
# Filters
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]) }
#########################
# Winget
#########################
# Winget separated for autocomplete
$wgFunctions = @{
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 }
}
$wgFunctions.Keys | ForEach-Object { Set-Item function:$_ -Value $wgFunctions.$_ }
#########################
# Autocompletion
#########################
# TODO Simplify
Register-ArgumentCompleter -Native -CommandName @($wgFunctions.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 ($wgFunctions.ContainsKey($_.Value)) {
return $wgFunctions[$_.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
###################################
# Prompt
###################################
# Configuration
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Set-PSReadLineOption -PredictionViewStyle ListView
Set-PSReadLineOption -MaximumHistoryCount 10000
Set-PSReadLineOption -BellStyle Audible -DingTone 300 -DingDuration 50
# Shortcuts
Set-PSReadlineKeyHandler Tab MenuComplete
Add-KeyboardShortcut Ctrl+Alt+Shift+C -Beep 'Clear-Host' 'Clear the console'
Add-KeyboardShortcut Ctrl+Alt+Shift+P -Beep '. $PROFILE' 'Reload the Powershell profile'
Add-KeyboardShortcut Ctrl+Alt+Shift+M -Beep '. cmp' 'Load autocompletions'
Add-KeyboardShortcut Ctrl+UpArrow 'Set-LocationZ ..' 'Navigate to the directory above'
Add-KeyboardShortcut Shift+Ctrl+Alt+Y 'Set-LocationZ -' 'Navigate back in directory history'
Add-KeyboardShortcut Shift+Ctrl+Alt+X 'Set-LocationZ +' 'Navigate forward in directory history'
$env:WINFETCH_CONFIG_PATH = "$($USERPATHS.config)/winfetch_config.ps1"
$env:POSH_THEME = "$($USERPATHS.config)/dmitr.io.omp.json"
oh-my-posh init pwsh | Invoke-Expression
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment