Suggest unsaved buffer content text as the default filename (#35707)
Closes #24672 This PR complements a feature added earlier by @JosephTLyons (in https://github.com/zed-industries/zed/pull/32353) where the text is considered as the tab title in a new buffer. It piggybacks off that change and sets the title as the suggested filename in the save dialog (completely mirroring the same functionality in VSCode):  Release Notes: - Text entered in a new untitled buffer is considered as the default filename when saving
This commit is contained in:
@@ -327,26 +327,35 @@ impl<P: LinuxClient + 'static> Platform for P {
|
||||
done_rx
|
||||
}
|
||||
|
||||
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Result<Option<PathBuf>>> {
|
||||
fn prompt_for_new_path(
|
||||
&self,
|
||||
directory: &Path,
|
||||
suggested_name: Option<&str>,
|
||||
) -> oneshot::Receiver<Result<Option<PathBuf>>> {
|
||||
let (done_tx, done_rx) = oneshot::channel();
|
||||
|
||||
#[cfg(not(any(feature = "wayland", feature = "x11")))]
|
||||
let _ = (done_tx.send(Ok(None)), directory);
|
||||
let _ = (done_tx.send(Ok(None)), directory, suggested_name);
|
||||
|
||||
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||
self.foreground_executor()
|
||||
.spawn({
|
||||
let directory = directory.to_owned();
|
||||
let suggested_name = suggested_name.map(|s| s.to_owned());
|
||||
|
||||
async move {
|
||||
let request = match ashpd::desktop::file_chooser::SaveFileRequest::default()
|
||||
.modal(true)
|
||||
.title("Save File")
|
||||
.current_folder(directory)
|
||||
.expect("pathbuf should not be nul terminated")
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
let mut request_builder =
|
||||
ashpd::desktop::file_chooser::SaveFileRequest::default()
|
||||
.modal(true)
|
||||
.title("Save File")
|
||||
.current_folder(directory)
|
||||
.expect("pathbuf should not be nul terminated");
|
||||
|
||||
if let Some(suggested_name) = suggested_name {
|
||||
request_builder = request_builder.current_name(suggested_name.as_str());
|
||||
}
|
||||
|
||||
let request = match request_builder.send().await {
|
||||
Ok(request) => request,
|
||||
Err(err) => {
|
||||
let result = match err {
|
||||
|
||||
@@ -737,8 +737,13 @@ impl Platform for MacPlatform {
|
||||
done_rx
|
||||
}
|
||||
|
||||
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Result<Option<PathBuf>>> {
|
||||
fn prompt_for_new_path(
|
||||
&self,
|
||||
directory: &Path,
|
||||
suggested_name: Option<&str>,
|
||||
) -> oneshot::Receiver<Result<Option<PathBuf>>> {
|
||||
let directory = directory.to_owned();
|
||||
let suggested_name = suggested_name.map(|s| s.to_owned());
|
||||
let (done_tx, done_rx) = oneshot::channel();
|
||||
self.foreground_executor()
|
||||
.spawn(async move {
|
||||
@@ -748,6 +753,11 @@ impl Platform for MacPlatform {
|
||||
let url = NSURL::fileURLWithPath_isDirectory_(nil, path, true.to_objc());
|
||||
panel.setDirectoryURL(url);
|
||||
|
||||
if let Some(suggested_name) = suggested_name {
|
||||
let name_string = ns_string(&suggested_name);
|
||||
let _: () = msg_send![panel, setNameFieldStringValue: name_string];
|
||||
}
|
||||
|
||||
let done_tx = Cell::new(Some(done_tx));
|
||||
let block = ConcreteBlock::new(move |response: NSModalResponse| {
|
||||
let mut result = None;
|
||||
|
||||
@@ -336,6 +336,7 @@ impl Platform for TestPlatform {
|
||||
fn prompt_for_new_path(
|
||||
&self,
|
||||
directory: &std::path::Path,
|
||||
_suggested_name: Option<&str>,
|
||||
) -> oneshot::Receiver<Result<Option<std::path::PathBuf>>> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.background_executor()
|
||||
|
||||
@@ -490,13 +490,18 @@ impl Platform for WindowsPlatform {
|
||||
rx
|
||||
}
|
||||
|
||||
fn prompt_for_new_path(&self, directory: &Path) -> Receiver<Result<Option<PathBuf>>> {
|
||||
fn prompt_for_new_path(
|
||||
&self,
|
||||
directory: &Path,
|
||||
suggested_name: Option<&str>,
|
||||
) -> Receiver<Result<Option<PathBuf>>> {
|
||||
let directory = directory.to_owned();
|
||||
let suggested_name = suggested_name.map(|s| s.to_owned());
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let window = self.find_current_active_window();
|
||||
self.foreground_executor()
|
||||
.spawn(async move {
|
||||
let _ = tx.send(file_save_dialog(directory, window));
|
||||
let _ = tx.send(file_save_dialog(directory, suggested_name, window));
|
||||
})
|
||||
.detach();
|
||||
|
||||
@@ -804,7 +809,11 @@ fn file_open_dialog(
|
||||
Ok(Some(paths))
|
||||
}
|
||||
|
||||
fn file_save_dialog(directory: PathBuf, window: Option<HWND>) -> Result<Option<PathBuf>> {
|
||||
fn file_save_dialog(
|
||||
directory: PathBuf,
|
||||
suggested_name: Option<String>,
|
||||
window: Option<HWND>,
|
||||
) -> Result<Option<PathBuf>> {
|
||||
let dialog: IFileSaveDialog = unsafe { CoCreateInstance(&FileSaveDialog, None, CLSCTX_ALL)? };
|
||||
if !directory.to_string_lossy().is_empty() {
|
||||
if let Some(full_path) = directory.canonicalize().log_err() {
|
||||
@@ -815,6 +824,11 @@ fn file_save_dialog(directory: PathBuf, window: Option<HWND>) -> Result<Option<P
|
||||
unsafe { dialog.SetFolder(&path_item).log_err() };
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(suggested_name) = suggested_name {
|
||||
unsafe { dialog.SetFileName(&HSTRING::from(suggested_name)).log_err() };
|
||||
}
|
||||
|
||||
unsafe {
|
||||
dialog.SetFileTypes(&[Common::COMDLG_FILTERSPEC {
|
||||
pszName: windows::core::w!("All files"),
|
||||
|
||||
Reference in New Issue
Block a user