✨ feat(vscode): 代码阅读预览里工作区外的库文件也能问 AI,问答记进第一个工作区文件夹,重写注释不对库文件开放
This commit is contained in:
1 parent
cecae0e244
commit
39dfd9b084
24 files changed
+463
-79
No files matched your search
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* 按文件 / 目录记东西的一份表(文件注释、代码问答):每个工作区文件夹一份,落盘到 `.spx` 里的一个 JSON 文件,
|
||||
* 形状是 `{ "相对路径": 值 }`。键相对这个工作区文件夹、`/` 分隔;改名、挪位置、删除时整棵子树跟着走。
|
||||
* 代码问答还记工作区外的库文件,键是 `~/…` 或绝对路径(见 [outsideKey])。
|
||||
*/
|
||||
|
||||
import { promises as fsp } from 'node:fs'
|
||||
@@ -31,6 +32,38 @@ export function toPathKey(rootPath: string, targetPath: string): string | undefi
|
||||
return normalizeKey(path.posix.relative(rootPath, targetPath))
|
||||
}
|
||||
|
||||
/**
|
||||
* 工作区外的文件 / 目录(比如库源码)的键:在家目录下写成 `~/…`,别处写绝对路径。
|
||||
* 工作区里的键是相对路径,开头不会是 `~/` 或 `/`,两边撞不上。
|
||||
*
|
||||
* @param targetPath 文件 / 目录的 `Uri.path`
|
||||
* @param homePath 家目录的 `Uri.path`
|
||||
*/
|
||||
export function outsideKey(targetPath: string, homePath: string): string {
|
||||
const underHome = toPathKey(homePath, targetPath)
|
||||
return underHome === undefined ? path.posix.normalize(targetPath).replace(/\/+$/, '') : `~/${underHome}`
|
||||
}
|
||||
|
||||
/** 工作区外的键(见 [outsideKey])在磁盘上的 `Uri.path`;工作区里的相对路径键返回 `undefined`。 */
|
||||
export function outsidePath(key: string, homePath: string): string | undefined {
|
||||
if (key.startsWith('~/'))
|
||||
return path.posix.join(homePath, key.slice(2))
|
||||
return key.startsWith('/') ? key : undefined
|
||||
}
|
||||
|
||||
/** 读表时把一个键规范成统一写法:相对路径同 [normalizeKey],工作区外的 `~/…`、绝对路径(见 [outsideKey])也认;跑出家目录的、空的返回 `undefined`。 */
|
||||
export function tableKey(raw: string): string | undefined {
|
||||
if (raw.startsWith('~/')) {
|
||||
const underHome = normalizeKey(raw.slice(2))
|
||||
return underHome === undefined ? undefined : `~/${underHome}`
|
||||
}
|
||||
if (raw.startsWith('/')) {
|
||||
const absolute = path.posix.normalize(raw).replace(/\/+$/, '')
|
||||
return absolute === '' ? undefined : absolute
|
||||
}
|
||||
return normalizeKey(raw)
|
||||
}
|
||||
|
||||
function isUnder(candidate: string, key: string): boolean {
|
||||
return candidate === key || candidate.startsWith(`${key}/`)
|
||||
}
|
||||
@@ -68,7 +101,7 @@ function fileIn<T>(workspaceRoot: string, file: PathMapFile<T>): string {
|
||||
return path.join(workspaceRoot, ...file.path.split('/'))
|
||||
}
|
||||
|
||||
/** 读工作区文件夹里的这份表。文件缺失 / 解析失败 / 不是对象都返回 `{}`;键不合法、值认不出的条目跳过。 */
|
||||
/** 读工作区文件夹里的这份表。文件缺失 / 解析失败 / 不是对象都返回 `{}`;键认不出(见 [tableKey])、值认不出的条目跳过。 */
|
||||
export async function readPathMap<T>(workspaceRoot: string, file: PathMapFile<T>): Promise<PathMap<T>> {
|
||||
let raw: string
|
||||
try {
|
||||
@@ -83,7 +116,7 @@ export async function readPathMap<T>(workspaceRoot: string, file: PathMapFile<T>
|
||||
return {}
|
||||
const map: PathMap<T> = {}
|
||||
for (const [rawKey, rawValue] of Object.entries(parsed as Record<string, unknown>)) {
|
||||
const key = normalizeKey(rawKey)
|
||||
const key = tableKey(rawKey)
|
||||
const value = file.parse(rawValue)
|
||||
if (key !== undefined && value !== undefined)
|
||||
map[key] = value
|
||||
|
||||
Reference in new issue
Block a user