@narumitw/pi-python-lsp 0.1.10 → 0.1.12

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 CHANGED
@@ -14,6 +14,7 @@ Use it to give Pi reliable Python type diagnostics, Ruff lint diagnostics, forma
14
14
  - Computes or writes Ruff source actions such as `source.fixAll.ruff` and `source.organizeImports.ruff`.
15
15
  - Supports workspace roots, file limits, and recursive Python file discovery.
16
16
  - Starts language servers only for tool calls, then shuts them down.
17
+ - Shows statusline activity only while Python LSP tools are running.
17
18
  - Provides clear setup errors when ty or Ruff is missing.
18
19
 
19
20
  ## 📦 Install
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narumitw/pi-python-lsp",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Pi extension that exposes ty and Ruff language-server tools for Python.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/python-lsp.ts CHANGED
@@ -28,6 +28,10 @@ interface ServerCommand {
28
28
  args: string[];
29
29
  }
30
30
 
31
+ interface StatusContext {
32
+ ui: { setStatus: (key: string, value: string | undefined) => void };
33
+ }
34
+
31
35
  interface LspPosition {
32
36
  line: number;
33
37
  character: number;
@@ -106,8 +110,8 @@ const tyDiagnosticsTool = defineTool({
106
110
  "If ty is missing, report the configuration error and suggest installing ty or setting PI_TY_LSP_COMMAND.",
107
111
  ],
108
112
  parameters: Type.Object(PathsParameters),
109
- async execute(_toolCallId, params, signal) {
110
- return runDiagnostics("ty", params, signal);
113
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
114
+ return runDiagnostics("ty", params, signal, ctx);
111
115
  },
112
116
  });
113
117
 
@@ -121,8 +125,8 @@ const ruffDiagnosticsTool = defineTool({
121
125
  "If ruff is missing, report the configuration error and suggest installing ruff or setting PI_RUFF_LSP_COMMAND.",
122
126
  ],
123
127
  parameters: Type.Object(PathsParameters),
124
- async execute(_toolCallId, params, signal) {
125
- return runDiagnostics("ruff", params, signal);
128
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
129
+ return runDiagnostics("ruff", params, signal, ctx);
126
130
  },
127
131
  });
128
132
 
@@ -140,12 +144,13 @@ const ruffFormatTool = defineTool({
140
144
  Type.Boolean({ description: "Write formatted text back to the file. Defaults to false." }),
141
145
  ),
142
146
  }),
143
- async execute(_toolCallId, params, signal) {
147
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
144
148
  const root = resolveRoot(params.root);
145
149
  const file = resolvePythonFile(root, params.path);
146
150
  const client = new LspClient("ruff", getServerCommand("ruff"), root, getTimeoutMs("ruff"));
147
151
  const abort = () => client.close();
148
152
  signal?.addEventListener("abort", abort, { once: true });
153
+ ctx.ui.setStatus(STATUS_KEY, "python-lsp: ruff format");
149
154
 
150
155
  try {
151
156
  await client.start();
@@ -168,6 +173,7 @@ const ruffFormatTool = defineTool({
168
173
  text: params.write ? undefined : newText,
169
174
  });
170
175
  } finally {
176
+ ctx.ui.setStatus(STATUS_KEY, undefined);
171
177
  signal?.removeEventListener("abort", abort);
172
178
  await client.shutdown();
173
179
  }
@@ -194,13 +200,14 @@ const ruffFixTool = defineTool({
194
200
  Type.Boolean({ description: "Write fixed text back to the file. Defaults to false." }),
195
201
  ),
196
202
  }),
197
- async execute(_toolCallId, params, signal) {
203
+ async execute(_toolCallId, params, signal, _onUpdate, ctx) {
198
204
  const root = resolveRoot(params.root);
199
205
  const file = resolvePythonFile(root, params.path);
200
206
  const actionKind = params.kind?.trim() || "source.fixAll.ruff";
201
207
  const client = new LspClient("ruff", getServerCommand("ruff"), root, getTimeoutMs("ruff"));
202
208
  const abort = () => client.close();
203
209
  signal?.addEventListener("abort", abort, { once: true });
210
+ ctx.ui.setStatus(STATUS_KEY, "python-lsp: ruff fix");
204
211
 
205
212
  try {
206
213
  await client.start();
@@ -228,6 +235,7 @@ const ruffFixTool = defineTool({
228
235
  text: params.write ? undefined : newText,
229
236
  });
230
237
  } finally {
238
+ ctx.ui.setStatus(STATUS_KEY, undefined);
231
239
  signal?.removeEventListener("abort", abort);
232
240
  await client.shutdown();
233
241
  }
@@ -244,12 +252,11 @@ export default function pythonLsp(pi: ExtensionAPI) {
244
252
  description: "Show Python LSP extension configuration",
245
253
  handler: async (_args, ctx) => {
246
254
  ctx.ui.notify(buildStatusMessage(), statusLevel());
247
- updateStatus(ctx);
248
255
  },
249
256
  });
250
257
 
251
258
  pi.on("session_start", (_event, ctx) => {
252
- updateStatus(ctx);
259
+ ctx.ui.setStatus(STATUS_KEY, undefined);
253
260
  });
254
261
 
255
262
  pi.on("session_shutdown", (_event, ctx) => {
@@ -261,6 +268,7 @@ async function runDiagnostics(
261
268
  kind: ServerKind,
262
269
  params: { root?: string; paths?: string[]; limit?: number },
263
270
  signal: AbortSignal | undefined,
271
+ ctx: StatusContext,
264
272
  ) {
265
273
  const root = resolveRoot(params.root);
266
274
  const files = collectPythonFiles(root, params.paths, params.limit ?? DEFAULT_FILE_LIMIT);
@@ -271,6 +279,7 @@ async function runDiagnostics(
271
279
  const client = new LspClient(kind, getServerCommand(kind), root, getTimeoutMs(kind));
272
280
  const abort = () => client.close();
273
281
  signal?.addEventListener("abort", abort, { once: true });
282
+ ctx.ui.setStatus(STATUS_KEY, `python-lsp: ${kind} diagnostics`);
274
283
 
275
284
  try {
276
285
  await client.start();
@@ -292,6 +301,7 @@ async function runDiagnostics(
292
301
  summary: summarize(entries),
293
302
  });
294
303
  } finally {
304
+ ctx.ui.setStatus(STATUS_KEY, undefined);
295
305
  signal?.removeEventListener("abort", abort);
296
306
  await client.shutdown();
297
307
  }
@@ -318,17 +328,6 @@ function getTimeoutMs(kind: ServerKind) {
318
328
  return Number.isFinite(rawValue) && rawValue > 0 ? rawValue : DEFAULT_TIMEOUT_MS;
319
329
  }
320
330
 
321
- function updateStatus(ctx: {
322
- ui: { setStatus: (key: string, value: string | undefined) => void };
323
- }) {
324
- const tyReady = commandExists(getServerCommand("ty").command);
325
- const ruffReady = commandExists(getServerCommand("ruff").command);
326
- ctx.ui.setStatus(
327
- STATUS_KEY,
328
- `python-lsp: ty ${tyReady ? "ready" : "missing"}, ruff ${ruffReady ? "ready" : "missing"}`,
329
- );
330
- }
331
-
332
331
  function buildStatusMessage() {
333
332
  const ty = getServerCommand("ty");
334
333
  const ruff = getServerCommand("ruff");