Seeker14491 / opener

Open a file or link in the system default program.
Apache License 2.0
49 stars 10 forks source link

Add function to open files in system file manager #11

Closed philippeitis closed 1 year ago

philippeitis commented 2 years ago

I'd like to use opener to open files in my application, but I also need to be able to open files in a file manager. I have added an implementation for this on Windows, MacOS, and Linux (but not WSL). I think something like explorer.exe /select,"path" would work, but I had issues with Process mangling the string escaping.

The Windows implementation is based on this answer from StackOverflow, adapted to Rust.

The MacOS implementation is based on this link, under the "Showing Files in Finder" subsection.

The Linux implementation uses dbus, though this only supports one or two file managers, based on this answer from StackOverflow.

Seeker14491 commented 2 years ago

Thanks for the PR, I think this functionality would be nice to have.

Regarding the implementation on Linux, we shouldn't just run Nautilus in the case where the path is not a directory; we can't assume Nautilus is installed or is the preferred file manager on a given system.

philippeitis commented 2 years ago

It doesn't seem like there are any alternatives besides manually calling known programs or using dbus, but dbus is hopefully a universal option, so I think that'd be the best solution. Accordingly, I've added an implementation using dbus.

However, it seems that calling the command from Rust doesn't work. When displayed by echo, the command appears to be in the correct format, and manually running it works correctly - I think that Rust is mangling the string quotes somehow.

Seeker14491 commented 2 years ago

The problem with the quotes was that we don't need them, since we're passing the arguments straight to the dbus-send, not going through a shell. I commited a fix. If the dbus command fails, I think we could fall back to calling the open() function with the parent directory path. I can take a look at WSL support; we might also just want to fall back to the open() function.

philippeitis commented 2 years ago

I don't have a WSL environment to test any changes in, so I can't really contribute there. In terms of falling back, I think that it would be possible to do this directly in the top level open_in_file_manager function (though I'm not sure how useful that would be for Mac/Windows)

Seeker14491 commented 2 years ago

Yes, I might do that. I was also testing out the implementation on Mac and Windows. I didn't find any issues with the Mac implementation, but on Windows if you pass in a non-existing path you don't get an error; the explorer window just opens on the top-level "This PC" view. Ideally we would get an error in this case instead.

philippeitis commented 2 years ago

I think we could check if the directory exists using https://doc.rust-lang.org/std/fs/fn.metadata.html, though it seems like this could error if the user doesn't have permissions to read it (in which case, I'd assume that they also couldn't view the file?).

I believe that fs::metadata is what is called by Path::exists, though Path::exists suppresses any errors.

Seeker14491 commented 2 years ago

Ideally the command we execute would just return an error; it's just more robust than doing our own check. But if that's not doable on Windows, then we might just have to do something like what you describe.

Seeker14491 commented 1 year ago

This functionality has been implemented in #18.