48 lines · 1.9 KB · TypeScript
RawDownload
// Enough hits to look past same-named neighbours (`ChatView.test.tsx`) without// asking for a full listing on a single click.export const WORKSPACE_BASENAME_LOOKUP_LIMIT = 25; // One counter for every caller: they all open the same panel, so the newest// click wins regardless of which one started the lookup.let latestLookupSequence = 0; /** Call the returned predicate when the search settles; false means a later click superseded it. */export function claimWorkspaceBasenameLookup(): () => boolean {  latestLookupSequence += 1;  const claimed = latestLookupSequence;  return () => claimed === latestLookupSequence;} export interface WorkspaceEntryCandidate {  readonly path: string;  readonly kind: "file" | "directory";} function basenameOfPath(path: string): string {  const separatorIndex = Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\"));  return separatorIndex >= 0 ? path.slice(separatorIndex + 1) : path;} export function needsWorkspaceBasenameLookup(relativePath: string): boolean {  const trimmed = relativePath.trim();  return trimmed.length > 0 && !trimmed.includes("/") && !trimmed.includes("\\");} export function pickWorkspaceBasenameMatch(  basename: string,  entries: ReadonlyArray<WorkspaceEntryCandidate>,): string | null {  const target = basename.trim();  if (!target) return null;  const files = entries.filter((entry) => entry.kind === "file");  const exact = files.find((entry) => basenameOfPath(entry.path) === target);  if (exact) return exact.path;  // Folded matching covers casing that drifted from disk, but `FOO.ts` against  // both `Foo.ts` and `foo.ts` has no right answer, so it resolves to nothing  // rather than opening whichever the index ranked first.  const folded = target.toLowerCase();  const foldedMatches = files.filter(    (entry) => basenameOfPath(entry.path).toLowerCase() === folded,  );  return foldedMatches.length === 1 ? (foldedMatches[0]?.path ?? null) : null;}