diff --git a/crates/chat_panel/src/lib.rs b/crates/chat_panel/src/lib.rs index 614022d4c9..d9d3ce64fa 100644 --- a/crates/chat_panel/src/lib.rs +++ b/crates/chat_panel/src/lib.rs @@ -61,6 +61,7 @@ impl ChatPanel { EditorSettings { tab_size: settings.tab_size, style: settings.theme.chat_panel.input_editor.as_editor(), + soft_wrap: editor::SoftWrap::EditorWidth, } } }, diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 2f4923985f..c8e307c0ac 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1,6 +1,6 @@ use super::{ DisplayPoint, DisplayRow, Editor, EditorMode, EditorSettings, EditorStyle, Input, Scroll, - Select, SelectPhase, Snapshot, MAX_LINE_LEN, + Select, SelectPhase, Snapshot, SoftWrap, MAX_LINE_LEN, }; use clock::ReplicaId; use gpui::{ @@ -703,7 +703,11 @@ impl Element for EditorElement { let em_width = style.text.em_width(cx.font_cache); let em_advance = style.text.em_advance(cx.font_cache); let overscroll = vec2f(em_width, 0.); - let wrap_width = text_width - text_offset.x() - overscroll.x() - em_width; + let wrap_width = match self.settings.soft_wrap { + SoftWrap::None => None, + SoftWrap::EditorWidth => Some(text_width - text_offset.x() - overscroll.x() - em_width), + SoftWrap::Column(column) => Some(column as f32 * em_advance), + }; let snapshot = self.update_view(cx.app, |view, cx| { if view.set_wrap_width(wrap_width, cx) { view.snapshot(cx) diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 7812af7820..e5dc4fb224 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -12,7 +12,8 @@ use project::{ProjectPath, Worktree}; use std::fmt::Write; use std::path::Path; use workspace::{ - EntryOpener, ItemHandle, ItemView, ItemViewHandle, Settings, StatusItemView, WeakItemHandle, + settings, EntryOpener, ItemHandle, ItemView, ItemViewHandle, Settings, StatusItemView, + WeakItemHandle, }; pub struct BufferOpener; @@ -47,6 +48,7 @@ impl ItemHandle for BufferItemHandle { settings: watch::Receiver, cx: &mut MutableAppContext, ) -> Box { + let buffer = self.0.downgrade(); Box::new(cx.add_view(window_id, |cx| { Editor::for_buffer( self.0.clone(), @@ -71,8 +73,18 @@ impl ItemHandle for BufferItemHandle { font_properties, underline: None, }; + let language = buffer.upgrade(cx).and_then(|buf| buf.read(cx).language()); + let soft_wrap = match settings.soft_wrap(language) { + settings::SoftWrap::None => crate::SoftWrap::None, + settings::SoftWrap::EditorWidth => crate::SoftWrap::EditorWidth, + settings::SoftWrap::PreferredLineLength => crate::SoftWrap::Column( + settings.preferred_line_length(language).saturating_sub(1), + ), + }; + EditorSettings { tab_size: settings.tab_size, + soft_wrap, style: theme, } }, diff --git a/crates/editor/src/lib.rs b/crates/editor/src/lib.rs index 453747e83f..9339f836db 100644 --- a/crates/editor/src/lib.rs +++ b/crates/editor/src/lib.rs @@ -333,9 +333,17 @@ pub enum EditorMode { #[derive(Clone)] pub struct EditorSettings { pub tab_size: usize, + pub soft_wrap: SoftWrap, pub style: EditorStyle, } +#[derive(Clone)] +pub enum SoftWrap { + None, + EditorWidth, + Column(u32), +} + pub struct Editor { handle: WeakViewHandle, buffer: ModelHandle, @@ -3379,9 +3387,9 @@ impl Editor { .text() } - pub fn set_wrap_width(&self, width: f32, cx: &mut MutableAppContext) -> bool { + pub fn set_wrap_width(&self, width: Option, cx: &mut MutableAppContext) -> bool { self.display_map - .update(cx, |map, cx| map.set_wrap_width(Some(width), cx)) + .update(cx, |map, cx| map.set_wrap_width(width, cx)) } pub fn set_highlighted_row(&mut self, row: Option) { @@ -3539,6 +3547,7 @@ impl EditorSettings { pub fn test(cx: &AppContext) -> Self { Self { tab_size: 4, + soft_wrap: SoftWrap::None, style: { let font_cache: &gpui::FontCache = cx.font_cache(); let font_family_name = Arc::from("Monaco"); @@ -4409,7 +4418,7 @@ mod tests { let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx)); view.update(cx, |view, cx| { - view.set_wrap_width(140., cx); + view.set_wrap_width(Some(140.), cx); assert_eq!( view.display_text(cx), "use one::{\n two::three::\n four::five\n};" diff --git a/crates/file_finder/src/lib.rs b/crates/file_finder/src/lib.rs index 7e000f957c..21280c2be5 100644 --- a/crates/file_finder/src/lib.rs +++ b/crates/file_finder/src/lib.rs @@ -275,6 +275,7 @@ impl FileFinder { EditorSettings { style: settings.theme.selector.input_editor.as_editor(), tab_size: settings.tab_size, + soft_wrap: editor::SoftWrap::None, } } }, diff --git a/crates/go_to_line/src/lib.rs b/crates/go_to_line/src/lib.rs index 6d623bfe6f..6670c4cf0d 100644 --- a/crates/go_to_line/src/lib.rs +++ b/crates/go_to_line/src/lib.rs @@ -54,6 +54,7 @@ impl GoToLine { EditorSettings { tab_size: settings.tab_size, style: settings.theme.selector.input_editor.as_editor(), + soft_wrap: editor::SoftWrap::None, } } }, diff --git a/crates/theme_selector/src/lib.rs b/crates/theme_selector/src/lib.rs index 18f29b4393..545b512a8b 100644 --- a/crates/theme_selector/src/lib.rs +++ b/crates/theme_selector/src/lib.rs @@ -69,6 +69,7 @@ impl ThemeSelector { EditorSettings { tab_size: settings.tab_size, style: settings.theme.selector.input_editor.as_editor(), + soft_wrap: editor::SoftWrap::None, } } }, diff --git a/crates/workspace/src/settings.rs b/crates/workspace/src/settings.rs index c6060119ef..a8f3c0b399 100644 --- a/crates/workspace/src/settings.rs +++ b/crates/workspace/src/settings.rs @@ -1,17 +1,33 @@ use anyhow::Result; use gpui::font_cache::{FamilyId, FontCache}; -use postage::watch; -use std::sync::Arc; -use theme::{Theme, ThemeRegistry, DEFAULT_THEME_NAME}; +use language::Language; +use std::{collections::HashMap, sync::Arc}; +use theme::Theme; #[derive(Clone)] pub struct Settings { pub buffer_font_family: FamilyId, pub buffer_font_size: f32, pub tab_size: usize, + pub soft_wrap: SoftWrap, + pub preferred_line_length: u32, + pub overrides: HashMap, pub theme: Arc, } +#[derive(Clone, Default)] +pub struct Override { + pub soft_wrap: Option, + pub preferred_line_length: Option, +} + +#[derive(Copy, Clone)] +pub enum SoftWrap { + None, + EditorWidth, + PreferredLineLength, +} + impl Settings { pub fn new( buffer_font_family: &str, @@ -22,6 +38,9 @@ impl Settings { buffer_font_family: font_cache.load_family(&[buffer_font_family])?, buffer_font_size: 16., tab_size: 4, + soft_wrap: SoftWrap::None, + preferred_line_length: 80, + overrides: Default::default(), theme, }) } @@ -30,22 +49,23 @@ impl Settings { self.tab_size = tab_size; self } -} -pub fn channel( - buffer_font_family: &str, - font_cache: &FontCache, - themes: &ThemeRegistry, -) -> Result<(watch::Sender, watch::Receiver)> { - let theme = match themes.get(DEFAULT_THEME_NAME) { - Ok(theme) => theme, - Err(err) => { - panic!("failed to deserialize default theme: {:?}", err) - } - }; - Ok(watch::channel_with(Settings::new( - buffer_font_family, - font_cache, - theme, - )?)) + pub fn with_overrides(mut self, language_name: impl Into, overrides: Override) -> Self { + self.overrides.insert(language_name.into(), overrides); + self + } + + pub fn soft_wrap(&self, language: Option<&Arc>) -> SoftWrap { + language + .and_then(|language| self.overrides.get(language.name())) + .and_then(|settings| settings.soft_wrap) + .unwrap_or(self.soft_wrap) + } + + pub fn preferred_line_length(&self, language: Option<&Arc>) -> u32 { + language + .and_then(|language| self.overrides.get(language.name())) + .and_then(|settings| settings.preferred_line_length) + .unwrap_or(self.preferred_line_length) + } } diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 13a3ccf643..16ca6ed67b 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -8,8 +8,8 @@ use log::LevelFilter; use parking_lot::Mutex; use simplelog::SimpleLogger; use std::{fs, path::PathBuf, sync::Arc}; -use theme::ThemeRegistry; -use workspace::{self, settings, OpenNew}; +use theme::{ThemeRegistry, DEFAULT_THEME_NAME}; +use workspace::{self, settings, OpenNew, Settings}; use zed::{self, assets::Assets, fs::RealFs, language, menus, AppState, OpenParams, OpenPaths}; fn main() { @@ -24,8 +24,17 @@ fn main() { app.platform().fonts().add_fonts(&embedded_fonts).unwrap(); let themes = ThemeRegistry::new(Assets, app.font_cache()); - let (settings_tx, settings) = - settings::channel("Inconsolata", &app.font_cache(), &themes).unwrap(); + let theme = themes.get(DEFAULT_THEME_NAME).unwrap(); + let settings = Settings::new("Inconsolata", &app.font_cache(), theme) + .unwrap() + .with_overrides( + "Markdown", + settings::Override { + soft_wrap: Some(settings::SoftWrap::PreferredLineLength), + ..Default::default() + }, + ); + let (settings_tx, settings) = postage::watch::channel_with(settings); let languages = Arc::new(language::build_language_registry()); languages.set_theme(&settings.borrow().theme.editor.syntax);