diff --git a/src/ui/app.rs b/src/ui/app.rs index 31a8dbdb..22abd2ad 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -3346,6 +3346,27 @@ impl Tty7App { cx.notify(); } + /// Fills a rename box with the current name and puts the caret after it. + /// + /// `default_value` leaves the caret at offset 0, which turns typing into + /// prepending — renaming "tty7" reached "buildtty7" before it reached + /// "build". `set_value` lands the caret at the end of a single-line input, + /// which is where it belongs and what the file-tree rename box already + /// did. (Selecting the name outright would be better still, and is what + /// the platform does, but `InputState::select_all` is not public.) + pub(crate) fn rename_box( + current: String, + window: &mut Window, + cx: &mut Context, + ) -> Entity { + let input = cx.new(|cx| InputState::new(window, cx)); + input.update(cx, |state, cx| { + state.set_value(current, window, cx); + state.focus(window, cx); + }); + input + } + pub(crate) fn start_rename( &mut self, index: usize, @@ -3356,8 +3377,7 @@ impl Tty7App { return; } let current = self.tab_label(&self.tabs[index], index, Some(&*window), cx); - let input = cx.new(|cx| InputState::new(window, cx).default_value(current)); - input.update(cx, |state, cx| state.focus(window, cx)); + let input = Self::rename_box(current, window, cx); let subs = vec![cx.subscribe_in( &input, window, @@ -3377,8 +3397,7 @@ impl Tty7App { pub(crate) fn start_workspace_rename(&mut self, window: &mut Window, cx: &mut Context) { let current = crate::ui::machine_mirror::display_name_for(cx, self.workspace).unwrap_or_default(); - let input = cx.new(|cx| InputState::new(window, cx).default_value(current)); - input.update(cx, |state, cx| state.focus(window, cx)); + let input = Self::rename_box(current, window, cx); let subs = vec![cx.subscribe_in( &input, window, @@ -7317,3 +7336,36 @@ mod shell_menu_gpui_tests { }); } } + +#[cfg(test)] +mod rename_gpui_tests { + use gpui::TestAppContext; + + use crate::ui::app::test_window::harness_with_tabs; + + #[gpui::test] + fn a_rename_box_opens_with_the_caret_after_the_name(cx: &mut TestAppContext) { + let (app, mut vcx, _streams) = harness_with_tabs(cx, 1); + + app.update_in(&mut vcx, |app, window, cx| app.start_rename(0, window, cx)); + vcx.background_executor.run_until_parked(); + + app.update(&mut vcx, |app, cx| { + let input = app + .renaming + .as_ref() + .expect("the rename box is up") + .input + .clone(); + let state = input.read(cx); + let value = state.value().to_string(); + assert!(!value.is_empty(), "the box starts on the current name"); + let end = value.len(); + assert_eq!( + state.selected_range(), + end..end, + "typing has to continue {value:?}, not land in front of it" + ); + }); + } +} diff --git a/src/ui/switcher.rs b/src/ui/switcher.rs index 61aa4c47..c5d8f291 100644 --- a/src/ui/switcher.rs +++ b/src/ui/switcher.rs @@ -768,8 +768,7 @@ impl Tty7App { fn switcher_rename(&mut self, id: WorkspaceId, window: &mut Window, cx: &mut Context) { let current = crate::ui::machine_mirror::display_name_for(cx, id).unwrap_or_default(); - let input = cx.new(|cx| InputState::new(window, cx).default_value(current)); - input.update(cx, |state, cx| state.focus(window, cx)); + let input = Self::rename_box(current, window, cx); let sub = cx.subscribe_in( &input, window,