dsh-vscode-mode 0.5.3 → 0.7.0

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.
Files changed (77) hide show
  1. package/README.md +72 -2
  2. package/lib/client.js +12082 -6420
  3. package/lib/client.js.map +1 -1
  4. package/lib/index.js +2750 -147
  5. package/lib/index.js.map +1 -1
  6. package/package.json +1 -1
  7. package/src/client/copyText.ts +28 -0
  8. package/src/client/dap/BpWidget.ts +262 -0
  9. package/src/client/dap/bpMenu.ts +91 -0
  10. package/src/client/dap/bpRowMenu.ts +53 -0
  11. package/src/client/dap/breakpoints.ts +222 -0
  12. package/src/client/dap/decorate.ts +128 -0
  13. package/src/client/dap/hintLine.ts +29 -0
  14. package/src/client/dap/hover.ts +166 -0
  15. package/src/client/dap/hoverMode.ts +159 -0
  16. package/src/client/dap/hoverTree.ts +722 -0
  17. package/src/client/dap/launchInsert.ts +229 -0
  18. package/src/client/dap/launchSnippetProvider.ts +206 -0
  19. package/src/client/dap/modelPath.ts +23 -0
  20. package/src/client/dap/panelSplit.ts +105 -0
  21. package/src/client/dap/pidPick.ts +24 -0
  22. package/src/client/dap/store.ts +571 -0
  23. package/src/client/dap/toolbarDrag.ts +51 -0
  24. package/src/client/dap/trace.ts +22 -0
  25. package/src/client/dap/variableTree.ts +62 -0
  26. package/src/client/fileClipboard.ts +46 -0
  27. package/src/client/index.ts +12 -3
  28. package/src/client/monaco/lsp/index.ts +15 -0
  29. package/src/client/monaco/lsp/providers.ts +2 -0
  30. package/src/client/monaco/theme.ts +15 -0
  31. package/src/client/openWithDialog.ts +66 -0
  32. package/src/client/searchSeed.ts +36 -0
  33. package/src/client/sidebar/contextMenu.ts +51 -10
  34. package/src/client/sidebar/menuItems.ts +473 -50
  35. package/src/client/sidebar/panels/DebugPanel.ts +613 -0
  36. package/src/client/sidebar/panels/SearchPanel.ts +24 -3
  37. package/src/client/sidebar/panels/SvnPanel.ts +167 -23
  38. package/src/client/sidebar/panels/index.ts +19 -0
  39. package/src/client/sidebar/types.ts +8 -0
  40. package/src/client/styles/editor.css +176 -0
  41. package/src/client/svnActions.ts +18 -1
  42. package/src/client/svnLog.ts +3 -3
  43. package/src/client/svnStatus.ts +140 -2
  44. package/src/client/tabActions.ts +22 -10
  45. package/src/client/ui/EditorView.ts +625 -23
  46. package/src/client/ui/OfficialSideTab.ts +1 -0
  47. package/src/client/ui/PromptDialog.ts +63 -0
  48. package/src/client/ui/SideBySideDiff.tsx +214 -29
  49. package/src/client/ui/SideEditorTab.ts +1 -0
  50. package/src/client/ui/SvnDiffPanel.ts +21 -8
  51. package/src/client/ui/SvnLogDialog.ts +44 -2
  52. package/src/client/ui/SvnPatchDialog.ts +63 -0
  53. package/src/client/ui/SvnSumDialog.ts +77 -0
  54. package/src/client/ui/commandCatalog.ts +63 -0
  55. package/src/client/ui/svnExport.ts +71 -0
  56. package/src/dap/configSnippets.ts +269 -0
  57. package/src/dap/discovery.ts +198 -0
  58. package/src/dap/launchConfig.ts +127 -0
  59. package/src/dap/manager.ts +588 -0
  60. package/src/dap/processList.ts +76 -0
  61. package/src/dap/protocol.ts +80 -0
  62. package/src/dap/provider.ts +49 -0
  63. package/src/dap/rpc.ts +192 -0
  64. package/src/dap/sourcePath.ts +82 -0
  65. package/src/index.ts +7 -3
  66. package/src/lsp/providers.ts +3 -2
  67. package/src/reveal.ts +31 -20
  68. package/src/rpc.ts +209 -5
  69. package/src/search/ripgrep.ts +127 -11
  70. package/src/shared/dap.ts +262 -0
  71. package/src/shared/fsNames.ts +115 -0
  72. package/src/shared/keybindings.ts +9 -0
  73. package/src/shared/rpc.ts +52 -2
  74. package/src/shared/svn.ts +147 -0
  75. package/src/shared/svnActions.ts +20 -0
  76. package/src/svn.ts +320 -11
  77. package/src/workspace.ts +0 -75
@@ -258,7 +258,7 @@ export async function svnDiffRev(sessionId: string | undefined, path: string, re
258
258
  try {
259
259
  const res = await rpc('svn.diffRev', { sessionId, path, revision })
260
260
  if (!res.ok) return { ok: false, left: null, right: null, error: res.error }
261
- return { ok: true, left: res.left ?? null, right: res.right ?? null, reason: res.reason, error: res.error }
261
+ return { ok: true, left: res.left ?? null, right: res.right ?? null, reason: res.reason, error: res.error, binary: res.binary === true, encodingHint: res.encodingHint === true }
262
262
  } catch (error) {
263
263
  return { ok: false, left: null, right: null, error: String(error) }
264
264
  }
@@ -278,7 +278,7 @@ export async function svnDiffPair(sessionId: string | undefined, path: string, r
278
278
  try {
279
279
  const res = await rpc('svn.diffPair', { sessionId, path, revA, revB })
280
280
  if (!res.ok) return { ok: false, left: null, right: null, error: res.error }
281
- return { ok: true, left: res.left ?? null, right: res.right ?? null, reason: res.reason, error: res.error }
281
+ return { ok: true, left: res.left ?? null, right: res.right ?? null, reason: res.reason, error: res.error, binary: res.binary === true, encodingHint: res.encodingHint === true }
282
282
  } catch (error) {
283
283
  return { ok: false, left: null, right: null, error: String(error) }
284
284
  }
@@ -297,7 +297,7 @@ export async function svnDiffWorking(sessionId: string | undefined, path: string
297
297
  try {
298
298
  const res = await rpc('svn.diffWorking', { sessionId, path, revision })
299
299
  if (!res.ok) return { ok: false, left: null, right: null, error: res.error }
300
- return { ok: true, left: res.left ?? null, right: res.right ?? null, reason: res.reason, error: res.error }
300
+ return { ok: true, left: res.left ?? null, right: res.right ?? null, reason: res.reason, error: res.error, binary: res.binary === true, encodingHint: res.encodingHint === true }
301
301
  } catch (error) {
302
302
  return { ok: false, left: null, right: null, error: String(error) }
303
303
  }
@@ -211,6 +211,10 @@ export interface SvnDiffBaseOutcome {
211
211
  reason?: string
212
212
  /** 失败提示文案(ok=false,或 ok=true 时的补充说明)。 */
213
213
  message: string
214
+ /** W2-6 护栏:内容含 NUL(二进制)。 */
215
+ binary?: boolean
216
+ /** W2-6 护栏:内容可能非 UTF-8。 */
217
+ encodingHint?: boolean
214
218
  }
215
219
 
216
220
  /**
@@ -228,9 +232,9 @@ export async function svnDiffBase(sessionId: string | undefined, path: string):
228
232
  const message = res.reason === 'no-pristine'
229
233
  ? '该文件尚无基线版本(未提交的新增文件)'
230
234
  : '读取基线失败' + (res.error ? ':' + res.error : '')
231
- return { ok: true, base: null, working: res.working, message }
235
+ return { ok: true, base: null, working: res.working, message, binary: res.binary === true, encodingHint: res.encodingHint === true }
232
236
  }
233
- return { ok: true, base: res.base, working: res.working, message: '已打开基线差异' }
237
+ return { ok: true, base: res.base, working: res.working, message: '已打开基线差异', binary: res.binary === true, encodingHint: res.encodingHint === true }
234
238
  } catch (error) {
235
239
  return { ok: false, base: null, working: '', message: '读取基线失败:' + String(error) }
236
240
  }
@@ -270,6 +274,140 @@ export async function svnAdd(sessionId: string | undefined, paths: string[]): Pr
270
274
  }
271
275
  }
272
276
 
277
+ // --region W2 差异管理补全(补丁/目录对比/远端检查/冲突/配对)
278
+
279
+ /**
280
+ * 生成统一格式补丁文本(W2-1,只读不落盘)。
281
+ * @author ddj 2026年09月20号
282
+ * @param sessionId 会话 id
283
+ * @param path 工作区相对路径(文件/目录)
284
+ * @param opts 扩展选项(空白语义/EOL/上下文行数;缺省 = svn 默认)
285
+ * @returns 补丁文本 + 截断/二进制标记,或错误文案
286
+ */
287
+ export async function svnPatchText(
288
+ sessionId: string | undefined,
289
+ path: string,
290
+ opts: { whitespace?: 'none' | 'b' | 'w'; ignoreEol?: boolean; unified?: number } = {},
291
+ ): Promise<{ ok: boolean; text?: string; truncated?: boolean; binary?: boolean; message: string }> {
292
+ try {
293
+ const res = await rpc('svn.patchText', { sessionId, path, ...opts })
294
+ if (!res.ok) return { ok: false, message: '生成补丁失败:' + res.error }
295
+ return { ok: true, text: res.text, truncated: res.truncated, binary: res.binary, message: '已生成补丁' }
296
+ } catch (error) {
297
+ return { ok: false, message: '生成补丁失败:' + String(error) }
298
+ }
299
+ }
300
+
301
+ /**
302
+ * 目录对比(W2-2,任意两修订的 summarize 变更列表)。
303
+ * @author ddj 2026年09月20号
304
+ * @param sessionId 会话 id
305
+ * @param revA 起始修订(较早)
306
+ * @param revB 结束修订(较晚)
307
+ * @param path 目标相对路径('' = 工作副本根)
308
+ * @returns 变更条目或错误文案
309
+ */
310
+ export async function svnDiffSum(
311
+ sessionId: string | undefined,
312
+ revA: number,
313
+ revB: number,
314
+ path = '',
315
+ ): Promise<{ ok: boolean; entries?: Array<{ path: string; item: string; kind: string; props: string }>; message: string }> {
316
+ try {
317
+ const res = await rpc('svn.diffSum', { sessionId, path, revA, revB })
318
+ if (!res.ok) return { ok: false, message: '目录对比失败:' + res.error }
319
+ return { ok: true, entries: res.entries, message: '已读取 ' + res.entries.length + ' 条变更' }
320
+ } catch (error) {
321
+ return { ok: false, message: '目录对比失败:' + String(error) }
322
+ }
323
+ }
324
+
325
+ /**
326
+ * 远端更新检查(W2-3,`svn status -u`;host 侧 15s 短超时,离线/超时走本函数错误分支)。
327
+ * @author ddj 2026年09月20号
328
+ * @param sessionId 会话 id
329
+ * @param path 目标相对路径('' = 工作副本根)
330
+ * @returns 落后条目 + against 修订,或错误文案
331
+ */
332
+ export async function svnRemoteStatus(
333
+ sessionId: string | undefined,
334
+ path = '',
335
+ ): Promise<{ ok: boolean; outdated?: Array<{ path: string; item: string }>; againstRev?: number | null; message: string }> {
336
+ try {
337
+ const res = await rpc('svn.remoteStatus', { sessionId, path })
338
+ if (!res.ok) return { ok: false, message: '远端检查失败:' + res.error }
339
+ return { ok: true, outdated: res.outdated, againstRev: res.againstRev, message: '远端检查完成' }
340
+ } catch (error) {
341
+ return { ok: false, message: '远端检查失败:' + String(error) }
342
+ }
343
+ }
344
+
345
+ /**
346
+ * 扫描冲突副本文件(W2-4,`.mine`/`.working`/`.rN`,纯本地只读)。
347
+ * @author ddj 2026年09月20号
348
+ * @param sessionId 会话 id
349
+ * @param path 冲突文件的工作区相对路径
350
+ * @returns 副本清单或错误文案
351
+ */
352
+ export async function svnConflictArtifacts(
353
+ sessionId: string | undefined,
354
+ path: string,
355
+ ): Promise<{ ok: boolean; artifacts?: Array<{ path: string; name: string; kind: 'mine' | 'working' | 'rev'; rev?: number }>; message: string }> {
356
+ try {
357
+ const res = await rpc('svn.conflictArtifacts', { sessionId, path })
358
+ if (!res.ok) return { ok: false, message: '扫描冲突副本失败:' + res.error }
359
+ return { ok: true, artifacts: res.artifacts, message: '发现 ' + res.artifacts.length + ' 个冲突副本' }
360
+ } catch (error) {
361
+ return { ok: false, message: '扫描冲突副本失败:' + String(error) }
362
+ }
363
+ }
364
+
365
+ /**
366
+ * 双侧本地文件差异(W2-4,冲突副本 `.rN` ↔ `.mine` 对比)。
367
+ * @author ddj 2026年09月20号
368
+ * @param sessionId 会话 id
369
+ * @param left 左侧工作区相对路径
370
+ * @param right 右侧工作区相对路径
371
+ * @returns 双侧内容(含护栏标记)或错误文案
372
+ */
373
+ export async function svnDiffLocalPair(
374
+ sessionId: string | undefined,
375
+ left: string,
376
+ right: string,
377
+ ): Promise<{ ok: boolean; leftText?: string | null; rightText?: string | null; binary?: boolean; encodingHint?: boolean; message: string }> {
378
+ try {
379
+ const res = await rpc('svn.diffLocalPair', { sessionId, left, right })
380
+ if (!res.ok) return { ok: false, message: '读取冲突副本失败:' + res.error }
381
+ return { ok: true, leftText: res.left, rightText: res.right, binary: res.binary === true, encodingHint: res.encodingHint === true, message: '已读取双侧内容' }
382
+ } catch (error) {
383
+ return { ok: false, message: '读取冲突副本失败:' + String(error) }
384
+ }
385
+ }
386
+
387
+ /**
388
+ * 批量取文件大小(W2-5,改名配对启发式用;未知/失败按 null)。
389
+ * @author ddj 2026年09月20号
390
+ * @param sessionId 会话 id
391
+ * @param paths 工作区相对路径列表(host 上限 200)
392
+ * @returns 路径 → 大小表
393
+ */
394
+ export async function svnFileSizes(
395
+ sessionId: string | undefined,
396
+ paths: string[],
397
+ ): Promise<Record<string, number | null>> {
398
+ try {
399
+ const res = await rpc('svn.fileSizes', { sessionId, paths })
400
+ if (!res.ok) return {}
401
+ const table: Record<string, number | null> = {}
402
+ for (const item of res.sizes) table[item.path] = item.size
403
+ return table
404
+ } catch (error) {
405
+ return {}
406
+ }
407
+ }
408
+
409
+ // --endregion
410
+
273
411
  /**
274
412
  * Monaco 右键菜单 SVN 动作条目(编辑区动态注册用)。
275
413
  *
@@ -374,6 +374,25 @@ function normalizeSlashes(path: string | null | undefined): string {
374
374
  return String(path ?? '').replace(/\\/g, '/')
375
375
  }
376
376
 
377
+ /**
378
+ * 路径改写(资源管理器右键重命名后页签/脏标同步用):
379
+ * 目标本身替换为新路径,其子树按前缀跟随改写,无关路径原样返回。
380
+ * @author ddj 2026年09月22号
381
+ * @param path 待改写路径
382
+ * @param from 原路径
383
+ * @param to 新路径
384
+ * @returns 改写后的路径
385
+ */
386
+ export function remapPathOf(path: string, from: string, to: string): string {
387
+ const text = normalizeSlashes(path)
388
+ const src = normalizeSlashes(from).replace(/\/+$/, '')
389
+ const dst = normalizeSlashes(to).replace(/\/+$/, '')
390
+ if (!src || !dst || src === dst) return text
391
+ if (text === src) return dst
392
+ if (text.startsWith(src + '/')) return dst + text.slice(src.length)
393
+ return text
394
+ }
395
+
377
396
  /**
378
397
  * 文件路径的祖先目录(由浅到深):`a/b/c.ts` → `['a', 'a/b']`。
379
398
  * 根级文件、绝对路径与含 `..` 的路径返回空数组。
@@ -392,14 +411,7 @@ export function ancestorDirsOf(path: string): string[] {
392
411
  return out
393
412
  }
394
413
 
395
- /**
396
- * 文件名(页签/状态栏展示与 tooltip 用)。
397
- * @author ddj 2026年09月11号
398
- * @param path 路径
399
- * @returns 末段文件名;空路径返回空串
400
- */
401
- export function baseNameOf(path: string): string {
402
- const text = normalizeSlashes(path)
403
- return text.split('/').filter(Boolean).pop() ?? ''
404
- }
414
+ // baseNameOf(取末段文件名)已收敛到 shared/fsNames.ts(host 与 client 共用同一份语义),
415
+ // 此处转出口保持既有引用不动。
416
+ export { baseNameOf } from '../shared/fsNames.js'
405
417
  // --endregion