Skip to content

Commit 3c72e24

Browse files
committed
Refactor context management to support nested folder structure and update UI terminology from "contexts" to "entries"
1 parent 22ffb5f commit 3c72e24

4 files changed

Lines changed: 455 additions & 573 deletions

File tree

‎packages/vscode/src/commands/apply-context-command/apply-context-command.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export function apply_context_command(
6262
main_quick_pick_options.push({
6363
label: 'Workspace state',
6464
description: `${internal_contexts.length} ${
65-
internal_contexts.length === 1 ? 'context' : 'contexts'
65+
internal_contexts.length == 1 ? 'entry' : 'entries'
6666
}`,
6767
value: 'internal'
6868
})
@@ -75,7 +75,7 @@ export function apply_context_command(
7575
main_quick_pick_options.push({
7676
label: 'JSON file',
7777
description: `${file_contexts_count} ${
78-
file_contexts_count === 1 ? 'context' : 'contexts'
78+
file_contexts_count == 1 ? 'entry' : 'entries'
7979
}`,
8080
value: 'file',
8181
buttons: [open_file_button]

‎packages/vscode/src/commands/apply-context-command/helpers/saving/context-file-utils.ts‎

Lines changed: 91 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,84 @@ export function get_contexts_file_path(workspace_root: string): string {
77
return path.join(workspace_root, '.vscode', 'contexts.json')
88
}
99

10+
export function flatten_contexts(
11+
items: any[],
12+
parent_name = ''
13+
): SavedContext[] {
14+
const result: SavedContext[] = []
15+
if (!Array.isArray(items)) return result
16+
17+
for (const item of items) {
18+
if (typeof item !== 'object' || item === null) continue
19+
20+
const name = item.name
21+
if (typeof name !== 'string' || !name) continue
22+
23+
const current_name = parent_name ? `${parent_name}/${name}` : name
24+
25+
if (
26+
Array.isArray(item.paths) &&
27+
item.paths.every((p: any) => typeof p === 'string')
28+
) {
29+
result.push({
30+
name: current_name,
31+
paths: item.paths
32+
})
33+
}
34+
35+
if (Array.isArray(item.children)) {
36+
result.push(...flatten_contexts(item.children, current_name))
37+
}
38+
}
39+
return result
40+
}
41+
42+
function nest_contexts(contexts: SavedContext[]): any[] {
43+
const root: any[] = []
44+
45+
const find_node = (nodes: any[], name: string) =>
46+
nodes.find((n) => n.name === name)
47+
48+
for (const ctx of contexts) {
49+
const parts = ctx.name.split('/')
50+
let current_level = root
51+
52+
for (let i = 0; i < parts.length; i++) {
53+
const part = parts[i]
54+
let node = find_node(current_level, part)
55+
56+
if (!node) {
57+
node = { name: part }
58+
current_level.push(node)
59+
}
60+
61+
if (i === parts.length - 1) {
62+
node.paths = ctx.paths
63+
} else {
64+
if (!node.children) {
65+
node.children = []
66+
}
67+
current_level = node.children
68+
}
69+
}
70+
}
71+
72+
return root
73+
}
74+
75+
export function load_contexts_from_file(file_path: string): SavedContext[] {
76+
try {
77+
if (fs.existsSync(file_path)) {
78+
const content = fs.readFileSync(file_path, 'utf8')
79+
const parsed = JSON.parse(content)
80+
return flatten_contexts(parsed)
81+
}
82+
} catch (error) {
83+
console.error(`Error reading contexts file from ${file_path}:`, error)
84+
}
85+
return []
86+
}
87+
1088
export async function load_all_contexts(): Promise<
1189
Map<string, { contexts: SavedContext[]; root: string }>
1290
> {
@@ -18,37 +96,19 @@ export async function load_all_contexts(): Promise<
1896

1997
for (const folder of workspace_folders) {
2098
const contexts_file_path = get_contexts_file_path(folder.uri.fsPath)
99+
const contexts = load_contexts_from_file(contexts_file_path)
21100

22-
try {
23-
if (fs.existsSync(contexts_file_path)) {
24-
const content = fs.readFileSync(contexts_file_path, 'utf8')
25-
const parsed = JSON.parse(content)
26-
if (Array.isArray(parsed)) {
27-
const contexts = parsed.filter(
28-
(item) =>
29-
typeof item == 'object' &&
30-
item !== null &&
31-
typeof item.name == 'string' &&
32-
Array.isArray(item.paths) &&
33-
item.paths.every((p: any) => typeof p == 'string')
34-
) as SavedContext[]
35-
36-
for (const context of contexts) {
37-
if (!contexts_by_name.has(context.name)) {
38-
contexts_by_name.set(context.name, {
39-
contexts: [],
40-
root: folder.uri.fsPath
41-
})
42-
}
43-
contexts_by_name.get(context.name)!.contexts.push({
44-
...context,
45-
_root: folder.uri.fsPath
46-
} as any)
47-
}
48-
}
101+
for (const context of contexts) {
102+
if (!contexts_by_name.has(context.name)) {
103+
contexts_by_name.set(context.name, {
104+
contexts: [],
105+
root: folder.uri.fsPath
106+
})
49107
}
50-
} catch (error: any) {
51-
console.error(`Error reading contexts file from ${folder.name}:`, error)
108+
contexts_by_name.get(context.name)!.contexts.push({
109+
...context,
110+
_root: folder.uri.fsPath
111+
} as any)
52112
}
53113
}
54114

@@ -70,7 +130,8 @@ export async function save_contexts_to_file(
70130
fs.unlinkSync(file_path)
71131
}
72132
} else {
73-
fs.writeFileSync(file_path, JSON.stringify(contexts, null, 2), 'utf8')
133+
const nested = nest_contexts(contexts)
134+
fs.writeFileSync(file_path, JSON.stringify(nested, null, 2), 'utf8')
74135
}
75136
} catch (error: any) {
76137
throw new Error(`Failed to save contexts to file: ${error.message}`)

0 commit comments

Comments
 (0)