Open bradphelan opened 5 years ago
I've updated my script.
####################################################
# This is a fuzzy finder for powershell. It works
# by building a cache in a root directory and
# then allows you to query that cache using simple keystrokes
#
# Keystrokes
# ------------
# <ctrl-shift-s>
# will rebuild an index '.hscache' in the current directory
#
# <ctrl-s>
# will start the fuzzy finder with the current word as the intial search string. Once
# the file has been selected by refining the pattern or using the arrow keys hit
# returns and the initial string will be replaced by the selected string
#
# Requirements
# ------------
# Install and setup heat seeker
# https://github.com/rschmitt/heatseeker
###################################################
$ps = $null
try {
# On Windows 10, PSReadLine ships with PowerShell
$ps = [Microsoft.PowerShell.PSConsoleReadline]
} catch [Exception] {
# Otherwise, it can be installed from the PowerShell Gallery:
# https://github.com/lzybkr/PSReadLine#installation
Import-Module PSReadLine
$ps = [PSConsoleUtilities.PSConsoleReadLine]
}
function PerformFuzzy {
param([bool]$absolute=$false)
if(!(test-path .hscache)){
write-warning "Please press <ctrl-shift-s> to build an index for this directory before trying to use the fuzzy finder"
return
}
$line = $null
$cursor0 = $null
$cursor1 = $null
$ps::NextWord()
$ps::GetBufferState([ref]$line, [ref]$cursor0)
$ps::BackwardWord()
$ps::GetBufferState([ref]$line, [ref]$cursor1)
$search = $line.SubString($cursor1,$cursor0-$cursor1)
$choices = [IO.File]::ReadAllText($(Resolve-Path .hscache)) | hs -s $search
$ps::KillWord()
$insert = $choices -join " "
if($absolute){
$insert = Resolve-Path $insert
}
if($cursor1 -eq 0){
$ps::Insert($insert)
}else{
$ps::Insert("'" + $insert + "'" )
}
}
# Trigger fuzzy search and replace with relative path
Set-PSReadlineKeyHandler `
-Chord 'Ctrl+s' `
-BriefDescription "InsertHeatseekerPathInCommandLine" `
-LongDescription "Run Heatseeker in the PWD, appending any selected paths to the current command" `
-ScriptBlock { PerformFuzzy($false) }
# Trigger fuzzy search and replace with absolute path
Set-PSReadlineKeyHandler `
-Chord 'Ctrl+S' `
-BriefDescription "InsertHeatseekerPathInCommandLine" `
-LongDescription "Run Heatseeker in the PWD, appending any absolute selected paths to the current command" `
-ScriptBlock { PerformFuzzy($true) }
# Rebuild cache
Set-PSReadlineKeyHandler `
-Chord 'Ctrl+Alt+s' `
-BriefDescription "RebuildHeatseekerPathInCommandLineCache" `
-LongDescription "Rebuilds the heatseaker cache" `
-ScriptBlock {
$job = start-job {
param($path)
Get-ChildItem -Name -Attributes !D -Recurse $path > $path/.hscache
} -arg $(pwd)
while( $job.State -ne "Completed") {
Write-Progress -Activity ".hscache-build " -Status $(get-childitem .hscache).length
sleep -m 200
}
Write-Progress -Activity ".hscache-build" -Completed
}
Currently I have the below setup. My folder heirachy is about 200k files and the suggested solution has a 10 to 15 second response time. To make hs respond immediately I have a cache of the directory contents which I can rebuild with ctrl-alt-s.
It's not the ideal solution. What would be nice is a companion tool that keeps the cache up to date by monitoring the file system. Not sure if this is possible in a general way. Just though I'd throw this out to you. Great tool by the way. Even with rebuilding the cache manually it's awesome.