update fixing the build of the app
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import { createRequire } from 'node:module'
|
||||
import { spawn } from 'node:child_process'
|
||||
import { relative, sep } from 'node:path'
|
||||
import { getConfig } from './config'
|
||||
@@ -6,18 +5,23 @@ import { getConfig } from './config'
|
||||
/** ripgrep is the single source of "what files are in the project": it powers
|
||||
* content search, the file-name list, AND the Explorer tree / content index
|
||||
* (via fs-service) — so gitignore + files.exclude are honored everywhere the
|
||||
* same way. Substring (fixed-string), smart-case search. */
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
let rgPath: string | null = null
|
||||
try {
|
||||
rgPath = (require('@vscode/ripgrep') as { rgPath: string }).rgPath
|
||||
// When packaged the binary is unpacked from the asar; rgPath still points
|
||||
// inside app.asar, so redirect it. No-op in dev (path has no app.asar).
|
||||
if (rgPath) rgPath = rgPath.replace(/\bapp\.asar\b/, 'app.asar.unpacked')
|
||||
} catch (e) {
|
||||
console.error('[helder] @vscode/ripgrep unavailable:', (e as Error).message)
|
||||
}
|
||||
* same way. Substring (fixed-string), smart-case search.
|
||||
*
|
||||
* @vscode/ripgrep ships as ESM, so load it with dynamic import() (works for
|
||||
* ESM and CJS) and cache the resolved binary path. */
|
||||
const rgPathPromise: Promise<string | null> = (async () => {
|
||||
try {
|
||||
const mod = await import('@vscode/ripgrep')
|
||||
let p = (mod as { rgPath: string }).rgPath
|
||||
// When packaged the binary is unpacked from the asar; rgPath still points
|
||||
// inside app.asar, so redirect it. No-op in dev (path has no app.asar).
|
||||
if (p) p = p.replace(/\bapp\.asar\b/, 'app.asar.unpacked')
|
||||
return p || null
|
||||
} catch (e) {
|
||||
console.error('[helder] @vscode/ripgrep unavailable:', (e as Error).message)
|
||||
return null
|
||||
}
|
||||
})()
|
||||
|
||||
export interface ContentHit { no: number; ln: string; ix: number }
|
||||
export interface ContentGroup { path: string; hits: ContentHit[] }
|
||||
@@ -31,8 +35,8 @@ const BASE_IGNORE = [
|
||||
const MAX_FILES = 400
|
||||
const MAX_LINE = 1000
|
||||
|
||||
export function rgAvailable(): boolean {
|
||||
return !!rgPath
|
||||
export async function rgAvailable(): Promise<boolean> {
|
||||
return !!(await rgPathPromise)
|
||||
}
|
||||
|
||||
/** Glob/ignore args derived from config (files.exclude, files.followGitignore). */
|
||||
@@ -49,9 +53,10 @@ function toRel(root: string, p: string): string {
|
||||
return relative(root, p).split(sep).join('/')
|
||||
}
|
||||
|
||||
export function searchContent(root: string, query: string): Promise<ContentGroup[]> {
|
||||
export async function searchContent(root: string, query: string): Promise<ContentGroup[]> {
|
||||
const rgPath = await rgPathPromise
|
||||
if (!rgPath || query.trim().length < 2) return []
|
||||
return new Promise((resolve) => {
|
||||
if (!rgPath || query.trim().length < 2) return resolve([])
|
||||
const child = spawn(rgPath, [
|
||||
'--json', '--fixed-strings', '--smart-case', '--hidden',
|
||||
'--max-count', '50', '--max-columns', '2000',
|
||||
@@ -90,9 +95,10 @@ export function searchContent(root: string, query: string): Promise<ContentGroup
|
||||
|
||||
/** All project files (relative paths), honoring gitignore + excludes. Includes
|
||||
* dotfiles (--hidden) so .env etc. show up unless ignored. */
|
||||
export function listFiles(root: string): Promise<string[]> {
|
||||
export async function listFiles(root: string): Promise<string[]> {
|
||||
const rgPath = await rgPathPromise
|
||||
if (!rgPath) return []
|
||||
return new Promise((resolve) => {
|
||||
if (!rgPath) return resolve([])
|
||||
const child = spawn(rgPath, ['--files', '--hidden', ...ignoreArgs(), '--', root])
|
||||
let buf = ''
|
||||
const out: string[] = []
|
||||
|
||||
@@ -289,9 +289,11 @@ body {
|
||||
/* ============ overlays ============ */
|
||||
.scrim { position:fixed; inset:0; background:rgba(8,9,11,0.5); z-index:50; display:flex; justify-content:center; align-items:flex-start; padding-top:90px; backdrop-filter:blur(1.5px); }
|
||||
.palette { width:620px; max-width:92vw; background:#212429; border:1px solid var(--border-2); border-radius:11px; box-shadow:0 24px 70px rgba(0,0,0,.55); overflow:hidden; }
|
||||
.palette .pi { display:flex; align-items:center; gap:10px; padding:12px 15px; border-bottom:1px solid var(--border); }
|
||||
.palette .pi input { flex:1; background:transparent; border:0; outline:0; color:var(--fg-0); font-size:15px; font-family:var(--ui); }
|
||||
.palette .pi .mode-chip { font-size:10px; color:var(--fg-3); border:1px solid var(--border-2); border-radius:5px; padding:2px 7px; font-family:var(--mono); }
|
||||
.palette .pi, .search-modal .pi { display:flex; align-items:center; gap:10px; padding:12px 15px; border-bottom:1px solid var(--border); }
|
||||
.palette .pi input, .search-modal .pi input { flex:1; min-width:0; background:transparent; border:0; outline:0; color:var(--fg-0); font-size:15px; font-family:var(--ui); }
|
||||
.palette .pi input::placeholder, .search-modal .pi input::placeholder { color:var(--fg-3); }
|
||||
.palette .pi svg, .search-modal .pi svg { flex:0 0 auto; }
|
||||
.palette .pi .mode-chip, .search-modal .pi .mode-chip { flex:0 0 auto; white-space:nowrap; font-size:10px; color:var(--fg-3); border:1px solid var(--border-2); border-radius:5px; padding:2px 7px; font-family:var(--mono); }
|
||||
.palette .results { max-height:380px; overflow:auto; padding:6px; }
|
||||
.pres { display:flex; align-items:center; gap:10px; padding:7px 10px; border-radius:7px; cursor:pointer; }
|
||||
.pres.sel { background:var(--accent-soft); }
|
||||
|
||||
Reference in New Issue
Block a user