Fix prompt truncation edge case and harden global state handling

Correct list truncation logic to avoid eliding prompts that already fit,
and gracefully handle narrow terminals. Sanitize project entries on load,
deduplicate registration through a shared registerPaths helper, and
simplify scanAndRegister by reusing it.
This commit is contained in:
Chris Wanstrath 2026-03-20 22:30:14 -07:00
parent da7adc674d
commit 4574749cde
2 changed files with 19 additions and 25 deletions

View File

@ -31,7 +31,7 @@ function renderSessions(
const status = statusMap.get(s) ?? "idle"
const { icon, color: bc } = styles[status]
const maxPrompt = cols - prefixWidth
const truncated = maxPrompt < 1 ? "" : maxPrompt > 3 && prompt.length > maxPrompt ? prompt.slice(0, maxPrompt - 3) + "..." : prompt
const truncated = maxPrompt < 1 ? "" : prompt.length <= maxPrompt ? prompt : maxPrompt > 3 ? prompt.slice(0, maxPrompt - 3) + "..." : prompt.slice(0, maxPrompt)
console.log(`${icon} ${bc}${s.branch.padEnd(branchWidth)}${reset} ${dim}${truncated}${reset}`)
}
}

View File

@ -101,7 +101,7 @@ async function loadGlobal(): Promise<GlobalState> {
if (await file.exists()) {
try {
const data = await file.json()
if (data && Array.isArray(data.projects)) return data
if (data && Array.isArray(data.projects)) return { projects: data.projects.filter((p: unknown) => typeof p === "string") }
} catch {}
}
return { projects: [] }
@ -117,18 +117,27 @@ export function normalizePath(dir: string): string {
return resolve(dir.replace(/^~(?=\/|$)/, homedir()))
}
/** Register a project directory in the global state. */
export async function registerProject(repoRoot: string): Promise<void> {
const normalized = normalizePath(repoRoot)
async function registerPaths(paths: string[]): Promise<void> {
if (paths.length === 0) return
await withGlobalLock(async () => {
const gs = await loadGlobal()
if (!gs.projects.includes(normalized)) {
gs.projects.push(normalized)
await saveGlobal(gs)
const existing = new Set(gs.projects)
let changed = false
for (const p of paths) {
if (!existing.has(p)) {
gs.projects.push(p)
changed = true
}
}
if (changed) await saveGlobal(gs)
})
}
/** Register a project directory in the global state. */
export async function registerProject(repoRoot: string): Promise<void> {
await registerPaths([normalizePath(repoRoot)])
}
/** Remove a project directory from the global state. */
export async function unregisterProject(dir: string): Promise<boolean> {
const target = normalizePath(dir)
@ -165,26 +174,11 @@ export async function scanAndRegister(dir: string, maxDepth = 5): Promise<string
}
const children = entries.filter(e => e.isDirectory() && !e.isSymbolicLink() && !e.name.startsWith(".") && e.name !== "node_modules")
await Promise.all(children.map(entry => walk(join(d, entry.name), depth + 1)))
for (const entry of children) await walk(join(d, entry.name), depth + 1)
}
await walk(root, 0)
if (found.length > 0) {
await withGlobalLock(async () => {
const gs = await loadGlobal()
const existing = new Set(gs.projects)
let changed = false
for (const p of found) {
if (!existing.has(p)) {
gs.projects.push(p)
changed = true
}
}
if (changed) await saveGlobal(gs)
})
}
await registerPaths(found)
return found
}