Skip to content

Commit 27b7e42

Browse files
committed
feat: 特质预览器打开指定特质所在文件
1 parent a14afc3 commit 27b7e42

File tree

14 files changed

+178
-81
lines changed

14 files changed

+178
-81
lines changed

VModer.Core/Dto/TraitDto.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Text.Json.Serialization;
2+
using EmmyLua.LanguageServer.Framework.Protocol.Model;
23
using VModer.Core.Models.Character;
34
using VModer.Core.Services;
45

@@ -17,4 +18,7 @@ public sealed class TraitDto
1718
/// </summary>
1819
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
1920
public string? Description { get; set; }
21+
22+
public required DocumentRange Position { get; init; }
23+
public required string FilePath { get; init; }
2024
}
Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using VModer.Core.Models.Modifiers;
1+
using ParadoxPower.Utilities;
2+
using VModer.Core.Models.Modifiers;
23

34
namespace VModer.Core.Models.Character;
45

@@ -7,22 +8,28 @@ namespace VModer.Core.Models.Character;
78
/// </summary>
89
public sealed class GeneralTrait
910
{
11+
public const string TraitSkillModifiersKey = "skill_modifiers_key";
12+
public const string TraitXpFactor = "trait_xp_factor";
13+
1014
public string Name { get; }
1115
public TraitType Type { get; }
1216
public IEnumerable<IModifier> AllModifiers =>
1317
ModifiersCollection
1418
.Where(collection => !collection.Key.Equals(TraitXpFactor, StringComparison.OrdinalIgnoreCase))
1519
.SelectMany(collection => collection.Modifiers);
16-
17-
public const string TraitSkillModifiersKey = "skill_modifiers_key";
18-
public const string TraitXpFactor = "trait_xp_factor";
19-
2020
public ModifierCollection[] ModifiersCollection { get; }
21+
public Position.Range Position { get; }
2122

22-
public GeneralTrait(string name, TraitType type, IEnumerable<ModifierCollection> modifiers)
23+
public GeneralTrait(
24+
string name,
25+
TraitType type,
26+
IEnumerable<ModifierCollection> modifiers,
27+
Position.Range range
28+
)
2329
{
2430
Name = name;
2531
Type = type;
2632
ModifiersCollection = modifiers.ToArray();
33+
Position = range;
2734
}
2835
}

VModer.Core/Services/GameResource/GeneralTraitsService.cs

Lines changed: 54 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ public List<TraitDto> GetAllTraitDto()
8888
LocalizedName = GetLocalizationName(trait),
8989
Modifiers = string.Join('\n', GetModifiersDescription(trait)),
9090
FileOrigin = fileOrigin,
91-
Type = trait.Type
91+
Type = trait.Type,
92+
Position = trait.Position.ToDocumentRange(),
93+
FilePath = fileResource.Key
9294
};
9395

9496
if (
@@ -111,12 +113,7 @@ public IEnumerable<string> GetModifiersDescription(GeneralTrait trait)
111113

112114
foreach (var modifierCollection in trait.ModifiersCollection)
113115
{
114-
if (
115-
modifierCollection.Key.Equals(
116-
GeneralTrait.TraitXpFactor,
117-
StringComparison.OrdinalIgnoreCase
118-
)
119-
)
116+
if (modifierCollection.Key.Equals(GeneralTrait.TraitXpFactor, StringComparison.OrdinalIgnoreCase))
120117
{
121118
foreach (var modifier in modifierCollection.Modifiers.OfType<LeafModifier>())
122119
{
@@ -200,60 +197,66 @@ private ReadOnlySpan<GeneralTrait> ParseTraitsNode(Node traitsNode)
200197
continue;
201198
}
202199

203-
string traitName = traitNode.Key;
200+
traits.Add(ParseTraitNode(traitNode));
201+
}
204202

205-
var modifiers = new List<ModifierCollection>(4);
206-
var skillModifiers = new List<LeafModifier>();
207-
var customModifiersTooltip = new List<LeafModifier>();
208-
var traitType = TraitType.None;
209-
foreach (var traitAttribute in traitNode.AllArray)
203+
return CollectionsMarshal.AsSpan(traits);
204+
}
205+
206+
private GeneralTrait ParseTraitNode(Node traitNode)
207+
{
208+
string traitName = traitNode.Key;
209+
210+
var modifiers = new List<ModifierCollection>(4);
211+
var skillModifiers = new List<LeafModifier>();
212+
var customModifiersTooltip = new List<LeafModifier>();
213+
var traitType = TraitType.None;
214+
foreach (var traitAttribute in traitNode.AllArray)
215+
{
216+
string? key = traitAttribute.GetKeyOrNull();
217+
// type 可以为 Leaf 或 Node
218+
if (StringComparer.OrdinalIgnoreCase.Equals(key, "type"))
210219
{
211-
string? key = traitAttribute.GetKeyOrNull();
212-
// type 可以为 Leaf 或 Node
213-
if (StringComparer.OrdinalIgnoreCase.Equals(key, "type"))
214-
{
215-
traitType = GetTraitType(traitAttribute);
216-
}
217-
else if (
218-
traitAttribute.TryGetNode(out var node)
219-
&& (
220-
Array.Exists(
221-
ModifierNodeKeys,
222-
keyword => StringComparer.OrdinalIgnoreCase.Equals(keyword, key)
223-
) || StringComparer.OrdinalIgnoreCase.Equals(key, GeneralTrait.TraitXpFactor)
224-
)
225-
)
226-
{
227-
modifiers.Add(ParseModifier(node));
228-
}
229-
else if (
230-
traitAttribute.TryGetLeaf(out var leaf)
231-
&& StringComparer.OrdinalIgnoreCase.Equals(LeafModifier.CustomEffectTooltipKey, key)
220+
traitType = GetTraitType(traitAttribute);
221+
}
222+
else if (
223+
traitAttribute.TryGetNode(out var node)
224+
&& (
225+
Array.Exists(
226+
ModifierNodeKeys,
227+
keyword => StringComparer.OrdinalIgnoreCase.Equals(keyword, key)
228+
) || StringComparer.OrdinalIgnoreCase.Equals(key, GeneralTrait.TraitXpFactor)
232229
)
233-
{
234-
customModifiersTooltip.Add(LeafModifier.FromLeaf(leaf));
235-
}
236-
else if (IsSkillModifier(traitAttribute, out leaf))
237-
{
238-
skillModifiers.Add(LeafModifier.FromLeaf(leaf));
239-
}
230+
)
231+
{
232+
modifiers.Add(ParseModifier(node));
240233
}
241-
242-
if (skillModifiers.Count != 0)
234+
else if (
235+
traitAttribute.TryGetLeaf(out var leaf)
236+
&& StringComparer.OrdinalIgnoreCase.Equals(LeafModifier.CustomEffectTooltipKey, key)
237+
)
243238
{
244-
modifiers.Add(new ModifierCollection(GeneralTrait.TraitSkillModifiersKey, skillModifiers));
239+
customModifiersTooltip.Add(LeafModifier.FromLeaf(leaf));
245240
}
246-
247-
if (customModifiersTooltip.Count != 0)
241+
else if (IsSkillModifier(traitAttribute, out leaf))
248242
{
249-
modifiers.Add(
250-
new ModifierCollection(LeafModifier.CustomEffectTooltipKey, customModifiersTooltip)
251-
);
243+
skillModifiers.Add(LeafModifier.FromLeaf(leaf));
252244
}
253-
traits.Add(new GeneralTrait(traitName, traitType, modifiers));
254245
}
255246

256-
return CollectionsMarshal.AsSpan(traits);
247+
if (skillModifiers.Count != 0)
248+
{
249+
modifiers.Add(new ModifierCollection(GeneralTrait.TraitSkillModifiersKey, skillModifiers));
250+
}
251+
252+
if (customModifiersTooltip.Count != 0)
253+
{
254+
modifiers.Add(
255+
new ModifierCollection(LeafModifier.CustomEffectTooltipKey, customModifiersTooltip)
256+
);
257+
}
258+
259+
return new GeneralTrait(traitName, traitType, modifiers, traitNode.Position);
257260
}
258261

259262
private TraitType GetTraitType(Child traitAttribute)

VModer.Core/VModer.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
<PackageReference Include="NeoLua" Version="1.3.14" />
4646
<PackageReference Include="NLog" Version="5.4.0" />
4747
<PackageReference Include="NLog.Extensions.Logging" Version="5.4.0" />
48-
<PackageReference Include="ParadoxPower" Version="0.8.5-beta" />
48+
<PackageReference Include="ParadoxPower" Version="0.8.6-beta" />
4949
<PackageReference Include="ParadoxPower.CSharpExtensions" Version="0.4.0-beta" />
5050
<PackageReference Include="Pfim" Version="0.11.3" />
5151
<PackageReference Include="Pidgin" Version="3.4.0" />

VModer.Extensions/client/extension/views/TraitsView.ts

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
1-
import { env, ExtensionContext, l10n, ViewColumn, WebviewPanel, window } from "vscode";
1+
import {
2+
env,
3+
ExtensionContext,
4+
l10n,
5+
Selection,
6+
Uri,
7+
ViewColumn,
8+
WebviewPanel,
9+
window,
10+
workspace,
11+
} from "vscode";
212
import { Disposable } from "vscode-languageclient";
313
import { WebviewHelpers } from "./WebviewHelpers";
414
import { LanguageClient } from "vscode-languageclient/node";
515
import type { TraitViewI18n } from "../../src/types/TraitViewI18n";
16+
import type { OpenInFileMessage } from '../../src/types/OpenInFileMessage';
17+
import type { DocumentRange } from '../../src/types/DocumentRange';
618

719
export class TraitView {
820
public static currentPanel: TraitView | undefined;
@@ -20,10 +32,15 @@ export class TraitView {
2032
if (TraitView.currentPanel) {
2133
TraitView.currentPanel._panel.reveal(ViewColumn.One);
2234
} else {
23-
const panel = window.createWebviewPanel("traitsView", l10n.t("TraitsView.Title"), ViewColumn.One, {
24-
enableScripts: true,
25-
retainContextWhenHidden: true,
26-
});
35+
const panel = window.createWebviewPanel(
36+
"traitsView",
37+
l10n.t("TraitsView.Title"),
38+
ViewColumn.One,
39+
{
40+
enableScripts: true,
41+
retainContextWhenHidden: true,
42+
}
43+
);
2744

2845
TraitView.currentPanel = new TraitView(panel, context);
2946

@@ -36,10 +53,11 @@ export class TraitView {
3653
modOnly: l10n.t("TraitsView.ModOnly"),
3754
traitType: l10n.t("TraitsView.TraitType"),
3855
copyTraitId: l10n.t("TraitsView.CopyTraitId"),
56+
openInFile: l10n.t("TraitsView.OpenInFile"),
3957
};
4058

4159
panel.webview.onDidReceiveMessage(
42-
async (message) => {
60+
async (message: string) => {
4361
if (message == "init_complete") {
4462
panel.webview.postMessage({ type: "i18n", data: i18n });
4563
panel.webview.postMessage({
@@ -53,7 +71,7 @@ export class TraitView {
5371
);
5472

5573
panel.webview.onDidReceiveMessage(
56-
async (message) => {
74+
async (message: ReceiveMessage<string>) => {
5775
if (message.type === "copyToClipboard") {
5876
try {
5977
await env.clipboard.writeText(message.data);
@@ -67,6 +85,32 @@ export class TraitView {
6785
null,
6886
TraitView.currentPanel._disposables
6987
);
88+
89+
panel.webview.onDidReceiveMessage(
90+
async (message: ReceiveMessage<OpenInFileMessage>) => {
91+
if (message.type === "openInFile") {
92+
try {
93+
const fileUri = Uri.file(message.data.filePath);
94+
95+
const position: DocumentRange = JSON.parse(message.data.position);
96+
// 创建选择区域
97+
const selection = new Selection(
98+
position.start,
99+
position.end
100+
);
101+
102+
// 打开文档并选中指定区域
103+
const document = await workspace.openTextDocument(fileUri);
104+
await window.showTextDocument(document, { selection });
105+
} catch (error) {
106+
console.error("无法打开文件:", error);
107+
window.showErrorMessage("无法打开文件");
108+
}
109+
}
110+
},
111+
null,
112+
TraitView.currentPanel._disposables
113+
);
70114
}
71115
}
72116

VModer.Extensions/client/l10n/bundle.l10n.en-US.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
"TraitsView.ModOnly": "Mod Only",
1111
"TraitsView.TraitType": "Trait Type:",
1212
"TraitsView.Title": "Character Traits Query",
13-
"TraitsView.CopyTraitId": "Copy Trait ID"
13+
"TraitsView.CopyTraitId": "Copy Trait ID",
14+
"TraitsView.OpenInFile": "Open in File"
1415
}

VModer.Extensions/client/l10n/bundle.l10n.zh-CN.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@
1010
"TraitsView.ModOnly": "仅模组",
1111
"TraitsView.TraitType": "特质类型:",
1212
"TraitsView.Title": "人物特质查询",
13-
"TraitsView.CopyTraitId": "复制特质ID"
13+
"TraitsView.CopyTraitId": "复制特质ID",
14+
"TraitsView.OpenInFile": "在文件中打开"
1415
}

0 commit comments

Comments
 (0)