ShellServer.psm1
# if you change the port number here, you must change below too $Port = 5432 $LocalHost = '127.0.0.1' $Enc = [System.Text.Encoding]::UTF8 $Sock = New-Object System.Net.Sockets.UdpClient $Sock.Connect($LocalHost, $Port) $Address = [System.Net.IpAddress]::Parse($LocalHost) $End = New-Object System.Net.IPEndPoint $Address, $Port $Buffer = $Enc.GetBytes('2Initpwsh') $Sock.Send($Buffer) > $nul Register-EngineEvent PowerShell.Exiting -action { $Sock = New-Object System.Net.Sockets.UdpClient # # Change port number below if you changed above # $Sock.Connect('127.0.0.1', 5432) $Sock.Send([System.Text.Encoding]::UTF8.GetBytes('2Exit')) } > $nul $firstEnterKeyPress = 1 $lastCmdId = (Get-History -Count 1).Id Set-PSReadLineKeyHandler -Key Enter -ScriptBlock { $line = $cursor = $null [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor) $venv = [int](Test-Path 'ENV:VIRTUAL_ENV') $currentCmdId = (Get-History -Count 1).Id if (($currentCmdId -ne $Script:lastCmdId) -or (-not $line) -or ($firstEnterKeyPress)) { $Script:lastCmdId = $currentCmdId # will treat the enter after an empty line as the first enter key press $Script:firstEnterKeyPress = [int](-not $line) [Console]::SetCursorPosition(0, [Console]::GetCursorPosition().Item2 - (2 - $venv)) Write-Host -NoNewline "`e[J`e[34m❯`e[0m $line" } [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() } $LightThemeColors = @{ Command = "DarkYellow" Comment = "DarkGreen" ContinuationPrompt = "DarkGray" Default = "DarkGray" Emphasis = "DarkBlue" InlinePrediction = "DarkGray" Keyword = "Green" ListPrediction = "DarkYellow" ListPredictionSelected = "`e[30;5;238m" Member = "Black" Number = "Black" Operator = "DarkGray" Parameter = "DarkGray" Selection = "`e[30;5;238m" String = "DarkCyan" Type = "Black" Variable = "Green" } $DefaultThemeColors = @{ Command = "`e[93m" Comment = "`e[32m" ContinuationPrompt = "`e[37m" Default = "`e[37m" Emphasis = "`e[96m" InlinePrediction = "`e[38;5;238m" Keyword = "`e[92m" ListPrediction = "`e[33m" ListPredictionSelected = "`e[48;5;238m" Member = "`e[97m" Number = "`e[97m" Operator = "`e[90m" Parameter = "`e[90m" Selection = "`e[30;47m" String = "`e[36m" Type = "`e[37m" Variable = "`e[92m" } function PSThemeChange { if ((get-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize).SystemUsesLightTheme) { Set-PSReadLineOption -Colors $LightThemeColors } else { Set-PSReadLineOption -Colors $DefaultThemeColors } } PSThemeChange Remove-Alias ls -ErrorAction 'Ignore' function global:prompt { $origDollarQuestion = $global:? $origLastExitCode = $global:LASTEXITCODE # if venv > 0: venv == venv.length $venv = $env:VIRTUAL_ENV if ($venv) { $venv = ($venv.Substring($venv.LastIndexOf('\')+1)).Length + 3 } else { Write-Host '' $venv = [int] [bool] $venv } $width = $Host.UI.RawUI.BufferSize.Width - $venv $duration = (Get-History -Count 1).Duration if (-Not $duration) { $duration = 0.0 } else { $duration = [string]$duration.TotalSeconds } $Buffer = $Enc.GetBytes('1' + [int] $origDollarQuestion + (Get-Location).Path + ";$width;$duration") $Sock.Send($Buffer) > $nul $response = $Enc.GetString($Sock.Receive([ref] $End)) $ExecutionContext.InvokeCommand.ExpandString($response) $global:LASTEXITCODE = $origLastExitCode if ($global:? -ne $origDollarQuestion) { if ($origDollarQuestion) { 1+1 } else { Write-Error '' -ErrorAction 'Ignore' } } } function p { param($arg) if (-not $arg) { Set-Location } else { if ($args) { $arg += ' ' + $args -join ' ' } $Buffer = $Enc.GetBytes("3$arg") $Sock.Send($Buffer) > $nul $response = $Enc.GetString($Sock.Receive([ref] $End)) if ($response) { Set-Location $response } else { Write-Output "ShellServer: No match found." } } } function pz { $Buffer = $Enc.GetBytes('4') $Sock.Send($Buffer) > $nul $response = $Enc.GetString($Sock.Receive([ref] $End)) $query = $args -Join ' ' if ($query) { $answer = Write-Output $response | fzf --height=~20 --layout=reverse -q $query } else { $answer = Write-Output $response | fzf --height=~20 --layout=reverse } $Sock.Send($Enc.GetBytes('4' + $answer)) > $nul Set-Location $answer } function ls { param($opts, $path) if ($path) { try {$resPath = (Resolve-Path $path -ErrorAction 'Stop').Path} catch {$resPath = (Get-Error).TargetObject} } else { $resPath = (Get-Location).Path } $Buffer = $Enc.GetBytes("5$opts;$resPath") $Sock.Send($Buffer) > $nul $response = $Enc.GetString($Sock.Receive([ref] $End)) $ExecutionContext.InvokeCommand.ExpandString($response) } function ll { ls '-cil' ($args -join ' ') } function la { ls '-acil' ($args -join ' ') } function Switch-Theme { [CmdletBinding()] param( [Parameter()] [ArgumentCompletions('all', 'terminal', 'system', 'blue')] $arg ) $Buffer = $Enc.GetBytes("6$arg") $Sock.Send($Buffer) > $nul Start-Sleep .1 if (($arg -eq 'terminal') -Or (-Not $arg)) { PSThemeChange } } function Search-History { $width = $Host.UI.RawUI.BufferSize.Width $height = $Host.UI.RawUI.BufferSize.Height $arg = $args -join ' ' $Buffer = $Enc.GetBytes("7$arg;$width;$height") $Sock.Send($Buffer) > $nul $response = $Enc.GetString($Sock.Receive([ref] $End)) $ExecutionContext.InvokeCommand.ExpandString($response) } $completions = @($Enc.GetString($Sock.Receive([ref] $End)) -split ';') $scriptBlock = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $completions | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { $_ } } Register-ArgumentCompleter -CommandName p -ParameterName arg -ScriptBlock $scriptBlock Export-ModuleMember -Function @("p", "pz", "ls", "ll", "la", "Switch-Theme", "Search-History") |