Skip to content
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

Some fixes to make edit() and file.edit() more robust #68

Merged
merged 2 commits into from
Jul 27, 2023

Conversation

DavisVaughan
Copy link
Contributor

@DavisVaughan DavisVaughan commented Jul 14, 2023

Addresses posit-dev/positron#856
Addresses part of posit-dev/positron#857 (we can open >1 file now, but enablePreview still messes with it)

Various improvements to make editing files through edit() and file.edit() more robust, I'll point them out inline

@kevinushey do we have any testing infra for the public/private modules? It seems like it would be nice to add some kinds of tests for the error cases here at least, but I'm not sure where to put them or how they'd get run 😢

Comment on lines +27 to +36
let uri = Url::from_file_path(&file);

let uri = unwrap!(uri, Err(_) => {
// The R side of this handles most issues, but we don't want to panic
// if some unknown file path slips through.
// `from_file_path()` doesn't return `Display`able errors, so we
// can't necessarily give a good reason.
log::error!("Can't open file at '{}'.", file);
return;
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in the comment, it is fairly hard to get here now, but just in case we do we don't want to panic

// `from_file_path()` doesn't return `Display`able errors, so we
// can't necessarily give a good reason.
log::error!("Can't open file at '{}'.", file);
return;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that this is an async function, and we use .await down below.

I don't need to do anything special before returning here, right? In my testing this seemed okay

.ps.Call("ps_editor", as.character(file), as.character(title))

options(editor = function(file, title, ..., name = NULL) {
handler_editor(file = file, title = title, ..., name = name)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have put this in its own private helper instead, as that makes it easier to debug by name, i.e. debugonce(handler_editor)

@@ -14,13 +14,69 @@
}

ensure_directory <- function(path) {
dir.create(path, showWarnings = FALSE, recursive = TRUE)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dir.create() is kind of lame unfortunately, since it only throws a warning if it can't create a directory, i.e. pass it dir.create("") for example.

I do think we want to error here, because we don't want to pass some invalid path to Rust

Comment on lines +26 to +29
# Try to create missing ones (`dir.create()` isn't vectorized)
for (elt in path) {
dir.create(elt, showWarnings = FALSE, recursive = TRUE)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +63 to +65
file.create(path, showWarnings = FALSE)

exists <- file.exists(path)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was scared to use the result of file.create() to detect file existence because of this note in dir.create()

One of the idiosyncrasies of Windows is that directory creation may report success but create a directory with a different name, for example dir.create("G.S.") creates ‘"G.S"’.

So rather than using the creation result, we check for existence of that original path again

title <- as.character(title)

# Get absolute path to file
file <- normalizePath(file, mustWork = FALSE)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was previously path.expand() but that won't work for something like edit(file = "foo"). To get an absolute path we need normalizePath().

Comment on lines +12 to +14
if (!is.null(name)) {
stop("Editing objects is not currently supported.", call. = FALSE)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

edit(mtcars) currently does work and goes through edit.data.frame(), but edit(1:5) goes through here and I've decided that we should just not allow this for now.

Comment on lines +16 to +20
if (identical(file, "")) {
# i.e. `edit()` with no arguments. Also `file.edit("")`.
# Opens a temporary file for editing.
file <- tempfile(fileext = ".txt")
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is documented behavior of ?edit

@DavisVaughan DavisVaughan requested a review from kevinushey July 14, 2023 19:42
Copy link
Contributor

@kevinushey kevinushey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@DavisVaughan DavisVaughan merged commit 47bbc42 into main Jul 27, 2023
@DavisVaughan DavisVaughan deleted the fix/edit-panic branch July 27, 2023 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants