@trim21/personal-pi-extensions 0.1.467 → 0.1.469
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/package.json +1 -1
- package/src/lib/lsp/server-config.ts +47 -2
package/README.md
CHANGED
|
@@ -365,10 +365,11 @@ read/edit/write 工具内置 LSP 诊断(写文件后等待并报告 ERROR 级
|
|
|
365
365
|
"bin": "gopls",
|
|
366
366
|
"args": [],
|
|
367
367
|
"cwd": "{root}", // 支持 {root} / {cwd} 模板
|
|
368
|
+
"env": { "VIRTUAL_ENV": "{root}/.venv", "PATH_SUFFIX": "${EXTRA_PATH}" }, // 追加到子进程环境变量;值支持 {root} / {cwd} 模板与 ${VAR} 引用
|
|
368
369
|
"languageIdByExtension": { ".go": "go" },
|
|
369
370
|
"startupTimeoutMs": 45000,
|
|
370
371
|
"diagnosticsWaitMs": 1500,
|
|
371
|
-
"initializationOptions": {}, // → initialize
|
|
372
|
+
"initializationOptions": { "pythonPath": "${VIRTUAL_ENV:-/opt/venv}/bin/python" }, // → initialize 请求;字符串值支持 ${VAR} / ${VAR:-default} 插值
|
|
372
373
|
"settings": {}, // → didChangeConfiguration / workspace/configuration 请求
|
|
373
374
|
},
|
|
374
375
|
},
|
|
@@ -389,7 +390,8 @@ read/edit/write 工具内置 LSP 诊断(写文件后等待并报告 ERROR 级
|
|
|
389
390
|
- `bin`:可执行文件——绝对路径、相对调用 cwd 的路径,或名字(先在项目内 `node_modules/.bin`、`.venv/bin`、`venv/bin` 找,再走 PATH)
|
|
390
391
|
- `languageIdByExtension`:扩展名 → LSP languageId(didOpen 用);缺省回退内置映射表
|
|
391
392
|
- `startupTimeoutMs` / `diagnosticsWaitMs`:per-server 超时,覆盖全局配置与默认值
|
|
392
|
-
- `
|
|
393
|
+
- `env`:追加到 LSP 子进程的环境变量(在 `process.env` 之上合并);值支持 `{root}` / `{cwd}` 模板与 `${VAR}` 环境变量引用
|
|
394
|
+
- `initializationOptions` 与 `settings` 按 LSP 语义分离:前者进 initialize 请求,后者进 didChangeConfiguration / workspace/configuration 请求;`initializationOptions` 的字符串值(含嵌套对象/数组)在启动时做 `${VAR}` 插值,`${VAR:-default}` 在变量未定义或为空时用 default,未定义且无 default 替换为空字符串;插值时可引用 `env` 里配置的变量
|
|
393
395
|
|
|
394
396
|
没有内置默认服务器:`servers` 的 key 就是服务器 id,全部来自你的配置,未定义 `servers` 时不启动任何语言服务器。executable 的发现逻辑(如 tsserver 路径、venv 里的 python)不内置,需要时用 `bin` / `args` / `settings` 自行表达。
|
|
395
397
|
|
package/package.json
CHANGED
|
@@ -39,13 +39,15 @@ export const serverConfigSchema = Type.Object({
|
|
|
39
39
|
args: Type.Optional(Type.Array(Type.String())),
|
|
40
40
|
/** 启动工作目录,支持 {root} / {cwd} 模板;缺省 {root}。 */
|
|
41
41
|
cwd: Type.Optional(Type.String()),
|
|
42
|
+
/** 追加到子进程的环境变量;值支持 {root} / {cwd} 模板与 ${VAR} 环境变量引用。 */
|
|
43
|
+
env: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
42
44
|
/** 文件扩展名(含点)→ LSP languageId,didOpen 用;缺省回退内置映射表。 */
|
|
43
45
|
languageIdByExtension: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
44
46
|
/** initialize 握手超时(ms);缺省用全局配置 / client 默认。 */
|
|
45
47
|
startupTimeoutMs: Type.Optional(Type.Number({ minimum: 1 })),
|
|
46
48
|
/** 写文件后等待诊断的时长(ms);缺省用全局配置 / client 默认。 */
|
|
47
49
|
diagnosticsWaitMs: Type.Optional(Type.Number({ minimum: 1 })),
|
|
48
|
-
/** initialize 请求的 initializationOptions
|
|
50
|
+
/** initialize 请求的 initializationOptions;字符串值支持 ${VAR} / ${VAR:-default} 插值。 */
|
|
49
51
|
initializationOptions: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
|
|
50
52
|
/** didChangeConfiguration / workspace/configuration 请求的 settings。 */
|
|
51
53
|
settings: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
|
|
@@ -77,6 +79,44 @@ function resolveTemplate(template: string, root: string, cwd: string): string {
|
|
|
77
79
|
return template.split("{root}").join(root).split("{cwd}").join(cwd);
|
|
78
80
|
}
|
|
79
81
|
|
|
82
|
+
/** ${VAR} / ${VAR:-default} 插值;shell 语义:未定义或空时用 default(缺省空字符串)。 */
|
|
83
|
+
const envVarPattern = /\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g;
|
|
84
|
+
|
|
85
|
+
function interpolateEnvVars(value: string, env: NodeJS.ProcessEnv): string {
|
|
86
|
+
return value.replaceAll(envVarPattern, (_match, name: string, fallback?: string) => {
|
|
87
|
+
const resolved = env[name];
|
|
88
|
+
return resolved !== undefined && resolved !== "" ? resolved : (fallback ?? "");
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** 深遍历配置值,对所有字符串做环境变量插值。 */
|
|
93
|
+
function interpolateEnvDeep(value: unknown, env: NodeJS.ProcessEnv): unknown {
|
|
94
|
+
if (typeof value === "string") return interpolateEnvVars(value, env);
|
|
95
|
+
if (Array.isArray(value)) return value.map((item) => interpolateEnvDeep(item, env));
|
|
96
|
+
if (value !== null && typeof value === "object") {
|
|
97
|
+
return Object.fromEntries(
|
|
98
|
+
Object.entries(value).map(([key, item]) => [key, interpolateEnvDeep(item, env)]),
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** 解析 per-server env:值先做 {root} / {cwd} 模板,再做环境变量引用插值。 */
|
|
105
|
+
function resolveEnv(
|
|
106
|
+
config: Record<string, string> | undefined,
|
|
107
|
+
root: string,
|
|
108
|
+
cwd: string,
|
|
109
|
+
): NodeJS.ProcessEnv | undefined {
|
|
110
|
+
const entries = Object.entries(config ?? {});
|
|
111
|
+
if (entries.length === 0) return undefined;
|
|
112
|
+
return Object.fromEntries(
|
|
113
|
+
entries.map(([key, value]) => [
|
|
114
|
+
key,
|
|
115
|
+
interpolateEnvVars(resolveTemplate(value, root, cwd), process.env),
|
|
116
|
+
]),
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
80
120
|
/** 解析可执行文件:绝对/相对路径直接用;名字走项目工作区(node_modules/.bin 等)→ PATH。 */
|
|
81
121
|
async function resolveBinary(bin: string, root: string, cwd: string): Promise<string | undefined> {
|
|
82
122
|
if (isAbsolute(bin)) return existsSync(bin) ? bin : undefined;
|
|
@@ -144,11 +184,16 @@ export class ConfigAdapter implements LspServerAdapter {
|
|
|
144
184
|
if (!bin) return undefined;
|
|
145
185
|
const resolved = await resolveBinary(bin, root, cwd);
|
|
146
186
|
if (!resolved) return undefined;
|
|
187
|
+
const env = resolveEnv(this.config.env, root, cwd);
|
|
147
188
|
return {
|
|
148
189
|
process: spawnProcess(resolved, this.config.args ?? [], {
|
|
149
190
|
cwd: resolveTemplate(this.config.cwd ?? "{root}", root, cwd),
|
|
191
|
+
env,
|
|
150
192
|
}),
|
|
151
|
-
initialization: this.config.initializationOptions,
|
|
193
|
+
initialization: interpolateEnvDeep(this.config.initializationOptions, {
|
|
194
|
+
...process.env,
|
|
195
|
+
...env,
|
|
196
|
+
}) as Record<string, unknown> | undefined,
|
|
152
197
|
settings: this.config.settings,
|
|
153
198
|
languageIds: this.config.languageIdByExtension,
|
|
154
199
|
};
|