Skip to content

Instantly share code, notes, and snippets.

@Konfekt
Last active March 23, 2021 01:39
Show Gist options
  • Save Konfekt/32e8e7ed0a77a3b6967fac0292493106 to your computer and use it in GitHub Desktop.
Save Konfekt/32e8e7ed0a77a3b6967fac0292493106 to your computer and use it in GitHub Desktop.
param(
[parameter(Position=0,Mandatory=$false)][string]$PSReadlineChordProvider = 'Ctrl+t',
[parameter(Position=1,Mandatory=$false)][string]$PSReadlineChordReverseHistory = 'Ctrl+r',
[parameter(Position=1,Mandatory=$false)][string]$PSReadlineChordSetLocation = 'Alt+c',
[parameter(Position=1,Mandatory=$false)][string]$PSReadlineChordReverseHistoryArgs = 'Alt+a')
function Invoke-FuzzyEdit() {
param($Directory=$null)
$files = @()
try {
if ($Directory) {
$prevDir = $PWD.Path
cd $Directory
}
Select-Poco | ForEach-Object { $files += """$_""" }
} catch {
}
finally {
if ($prevDir) {
cd $prevDir
}
}
if ($null -ne $files) {
Invoke-Expression -Command ("$env:EDITOR {0}" -f ($files -join ' '))
}
}
Set-Alias "fe" Invoke-FuzzyEdit
function Invoke-FuzzyHistory() {
$result = Get-History | ForEach-Object { $_.CommandLine } | Select-Poco --layout=bottom-up
if ($null -ne $result) {
Write-Output "Invoking '$result'`n"
Invoke-Expression "$result" -Verbose
}
}
Set-Alias "fh" Invoke-FuzzyHistory
function Invoke-FuzzyKillProcess() {
$result = Get-Process | Where-Object { ![string]::IsNullOrEmpty($_.ProcessName) } | ForEach-Object { "{0}: {1}" -f $_.Id,$_.ProcessName } | Select-Poco
$result | ForEach-Object {
$id = $_ -replace "([0-9]+)(:)(.*)",'$1'
Stop-Process $id -Verbose
}
}
Set-Alias "fk" Invoke-FuzzyKillProcess
function Invoke-FuzzySetLocation() {
param($Directory=$null)
if ($null -eq $Directory) { $Directory = $PWD.Path }
$result = $null
try {
if ([string]::IsNullOrWhiteSpace($env:POCO_DEFAULT_COMMAND)) {
Get-ChildItem $Directory -Recurse -ErrorAction Ignore | Where-Object{ $_.PSIsContainer } | Select-Poco | ForEach-Object { $result = $_ }
} else {
Select-Poco | ForEach-Object { $result = $_ }
}
} catch {
}
if ($null -ne $result) {
Set-Location $result
}
}
Set-Alias "fd" Invoke-FuzzySetLocation
if (Get-Command Search-Everything -ErrorAction Ignore) {
function Set-LocationFuzzyEverything() {
param($Directory=$null)
if ($null -eq $Directory) {
$Directory = $PWD.Path
$Global = $False
} else {
$Global = $True
}
$result = $null
try {
Search-Everything -Global:$Global -PathInclude $Directory -FolderInclude @('') | Select-Poco | ForEach-Object { $result = $_ }
} catch {
}
if ($null -ne $result) {
# use cd in case it's aliased to something else:
cd $result
}
}
}
Set-Alias "fs" Set-LocationFuzzyEverything
$script:IsWindows = ($PSVersionTable.PSVersion.Major -le 5) -or $IsWindows
if ($script:IsWindows) {
$script:ShellCmd = 'cmd.exe /S /C {0}'
$script:DefaultFileSystemCmd = @"
dir /s/b "{0}"
"@
} else {
$script:ShellCmd = '/bin/sh -c "{0}"'
$script:DefaultFileSystemCmd = @"
find {0} -path '*/\.*' -prune -o -type f -print -o -type l -print 2> /dev/null
"@
}
function Get-FileSystemCmd {
if ([string]::IsNullOrWhiteSpace($env:POCO_DEFAULT_COMMAND)) {
$script:DefaultFileSystemCmd
} else {
$env:POCO_DEFAULT_COMMAND
}
}
$script:PSReadlineHandlerChords = @()
$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
$script:PSReadlineHandlerChords | ForEach-Object {
Remove-PSReadlineKeyHandler $_
}
}
if (Get-Module -ListAvailable -Name PSReadline) {
SetPsReadlineShortcut "$PSReadlineChordProvider" -Override:$PSBoundParameters.ContainsKey('PSReadlineChordProvider') 'Fzf Provider Select' 'Run fzf for current provider based on current token' { Invoke-FzfPsReadlineHandlerProvider }
SetPsReadlineShortcut "$PSReadlineChordReverseHistory" -Override:$PSBoundParameters.ContainsKey('PSReadlineChordReverseHistory') 'Fzf Reverse History Select' 'Run fzf to search through PSReadline history' { Invoke-FzfPsReadlineHandlerHistory }
SetPsReadlineShortcut "$PSReadlineChordSetLocation" -Override:$PSBoundParameters.ContainsKey('PSReadlineChordSetLocation') 'Fzf Set Location' 'Run fzf to select directory to set current location' { Invoke-FzfPsReadlineHandlerSetLocation }
SetPsReadlineShortcut "$PSReadlineChordReverseHistoryArgs" -Override:$PSBoundParameters.ContainsKey('PSReadlineChordReverseHistoryArgs') 'Fzf Reverse History Arg Select' 'Run fzf to search through command line arguments in PSReadline history' { Invoke-FzfPsReadlineHandlerHistoryArgs }
} else {
Write-Warning "PSReadline module not found - keyboard handlers not installed"
}
function Invoke-FzfPsReadlineHandlerProvider {
$leftCursor = $null
$rightCursor = $null
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadline]::GetBufferState([ref]$line, [ref]$cursor)
$currentPath = Find-CurrentPath $line $cursor ([ref]$leftCursor) ([ref]$rightCursor)
$addSpace = $null -ne $currentPath -and $currentPath.StartsWith(" ")
if ([String]::IsNullOrWhitespace($currentPath) -or !(Test-Path $currentPath)) {
$currentPath = $PWD
}
$fileSystemCmd = Get-FileSystemCmd
$result = @()
try
{
if (-not [System.String]::IsNullOrWhiteSpace($env:POCO_CTRL_T_COMMAND)) {
Invoke-Expression ($env:POCO_CTRL_T_COMMAND) | Select-Poco | ForEach-Object { $result += $_ }
} else {
if ([string]::IsNullOrWhiteSpace($currentPath)) {
Select-Poco | ForEach-Object { $result += $_ }
} else {
$resolvedPath = Resolve-Path $currentPath -ErrorAction SilentlyContinue
$providerName = $null
if ($null -ne $resolvedPath) {
$providerName = $resolvedPath.Provider.Name
}
switch ($providerName) {
# Get-ChildItem is way too slow - we optimize for the FileSystem provider by
# using batch commands:
'FileSystem' { Invoke-Expression ($script:ShellCmd -f ($fileSystemCmd -f $resolvedPath.ProviderPath)) | Select-Poco | ForEach-Object { $result += $_ } }
'Registry' { Get-ChildItem $currentPath -Recurse -ErrorAction SilentlyContinue | Select-Object Name -ExpandProperty Name | Select-Poco | ForEach-Object { $result += $_ } }
$null { Get-ChildItem $currentPath -Recurse -ErrorAction SilentlyContinue | Select-Object FullName -ExpandProperty FullName | Select-Poco | ForEach-Object { $result += $_ } }
Default {}
}
}
}
}
catch
{
# catch custom exception
}
if ($null -ne $result) {
# quote strings if we need to:
if ($result -is [system.array]) {
for ($i = 0;$i -lt $result.Length;$i++) {
if ($result[$i].Contains(" ") -or $result[$i].Contains("`t")) {
$result[$i] = "'{0}'" -f $result[$i].Replace("`r`n","")
} else {
$result[$i] = $result[$i].Replace("`r`n","")
}
}
} else {
if ($result.Contains(" ") -or $result.Contains("`t")) {
$result = "'{0}'" -f $result.Replace("`r`n","")
} else {
$result = $result.Replace("`r`n","")
}
}
$str = $result -join ','
if ($addSpace) {
$str = ' ' + $str
}
$replaceLen = $rightCursor - $leftCursor
if ($rightCursor -eq 0 -and $leftCursor -eq 0) {
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($str)
} else {
[Microsoft.PowerShell.PSConsoleReadLine]::Replace($leftCursor,$replaceLen+1,$str)
}
}
}
function Invoke-FzfPsReadlineHandlerHistory {
$result = $null
try
{
Get-History | Select-Poco | ForEach-Object { $result = $_ }
}
catch
{
# catch custom exception
}
finally
{
# ensure that stream is closed:
$reader.Dispose()
}
if (-not [string]::IsNullOrEmpty($result)) {
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($result)
}
}
function Invoke-FzfPsReadlineHandlerHistoryArgs {
try
{
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadline]::GetBufferState([ref]$line, [ref]$cursor)
$line = $line.Insert($cursor,"{}") # add marker for fzf
$contentTable = @{}
Get-History | Select-Poco | ForEach-Object { $result = $_ }
}
catch
{
# catch custom exception
}
finally
{
$reader.Dispose()
}
if (-not [string]::IsNullOrEmpty($result)) {
# add quotes:
if ($result.Contains(" ") -or $result.Contains("`t")) {
$result = "'{0}'" -f $result.Replace("'","''")
}
[Microsoft.PowerShell.PSConsoleReadLine]::Replace($cursor,0,$result)
}
}
function Invoke-FzfPsReadlineHandlerSetLocation {
$result = $null
try
{
if ($null -eq $env:POCO_ALT_C_COMMAND) {
Get-ChildItem . -Recurse -ErrorAction SilentlyContinue -Directory | Select-Poco | ForEach-Object { $result = $_ }
} else {
Invoke-Expression ($env:POCO_ALT_C_COMMAND + ' ' + $env:POCO_ALT_C_OPTS) | Select-Poco | ForEach-Object { $result = $_ }
}
}
catch
{
# catch custom exception
}
if (-not [string]::IsNullOrEmpty($result)) {
Set-Location $result
[Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
}
}
function SetPsReadlineShortcut($Chord,[switch]$Override,$BriefDesc,$Desc,[scriptblock]$scriptBlock) {
if ([string]::IsNullOrEmpty($Chord)) {
return
}
if ((Get-PSReadlineKeyHandler -Bound | Where-Object {$_.Key.ToLower() -eq $Chord}) -and -not $Override) {
Write-Warning ("PSReadline chord {0} already in use - keyboard handler not installed. To bind your own keyboard chord, use the -ArgumentList parameter when you call Import-Module." -f $Chord)
} else {
$script:PSReadlineHandlerChords += $Chord
Set-PSReadlineKeyHandler -Key $Chord -Description $Desc -BriefDescription $BriefDesc -ScriptBlock $scriptBlock
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment