41 lines
2.3 KiB
TypeScript
41 lines
2.3 KiB
TypeScript
/**
|
|
* 顶部问答带给模型的材料:文件是路径加开头若干行,文件夹是路径加这一层的名字,还有它所在的 git 仓库根(回答里的链接从这里算路径)。
|
|
* 路径见 [QaLocation.promptPath]:工作区里的是相对路径,工作区外的库文件是绝对路径。
|
|
*/
|
|
|
|
import type { Uri, WorkspaceFolder } from 'vscode'
|
|
import type { ExcludeSetting } from '../explorer/fileEntries'
|
|
import type { QaLocation } from '../folderStore'
|
|
import type { PathAskSubject, PathChild } from './pathAskPrompt'
|
|
import { FileType, workspace } from 'vscode'
|
|
import { repoRootOf } from '../editor/repoPath'
|
|
import { createExcludeMatcher, sortEntries } from '../explorer/fileEntries'
|
|
import { readFileHead } from './pathAskContext'
|
|
import { displayRelativePath } from './pathQa'
|
|
|
|
export async function describePath(target: { uri: Uri, isDirectory: boolean, at: QaLocation }): Promise<PathAskSubject> {
|
|
const { uri, isDirectory, at } = target
|
|
const repoRoot = await repoRootOf(uri.fsPath)
|
|
const where = { path: displayRelativePath(at.promptPath), ...(at.outsideDir !== undefined && { outside: true as const }), ...(repoRoot !== undefined && { repoRoot }) }
|
|
if (isDirectory)
|
|
return { kind: 'folder', ...where, children: await folderChildren(uri, at.folder, at.key) }
|
|
return { kind: 'file', ...where, head: await readFileHead(uri.fsPath) }
|
|
}
|
|
|
|
/** 文件夹这一层的子文件和子目录;files.exclude 排除的不列。列不出来时只留原因。 */
|
|
async function folderChildren(uri: Uri, folder: WorkspaceFolder, relativePath: string): Promise<PathChild[] | { unavailable: string }> {
|
|
let entries: [string, FileType][]
|
|
try {
|
|
entries = await workspace.fs.readDirectory(uri)
|
|
}
|
|
catch (err) {
|
|
const message = err instanceof Error ? err.message : String(err)
|
|
return { unavailable: `列不出来(${message})。` }
|
|
}
|
|
const excluded = createExcludeMatcher(workspace.getConfiguration('files', folder).get<ExcludeSetting>('exclude'))
|
|
const names = new Set(entries.map(([name]) => name))
|
|
return sortEntries(entries.map(([name, type]) => ({ name, isDirectory: (type & FileType.Directory) !== 0 })))
|
|
.filter(entry => !excluded(relativePath ? `${relativePath}/${entry.name}` : entry.name, names))
|
|
.map(entry => ({ name: entry.name, kind: entry.isDirectory ? 'folder' : 'file' }))
|
|
}
|