feat(tui): add fzf-based folder browser for export/import path prompts
Read-Host has no tab-completion (that's a top-level PSReadLine feature, not available to script prompts), so reuse the fzf dependency already required for menus to browse folders interactively instead: navigate into subfolders, go up with .., confirm current folder, or type a path manually. Falls back to plain Read-Host when fzf isn't installed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -107,6 +107,41 @@ function Select-MenuItem
|
||||
return Show-NumberedMenu -Items $Items -Header $Header -Multi:$Multi
|
||||
}
|
||||
|
||||
function Select-FolderPath
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Prompt,
|
||||
[string]$StartPath = (Get-Location).Path
|
||||
)
|
||||
if(-not (Test-FzfAvailable))
|
||||
{
|
||||
return Read-Host $Prompt
|
||||
}
|
||||
|
||||
$current = if(Test-Path -LiteralPath $StartPath) { (Resolve-Path -LiteralPath $StartPath).Path } else { (Get-Location).Path }
|
||||
|
||||
while($true)
|
||||
{
|
||||
$entries = @("[Use this folder]", "[Type path manually]")
|
||||
$parent = Split-Path -Path $current -Parent
|
||||
if($parent) { $entries += ".." }
|
||||
$subdirs = Get-ChildItem -LiteralPath $current -Directory -ErrorAction SilentlyContinue | Sort-Object Name | ForEach-Object { "$($_.Name)/" }
|
||||
$entries += $subdirs
|
||||
|
||||
$choice = $entries | fzf --header="$Prompt [current: $current]"
|
||||
if(-not $choice) { return $null }
|
||||
|
||||
switch ($choice)
|
||||
{
|
||||
"[Use this folder]" { return $current }
|
||||
"[Type path manually]" { $typed = Read-Host "Enter path"; if(-not [string]::IsNullOrWhiteSpace($typed)) { return $typed }; continue }
|
||||
".." { $current = $parent; continue }
|
||||
default { $current = Join-Path $current ($choice.TrimEnd('/')); continue }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Read-YesNo
|
||||
{
|
||||
param(
|
||||
@@ -275,18 +310,18 @@ while($true)
|
||||
if([string]::IsNullOrWhiteSpace($tenantIdForReport)) { Write-Host "Tenant ID is required." -ForegroundColor Red; continue }
|
||||
}
|
||||
|
||||
$exportPath = Read-Host "Export path (where to save fresh data)"
|
||||
$exportPath = Select-FolderPath -Prompt "Select export path (where to save fresh data)"
|
||||
if([string]::IsNullOrWhiteSpace($exportPath)) { Write-Host "Export path is required." -ForegroundColor Red; continue }
|
||||
$backupRoot = $exportPath
|
||||
}
|
||||
else
|
||||
{
|
||||
$backupRoot = Read-Host "Backup root path (folder containing 'Settings Catalog', etc.)"
|
||||
$backupRoot = Select-FolderPath -Prompt "Select backup root (folder containing 'Settings Catalog', etc.)"
|
||||
if([string]::IsNullOrWhiteSpace($backupRoot)) { Write-Host "Backup root is required." -ForegroundColor Red; continue }
|
||||
if(-not (Test-Path $backupRoot)) { Write-Host "Path not found: $backupRoot" -ForegroundColor Red; continue }
|
||||
}
|
||||
|
||||
$outputDir = Read-Host "Enter output directory for reports"
|
||||
$outputDir = Select-FolderPath -Prompt "Select output directory for reports"
|
||||
if([string]::IsNullOrWhiteSpace($outputDir)) { Write-Host "Output directory is required." -ForegroundColor Red; continue }
|
||||
|
||||
$includeAssignmentsInSettings = $false
|
||||
@@ -358,8 +393,8 @@ while($true)
|
||||
if(-not $typeSelection) { continue }
|
||||
|
||||
# 4. Path
|
||||
$pathPrompt = if($action -eq "Export") { "Enter export root folder path" } else { "Enter import root folder path" }
|
||||
$path = Read-Host $pathPrompt
|
||||
$pathPrompt = if($action -eq "Export") { "Select export root folder" } else { "Select import root folder" }
|
||||
$path = Select-FolderPath -Prompt $pathPrompt
|
||||
if([string]::IsNullOrWhiteSpace($path)) { Write-Host "Path is required." -ForegroundColor Red; return $null }
|
||||
|
||||
# 5. Name Filter
|
||||
|
||||
Reference in New Issue
Block a user