Skip to content

Commit db482aa

Browse files
author
Eric Wheeler
committed
fix: improve directory link handling in markdown
Enhance the openFile function to better handle directory links in markdown: - Add support for resolving ./SimpleName paths to home directory if not found in workspace - Improve path resolution by checking multiple potential locations - Ensure directories are properly revealed in the Explorer view - Attempt to expand directories after revealing them Fixes: #3686 Signed-off-by: Eric Wheeler <[email protected]>
1 parent 6e958df commit db482aa

File tree

1 file changed

+86
-21
lines changed

1 file changed

+86
-21
lines changed

src/integrations/misc/open-file.ts

Lines changed: 86 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,39 +28,104 @@ interface OpenFileOptions {
2828

2929
export async function openFile(filePath: string, options: OpenFileOptions = {}) {
3030
try {
31-
// Get workspace root
3231
const workspaceRoot = getWorkspacePath()
32+
const homeDir = os.homedir()
33+
const originalFilePathForError = filePath // Keep original for error messages
3334

34-
// If path starts with ./, resolve it relative to workspace root if available
35-
// Otherwise, use the path as provided without modification
36-
const fullPath = filePath.startsWith("./")
37-
? workspaceRoot
38-
? path.join(workspaceRoot, filePath.slice(2))
39-
: filePath
40-
: filePath
35+
const attemptPaths: string[] = []
4136

42-
const uri = vscode.Uri.file(fullPath)
37+
if (filePath.startsWith("./")) {
38+
const relativePart = filePath.slice(2)
39+
if (workspaceRoot) {
40+
attemptPaths.push(path.join(workspaceRoot, relativePart))
41+
}
42+
if (homeDir) {
43+
const homePath = path.join(homeDir, relativePart)
44+
// Add home path if it's different from what might have been added via workspaceRoot
45+
// (e.g. if workspaceRoot itself is the home directory)
46+
if (!attemptPaths.includes(homePath)) {
47+
attemptPaths.push(homePath)
48+
}
49+
}
50+
// If no workspace and no home, or if paths were identical.
51+
if (attemptPaths.length === 0) {
52+
attemptPaths.push(filePath) // Try the original relative path as a last resort
53+
}
54+
} else {
55+
attemptPaths.push(filePath) // Assumed absolute or directly resolvable
56+
}
4357

44-
// Check if file exists
45-
try {
46-
await vscode.workspace.fs.stat(uri)
47-
} catch {
48-
// File doesn't exist
49-
if (!options.create) {
50-
throw new Error("File does not exist")
58+
let fileStat: vscode.FileStat | undefined
59+
let successfulUri: vscode.Uri | undefined
60+
61+
for (const p of attemptPaths) {
62+
try {
63+
const tempUri = vscode.Uri.file(p)
64+
fileStat = await vscode.workspace.fs.stat(tempUri)
65+
successfulUri = tempUri // Path found
66+
break // Exit loop once a path is successfully stated
67+
} catch (e) {
68+
// Stat failed for this path, continue to the next one
5169
}
70+
}
5271

53-
// Create with provided content or empty string
54-
const content = options.content || ""
55-
await vscode.workspace.fs.writeFile(uri, Buffer.from(content, "utf8"))
72+
let uriToProcess: vscode.Uri
73+
74+
if (fileStat && successfulUri) {
75+
// Path was found
76+
if (fileStat.type === vscode.FileType.Directory) {
77+
await vscode.commands.executeCommand("revealInExplorer", successfulUri)
78+
// Attempt to expand the revealed directory in the explorer.
79+
// This requires the explorer to have focus and the item to be selected.
80+
// A slight delay might sometimes be needed for focus to shift,
81+
// but often it works immediately after revealInExplorer.
82+
try {
83+
await vscode.commands.executeCommand("list.expand")
84+
} catch (expandError) {
85+
// Log or handle if expansion specifically fails, though often not critical
86+
console.warn("Could not expand directory in explorer:", expandError)
87+
}
88+
return // Done for directories
89+
}
90+
uriToProcess = successfulUri // It's an existing file
91+
} else {
92+
// Path was not found in any attempted locations. Consider creation.
93+
if (
94+
options.create &&
95+
!(originalFilePathForError.endsWith("/") || originalFilePathForError.endsWith("\\"))
96+
) {
97+
let pathToCreateAt: string
98+
if (originalFilePathForError.startsWith("./")) {
99+
const relativePart = originalFilePathForError.slice(2)
100+
if (workspaceRoot) {
101+
pathToCreateAt = path.join(workspaceRoot, relativePart)
102+
} else if (homeDir) {
103+
pathToCreateAt = path.join(homeDir, relativePart)
104+
} else {
105+
pathToCreateAt = originalFilePathForError // Fallback: use original relative path
106+
}
107+
} else {
108+
pathToCreateAt = originalFilePathForError // Absolute path
109+
}
110+
111+
uriToProcess = vscode.Uri.file(pathToCreateAt)
112+
const contentToCreate = options.content || ""
113+
await vscode.workspace.fs.writeFile(uriToProcess, Buffer.from(contentToCreate, "utf8"))
114+
// File is now created, uriToProcess points to it.
115+
} else {
116+
// Not creating, or it's a directory-like path that doesn't exist.
117+
throw new Error(`Path does not exist: ${originalFilePathForError}`)
118+
}
56119
}
57120

121+
// At this point, uriToProcess points to an existing file or a newly created file.
58122
// Check if the document is already open in a tab group that's not in the active editor's column
59123
try {
60124
for (const group of vscode.window.tabGroups.all) {
61125
const existingTab = group.tabs.find(
62126
(tab) =>
63-
tab.input instanceof vscode.TabInputText && arePathsEqual(tab.input.uri.fsPath, uri.fsPath),
127+
tab.input instanceof vscode.TabInputText &&
128+
arePathsEqual(tab.input.uri.fsPath, uriToProcess.fsPath),
64129
)
65130
if (existingTab) {
66131
const activeColumn = vscode.window.activeTextEditor?.viewColumn
@@ -75,7 +140,7 @@ export async function openFile(filePath: string, options: OpenFileOptions = {})
75140
}
76141
} catch {} // not essential, sometimes tab operations fail
77142

78-
const document = await vscode.workspace.openTextDocument(uri)
143+
const document = await vscode.workspace.openTextDocument(uriToProcess)
79144
const selection =
80145
options.line !== undefined ? new vscode.Selection(options.line - 1, 0, options.line - 1, 0) : undefined
81146
await vscode.window.showTextDocument(document, {

0 commit comments

Comments
 (0)