-
Notifications
You must be signed in to change notification settings - Fork 499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add CurrentFile SaveAs() support #1261
Conversation
Yeah, getting rid of the nesting is tough because you're building context as you go (it's secretly a monad). But I think you're quite right, we can reduce the complexity by loosening the sequencing requirements. |
I think I tried using |
src/features/ExtensionCommands.ts
Outdated
}); | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a nice syntactic sugar I think...
I'm considering posting on Stack Overflow on how one might saveAs using the vscode API. I feel like it's a reasonable question and people would have use of it. Thoughts? |
Yeah I agree. Either there or on their GitHub page |
Here it is: https://stackoverflow.com/questions/49787354/implementing-a-save-as-using-the-vscode-api We can open an issue in a day or so if we don't get any bites. |
Any reason an async method won't work? private async saveFile(saveFileDetails: ISaveFileDetails): Promise<EditorOperationResponse> {
// If the file to save can't be found, just complete the request
if (!this.findTextDocument(this.normalizeFilePath(saveFileDetails.filePath))) {
return EditorOperationResponse.Completed;
}
// If no newFile is given, just save the current file
if (!saveFileDetails.newPath) {
const doc = await vscode.workspace.openTextDocument(saveFileDetails.filePath);
if (doc.isDirty) {
await doc.save();
}
return EditorOperationResponse.Completed;
}
// Otherwise we want to save as a new file
// First turn the path we were given into an absolute path
// Relative paths are interpreted as relative to the original file
const newFileAbsolutePath = path.isAbsolute(saveFileDetails.newPath) ?
saveFileDetails.newPath :
path.resolve(path.dirname(saveFileDetails.filePath), saveFileDetails.newPath);
// Create an "untitled-scheme" path so that VSCode will let us create a new file with a given path
const newFileUri = vscode.Uri.parse("untitled:" + newFileAbsolutePath);
// Now we need to copy the content of the current file,
// then create a new file at the given path, insert the content,
// save it and open the document
const oldDoc = await vscode.workspace.openTextDocument(saveFileDetails.filePath);
const newDoc = await vscode.workspace.openTextDocument(newFileUri);
const editor = await vscode.window.showTextDocument(newDoc, 1, false);
await editor.edit((editBuilder) => {
editBuilder.insert(new vscode.Position(0, 0), oldDoc.getText());
});
await newDoc.save();
return EditorOperationResponse.Completed;
} Edit: Completely missed the part about it not working in general. Whoops :) |
Wow, that's much better. I had no idea |
Now the question remains, how do we bring the new document window into focus. (The |
didn't realize we could use async/await here 😄 thanks for that @SeeminglyScience! |
I wonder if it's because you're saving an untitled file: const newFileUri = vscode.Uri.parse("untitled:" + newFileAbsolutePath); |
I've been trying various ways to "save-as" and then open that window. Opening with a new "file://" URI after the save, I get the new file opened. But then the old one closes, which isn't what I imagine people wanting. I'm mildly reluctant to bypass VSCode and just use |
Ok, I've fixed up the code (resolved by pulling the text out of the unsaved buffer, saving it to the filesystem and the opening the new file...) and it now seems to do what I want. We should probably test it out a bit and validate the behaviour (and see if using different paths breaks it) before merging, but I think it's good to go. |
I wonder if we should just ignore the
|
Yeah, I had added it to the ignore on the basis that it was generated by the user's environment, but @tylerl0706 suggested we should keep it in as it represents some pre-resolved work for npm. npm's pages state that it's intended to be tracked, but if it keeps changing in every commit because different machines use it differently, then I'd argue that it's noise in the commit and we should ignore it (and npm should work out what they're trying to achieve with this file...). But I don't have a strong opinion either way (as long as deleting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
async/await is beautiful and this LGTM! Just a couple questions that I'm curious about.
src/features/ExtensionCommands.ts
Outdated
const oldDocText = oldDocument.getText(); | ||
|
||
// Write it to the new document path | ||
fs.writeFileSync(newFileAbsolutePath, oldDocText); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick:
fs.writeFileSync(newFileAbsolutePath, oldDocument.getText());
deletes a line.
might be worth it but don't care that much.
src/features/ExtensionCommands.ts
Outdated
// Finally open the new document | ||
const newFileUri = vscode.Uri.file(newFileAbsolutePath); | ||
const newFile = await vscode.workspace.openTextDocument(newFileUri); | ||
vscode.window.showTextDocument(newFile, { preview: false }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you choose to open it not as a preview? Just curious. Not really leaning either way personally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, didn't know what it was (just followed the response on SO figuring it prevented some behaviour). I feel like maybe it actually should be a preview...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm leaning on preview actually too 😄
@@ -382,24 +388,45 @@ export class ExtensionCommandsFeature implements IFeature { | |||
return promise; | |||
} | |||
|
|||
private saveFile(filePath: string): Thenable<EditorOperationResponse> { | |||
private async saveFile(saveFileDetails: ISaveFileDetails): Promise<EditorOperationResponse> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you have to switch this from a Thenable to a Promise to use async/await?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah -- as in @SeeminglyScience's snippet. Thenable
doesn't type check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good to know!
// Finally open the new document | ||
const newFileUri = vscode.Uri.file(newFileAbsolutePath); | ||
const newFile = await vscode.workspace.openTextDocument(newFileUri); | ||
vscode.window.showTextDocument(newFile, { preview: true }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
preview should be true by default. Were you seeing otherwise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No no, and actually I originally just took it out. But I couldn't find a reference to what the default is in the documentation and decided that we may as well make the expected behaviour explicit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good!
I have tested out the SaveAs('d:\test.ps1') This appears to work if the file is already saved as another file, however not if the file is Untitled? E.g. Is someone able to test this and see if they have the same experience ? |
You're quite right. I've opened an issue: #1303. |
In combination with PSES #650, this adds the ability to run
$psEditor.GetEditorContext().CurrentFile.SaveAs("newFile")
.Some things to note (that I'm looking for input on):
SaveAs
method supports both absolute and relative paths, relative being relative to the current file path.