Allow overriding editor settings on a per-language basis

This commit is contained in:
Antonio Scandurra 2021-11-29 09:35:38 +01:00
parent e0998dbfda
commit 93de2bcfed
9 changed files with 88 additions and 30 deletions

View File

@ -61,6 +61,7 @@ impl ChatPanel {
EditorSettings { EditorSettings {
tab_size: settings.tab_size, tab_size: settings.tab_size,
style: settings.theme.chat_panel.input_editor.as_editor(), style: settings.theme.chat_panel.input_editor.as_editor(),
soft_wrap: editor::SoftWrap::EditorWidth,
} }
} }
}, },

View File

@ -1,6 +1,6 @@
use super::{ use super::{
DisplayPoint, DisplayRow, Editor, EditorMode, EditorSettings, EditorStyle, Input, Scroll, 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 clock::ReplicaId;
use gpui::{ use gpui::{
@ -703,7 +703,11 @@ impl Element for EditorElement {
let em_width = style.text.em_width(cx.font_cache); let em_width = style.text.em_width(cx.font_cache);
let em_advance = style.text.em_advance(cx.font_cache); let em_advance = style.text.em_advance(cx.font_cache);
let overscroll = vec2f(em_width, 0.); 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| { let snapshot = self.update_view(cx.app, |view, cx| {
if view.set_wrap_width(wrap_width, cx) { if view.set_wrap_width(wrap_width, cx) {
view.snapshot(cx) view.snapshot(cx)

View File

@ -12,7 +12,8 @@ use project::{ProjectPath, Worktree};
use std::fmt::Write; use std::fmt::Write;
use std::path::Path; use std::path::Path;
use workspace::{ use workspace::{
EntryOpener, ItemHandle, ItemView, ItemViewHandle, Settings, StatusItemView, WeakItemHandle, settings, EntryOpener, ItemHandle, ItemView, ItemViewHandle, Settings, StatusItemView,
WeakItemHandle,
}; };
pub struct BufferOpener; pub struct BufferOpener;
@ -47,6 +48,7 @@ impl ItemHandle for BufferItemHandle {
settings: watch::Receiver<Settings>, settings: watch::Receiver<Settings>,
cx: &mut MutableAppContext, cx: &mut MutableAppContext,
) -> Box<dyn ItemViewHandle> { ) -> Box<dyn ItemViewHandle> {
let buffer = self.0.downgrade();
Box::new(cx.add_view(window_id, |cx| { Box::new(cx.add_view(window_id, |cx| {
Editor::for_buffer( Editor::for_buffer(
self.0.clone(), self.0.clone(),
@ -71,8 +73,18 @@ impl ItemHandle for BufferItemHandle {
font_properties, font_properties,
underline: None, 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 { EditorSettings {
tab_size: settings.tab_size, tab_size: settings.tab_size,
soft_wrap,
style: theme, style: theme,
} }
}, },

View File

@ -333,9 +333,17 @@ pub enum EditorMode {
#[derive(Clone)] #[derive(Clone)]
pub struct EditorSettings { pub struct EditorSettings {
pub tab_size: usize, pub tab_size: usize,
pub soft_wrap: SoftWrap,
pub style: EditorStyle, pub style: EditorStyle,
} }
#[derive(Clone)]
pub enum SoftWrap {
None,
EditorWidth,
Column(u32),
}
pub struct Editor { pub struct Editor {
handle: WeakViewHandle<Self>, handle: WeakViewHandle<Self>,
buffer: ModelHandle<Buffer>, buffer: ModelHandle<Buffer>,
@ -3379,9 +3387,9 @@ impl Editor {
.text() .text()
} }
pub fn set_wrap_width(&self, width: f32, cx: &mut MutableAppContext) -> bool { pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
self.display_map 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<u32>) { pub fn set_highlighted_row(&mut self, row: Option<u32>) {
@ -3539,6 +3547,7 @@ impl EditorSettings {
pub fn test(cx: &AppContext) -> Self { pub fn test(cx: &AppContext) -> Self {
Self { Self {
tab_size: 4, tab_size: 4,
soft_wrap: SoftWrap::None,
style: { style: {
let font_cache: &gpui::FontCache = cx.font_cache(); let font_cache: &gpui::FontCache = cx.font_cache();
let font_family_name = Arc::from("Monaco"); 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)); let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
view.update(cx, |view, cx| { view.update(cx, |view, cx| {
view.set_wrap_width(140., cx); view.set_wrap_width(Some(140.), cx);
assert_eq!( assert_eq!(
view.display_text(cx), view.display_text(cx),
"use one::{\n two::three::\n four::five\n};" "use one::{\n two::three::\n four::five\n};"

View File

@ -275,6 +275,7 @@ impl FileFinder {
EditorSettings { EditorSettings {
style: settings.theme.selector.input_editor.as_editor(), style: settings.theme.selector.input_editor.as_editor(),
tab_size: settings.tab_size, tab_size: settings.tab_size,
soft_wrap: editor::SoftWrap::None,
} }
} }
}, },

View File

@ -54,6 +54,7 @@ impl GoToLine {
EditorSettings { EditorSettings {
tab_size: settings.tab_size, tab_size: settings.tab_size,
style: settings.theme.selector.input_editor.as_editor(), style: settings.theme.selector.input_editor.as_editor(),
soft_wrap: editor::SoftWrap::None,
} }
} }
}, },

View File

@ -69,6 +69,7 @@ impl ThemeSelector {
EditorSettings { EditorSettings {
tab_size: settings.tab_size, tab_size: settings.tab_size,
style: settings.theme.selector.input_editor.as_editor(), style: settings.theme.selector.input_editor.as_editor(),
soft_wrap: editor::SoftWrap::None,
} }
} }
}, },

View File

@ -1,17 +1,33 @@
use anyhow::Result; use anyhow::Result;
use gpui::font_cache::{FamilyId, FontCache}; use gpui::font_cache::{FamilyId, FontCache};
use postage::watch; use language::Language;
use std::sync::Arc; use std::{collections::HashMap, sync::Arc};
use theme::{Theme, ThemeRegistry, DEFAULT_THEME_NAME}; use theme::Theme;
#[derive(Clone)] #[derive(Clone)]
pub struct Settings { pub struct Settings {
pub buffer_font_family: FamilyId, pub buffer_font_family: FamilyId,
pub buffer_font_size: f32, pub buffer_font_size: f32,
pub tab_size: usize, pub tab_size: usize,
pub soft_wrap: SoftWrap,
pub preferred_line_length: u32,
pub overrides: HashMap<String, Override>,
pub theme: Arc<Theme>, pub theme: Arc<Theme>,
} }
#[derive(Clone, Default)]
pub struct Override {
pub soft_wrap: Option<SoftWrap>,
pub preferred_line_length: Option<u32>,
}
#[derive(Copy, Clone)]
pub enum SoftWrap {
None,
EditorWidth,
PreferredLineLength,
}
impl Settings { impl Settings {
pub fn new( pub fn new(
buffer_font_family: &str, buffer_font_family: &str,
@ -22,6 +38,9 @@ impl Settings {
buffer_font_family: font_cache.load_family(&[buffer_font_family])?, buffer_font_family: font_cache.load_family(&[buffer_font_family])?,
buffer_font_size: 16., buffer_font_size: 16.,
tab_size: 4, tab_size: 4,
soft_wrap: SoftWrap::None,
preferred_line_length: 80,
overrides: Default::default(),
theme, theme,
}) })
} }
@ -30,22 +49,23 @@ impl Settings {
self.tab_size = tab_size; self.tab_size = tab_size;
self self
} }
pub fn with_overrides(mut self, language_name: impl Into<String>, overrides: Override) -> Self {
self.overrides.insert(language_name.into(), overrides);
self
} }
pub fn channel( pub fn soft_wrap(&self, language: Option<&Arc<Language>>) -> SoftWrap {
buffer_font_family: &str, language
font_cache: &FontCache, .and_then(|language| self.overrides.get(language.name()))
themes: &ThemeRegistry, .and_then(|settings| settings.soft_wrap)
) -> Result<(watch::Sender<Settings>, watch::Receiver<Settings>)> { .unwrap_or(self.soft_wrap)
let theme = match themes.get(DEFAULT_THEME_NAME) { }
Ok(theme) => theme,
Err(err) => { pub fn preferred_line_length(&self, language: Option<&Arc<Language>>) -> u32 {
panic!("failed to deserialize default theme: {:?}", err) language
.and_then(|language| self.overrides.get(language.name()))
.and_then(|settings| settings.preferred_line_length)
.unwrap_or(self.preferred_line_length)
} }
};
Ok(watch::channel_with(Settings::new(
buffer_font_family,
font_cache,
theme,
)?))
} }

View File

@ -8,8 +8,8 @@ use log::LevelFilter;
use parking_lot::Mutex; use parking_lot::Mutex;
use simplelog::SimpleLogger; use simplelog::SimpleLogger;
use std::{fs, path::PathBuf, sync::Arc}; use std::{fs, path::PathBuf, sync::Arc};
use theme::ThemeRegistry; use theme::{ThemeRegistry, DEFAULT_THEME_NAME};
use workspace::{self, settings, OpenNew}; use workspace::{self, settings, OpenNew, Settings};
use zed::{self, assets::Assets, fs::RealFs, language, menus, AppState, OpenParams, OpenPaths}; use zed::{self, assets::Assets, fs::RealFs, language, menus, AppState, OpenParams, OpenPaths};
fn main() { fn main() {
@ -24,8 +24,17 @@ fn main() {
app.platform().fonts().add_fonts(&embedded_fonts).unwrap(); app.platform().fonts().add_fonts(&embedded_fonts).unwrap();
let themes = ThemeRegistry::new(Assets, app.font_cache()); let themes = ThemeRegistry::new(Assets, app.font_cache());
let (settings_tx, settings) = let theme = themes.get(DEFAULT_THEME_NAME).unwrap();
settings::channel("Inconsolata", &app.font_cache(), &themes).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()); let languages = Arc::new(language::build_language_registry());
languages.set_theme(&settings.borrow().theme.editor.syntax); languages.set_theme(&settings.borrow().theme.editor.syntax);