diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 5da098a6602df6e31da3e4c5d327a6c290e4f8f8..03c8001dab91b242f442e36cdd4966d665730e91 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -608,12 +608,6 @@ pub trait Addon: 'static { fn to_any(&self) -> &dyn std::any::Any; } -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum IsVimMode { - Yes, - No, -} - /// Zed's primary implementation of text input, allowing users to edit a [`MultiBuffer`]. /// /// See the [module level documentation](self) for more information. @@ -645,6 +639,7 @@ pub struct Editor { inline_diagnostics_enabled: bool, inline_diagnostics: Vec<(Anchor, InlineDiagnostic)>, soft_wrap_mode_override: Option, + hard_wrap: Option, // TODO: make this a access method pub project: Option>, @@ -1356,6 +1351,7 @@ impl Editor { inline_diagnostics_update: Task::ready(()), inline_diagnostics: Vec::new(), soft_wrap_mode_override, + hard_wrap: None, completion_provider: project.clone().map(|project| Box::new(project) as _), semantics_provider: project.clone().map(|project| Rc::new(project) as _), collaboration_hub: project.clone().map(|project| Box::new(project) as _), @@ -3193,6 +3189,19 @@ impl Editor { let trigger_in_words = this.show_edit_predictions_in_menu() || !had_active_inline_completion; + if this.hard_wrap.is_some() { + let latest: Range = this.selections.newest(cx).range(); + if latest.is_empty() + && this + .buffer() + .read(cx) + .snapshot(cx) + .line_len(MultiBufferRow(latest.start.row)) + == latest.start.column + { + this.rewrap_impl(true, cx) + } + } this.trigger_completion_on_input(&text, trigger_in_words, window, cx); linked_editing_ranges::refresh_linked_ranges(this, window, cx); this.refresh_inline_completion(true, false, window, cx); @@ -8597,10 +8606,10 @@ impl Editor { } pub fn rewrap(&mut self, _: &Rewrap, _: &mut Window, cx: &mut Context) { - self.rewrap_impl(IsVimMode::No, cx) + self.rewrap_impl(false, cx) } - pub fn rewrap_impl(&mut self, is_vim_mode: IsVimMode, cx: &mut Context) { + pub fn rewrap_impl(&mut self, override_language_settings: bool, cx: &mut Context) { let buffer = self.buffer.read(cx).snapshot(cx); let selections = self.selections.all::(cx); let mut selections = selections.iter().peekable(); @@ -8674,7 +8683,9 @@ impl Editor { RewrapBehavior::Anywhere => true, }; - let should_rewrap = is_vim_mode == IsVimMode::Yes || allow_rewrap_based_on_language; + let should_rewrap = override_language_settings + || allow_rewrap_based_on_language + || self.hard_wrap.is_some(); if !should_rewrap { continue; } @@ -8722,9 +8733,11 @@ impl Editor { continue; }; - let wrap_column = buffer - .language_settings_at(Point::new(start_row, 0), cx) - .preferred_line_length as usize; + let wrap_column = self.hard_wrap.unwrap_or_else(|| { + buffer + .language_settings_at(Point::new(start_row, 0), cx) + .preferred_line_length as usize + }); let wrapped_text = wrap_with_prefix( line_prefix, lines_without_prefixes.join(" "), @@ -8735,7 +8748,7 @@ impl Editor { // TODO: should always use char-based diff while still supporting cursor behavior that // matches vim. let mut diff_options = DiffOptions::default(); - if is_vim_mode == IsVimMode::Yes { + if override_language_settings { diff_options.max_word_diff_len = 0; diff_options.max_word_diff_line_count = 0; } else { @@ -14305,6 +14318,11 @@ impl Editor { cx.notify(); } + pub fn set_hard_wrap(&mut self, hard_wrap: Option, cx: &mut Context) { + self.hard_wrap = hard_wrap; + cx.notify(); + } + pub fn set_text_style_refinement(&mut self, style: TextStyleRefinement) { self.text_style_refinement = Some(style); } diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 3c4c9622a4f15ac1ea8e00ddd2ae71705cc78ae3..5b86c74d7a4ff6e88152c3a475e13b5ade814122 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -4738,6 +4738,31 @@ async fn test_rewrap(cx: &mut TestAppContext) { } } +#[gpui::test] +async fn test_hard_wrap(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + let mut cx = EditorTestContext::new(cx).await; + + cx.update_editor(|editor, _, cx| { + editor.set_hard_wrap(Some(14), cx); + }); + + cx.set_state(indoc!( + " + one two three ˇ + " + )); + cx.simulate_input("four"); + cx.run_until_parked(); + + cx.assert_editor_state(indoc!( + " + one two three + fourˇ + " + )); +} + #[gpui::test] async fn test_clipboard(cx: &mut TestAppContext) { init_test(cx, |_| {}); diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index afe83b0c02a9ab6ca9780794618133422f0ea955..f42b085480c404ed057bb863329e1a20f5e37692 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -367,6 +367,7 @@ pub(crate) fn commit_message_editor( commit_editor.set_show_gutter(false, cx); commit_editor.set_show_wrap_guides(false, cx); commit_editor.set_show_indent_guides(false, cx); + commit_editor.set_hard_wrap(Some(72), cx); let placeholder = placeholder.unwrap_or("Enter commit message"); commit_editor.set_placeholder_text(placeholder, cx); commit_editor diff --git a/crates/vim/src/rewrap.rs b/crates/vim/src/rewrap.rs index 61728d6537feaee0d3e9f833100283c44d44b110..a889b0bf99faf6a46643e948284d343bd0fc9bac 100644 --- a/crates/vim/src/rewrap.rs +++ b/crates/vim/src/rewrap.rs @@ -1,6 +1,6 @@ use crate::{motion::Motion, object::Object, state::Mode, Vim}; use collections::HashMap; -use editor::{display_map::ToDisplayPoint, scroll::Autoscroll, Bias, Editor, IsVimMode}; +use editor::{display_map::ToDisplayPoint, scroll::Autoscroll, Bias, Editor}; use gpui::{actions, Context, Window}; use language::SelectionGoal; @@ -14,7 +14,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut Context) { vim.update_editor(window, cx, |vim, editor, window, cx| { editor.transact(window, cx, |editor, window, cx| { let mut positions = vim.save_selection_starts(editor, cx); - editor.rewrap_impl(IsVimMode::Yes, cx); + editor.rewrap_impl(true, cx); editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| { s.move_with(|map, selection| { if let Some(anchor) = positions.remove(&selection.id) { @@ -52,7 +52,7 @@ impl Vim { motion.expand_selection(map, selection, times, false, &text_layout_details); }); }); - editor.rewrap_impl(IsVimMode::Yes, cx); + editor.rewrap_impl(true, cx); editor.change_selections(None, window, cx, |s| { s.move_with(|map, selection| { let anchor = selection_starts.remove(&selection.id).unwrap(); @@ -83,7 +83,7 @@ impl Vim { object.expand_selection(map, selection, around); }); }); - editor.rewrap_impl(IsVimMode::Yes, cx); + editor.rewrap_impl(true, cx); editor.change_selections(None, window, cx, |s| { s.move_with(|map, selection| { let anchor = original_positions.remove(&selection.id).unwrap();