diff --git a/crates/chat_panel/src/lib.rs b/crates/chat_panel/src/lib.rs index 614022d4c9e772063551db0d021631dd377c60f1..d9d3ce64fa9590a0c643fdc3bdea014064a291c8 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/display_map.rs b/crates/editor/src/display_map.rs index 506faa27165eba1b2f70d41c296283d1c543c3e9..da92260ec812dc27e334216cb513ddbc2035a6fe 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -778,7 +778,7 @@ mod tests { path_suffixes: vec![".test".to_string()], ..Default::default() }, - tree_sitter_rust::language(), + Some(tree_sitter_rust::language()), ) .with_highlights_query( r#" @@ -865,7 +865,7 @@ mod tests { path_suffixes: vec![".test".to_string()], ..Default::default() }, - tree_sitter_rust::language(), + Some(tree_sitter_rust::language()), ) .with_highlights_query( r#" diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 2f4923985f98061803e2af901e3fdd98c760bb96..c8e307c0acee665d5fa002e9136d80dc8fc72893 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 7812af7820e3d708a44ad3431d177e562166dc94..e5dc4fb224d7af879d02b4c216fd49684aefa52d 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 453747e83f33ac2fb3d0f7617c46c82f7f1fa2ad..4566badd9859b6ccb1bde33a34c975e7656a4829 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, @@ -510,7 +518,9 @@ impl Editor { _: &workspace::OpenNew, cx: &mut ViewContext, ) { - let buffer = cx.add_model(|cx| Buffer::new(0, "", cx)); + let buffer = cx.add_model(|cx| { + Buffer::new(0, "", cx).with_language(Some(language::PLAIN_TEXT.clone()), None, cx) + }); workspace.add_item(BufferItemHandle(buffer), cx); } @@ -3379,9 +3389,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 +3549,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 +4420,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};" @@ -5286,7 +5297,7 @@ mod tests { let settings = cx.read(EditorSettings::test); let language = Some(Arc::new(Language::new( LanguageConfig::default(), - tree_sitter_rust::language(), + Some(tree_sitter_rust::language()), ))); let text = r#" @@ -5443,7 +5454,7 @@ mod tests { ], ..Default::default() }, - tree_sitter_rust::language(), + Some(tree_sitter_rust::language()), ))); let text = r#" @@ -5542,7 +5553,7 @@ mod tests { line_comment: Some("// ".to_string()), ..Default::default() }, - tree_sitter_rust::language(), + Some(tree_sitter_rust::language()), ))); let text = " @@ -5640,7 +5651,7 @@ mod tests { ], ..Default::default() }, - tree_sitter_rust::language(), + Some(tree_sitter_rust::language()), ))); let text = concat!( diff --git a/crates/file_finder/src/lib.rs b/crates/file_finder/src/lib.rs index 7e000f957c595fbba41b1d5bf22882894e6315d3..21280c2be502f33edfe599b02b2c12897bd5a868 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 6d623bfe6fb0cc5e543416b6e5dfb280d63ec693..6670c4cf0d57a93d07ed27a06902ef89793325d4 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/language/src/language.rs b/crates/language/src/language.rs index e80f34116cb87cafd5354d19dfe9283aa0a8aa48..f8201b179b44682a2e8bcc7412c4a8a6897985a3 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -1,14 +1,28 @@ use crate::HighlightMap; -use anyhow::Result; +use anyhow::{anyhow, Result}; use gpui::{executor::Background, AppContext}; +use lazy_static::lazy_static; use lsp::LanguageServer; use parking_lot::Mutex; use serde::Deserialize; use std::{collections::HashSet, path::Path, str, sync::Arc}; use theme::SyntaxTheme; -use tree_sitter::{Language as Grammar, Query}; +use tree_sitter::{self, Query}; pub use tree_sitter::{Parser, Tree}; +lazy_static! { + pub static ref PLAIN_TEXT: Arc = Arc::new(Language::new( + LanguageConfig { + name: "Plain Text".to_string(), + path_suffixes: Default::default(), + brackets: Default::default(), + line_comment: None, + language_server: None, + }, + None, + )); +} + #[derive(Default, Deserialize)] pub struct LanguageConfig { pub name: String, @@ -37,7 +51,11 @@ pub struct BracketPair { pub struct Language { pub(crate) config: LanguageConfig, - pub(crate) grammar: Grammar, + pub(crate) grammar: Option>, +} + +pub struct Grammar { + pub(crate) ts_language: tree_sitter::Language, pub(crate) highlights_query: Query, pub(crate) brackets_query: Query, pub(crate) indents_query: Query, @@ -86,29 +104,48 @@ impl LanguageRegistry { } impl Language { - pub fn new(config: LanguageConfig, grammar: Grammar) -> Self { + pub fn new(config: LanguageConfig, ts_language: Option) -> Self { Self { config, - brackets_query: Query::new(grammar, "").unwrap(), - highlights_query: Query::new(grammar, "").unwrap(), - indents_query: Query::new(grammar, "").unwrap(), - grammar, - highlight_map: Default::default(), + grammar: ts_language.map(|ts_language| { + Arc::new(Grammar { + brackets_query: Query::new(ts_language, "").unwrap(), + highlights_query: Query::new(ts_language, "").unwrap(), + indents_query: Query::new(ts_language, "").unwrap(), + ts_language, + highlight_map: Default::default(), + }) + }), } } pub fn with_highlights_query(mut self, source: &str) -> Result { - self.highlights_query = Query::new(self.grammar, source)?; + let grammar = self + .grammar + .as_mut() + .and_then(Arc::get_mut) + .ok_or_else(|| anyhow!("grammar does not exist or is already being used"))?; + grammar.highlights_query = Query::new(grammar.ts_language, source)?; Ok(self) } pub fn with_brackets_query(mut self, source: &str) -> Result { - self.brackets_query = Query::new(self.grammar, source)?; + let grammar = self + .grammar + .as_mut() + .and_then(Arc::get_mut) + .ok_or_else(|| anyhow!("grammar does not exist or is already being used"))?; + grammar.brackets_query = Query::new(grammar.ts_language, source)?; Ok(self) } pub fn with_indents_query(mut self, source: &str) -> Result { - self.indents_query = Query::new(self.grammar, source)?; + let grammar = self + .grammar + .as_mut() + .and_then(Arc::get_mut) + .ok_or_else(|| anyhow!("grammar does not exist or is already being used"))?; + grammar.indents_query = Query::new(grammar.ts_language, source)?; Ok(self) } @@ -156,13 +193,17 @@ impl Language { &self.config.brackets } - pub fn highlight_map(&self) -> HighlightMap { - self.highlight_map.lock().clone() + pub fn set_theme(&self, theme: &SyntaxTheme) { + if let Some(grammar) = self.grammar.as_ref() { + *grammar.highlight_map.lock() = + HighlightMap::new(grammar.highlights_query.capture_names(), theme); + } } +} - pub fn set_theme(&self, theme: &SyntaxTheme) { - *self.highlight_map.lock() = - HighlightMap::new(self.highlights_query.capture_names(), theme); +impl Grammar { + pub fn highlight_map(&self) -> HighlightMap { + self.highlight_map.lock().clone() } } @@ -189,7 +230,6 @@ mod tests { #[test] fn test_select_language() { - let grammar = tree_sitter_rust::language(); let registry = LanguageRegistry { languages: vec![ Arc::new(Language::new( @@ -198,7 +238,7 @@ mod tests { path_suffixes: vec!["rs".to_string()], ..Default::default() }, - grammar, + Some(tree_sitter_rust::language()), )), Arc::new(Language::new( LanguageConfig { @@ -206,7 +246,7 @@ mod tests { path_suffixes: vec!["Makefile".to_string(), "mk".to_string()], ..Default::default() }, - grammar, + Some(tree_sitter_rust::language()), )), ], }; diff --git a/crates/language/src/lib.rs b/crates/language/src/lib.rs index 4c3fa9a51511930d2e467a8ee1a0b9173bbd2981..07602e227f7df1e82cd38e361e0f558bf8c4886e 100644 --- a/crates/language/src/lib.rs +++ b/crates/language/src/lib.rs @@ -6,7 +6,10 @@ mod tests; pub use self::{ highlight_map::{HighlightId, HighlightMap}, - language::{BracketPair, Language, LanguageConfig, LanguageRegistry, LanguageServerConfig}, + language::{ + BracketPair, Grammar, Language, LanguageConfig, LanguageRegistry, LanguageServerConfig, + PLAIN_TEXT, + }, }; use anyhow::{anyhow, Result}; pub use buffer::{Buffer as TextBuffer, Operation as _, *}; @@ -594,13 +597,13 @@ impl Buffer { return false; } - if let Some(language) = self.language.clone() { + if let Some(grammar) = self.grammar().cloned() { let old_tree = self.syntax_tree(); let text = self.as_rope().clone(); let parsed_version = self.version(); let parse_task = cx.background().spawn({ - let language = language.clone(); - async move { Self::parse_text(&text, old_tree, &language) } + let grammar = grammar.clone(); + async move { Self::parse_text(&text, old_tree, &grammar) } }); match cx @@ -616,11 +619,10 @@ impl Buffer { cx.spawn(move |this, mut cx| async move { let new_tree = parse_task.await; this.update(&mut cx, move |this, cx| { - let language_changed = - this.language.as_ref().map_or(true, |curr_language| { - !Arc::ptr_eq(curr_language, &language) - }); - let parse_again = this.version.gt(&parsed_version) || language_changed; + let grammar_changed = this + .grammar() + .map_or(true, |curr_grammar| !Arc::ptr_eq(&grammar, curr_grammar)); + let parse_again = this.version.gt(&parsed_version) || grammar_changed; this.parsing_in_background = false; this.did_finish_parsing(new_tree, parsed_version, cx); @@ -636,11 +638,11 @@ impl Buffer { false } - fn parse_text(text: &Rope, old_tree: Option, language: &Language) -> Tree { + fn parse_text(text: &Rope, old_tree: Option, grammar: &Grammar) -> Tree { PARSER.with(|parser| { let mut parser = parser.borrow_mut(); parser - .set_language(language.grammar) + .set_language(grammar.ts_language) .expect("incompatible grammar"); let mut chunks = text.chunks_in_range(0..text.len()); let tree = parser @@ -1069,15 +1071,15 @@ impl Buffer { &self, range: Range, ) -> Option<(Range, Range)> { - let (lang, tree) = self.language.as_ref().zip(self.syntax_tree())?; - let open_capture_ix = lang.brackets_query.capture_index_for_name("open")?; - let close_capture_ix = lang.brackets_query.capture_index_for_name("close")?; + let (grammar, tree) = self.grammar().zip(self.syntax_tree())?; + let open_capture_ix = grammar.brackets_query.capture_index_for_name("open")?; + let close_capture_ix = grammar.brackets_query.capture_index_for_name("close")?; // Find bracket pairs that *inclusively* contain the given range. let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1; let mut cursor = QueryCursorHandle::new(); let matches = cursor.set_byte_range(range).matches( - &lang.brackets_query, + &grammar.brackets_query, tree.root_node(), TextProvider(self.as_rope()), ); @@ -1342,6 +1344,10 @@ impl Buffer { cx.notify(); } + fn grammar(&self) -> Option<&Arc> { + self.language.as_ref().and_then(|l| l.grammar.as_ref()) + } + pub fn add_selection_set( &mut self, selections: &[Selection], @@ -1550,19 +1556,19 @@ impl Snapshot { row_range: Range, ) -> Option + 'a> { let mut query_cursor = QueryCursorHandle::new(); - if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) { + if let Some((grammar, tree)) = self.grammar().zip(self.tree.as_ref()) { let prev_non_blank_row = self.prev_non_blank_row(row_range.start); // Get the "indentation ranges" that intersect this row range. - let indent_capture_ix = language.indents_query.capture_index_for_name("indent"); - let end_capture_ix = language.indents_query.capture_index_for_name("end"); + let indent_capture_ix = grammar.indents_query.capture_index_for_name("indent"); + let end_capture_ix = grammar.indents_query.capture_index_for_name("end"); query_cursor.set_point_range( Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0).to_ts_point() ..Point::new(row_range.end, 0).to_ts_point(), ); let mut indentation_ranges = Vec::<(Range, &'static str)>::new(); for mat in query_cursor.matches( - &language.indents_query, + &grammar.indents_query, tree.root_node(), TextProvider(self.as_rope()), ) { @@ -1682,7 +1688,7 @@ impl Snapshot { diagnostic_endpoints .sort_unstable_by_key(|endpoint| (endpoint.offset, !endpoint.is_start)); - if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) { + if let Some((grammar, tree)) = self.grammar().zip(self.tree.as_ref()) { let mut query_cursor = QueryCursorHandle::new(); // TODO - add a Tree-sitter API to remove the need for this. @@ -1690,7 +1696,7 @@ impl Snapshot { std::mem::transmute::<_, &'static mut QueryCursor>(query_cursor.deref_mut()) }; let captures = cursor.set_byte_range(range.clone()).captures( - &language.highlights_query, + &grammar.highlights_query, tree.root_node(), TextProvider(self.text.as_rope()), ); @@ -1698,7 +1704,7 @@ impl Snapshot { captures, next_capture: None, stack: Default::default(), - highlight_map: language.highlight_map(), + highlight_map: grammar.highlight_map(), _query_cursor: query_cursor, theme, }) @@ -1719,6 +1725,12 @@ impl Snapshot { highlights, } } + + fn grammar(&self) -> Option<&Arc> { + self.language + .as_ref() + .and_then(|language| language.grammar.as_ref()) + } } impl Clone for Snapshot { diff --git a/crates/language/src/tests.rs b/crates/language/src/tests.rs index 671755195d1b2a537a29234b9dd52d97921562a9..4a05f108cfdd882858bea3b03aa888edf750cf1c 100644 --- a/crates/language/src/tests.rs +++ b/crates/language/src/tests.rs @@ -970,7 +970,7 @@ fn rust_lang() -> Language { language_server: None, ..Default::default() }, - tree_sitter_rust::language(), + Some(tree_sitter_rust::language()), ) .with_indents_query( r#" diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 7187310be7419fd64db0ffec43b61b54b18f535c..36df02112c701b520916c08860ac3d01e1b065e7 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -3671,7 +3671,7 @@ mod tests { language_server: Some(language_server_config), ..Default::default() }, - tree_sitter_rust::language(), + Some(tree_sitter_rust::language()), ))); let dir = temp_tree(json!({ diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 0e317028c70c54d84860be0c3273c2e813d8ce8c..ab406966c1695b0b747379df500d261311c69c22 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -1616,7 +1616,7 @@ mod tests { language_server: Some(language_server_config), ..Default::default() }, - tree_sitter_rust::language(), + Some(tree_sitter_rust::language()), ))); let lang_registry = Arc::new(lang_registry); diff --git a/crates/theme_selector/src/lib.rs b/crates/theme_selector/src/lib.rs index 18f29b4393666b7994a170fdc7cbc520e7bd2faa..545b512a8bfd4ec5a6ba9d3c83e0113e4e9441bd 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 c6060119ef1af95254534807a239806970ecc14f..c74576ef7ec541614fd8e46f6a3a4177589dc9ac 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, + soft_wrap: SoftWrap, + preferred_line_length: u32, + 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/languages/markdown/config.toml b/crates/zed/languages/markdown/config.toml new file mode 100644 index 0000000000000000000000000000000000000000..340189e412d8da51870bc1049e73b25e999188f8 --- /dev/null +++ b/crates/zed/languages/markdown/config.toml @@ -0,0 +1,8 @@ +name = "Markdown" +path_suffixes = ["md"] +brackets = [ + { start = "{", end = "}", close = true, newline = true }, + { start = "[", end = "]", close = true, newline = true }, + { start = "(", end = ")", close = true, newline = true }, + { start = "<", end = ">", close = true, newline = true }, +] diff --git a/crates/zed/src/language.rs b/crates/zed/src/language.rs index 3b77a0cf3ad82dff5d14de8b167174669b072068..c045804e92d92abf35c6e183e6bdb3b858536358 100644 --- a/crates/zed/src/language.rs +++ b/crates/zed/src/language.rs @@ -10,14 +10,14 @@ struct LanguageDir; pub fn build_language_registry() -> LanguageRegistry { let mut languages = LanguageRegistry::default(); languages.add(Arc::new(rust())); + languages.add(Arc::new(markdown())); languages } fn rust() -> Language { let grammar = tree_sitter_rust::language(); - let rust_config = - toml::from_slice(&LanguageDir::get("rust/config.toml").unwrap().data).unwrap(); - Language::new(rust_config, grammar) + let config = toml::from_slice(&LanguageDir::get("rust/config.toml").unwrap().data).unwrap(); + Language::new(config, Some(grammar)) .with_highlights_query(load_query("rust/highlights.scm").as_ref()) .unwrap() .with_brackets_query(load_query("rust/brackets.scm").as_ref()) @@ -26,6 +26,11 @@ fn rust() -> Language { .unwrap() } +fn markdown() -> Language { + let config = toml::from_slice(&LanguageDir::get("markdown/config.toml").unwrap().data).unwrap(); + Language::new(config, None) +} + fn load_query(path: &str) -> Cow<'static, str> { match LanguageDir::get(path).unwrap().data { Cow::Borrowed(s) => Cow::Borrowed(str::from_utf8(s).unwrap()), diff --git a/crates/zed/src/lib.rs b/crates/zed/src/lib.rs index 49e5c30120f2dcb2d722955d443e735410ff692f..16f67fa17180e77fd7ad4e7a6794c423454a0667 100644 --- a/crates/zed/src/lib.rs +++ b/crates/zed/src/lib.rs @@ -589,7 +589,10 @@ mod tests { editor.update(&mut cx, |editor, cx| { assert!(!editor.is_dirty(cx.as_ref())); assert_eq!(editor.title(cx.as_ref()), "untitled"); - assert!(editor.language(cx).is_none()); + assert!(Arc::ptr_eq( + editor.language(cx).unwrap(), + &language::PLAIN_TEXT + )); editor.handle_input(&editor::Input("hi".into()), cx); assert!(editor.is_dirty(cx.as_ref())); }); @@ -683,7 +686,10 @@ mod tests { }); editor.update(&mut cx, |editor, cx| { - assert!(editor.language(cx).is_none()); + assert!(Arc::ptr_eq( + editor.language(cx).unwrap(), + &language::PLAIN_TEXT + )); editor.handle_input(&editor::Input("hi".into()), cx); assert!(editor.is_dirty(cx.as_ref())); }); diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 13a3ccf643e2b43843f3d6952413afbbc63523c8..c6374c66e71f25dd5fc8015504086eb0dff916d0 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,24 @@ 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( + language::PLAIN_TEXT.name(), + settings::Override { + soft_wrap: Some(settings::SoftWrap::PreferredLineLength), + ..Default::default() + }, + ) + .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); diff --git a/crates/zed/src/test.rs b/crates/zed/src/test.rs index 5cb9b5f0e8944e0d1c9cdf0067b625729254eb25..91f1c165ee825d8a31a0a2681bf58bc6cb10d24c 100644 --- a/crates/zed/src/test.rs +++ b/crates/zed/src/test.rs @@ -30,7 +30,7 @@ pub fn test_app_state(cx: &mut MutableAppContext) -> Arc { path_suffixes: vec!["rs".to_string()], ..Default::default() }, - tree_sitter_rust::language(), + Some(tree_sitter_rust::language()), ))); Arc::new(AppState { settings_tx: Arc::new(Mutex::new(settings_tx)),