dsh-vscode-mode 0.1.36 → 0.1.43
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/lib/client.js +730 -29
- package/lib/client.js.map +1 -1
- package/lib/index.js +699 -88
- package/lib/index.js.map +1 -1
- package/package.json +1 -5
- package/src/client/monaco/loader.ts +12 -1
- package/src/client/monaco/lsp/lspClient.ts +65 -11
- package/src/client/monaco/lsp/providers.ts +34 -1
- package/src/client/monaco/theme.ts +229 -0
- package/src/client/ui/EditorView.ts +21 -2
- package/src/client/ui/LspSettings.ts +39 -7
- package/src/client/ui/McpSettings.ts +5 -1
- package/src/compat.ts +46 -5
- package/src/dshVersion.ts +121 -0
- package/src/fileOpenSettings.ts +143 -24
- package/src/host-deps.d.ts +5 -5
- package/src/index.ts +2 -1
- package/src/lsp/client.ts +29 -2
- package/src/lsp/manager.ts +15 -0
- package/src/lsp/providers.ts +203 -24
- package/src/lsp/rpc.ts +86 -4
- package/src/lsp/server.ts +80 -3
- package/src/lsp/settings.ts +12 -6
- package/src/paths.ts +7 -0
- package/src/rpc.ts +4 -1
- package/src/shared/compat.ts +9 -3
- package/src/shared/lsp.ts +24 -0
- package/src/shared/rpc.ts +6 -2
package/lib/client.js
CHANGED
|
@@ -385,6 +385,523 @@ window.__ModuleLoader__.load({
|
|
|
385
385
|
window.dispatchEvent(new CustomEvent("edrv:show-launcher", { detail: { tab } }));
|
|
386
386
|
}
|
|
387
387
|
//#endregion
|
|
388
|
+
//#region src/client/monaco/theme.ts
|
|
389
|
+
/**
|
|
390
|
+
* dsh-vscode-mode client — Monaco 语法分色主题(rich token 配色)。
|
|
391
|
+
* 编辑器原先硬编码 'vs'(内置基础主题),token 分色层次少;
|
|
392
|
+
* 这里定义 edrv-dark / edrv-light 两套完整 token 配色(对齐 VSCode Dark+ 语义分层),
|
|
393
|
+
* 并随 DSH 明暗主题自动切换(跟随文档根 data 主题属性 / prefers-color-scheme)。
|
|
394
|
+
* 作者 ddj 2026-08-28
|
|
395
|
+
*/
|
|
396
|
+
const EDRV_DARK = "edrv-dark";
|
|
397
|
+
const EDRV_LIGHT = "edrv-light";
|
|
398
|
+
/** 语法分色(语义分层:关键字/字符串/数字/注释/函数/变量/类型/运算符/正则/标签/属性…)。 */
|
|
399
|
+
const DARK_RULES = [
|
|
400
|
+
{
|
|
401
|
+
token: "",
|
|
402
|
+
foreground: "d4d4d4",
|
|
403
|
+
background: "1e1e1e"
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
token: "comment",
|
|
407
|
+
foreground: "6a9955",
|
|
408
|
+
fontStyle: "italic"
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
token: "comment.doc",
|
|
412
|
+
foreground: "7ca97c",
|
|
413
|
+
fontStyle: "italic"
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
token: "keyword",
|
|
417
|
+
foreground: "c586c0"
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
token: "keyword.control",
|
|
421
|
+
foreground: "c586c0"
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
token: "keyword.operator",
|
|
425
|
+
foreground: "d4d4d4"
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
token: "keyword.json",
|
|
429
|
+
foreground: "9cdcfe"
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
token: "string",
|
|
433
|
+
foreground: "ce9178"
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
token: "string.escape",
|
|
437
|
+
foreground: "d7ba7d"
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
token: "string.key.json",
|
|
441
|
+
foreground: "9cdcfe"
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
token: "string.value.json",
|
|
445
|
+
foreground: "ce9178"
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
token: "string.yaml",
|
|
449
|
+
foreground: "ce9178"
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
token: "number",
|
|
453
|
+
foreground: "b5cea8"
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
token: "number.hex",
|
|
457
|
+
foreground: "b5cea8"
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
token: "regexp",
|
|
461
|
+
foreground: "d16969"
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
token: "type",
|
|
465
|
+
foreground: "4ec9b0"
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
token: "type.identifier",
|
|
469
|
+
foreground: "4ec9b0"
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
token: "identifier",
|
|
473
|
+
foreground: "d4d4d4"
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
token: "variable",
|
|
477
|
+
foreground: "9cdcfe"
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
token: "variable.global",
|
|
481
|
+
foreground: "ff6699"
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
token: "variable.local",
|
|
485
|
+
foreground: "9cdcfe"
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
token: "variable.mutable",
|
|
489
|
+
foreground: "9cdcfe"
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
token: "variable.predefined",
|
|
493
|
+
foreground: "4fc1ff"
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
token: "variable.parameter",
|
|
497
|
+
foreground: "00bfae"
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
token: "parameter",
|
|
501
|
+
foreground: "00bfae"
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
token: "function",
|
|
505
|
+
foreground: "dcdcaa"
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
token: "method",
|
|
509
|
+
foreground: "dcdcaa"
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
token: "property",
|
|
513
|
+
foreground: "9cdcfe"
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
token: "function.identifier",
|
|
517
|
+
foreground: "dcdcaa"
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
token: "member",
|
|
521
|
+
foreground: "dcdcaa"
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
token: "constant",
|
|
525
|
+
foreground: "4fc1ff"
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
token: "constant.numeric",
|
|
529
|
+
foreground: "b5cea8"
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
token: "constant.language",
|
|
533
|
+
foreground: "569cd6"
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
token: "tag",
|
|
537
|
+
foreground: "569cd6"
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
token: "tag.xml",
|
|
541
|
+
foreground: "569cd6"
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
token: "metatag",
|
|
545
|
+
foreground: "808080"
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
token: "attribute.name",
|
|
549
|
+
foreground: "9cdcfe"
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
token: "attribute.value",
|
|
553
|
+
foreground: "ce9178"
|
|
554
|
+
},
|
|
555
|
+
{
|
|
556
|
+
token: "delimiter",
|
|
557
|
+
foreground: "d4d4d4"
|
|
558
|
+
},
|
|
559
|
+
{
|
|
560
|
+
token: "delimiter.bracket",
|
|
561
|
+
foreground: "ffd700"
|
|
562
|
+
},
|
|
563
|
+
{
|
|
564
|
+
token: "delimiter.html",
|
|
565
|
+
foreground: "808080"
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
token: "operator",
|
|
569
|
+
foreground: "d4d4d4"
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
token: "namespace",
|
|
573
|
+
foreground: "4ec9b0"
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
token: "class",
|
|
577
|
+
foreground: "4ec9b0"
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
token: "interface",
|
|
581
|
+
foreground: "4ec9b0"
|
|
582
|
+
},
|
|
583
|
+
{
|
|
584
|
+
token: "enum",
|
|
585
|
+
foreground: "4ec9b0"
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
token: "struct",
|
|
589
|
+
foreground: "4ec9b0"
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
token: "annotation",
|
|
593
|
+
foreground: "dcdcaa"
|
|
594
|
+
},
|
|
595
|
+
{
|
|
596
|
+
token: "punctuation",
|
|
597
|
+
foreground: "d4d4d4"
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
token: "invalid",
|
|
601
|
+
foreground: "f44747"
|
|
602
|
+
}
|
|
603
|
+
];
|
|
604
|
+
const LIGHT_RULES = [
|
|
605
|
+
{
|
|
606
|
+
token: "",
|
|
607
|
+
foreground: "1e1e1e",
|
|
608
|
+
background: "ffffff"
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
token: "comment",
|
|
612
|
+
foreground: "008000",
|
|
613
|
+
fontStyle: "italic"
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
token: "comment.doc",
|
|
617
|
+
foreground: "2e7d32",
|
|
618
|
+
fontStyle: "italic"
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
token: "keyword",
|
|
622
|
+
foreground: "0000ff"
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
token: "keyword.control",
|
|
626
|
+
foreground: "af00db"
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
token: "keyword.operator",
|
|
630
|
+
foreground: "1e1e1e"
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
token: "keyword.json",
|
|
634
|
+
foreground: "0451a5"
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
token: "string",
|
|
638
|
+
foreground: "a31515"
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
token: "string.escape",
|
|
642
|
+
foreground: "ee0000"
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
token: "string.key.json",
|
|
646
|
+
foreground: "0451a5"
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
token: "string.value.json",
|
|
650
|
+
foreground: "a31515"
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
token: "string.yaml",
|
|
654
|
+
foreground: "a31515"
|
|
655
|
+
},
|
|
656
|
+
{
|
|
657
|
+
token: "number",
|
|
658
|
+
foreground: "098658"
|
|
659
|
+
},
|
|
660
|
+
{
|
|
661
|
+
token: "number.hex",
|
|
662
|
+
foreground: "098658"
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
token: "regexp",
|
|
666
|
+
foreground: "811f3f"
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
token: "type",
|
|
670
|
+
foreground: "267f99"
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
token: "type.identifier",
|
|
674
|
+
foreground: "267f99"
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
token: "identifier",
|
|
678
|
+
foreground: "1e1e1e"
|
|
679
|
+
},
|
|
680
|
+
{
|
|
681
|
+
token: "variable",
|
|
682
|
+
foreground: "001080"
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
token: "variable.global",
|
|
686
|
+
foreground: "c2185b"
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
token: "variable.local",
|
|
690
|
+
foreground: "001080"
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
token: "variable.mutable",
|
|
694
|
+
foreground: "001080"
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
token: "variable.predefined",
|
|
698
|
+
foreground: "001080"
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
token: "variable.parameter",
|
|
702
|
+
foreground: "008577"
|
|
703
|
+
},
|
|
704
|
+
{
|
|
705
|
+
token: "parameter",
|
|
706
|
+
foreground: "008577"
|
|
707
|
+
},
|
|
708
|
+
{
|
|
709
|
+
token: "function",
|
|
710
|
+
foreground: "795e26"
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
token: "method",
|
|
714
|
+
foreground: "795e26"
|
|
715
|
+
},
|
|
716
|
+
{
|
|
717
|
+
token: "function.identifier",
|
|
718
|
+
foreground: "795e26"
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
token: "member",
|
|
722
|
+
foreground: "795e26"
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
token: "property",
|
|
726
|
+
foreground: "001080"
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
token: "constant",
|
|
730
|
+
foreground: "0070c1"
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
token: "constant.numeric",
|
|
734
|
+
foreground: "098658"
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
token: "constant.language",
|
|
738
|
+
foreground: "0000ff"
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
token: "tag",
|
|
742
|
+
foreground: "800000"
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
token: "tag.xml",
|
|
746
|
+
foreground: "800000"
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
token: "metatag",
|
|
750
|
+
foreground: "6b6b6b"
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
token: "attribute.name",
|
|
754
|
+
foreground: "e50000"
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
token: "attribute.value",
|
|
758
|
+
foreground: "0451a5"
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
token: "delimiter",
|
|
762
|
+
foreground: "1e1e1e"
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
token: "delimiter.bracket",
|
|
766
|
+
foreground: "b46400"
|
|
767
|
+
},
|
|
768
|
+
{
|
|
769
|
+
token: "delimiter.html",
|
|
770
|
+
foreground: "800000"
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
token: "operator",
|
|
774
|
+
foreground: "1e1e1e"
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
token: "namespace",
|
|
778
|
+
foreground: "267f99"
|
|
779
|
+
},
|
|
780
|
+
{
|
|
781
|
+
token: "class",
|
|
782
|
+
foreground: "267f99"
|
|
783
|
+
},
|
|
784
|
+
{
|
|
785
|
+
token: "interface",
|
|
786
|
+
foreground: "267f99"
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
token: "enum",
|
|
790
|
+
foreground: "267f99"
|
|
791
|
+
},
|
|
792
|
+
{
|
|
793
|
+
token: "struct",
|
|
794
|
+
foreground: "267f99"
|
|
795
|
+
},
|
|
796
|
+
{
|
|
797
|
+
token: "annotation",
|
|
798
|
+
foreground: "795e26"
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
token: "punctuation",
|
|
802
|
+
foreground: "1e1e1e"
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
token: "invalid",
|
|
806
|
+
foreground: "cd3131"
|
|
807
|
+
}
|
|
808
|
+
];
|
|
809
|
+
/** 编辑器 UI 配色(与语法配色同套,保证 gutter/minimap/selection 一致)。 */
|
|
810
|
+
const DARK_COLORS = {
|
|
811
|
+
"editor.background": "#1e1e1e",
|
|
812
|
+
"editor.foreground": "#d4d4d4",
|
|
813
|
+
"editorLineNumber.foreground": "#6e7681",
|
|
814
|
+
"editorLineNumber.activeForeground": "#c6c6c6",
|
|
815
|
+
"editor.selectionBackground": "#264f78",
|
|
816
|
+
"editor.inactiveSelectionBackground": "#3a3d41",
|
|
817
|
+
"editor.lineHighlightBackground": "#2a2d2e",
|
|
818
|
+
"editorCursor.foreground": "#aeafad",
|
|
819
|
+
"editorIndentGuide.background1": "#404040",
|
|
820
|
+
"editorIndentGuide.activeBackground1": "#707070",
|
|
821
|
+
"editorWidget.background": "#252526",
|
|
822
|
+
"editorHoverWidget.background": "#252526",
|
|
823
|
+
"editorGutter.background": "#1e1e1e",
|
|
824
|
+
"minimap.background": "#1e1e1e",
|
|
825
|
+
"scrollbarSlider.background": "#79797966",
|
|
826
|
+
"scrollbarSlider.hoverBackground": "#646464b3",
|
|
827
|
+
"scrollbarSlider.activeBackground": "#bfbfbf66"
|
|
828
|
+
};
|
|
829
|
+
const LIGHT_COLORS = {
|
|
830
|
+
"editor.background": "#ffffff",
|
|
831
|
+
"editor.foreground": "#1e1e1e",
|
|
832
|
+
"editorLineNumber.foreground": "#6c6c6c",
|
|
833
|
+
"editorLineNumber.activeForeground": "#171184",
|
|
834
|
+
"editor.selectionBackground": "#add6ff",
|
|
835
|
+
"editor.inactiveSelectionBackground": "#e5ebf1",
|
|
836
|
+
"editor.lineHighlightBackground": "#f0f0f0",
|
|
837
|
+
"editorCursor.foreground": "#000000",
|
|
838
|
+
"editorIndentGuide.background1": "#d3d3d3",
|
|
839
|
+
"editorIndentGuide.activeBackground1": "#939393",
|
|
840
|
+
"editorWidget.background": "#f3f3f3",
|
|
841
|
+
"editorHoverWidget.background": "#f3f3f3",
|
|
842
|
+
"editorGutter.background": "#ffffff",
|
|
843
|
+
"minimap.background": "#ffffff",
|
|
844
|
+
"scrollbarSlider.background": "#64646466",
|
|
845
|
+
"scrollbarSlider.hoverBackground": "#646464b3",
|
|
846
|
+
"scrollbarSlider.activeBackground": "#00000099"
|
|
847
|
+
};
|
|
848
|
+
/**
|
|
849
|
+
* 注册 edrv 双套主题(幂等;Monaco 未加载时静默跳过)。
|
|
850
|
+
* @author ddj 2026年08月28号
|
|
851
|
+
* @param monaco Monaco 实例(window.monaco)
|
|
852
|
+
*/
|
|
853
|
+
function registerThemes(monaco) {
|
|
854
|
+
if (!monaco?.editor?.defineTheme) return;
|
|
855
|
+
try {
|
|
856
|
+
monaco.editor.defineTheme(EDRV_DARK, {
|
|
857
|
+
base: "vs-dark",
|
|
858
|
+
inherit: true,
|
|
859
|
+
rules: DARK_RULES,
|
|
860
|
+
colors: DARK_COLORS
|
|
861
|
+
});
|
|
862
|
+
monaco.editor.defineTheme(EDRV_LIGHT, {
|
|
863
|
+
base: "vs",
|
|
864
|
+
inherit: true,
|
|
865
|
+
rules: LIGHT_RULES,
|
|
866
|
+
colors: LIGHT_COLORS
|
|
867
|
+
});
|
|
868
|
+
} catch (error) {}
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* 探测当前 DSH 明暗(文档根 data 主题属性 → prefers-color-scheme → 暗)。
|
|
872
|
+
* @author ddj 2026年08月28号
|
|
873
|
+
* @returns 'dark' | 'light'
|
|
874
|
+
*/
|
|
875
|
+
function detectColorScheme() {
|
|
876
|
+
try {
|
|
877
|
+
const attr = document.documentElement?.getAttribute?.("data-theme") ?? document.body?.getAttribute?.("data-theme");
|
|
878
|
+
const value = String(attr ?? "").toLowerCase();
|
|
879
|
+
if (value.includes("light") || value.includes("catppuccin-latte")) return "light";
|
|
880
|
+
if (value.includes("dark") || value.includes("frappe") || value.includes("macchiato") || value.includes("mocha")) return "dark";
|
|
881
|
+
if (typeof window.matchMedia === "function") return window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
|
|
882
|
+
} catch (error) {}
|
|
883
|
+
return "dark";
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* 主题名:按当前明暗返回已注册主题(未注册回落 vs)。
|
|
887
|
+
* @author ddj 2026年08月28号
|
|
888
|
+
* @returns 主题 id
|
|
889
|
+
*/
|
|
890
|
+
function themeNameOf() {
|
|
891
|
+
return detectColorScheme() === "light" ? EDRV_LIGHT : EDRV_DARK;
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* 应用主题到 Monaco(全局切换;新建编辑器也用该主题)。
|
|
895
|
+
* @author ddj 2026年08月28号
|
|
896
|
+
* @param monaco Monaco 实例
|
|
897
|
+
*/
|
|
898
|
+
function applyTheme(monaco) {
|
|
899
|
+
if (!monaco?.editor?.setTheme) return;
|
|
900
|
+
try {
|
|
901
|
+
monaco.editor.setTheme(themeNameOf());
|
|
902
|
+
} catch (error) {}
|
|
903
|
+
}
|
|
904
|
+
//#endregion
|
|
388
905
|
//#region src/client/monaco/loader.ts
|
|
389
906
|
/**
|
|
390
907
|
* dsh-vscode-mode client — Monaco 加载与语言映射(AMD 构建,离线随包分发)。
|
|
@@ -500,7 +1017,20 @@ window.__ModuleLoader__.load({
|
|
|
500
1017
|
kt: "kotlin",
|
|
501
1018
|
kts: "kotlin",
|
|
502
1019
|
dart: "dart",
|
|
503
|
-
dockerfile: "dockerfile"
|
|
1020
|
+
dockerfile: "dockerfile",
|
|
1021
|
+
csproj: "xml",
|
|
1022
|
+
props: "xml",
|
|
1023
|
+
targets: "xml",
|
|
1024
|
+
plist: "xml",
|
|
1025
|
+
lua51: "lua",
|
|
1026
|
+
luac: "lua",
|
|
1027
|
+
gitattributes: "ini",
|
|
1028
|
+
editorconfig: "ini",
|
|
1029
|
+
env: "ini",
|
|
1030
|
+
properties: "ini",
|
|
1031
|
+
json5: "jsonc",
|
|
1032
|
+
log: "plaintext",
|
|
1033
|
+
txt: "plaintext"
|
|
504
1034
|
};
|
|
505
1035
|
/**
|
|
506
1036
|
* 路径 → Monaco language id:取 basename 扩展名(dockerfile/Dockerfile 特判)。
|
|
@@ -536,6 +1066,10 @@ window.__ModuleLoader__.load({
|
|
|
536
1066
|
publishStage("core", MONACO_STAGES.core.progress, MONACO_STAGES.core.message);
|
|
537
1067
|
window.require(["vs/editor/editor.main"], () => {
|
|
538
1068
|
publishStage("ready", MONACO_STAGES.ready.progress, MONACO_STAGES.ready.message);
|
|
1069
|
+
try {
|
|
1070
|
+
registerThemes(window.monaco);
|
|
1071
|
+
applyTheme(window.monaco);
|
|
1072
|
+
} catch (error) {}
|
|
539
1073
|
resolve(window.monaco);
|
|
540
1074
|
}, (err) => fail(/* @__PURE__ */ new Error("Monaco 模块加载失败:" + String(err))));
|
|
541
1075
|
} catch (error) {
|
|
@@ -1971,6 +2505,48 @@ window.__ModuleLoader__.load({
|
|
|
1971
2505
|
}
|
|
1972
2506
|
//#endregion
|
|
1973
2507
|
//#region src/shared/lsp.ts
|
|
2508
|
+
/** LSP semantic token 标准类型(host 归一化后,client 与 Monaco 共用)。 */
|
|
2509
|
+
const LSP_SEMANTIC_TOKEN_TYPES = [
|
|
2510
|
+
"namespace",
|
|
2511
|
+
"type",
|
|
2512
|
+
"class",
|
|
2513
|
+
"enum",
|
|
2514
|
+
"interface",
|
|
2515
|
+
"struct",
|
|
2516
|
+
"typeParameter",
|
|
2517
|
+
"parameter",
|
|
2518
|
+
"variable",
|
|
2519
|
+
"property",
|
|
2520
|
+
"enumMember",
|
|
2521
|
+
"event",
|
|
2522
|
+
"function",
|
|
2523
|
+
"method",
|
|
2524
|
+
"macro",
|
|
2525
|
+
"label",
|
|
2526
|
+
"comment",
|
|
2527
|
+
"string",
|
|
2528
|
+
"keyword",
|
|
2529
|
+
"number",
|
|
2530
|
+
"regexp",
|
|
2531
|
+
"operator",
|
|
2532
|
+
"decorator"
|
|
2533
|
+
];
|
|
2534
|
+
/** LSP semantic token 标准修饰符(host 归一化后,client 与 Monaco 共用)。 */
|
|
2535
|
+
const LSP_SEMANTIC_TOKEN_MODIFIERS = [
|
|
2536
|
+
"declaration",
|
|
2537
|
+
"definition",
|
|
2538
|
+
"readonly",
|
|
2539
|
+
"static",
|
|
2540
|
+
"deprecated",
|
|
2541
|
+
"abstract",
|
|
2542
|
+
"async",
|
|
2543
|
+
"modification",
|
|
2544
|
+
"documentation",
|
|
2545
|
+
"defaultLibrary",
|
|
2546
|
+
"global",
|
|
2547
|
+
"local",
|
|
2548
|
+
"mutable"
|
|
2549
|
+
];
|
|
1974
2550
|
/**
|
|
1975
2551
|
* Monaco 位置(1-based lineNumber/column)→ LSP Position(0-based)。
|
|
1976
2552
|
* @author ddj 2026年08月27号
|
|
@@ -2113,6 +2689,16 @@ window.__ModuleLoader__.load({
|
|
|
2113
2689
|
if (!res || !res.ok) return null;
|
|
2114
2690
|
return res.hover || null;
|
|
2115
2691
|
}
|
|
2692
|
+
/** 查询当前文档的 semantic tokens(host 已归一化 legend 与 delta data)。 */
|
|
2693
|
+
async function fetchSemanticTokens(path, text) {
|
|
2694
|
+
await syncDoc(path, text, true);
|
|
2695
|
+
const res = await rpc("edrv.lsp.semanticTokens", {
|
|
2696
|
+
sessionId,
|
|
2697
|
+
path
|
|
2698
|
+
}).catch(() => null);
|
|
2699
|
+
if (!res || !res.ok || !res.tokens || !Array.isArray(res.tokens.data)) return null;
|
|
2700
|
+
return res.tokens;
|
|
2701
|
+
}
|
|
2116
2702
|
/** 拉取服务器状态(带 5s 缓存)。 */
|
|
2117
2703
|
async function refreshStatus(force = false) {
|
|
2118
2704
|
if (!force && Date.now() - statusCache.at < 1500) return statusCache.servers;
|
|
@@ -2132,7 +2718,10 @@ window.__ModuleLoader__.load({
|
|
|
2132
2718
|
const end = range.end || {};
|
|
2133
2719
|
return {
|
|
2134
2720
|
uri: window.monaco.Uri.parse(toEdrvUri(loc.uri, loc.root)),
|
|
2135
|
-
range: new window.monaco.Range(Math.max(1, (start.line ?? 0) + 1), Math.max(1, (start.character ?? 0) + 1), Math.max(1, (end.line ?? 0) + 1), Math.max(1, (end.character ?? 0) + 1))
|
|
2721
|
+
range: new window.monaco.Range(Math.max(1, (start.line ?? 0) + 1), Math.max(1, (start.character ?? 0) + 1), Math.max(1, (end.line ?? 0) + 1), Math.max(1, (end.character ?? 0) + 1)),
|
|
2722
|
+
lspUri: loc.uri,
|
|
2723
|
+
lspRoot: loc.root,
|
|
2724
|
+
lspRange: loc.range
|
|
2136
2725
|
};
|
|
2137
2726
|
}
|
|
2138
2727
|
/** file:// URI(或裸路径)→ edrv:// 相对路径(去掉盘符/根,与编辑器模型路径一致)。 */
|
|
@@ -2144,30 +2733,68 @@ window.__ModuleLoader__.load({
|
|
|
2144
2733
|
}
|
|
2145
2734
|
/** 将 LSP 目标解析为当前工作区相对路径(跨文件跳转与 model URI 对齐)。 */
|
|
2146
2735
|
function targetOpenPath(loc) {
|
|
2147
|
-
return relativeLspPath(loc?.uri, loc?.root);
|
|
2736
|
+
return relativeLspPath(loc?.lspUri ?? loc?.uri, loc?.lspRoot ?? loc?.root);
|
|
2148
2737
|
}
|
|
2149
|
-
/**
|
|
2150
|
-
|
|
2738
|
+
/**
|
|
2739
|
+
* 归一化 Location 的 uri → 工作区路径(剥离 scheme,不补盘符)。
|
|
2740
|
+
* 三种输入形态(缺一即导致 scheme 泄漏进文件路径 → 跳转"文件不存在"):
|
|
2741
|
+
* - Monaco Uri 对象(toClientLocation 产物,scheme=edrv)→ 取 .path(已是工作区相对路径)
|
|
2742
|
+
* - 'edrv:///x' 字符串 → 取路径部分
|
|
2743
|
+
* - 'file:///D:/x' → 去 authority 空段保留盘符
|
|
2744
|
+
* @author ddj 2026年08月28号
|
|
2745
|
+
* @param uri Monaco Uri 对象 / file:// 或 edrv:// URI / 裸路径
|
|
2746
|
+
* @returns / 分隔的路径(edrv 相对路径 或 带盘符绝对路径)
|
|
2747
|
+
*/
|
|
2748
|
+
function lspUriToAbs(uri) {
|
|
2151
2749
|
if (!uri) return "";
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2750
|
+
const isObject = typeof uri === "object";
|
|
2751
|
+
const raw = isObject && typeof uri.path === "string" ? uri.path : String(uri);
|
|
2752
|
+
let path = raw;
|
|
2753
|
+
if (path.startsWith("file://")) {
|
|
2754
|
+
try {
|
|
2755
|
+
path = decodeURIComponent(path.replace(/^file:\/\/\/?/, ""));
|
|
2756
|
+
} catch (error) {
|
|
2757
|
+
path = path.replace(/^file:\/\/\/?/, "");
|
|
2758
|
+
}
|
|
2759
|
+
return path.replace(/\\/g, "/").replace(/^\/([A-Za-z]:)/, "$1");
|
|
2760
|
+
}
|
|
2761
|
+
if (path.startsWith("edrv://")) try {
|
|
2762
|
+
path = decodeURIComponent(path.replace(/^edrv:\/\/\/?/, ""));
|
|
2155
2763
|
} catch (error) {
|
|
2156
|
-
path = path.replace(/^
|
|
2764
|
+
path = path.replace(/^edrv:\/\/\/?/, "");
|
|
2157
2765
|
}
|
|
2158
|
-
|
|
2766
|
+
if (isObject ? uri.scheme === "edrv" : raw.startsWith("edrv://")) return path.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
2767
|
+
return path.replace(/\\/g, "/").replace(/^\/([A-Za-z]:)/, "$1");
|
|
2768
|
+
}
|
|
2769
|
+
/**
|
|
2770
|
+
* file URI/裸路径 → root 下的 / 分隔相对路径。
|
|
2771
|
+
* root 匹配返回工作区相对路径;root 不匹配返回完整绝对路径(保留盘符),
|
|
2772
|
+
* 供 edrv.read 按绝对路径解析(原先错误剥掉首个 / 导致跳转"文件不存在")。
|
|
2773
|
+
* @author ddj 2026年08月28号
|
|
2774
|
+
* @param uri file:// URI 或裸路径
|
|
2775
|
+
* @param root 工作区根(可选)
|
|
2776
|
+
* @returns 可 edrv.read 的路径
|
|
2777
|
+
*/
|
|
2778
|
+
function relativeLspPath(uri, root) {
|
|
2779
|
+
if (!uri) return "";
|
|
2780
|
+
const path = lspUriToAbs(uri);
|
|
2159
2781
|
const normalizedRoot = root ? String(root).replace(/\\/g, "/").replace(/^\/([A-Za-z]:)/, "$1").replace(/\/+$/, "") : "";
|
|
2160
2782
|
const lowerPath = path.toLowerCase();
|
|
2161
2783
|
const lowerRoot = normalizedRoot.toLowerCase();
|
|
2162
2784
|
if (normalizedRoot && (lowerPath === lowerRoot || lowerPath.startsWith(lowerRoot + "/"))) return path.slice(normalizedRoot.length).replace(/^\/+/, "");
|
|
2163
|
-
return path
|
|
2785
|
+
return path;
|
|
2164
2786
|
}
|
|
2165
2787
|
/** 目标行/列(0-based LSP → 1-based Monaco)。 */
|
|
2166
2788
|
function targetMonoPosition(loc) {
|
|
2167
|
-
const
|
|
2789
|
+
const lspRange = loc?.lspRange;
|
|
2790
|
+
if (lspRange?.start) return {
|
|
2791
|
+
line: Math.max(1, (lspRange.start.line ?? 0) + 1),
|
|
2792
|
+
column: Math.max(1, (lspRange.start.character ?? 0) + 1)
|
|
2793
|
+
};
|
|
2794
|
+
const range = loc?.range ?? {};
|
|
2168
2795
|
return {
|
|
2169
|
-
line: Math.max(1,
|
|
2170
|
-
column: Math.max(1,
|
|
2796
|
+
line: Math.max(1, range.startLineNumber ?? 1),
|
|
2797
|
+
column: Math.max(1, range.startColumn ?? 1)
|
|
2171
2798
|
};
|
|
2172
2799
|
}
|
|
2173
2800
|
//#endregion
|
|
@@ -2180,6 +2807,10 @@ window.__ModuleLoader__.load({
|
|
|
2180
2807
|
* 作者 ddj 2026-08-27
|
|
2181
2808
|
*/
|
|
2182
2809
|
const LSP_LANGS = ["lua", "csharp"];
|
|
2810
|
+
const SEMANTIC_LEGEND = {
|
|
2811
|
+
tokenTypes: [...LSP_SEMANTIC_TOKEN_TYPES],
|
|
2812
|
+
tokenModifiers: [...LSP_SEMANTIC_TOKEN_MODIFIERS]
|
|
2813
|
+
};
|
|
2183
2814
|
let registered = false;
|
|
2184
2815
|
const disposables = [];
|
|
2185
2816
|
let overlayEl = null;
|
|
@@ -2214,6 +2845,19 @@ window.__ModuleLoader__.load({
|
|
|
2214
2845
|
};
|
|
2215
2846
|
disposables.push(monaco.editor.onDidCreateModel(attachModel));
|
|
2216
2847
|
for (const model of monaco.editor.getModels()) attachModel(model);
|
|
2848
|
+
const onRedetect = (event) => {
|
|
2849
|
+
const languageId = event?.detail?.languageId;
|
|
2850
|
+
if (!languageId) return;
|
|
2851
|
+
for (const model of monaco.editor.getModels()) {
|
|
2852
|
+
const path = pathOfModel(model);
|
|
2853
|
+
if (!path) continue;
|
|
2854
|
+
if (model.getLanguageId && model.getLanguageId() !== languageId) continue;
|
|
2855
|
+
syncDoc(path, model.getValue(), true);
|
|
2856
|
+
}
|
|
2857
|
+
refreshStatus(true);
|
|
2858
|
+
};
|
|
2859
|
+
window.addEventListener("edrv:lsp-redetect", onRedetect);
|
|
2860
|
+
disposables.push(() => window.removeEventListener("edrv:lsp-redetect", onRedetect));
|
|
2217
2861
|
disposables.push(monaco.languages.registerDefinitionProvider(LSP_LANGS, { provideDefinition: (model, position, token) => {
|
|
2218
2862
|
const path = pathOfModel(model);
|
|
2219
2863
|
if (!path) return [];
|
|
@@ -2236,7 +2880,17 @@ window.__ModuleLoader__.load({
|
|
|
2236
2880
|
contents: hover.contents.map((text) => ({ value: text })),
|
|
2237
2881
|
range: range || void 0
|
|
2238
2882
|
};
|
|
2239
|
-
} })
|
|
2883
|
+
} }), monaco.languages.registerDocumentSemanticTokensProvider(LSP_LANGS, {
|
|
2884
|
+
getLegend: () => SEMANTIC_LEGEND,
|
|
2885
|
+
provideDocumentSemanticTokens: async (model, token) => {
|
|
2886
|
+
const path = pathOfModel(model);
|
|
2887
|
+
if (!path || token?.isCancellationRequested) return { data: /* @__PURE__ */ new Uint32Array() };
|
|
2888
|
+
const result = await fetchSemanticTokens(path, model.getValue());
|
|
2889
|
+
if (!result || token?.isCancellationRequested) return { data: /* @__PURE__ */ new Uint32Array() };
|
|
2890
|
+
return { data: Uint32Array.from(result.data) };
|
|
2891
|
+
},
|
|
2892
|
+
releaseDocumentSemanticTokens: () => {}
|
|
2893
|
+
}));
|
|
2240
2894
|
}
|
|
2241
2895
|
/** LSP SymbolInfo(host 归一化后)→ Monaco DocumentSymbol。 */
|
|
2242
2896
|
function toMonacoSymbol(symbol) {
|
|
@@ -2625,7 +3279,8 @@ window.__ModuleLoader__.load({
|
|
|
2625
3279
|
}));
|
|
2626
3280
|
setStatus("已加载");
|
|
2627
3281
|
} else {
|
|
2628
|
-
const
|
|
3282
|
+
const base = res?.error ? String(res.error) : "读取失败";
|
|
3283
|
+
const message = res?.resolvedPath ? base + ":" + String(res.resolvedPath) : base;
|
|
2629
3284
|
setLoadError(message);
|
|
2630
3285
|
setError(message);
|
|
2631
3286
|
setStatus("读取失败");
|
|
@@ -2892,6 +3547,20 @@ window.__ModuleLoader__.load({
|
|
|
2892
3547
|
alive = false;
|
|
2893
3548
|
};
|
|
2894
3549
|
}, [monaco, monacoErr]);
|
|
3550
|
+
react.default.useEffect(() => {
|
|
3551
|
+
if (!monaco) return;
|
|
3552
|
+
registerThemes(monaco);
|
|
3553
|
+
applyTheme(monaco);
|
|
3554
|
+
if (typeof window.matchMedia !== "function") return;
|
|
3555
|
+
const query = window.matchMedia("(prefers-color-scheme: dark)");
|
|
3556
|
+
const onChange = () => applyTheme(monaco);
|
|
3557
|
+
if (typeof query.addEventListener === "function") {
|
|
3558
|
+
query.addEventListener("change", onChange);
|
|
3559
|
+
return () => query.removeEventListener("change", onChange);
|
|
3560
|
+
}
|
|
3561
|
+
query.addListener(onChange);
|
|
3562
|
+
return () => query.removeListener(onChange);
|
|
3563
|
+
}, [monaco]);
|
|
2895
3564
|
monacoRef.current = monaco;
|
|
2896
3565
|
const getModel = (path, text) => {
|
|
2897
3566
|
const cache = modelsRef.current;
|
|
@@ -3005,7 +3674,7 @@ window.__ModuleLoader__.load({
|
|
|
3005
3674
|
const ed = m.editor.create(node, {
|
|
3006
3675
|
value: "",
|
|
3007
3676
|
language: "plaintext",
|
|
3008
|
-
theme:
|
|
3677
|
+
theme: themeNameOf(),
|
|
3009
3678
|
fontFamily: "var(--ds-font-family-code, ui-monospace, monospace)",
|
|
3010
3679
|
fontSize: 13,
|
|
3011
3680
|
lineHeight: 20,
|
|
@@ -4639,8 +5308,8 @@ window.__ModuleLoader__.load({
|
|
|
4639
5308
|
*/
|
|
4640
5309
|
const LANGUAGES = [{
|
|
4641
5310
|
id: "lua",
|
|
4642
|
-
label: "Lua(LuaLS)",
|
|
4643
|
-
hint: "lua-language-server
|
|
5311
|
+
label: "Lua(EmmyLua / LuaLS)",
|
|
5312
|
+
hint: "优先使用已安装 EmmyLua;未安装时回退 LuaLS 或 PATH 中的 lua-language-server"
|
|
4644
5313
|
}, {
|
|
4645
5314
|
id: "csharp",
|
|
4646
5315
|
label: "C#(Roslyn / OmniSharp)",
|
|
@@ -4678,8 +5347,8 @@ window.__ModuleLoader__.load({
|
|
|
4678
5347
|
label: "更新"
|
|
4679
5348
|
}
|
|
4680
5349
|
];
|
|
4681
|
-
/** 语言卡片:状态 + 启用开关 +
|
|
4682
|
-
function LangCard({ lang, config, status, busy, onToggle, onSave }) {
|
|
5350
|
+
/** 语言卡片:状态 + 启用开关 + 命令/路径配置 + 重新检测。 */
|
|
5351
|
+
function LangCard({ lang, config, status, busy, onToggle, onSave, onRedetect }) {
|
|
4683
5352
|
const [pathDraft, setPathDraft] = react.default.useState(config?.path ?? "");
|
|
4684
5353
|
const [commandDraft, setCommandDraft] = react.default.useState(config?.command ?? "");
|
|
4685
5354
|
react.default.useEffect(() => {
|
|
@@ -4691,7 +5360,7 @@ window.__ModuleLoader__.load({
|
|
|
4691
5360
|
className: "vsm-switch " + (config?.enabled !== false ? "on" : ""),
|
|
4692
5361
|
onClick: () => onToggle(lang.id, config?.enabled !== false ? false : true),
|
|
4693
5362
|
"aria-label": "启用/禁用"
|
|
4694
|
-
}, config?.enabled !== false ? "●" : "○"))), react.default.createElement("div", { className: "vsm-mcp-meta" }, PHASE_LABEL[phase] ?? phase, " · ", SOURCE_LABEL[status?.source] ?? status?.source, phase === "ready" && status?.root ? " · " + String(status.root).split(/[\\/]/).pop() : ""), status?.reason ? react.default.createElement("div", { className: "vsm-mcp-error" }, status.reason) : null, react.default.createElement("div", { className: "vsm-lsp-form" }, react.default.createElement("label", null, react.default.createElement("span", null, "可执行文件路径(绝对路径,优先)"), react.default.createElement("input", {
|
|
5363
|
+
}, config?.enabled !== false ? "●" : "○"))), react.default.createElement("div", { className: "vsm-mcp-meta" }, PHASE_LABEL[phase] ?? phase, " · ", SOURCE_LABEL[status?.source] ?? status?.source, status?.providerName ? " · " + status.providerName : "", status?.version ? " · v" + status.version : "", phase === "ready" && status?.root ? " · " + String(status.root).split(/[\\/]/).pop() : ""), status?.reason ? react.default.createElement("div", { className: "vsm-mcp-error" }, status.reason) : null, react.default.createElement("div", { className: "vsm-lsp-form" }, react.default.createElement("label", null, react.default.createElement("span", null, "可执行文件路径(绝对路径,优先)"), react.default.createElement("input", {
|
|
4695
5364
|
value: pathDraft,
|
|
4696
5365
|
placeholder: "如 C:/.../lua-language-server.exe",
|
|
4697
5366
|
onChange: (e) => setPathDraft(e.target.value)
|
|
@@ -4703,7 +5372,12 @@ window.__ModuleLoader__.load({
|
|
|
4703
5372
|
className: "vsm-primary",
|
|
4704
5373
|
disabled: busy === lang.id,
|
|
4705
5374
|
onClick: () => onSave(lang.id, pathDraft, commandDraft)
|
|
4706
|
-
}, busy === lang.id ? "保存中…" : "保存配置")
|
|
5375
|
+
}, busy === lang.id ? "保存中…" : "保存配置"), react.default.createElement("button", {
|
|
5376
|
+
className: "vsm-primary vsm-small",
|
|
5377
|
+
disabled: busy === lang.id,
|
|
5378
|
+
onClick: () => onRedetect(lang.id),
|
|
5379
|
+
title: "清缓存并重新选择语言服务器(EmmyLua / LuaLS)"
|
|
5380
|
+
}, busy === lang.id ? "检测中…" : "重新检测")), react.default.createElement("div", { className: "vsm-lsp-hint" }, lang.hint));
|
|
4707
5381
|
}
|
|
4708
5382
|
/** 已装扩展卡片:清单 + 卸载/更新。 */
|
|
4709
5383
|
function InstalledCard({ ext, busy, onUninstall, onUpdate }) {
|
|
@@ -4770,6 +5444,14 @@ window.__ModuleLoader__.load({
|
|
|
4770
5444
|
if (next === "installed" || next === "updates") refreshExt();
|
|
4771
5445
|
if (next === "servers") refreshServers();
|
|
4772
5446
|
};
|
|
5447
|
+
/** 合并 redetect/configUpdate 返回的服务器状态:只替换该语言条目。 */
|
|
5448
|
+
const mergeServers = (languageId, list) => {
|
|
5449
|
+
setServers((prev) => Array.isArray(list) ? [...prev.filter((s) => s.languageId !== languageId), ...list] : prev);
|
|
5450
|
+
};
|
|
5451
|
+
/** 重检测后通知编辑器:与 host 重新同步已打开的模型(触发重新 acquire)。 */
|
|
5452
|
+
const notifyResync = (languageId) => {
|
|
5453
|
+
window.dispatchEvent(new CustomEvent("edrv:lsp-redetect", { detail: { languageId } }));
|
|
5454
|
+
};
|
|
4773
5455
|
const saveLang = (languageId, path, command) => {
|
|
4774
5456
|
setBusy(languageId);
|
|
4775
5457
|
setError("");
|
|
@@ -4783,6 +5465,8 @@ window.__ModuleLoader__.load({
|
|
|
4783
5465
|
return;
|
|
4784
5466
|
}
|
|
4785
5467
|
setConfig(res.config ?? {});
|
|
5468
|
+
mergeServers(languageId, res.servers);
|
|
5469
|
+
notifyResync(languageId);
|
|
4786
5470
|
}).catch((e) => setError(String(e))).finally(() => setBusy(""));
|
|
4787
5471
|
};
|
|
4788
5472
|
const toggleLang = (languageId, enabled) => {
|
|
@@ -4791,10 +5475,25 @@ window.__ModuleLoader__.load({
|
|
|
4791
5475
|
languageId,
|
|
4792
5476
|
enabled
|
|
4793
5477
|
}).then((res) => {
|
|
4794
|
-
if (res?.ok) {
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
}
|
|
5478
|
+
if (!res?.ok) {
|
|
5479
|
+
setError(res?.error ?? "切换失败");
|
|
5480
|
+
return;
|
|
5481
|
+
}
|
|
5482
|
+
setConfig(res.config ?? {});
|
|
5483
|
+
mergeServers(languageId, res.servers);
|
|
5484
|
+
notifyResync(languageId);
|
|
5485
|
+
}).catch((e) => setError(String(e))).finally(() => setBusy(""));
|
|
5486
|
+
};
|
|
5487
|
+
const redetectLang = (languageId) => {
|
|
5488
|
+
setBusy(languageId);
|
|
5489
|
+
setError("");
|
|
5490
|
+
rpc("edrv.lsp.redetect", { languageId }).then((res) => {
|
|
5491
|
+
if (!res?.ok) {
|
|
5492
|
+
setError(res?.error ?? "重新检测失败");
|
|
5493
|
+
return;
|
|
5494
|
+
}
|
|
5495
|
+
mergeServers(languageId, res.servers);
|
|
5496
|
+
notifyResync(languageId);
|
|
4798
5497
|
}).catch((e) => setError(String(e))).finally(() => setBusy(""));
|
|
4799
5498
|
};
|
|
4800
5499
|
const searchMarket = () => {
|
|
@@ -4874,7 +5573,8 @@ window.__ModuleLoader__.load({
|
|
|
4874
5573
|
status: servers.find((s) => s.languageId === lang.id),
|
|
4875
5574
|
busy,
|
|
4876
5575
|
onToggle: toggleLang,
|
|
4877
|
-
onSave: saveLang
|
|
5576
|
+
onSave: saveLang,
|
|
5577
|
+
onRedetect: redetectLang
|
|
4878
5578
|
})), react.default.createElement("div", { className: "vsm-lsp-hint" }, "提示:打开 Lua/C# 文件即自动(惰性)启动对应语言服务器;未配置时编辑器功能不受影响,大纲回退内置解析。")));
|
|
4879
5579
|
else if (tab === "installed") body = panel("已安装扩展", react.default.createElement(react.default.Fragment, null, react.default.createElement("div", { className: "vsm-lsp-hint" }, "已安装的语言服务器扩展(存于 ~/.dsh/dsh-vscode-mode/extensions/)。语言服务器被自动发现为「扩展」源。"), installed.length ? installed.map((ext) => react.default.createElement(InstalledCard, {
|
|
4880
5580
|
key: ext.id,
|
|
@@ -5592,7 +6292,8 @@ window.__ModuleLoader__.load({
|
|
|
5592
6292
|
const group = (title, children) => react.default.createElement("section", { className: "vsm-panel" }, react.default.createElement("h3", { className: "vsm-panel-title" }, title), react.default.createElement("div", { className: "vsm-panel-body" }, children));
|
|
5593
6293
|
const warnings = report?.warnings ?? [];
|
|
5594
6294
|
const devForm = report?.devForm;
|
|
5595
|
-
|
|
6295
|
+
const versionText = report?.dshVersion ? "(DSH " + report.dshVersion + " · 插件 " + (report?.pluginVersion ?? "") + ")" : report?.pluginVersion ? "(插件版本 " + report.pluginVersion + ")" : "";
|
|
6296
|
+
return react.default.createElement("section", { className: "vsm-general-page" }, react.default.createElement("h2", null, "兼容性"), react.default.createElement("p", null, "检测与其他插件 / DSH 版本的适配状态与已知问题。" + versionText), error && react.default.createElement("div", { className: "vsm-mcp-error vsm-mcp-banner" }, error), devForm?.enabled && group("开发形态", react.default.createElement("div", { className: "vsm-compat-item ok" }, react.default.createElement("span", { className: "vsm-compat-name" }, "开发形态开启(工作区链接安装)"), react.default.createElement("span", { className: "vsm-compat-note" }, devForm.path))), group("版本适配", renderItems(report?.adapters)), group("外部插件与服务", renderItems(report?.external)), group("客户端适配", renderItems(getSummary?.() ?? [])), group("护栏", renderItems(report?.guards)), group("警告", warnings.length ? warnings.map((w, index) => react.default.createElement("div", {
|
|
5596
6297
|
key: index,
|
|
5597
6298
|
className: "vsm-mcp-error vsm-mcp-banner"
|
|
5598
6299
|
}, w)) : react.default.createElement("div", { className: "vsm-compat-item ok" }, react.default.createElement("span", { className: "vsm-compat-name" }, "未检测到兼容性问题"), react.default.createElement("span", { className: "vsm-compat-note" }, ""))));
|