Skip to content

Commit 5a57496

Browse files
committed
feat(search): Add in-memory index search function
Add search_by_index() which performs zero-I/O substring matching: - Iterates cached app names for name matches - Iterates cached binary names for binary-only matches - Only JSON-parses manifests for apps that matched - Guard clause returns early on null/empty query Uses IndexOf() with OrdinalIgnoreCase for case-insensitive substring matching, consistent with SQLite LIKE '%query%' behavior.
1 parent 5b1221c commit 5a57496

1 file changed

Lines changed: 44 additions & 0 deletions

File tree

libexec/scoop-search.ps1

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,50 @@ function build_search_cache {
9191
return $true
9292
}
9393

94+
function search_by_index($query) {
95+
if (-not $query) { return }
96+
$matched = @{}
97+
# Search app names (case-insensitive substring)
98+
foreach ($appName in $searchIndexApps.Keys) {
99+
if ($appName.IndexOf($query, [StringComparison]::OrdinalIgnoreCase) -ge 0) {
100+
if (-not $matched.ContainsKey($appName)) { $matched[$appName] = $true }
101+
}
102+
}
103+
# Search binary names (case-insensitive substring)
104+
foreach ($binName in $searchIndexBins.Keys) {
105+
if ($binName.IndexOf($query, [StringComparison]::OrdinalIgnoreCase) -ge 0) {
106+
foreach ($appName in $searchIndexBins[$binName]) {
107+
if (-not $matched.ContainsKey($appName)) { $matched[$appName] = $true }
108+
}
109+
}
110+
}
111+
# Parse manifests only for matched apps
112+
foreach ($appName in $matched.Keys) {
113+
$info = $searchIndexApps[$appName]
114+
try {
115+
$manifest = Get-Content -Path $info.path -Raw | ConvertFrom-Json -ErrorAction Stop
116+
$binaries = ''
117+
$binMatches = @()
118+
if ($manifest.bin) {
119+
foreach ($binEntry in $manifest.bin) {
120+
$exe = $null; $alias = $null
121+
if ($binEntry -is [System.Object[]]) {
122+
$exe = $binEntry[0]
123+
$alias = if ($binEntry.Count -gt 1) { $binEntry[1] } else { $null }
124+
} else { $exe = $binEntry }
125+
$exeName = [System.IO.Path]::GetFileNameWithoutExtension([string]$exe)
126+
if ($exeName.IndexOf($query, [StringComparison]::OrdinalIgnoreCase) -ge 0 -or
127+
($alias -and $alias.IndexOf($query, [StringComparison]::OrdinalIgnoreCase) -ge 0)) {
128+
$binMatches += [System.IO.Path]::GetFileName([string]$exe)
129+
}
130+
}
131+
if ($binMatches) { $binaries = $binMatches -join ' | ' }
132+
}
133+
$list.Add([PSCustomObject]@{ Name = $appName; Version = $manifest.version; Source = $info.bucket; Binaries = $binaries })
134+
} catch { }
135+
}
136+
}
137+
94138
function bin_match($manifest, $query) {
95139
if (!$manifest.bin) { return $false }
96140
$bins = foreach ($bin in $manifest.bin) {

0 commit comments

Comments
 (0)