From 8cc988d37474fe34054580bb33b2eda3b805e03b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 4 Jan 2023 20:03:03 -0700 Subject: [PATCH] Run cargo fmt --- examples/editor-libcosmic/src/main.rs | 103 +++++----- examples/editor-libcosmic/src/text.rs | 48 ++--- examples/editor-libcosmic/src/text_box.rs | 156 ++++++++-------- examples/editor-orbclient/src/main.rs | 37 ++-- examples/editor-test/src/main.rs | 10 +- examples/rich-text/src/main.rs | 84 +++++---- examples/terminal/src/main.rs | 13 +- rustfmt.toml | 1 - src/attrs.rs | 49 +++-- src/buffer.rs | 153 ++++++++------- src/buffer_line.rs | 28 +-- src/edit/editor.rs | 144 ++++++++------ src/edit/mod.rs | 5 +- src/edit/syntect.rs | 99 ++++------ src/edit/vi.rs | 100 +++++----- src/font/fallback/macos.rs | 4 +- src/font/fallback/mod.rs | 19 +- src/font/fallback/windows.rs | 2 +- src/font/matches.rs | 5 +- src/font/system/no_std.rs | 11 +- src/font/system/redox.rs | 13 +- src/font/system/std.rs | 100 ++++++---- src/lib.rs | 4 - src/shape.rs | 218 ++++++++++++---------- src/swash.rs | 57 +++--- 25 files changed, 732 insertions(+), 731 deletions(-) delete mode 100644 rustfmt.toml diff --git a/examples/editor-libcosmic/src/main.rs b/examples/editor-libcosmic/src/main.rs index 0b47a2e..250bba7 100644 --- a/examples/editor-libcosmic/src/main.rs +++ b/examples/editor-libcosmic/src/main.rs @@ -1,45 +1,20 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use cosmic::{ - Element, iced::{ self, - Color, - Alignment, - Application, - Command, - Length, - widget::{ - column, - horizontal_space, - pick_list, - row, - }, + widget::{column, horizontal_space, pick_list, row}, + Alignment, Application, Color, Command, Length, }, settings, theme::{self, Theme}, - widget::{ - button, - toggler, - }, + widget::{button, toggler}, + Element, }; use cosmic_text::{ - Attrs, - AttrsList, - Buffer, - Edit, - FontSystem, - Metrics, - SyntaxEditor, - SyntaxSystem, - Wrap, -}; -use std::{ - env, - fs, - path::PathBuf, - sync::Mutex, + Attrs, AttrsList, Buffer, Edit, FontSystem, Metrics, SyntaxEditor, SyntaxSystem, Wrap, }; +use std::{env, fs, path::PathBuf, sync::Mutex}; use self::text::text; mod text; @@ -61,11 +36,7 @@ static FONT_SIZES: &'static [Metrics] = &[ Metrics::new(32, 44), // Title 1 ]; -static WRAP_MODE: &'static [Wrap] = & [ - Wrap::None, - Wrap::Glyph, - Wrap::Word, -]; +static WRAP_MODE: &'static [Wrap] = &[Wrap::None, Wrap::Glyph, Wrap::Word]; fn main() -> cosmic::iced::Result { env_logger::init(); @@ -105,7 +76,7 @@ impl Window { Ok(()) => { log::info!("opened '{}'", path.display()); self.path_opt = Some(path); - }, + } Err(err) => { log::error!("failed to open '{}': {}", path.display(), err); self.path_opt = None; @@ -128,8 +99,9 @@ impl Application for Window { let mut editor = SyntaxEditor::new( Buffer::new(&FONT_SYSTEM, FONT_SIZES[1 /* Body */]), &SYNTAX_SYSTEM, - "base16-eighties.dark" - ).unwrap(); + "base16-eighties.dark", + ) + .unwrap(); #[cfg(feature = "vi")] let mut editor = cosmic_text::ViEditor::new(editor); @@ -154,7 +126,11 @@ impl Application for Window { fn title(&self) -> String { if let Some(path) = &self.path_opt { - format!("COSMIC Text - {} - {}", FONT_SYSTEM.locale(), path.display()) + format!( + "COSMIC Text - {} - {}", + FONT_SYSTEM.locale(), + path.display() + ) } else { format!("COSMIC Text - {}", FONT_SYSTEM.locale()) } @@ -166,7 +142,7 @@ impl Application for Window { if let Some(path) = rfd::FileDialog::new().pick_file() { self.open(path); } - }, + } Message::Save => { if let Some(path) = &self.path_opt { let editor = self.editor.lock().unwrap(); @@ -178,13 +154,13 @@ impl Application for Window { match fs::write(path, text) { Ok(()) => { log::info!("saved '{}'", path.display()); - }, + } Err(err) => { log::error!("failed to save '{}': {}", path.display(), err); } } } - }, + } Message::Bold(bold) => { self.attrs = self.attrs.weight(if bold { cosmic_text::Weight::BOLD @@ -194,7 +170,7 @@ impl Application for Window { let mut editor = self.editor.lock().unwrap(); update_attrs(&mut *editor, self.attrs); - }, + } Message::Italic(italic) => { self.attrs = self.attrs.style(if italic { cosmic_text::Style::Italic @@ -204,9 +180,10 @@ impl Application for Window { let mut editor = self.editor.lock().unwrap(); update_attrs(&mut *editor, self.attrs); - }, + } Message::Monospaced(monospaced) => { - self.attrs = self.attrs + self.attrs = self + .attrs .family(if monospaced { cosmic_text::Family::Monospace } else { @@ -216,15 +193,15 @@ impl Application for Window { let mut editor = self.editor.lock().unwrap(); update_attrs(&mut *editor, self.attrs); - }, + } Message::MetricsChanged(metrics) => { let mut editor = self.editor.lock().unwrap(); editor.buffer_mut().set_metrics(metrics); - }, + } Message::WrapChanged(wrap) => { let mut editor = self.editor.lock().unwrap(); editor.buffer_mut().set_wrap(wrap); - }, + } Message::ThemeChanged(theme) => { self.theme = match theme { "Dark" => Theme::Dark, @@ -234,11 +211,16 @@ impl Application for Window { let Color { r, g, b, a } = self.theme.palette().text; let as_u8 = |component: f32| (component * 255.0) as u8; - self.attrs = self.attrs.color(cosmic_text::Color::rgba(as_u8(r), as_u8(g), as_u8(b), as_u8(a))); + self.attrs = self.attrs.color(cosmic_text::Color::rgba( + as_u8(r), + as_u8(g), + as_u8(b), + as_u8(a), + )); let mut editor = self.editor.lock().unwrap(); update_attrs(&mut *editor, self.attrs); - }, + } } Command::none() @@ -252,7 +234,7 @@ impl Application for Window { Theme::Dark => THEMES[0], Theme::Light => THEMES[1], }), - Message::ThemeChanged + Message::ThemeChanged, ); let font_size_picker = { @@ -260,7 +242,7 @@ impl Application for Window { pick_list( FONT_SIZES, Some(editor.buffer().metrics()), - Message::MetricsChanged + Message::MetricsChanged, ) }; @@ -283,9 +265,17 @@ impl Application for Window { .on_press(Message::Save), horizontal_space(Length::Fill), text("Bold:"), - toggler(None, self.attrs.weight == cosmic_text::Weight::BOLD, Message::Bold), + toggler( + None, + self.attrs.weight == cosmic_text::Weight::BOLD, + Message::Bold + ), text("Italic:"), - toggler(None, self.attrs.style == cosmic_text::Style::Italic, Message::Italic), + toggler( + None, + self.attrs.style == cosmic_text::Style::Italic, + Message::Italic + ), text("Monospaced:"), toggler(None, self.attrs.monospaced, Message::Monospaced), text("Theme:"), @@ -296,8 +286,7 @@ impl Application for Window { wrap_picker, ] .align_items(Alignment::Center) - .spacing(8) - , + .spacing(8), text_box(&self.editor) ] .spacing(8) diff --git a/examples/editor-libcosmic/src/text.rs b/examples/editor-libcosmic/src/text.rs index d3bdef7..66a9c81 100644 --- a/examples/editor-libcosmic/src/text.rs +++ b/examples/editor-libcosmic/src/text.rs @@ -2,26 +2,16 @@ use cosmic::{ iced_native::{ - {Color, Element, Length, Point, Rectangle, Size}, image, layout::{self, Layout}, renderer, widget::{self, tree, Widget}, + {Color, Element, Length, Point, Rectangle, Size}, }, theme::Theme, }; -use cosmic_text::{ - Attrs, - AttrsList, - SwashCache, - BufferLine, - Metrics, -}; -use std::{ - cmp, - sync::Mutex, - time::Instant, -}; +use cosmic_text::{Attrs, AttrsList, BufferLine, Metrics, SwashCache}; +use std::{cmp, sync::Mutex, time::Instant}; pub struct Appearance { background_color: Option, @@ -57,10 +47,7 @@ impl Text { let instant = Instant::now(); //TODO: make it possible to set attrs - let mut line = BufferLine::new( - string, - AttrsList::new(Attrs::new()) - ); + let mut line = BufferLine::new(string, AttrsList::new(Attrs::new())); //TODO: do we have to immediately shape? line.shape(&crate::FONT_SYSTEM); @@ -101,11 +88,7 @@ where Length::Shrink } - fn layout( - &self, - _renderer: &Renderer, - limits: &layout::Limits, - ) -> layout::Node { + fn layout(&self, _renderer: &Renderer, limits: &layout::Limits) -> layout::Node { let instant = Instant::now(); let limits = limits.width(Length::Shrink).height(Length::Shrink); @@ -116,7 +99,7 @@ where let layout_lines = shape.layout( self.metrics.font_size, limits.max().width as i32, - self.line.wrap() + self.line.wrap(), ); let mut width = 0; @@ -160,7 +143,7 @@ where border_width: 0.0, border_color: Color::TRANSPARENT, }, - background_color + background_color, ); } @@ -177,11 +160,7 @@ where let shape = self.line.shape_opt().as_ref().unwrap(); //TODO: can we cache this? - let layout_lines = shape.layout( - self.metrics.font_size, - layout_w, - self.line.wrap() - ); + let layout_lines = shape.layout(self.metrics.font_size, layout_w, self.line.wrap()); let mut cache = state.cache.lock().unwrap(); @@ -219,7 +198,7 @@ pub fn draw_pixel( height: i32, x: i32, y: i32, - color: cosmic_text::Color + color: cosmic_text::Color, ) { let alpha = (color.0 >> 24) & 0xFF; if alpha == 0 { @@ -239,11 +218,10 @@ pub fn draw_pixel( let offset = (y as usize * width as usize + x as usize) * 4; - let mut current = - buffer[offset + 2] as u32 | - (buffer[offset + 1] as u32) << 8 | - (buffer[offset + 0] as u32) << 16 | - (buffer[offset + 3] as u32) << 24; + let mut current = buffer[offset + 2] as u32 + | (buffer[offset + 1] as u32) << 8 + | (buffer[offset + 0] as u32) << 16 + | (buffer[offset + 3] as u32) << 24; if alpha >= 255 || current == 0 { // Alpha is 100% or current is null, replace with no blending diff --git a/examples/editor-libcosmic/src/text_box.rs b/examples/editor-libcosmic/src/text_box.rs index 813cf7f..1faeff8 100644 --- a/examples/editor-libcosmic/src/text_box.rs +++ b/examples/editor-libcosmic/src/text_box.rs @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 +use super::text; use cosmic::{ iced_native::{ - {Color, Element, Length, Point, Rectangle, Shell, Size}, clipboard::Clipboard, event::{Event, Status}, image, @@ -11,21 +11,12 @@ use cosmic::{ mouse::{self, Button, Event as MouseEvent, ScrollDelta}, renderer, widget::{self, tree, Widget}, - Padding + Padding, {Color, Element, Length, Point, Rectangle, Shell, Size}, }, theme::Theme, }; -use cosmic_text::{ - Action, - Edit, - SwashCache, -}; -use std::{ - cmp, - sync::Mutex, - time::Instant, -}; -use super::text; +use cosmic_text::{Action, Edit, SwashCache}; +use std::{cmp, sync::Mutex, time::Instant}; pub struct Appearance { background_color: Option, @@ -68,7 +59,6 @@ impl<'a, Editor> TextBox<'a, Editor> { self.padding = padding.into(); self } - } pub fn text_box<'a, Editor>(editor: &'a Mutex) -> TextBox<'a, Editor> { @@ -97,11 +87,7 @@ where Length::Fill } - fn layout( - &self, - _renderer: &Renderer, - limits: &layout::Limits, - ) -> layout::Node { + fn layout(&self, _renderer: &Renderer, limits: &layout::Limits) -> layout::Node { let limits = limits.width(Length::Fill).height(Length::Fill); //TODO: allow lazy shape @@ -160,7 +146,7 @@ where border_width: 0.0, border_color: Color::TRANSPARENT, }, - background_color + background_color, ); } @@ -173,8 +159,10 @@ where let mut editor = self.editor.lock().unwrap(); - let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32) - self.padding.horizontal() as i32; - let view_h = cmp::min(viewport.height as i32, layout.bounds().height as i32) - self.padding.vertical() as i32; + let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32) + - self.padding.horizontal() as i32; + let view_h = cmp::min(viewport.height as i32, layout.bounds().height as i32) + - self.padding.vertical() as i32; editor.buffer_mut().set_size(view_w, view_h); editor.shape_as_needed(); @@ -183,41 +171,51 @@ where let mut pixels = vec![0; view_w as usize * view_h as usize * 4]; - editor.draw(&mut state.cache.lock().unwrap(), text_color, |x, y, w, h, color| { - if w <= 0 || h <= 0 { - // Do not draw invalid sized rectangles - return; - } + editor.draw( + &mut state.cache.lock().unwrap(), + text_color, + |x, y, w, h, color| { + if w <= 0 || h <= 0 { + // Do not draw invalid sized rectangles + return; + } - if w > 1 || h > 1 { - // Draw rectangles with optimized quad renderer - renderer.fill_quad( - renderer::Quad { - bounds: Rectangle::new( - layout.position() + [x as f32, y as f32].into() + [self.padding.left as f32, self.padding.top as f32].into(), - Size::new(w as f32 , h as f32) + if w > 1 || h > 1 { + // Draw rectangles with optimized quad renderer + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle::new( + layout.position() + + [x as f32, y as f32].into() + + [self.padding.left as f32, self.padding.top as f32].into(), + Size::new(w as f32, h as f32), + ), + border_radius: 0.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + }, + Color::from_rgba8( + color.r(), + color.g(), + color.b(), + (color.a() as f32) / 255.0, ), - border_radius: 0.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - }, - Color::from_rgba8( - color.r(), - color.g(), - color.b(), - (color.a() as f32) / 255.0 - ) - ); - } else { - text::draw_pixel(&mut pixels, view_w, view_h, x, y, color); - } - }); + ); + } else { + text::draw_pixel(&mut pixels, view_w, view_h, x, y, color); + } + }, + ); let handle = image::Handle::from_pixels(view_w as u32, view_h as u32, pixels); - image::Renderer::draw(renderer, handle, Rectangle::new( - layout.position() + [self.padding.left as f32, self.padding.top as f32].into(), - Size::new(view_w as f32, view_h as f32) - )); + image::Renderer::draw( + renderer, + handle, + Rectangle::new( + layout.position() + [self.padding.left as f32, self.padding.top as f32].into(), + Size::new(view_w as f32, view_h as f32), + ), + ); let duration = instant.elapsed(); log::debug!("redraw {}, {}: {:?}", view_w, view_h, duration); @@ -238,101 +236,107 @@ where let mut status = Status::Ignored; match event { - Event::Keyboard(KeyEvent::KeyPressed { key_code, modifiers }) => match key_code { + Event::Keyboard(KeyEvent::KeyPressed { + key_code, + modifiers, + }) => match key_code { KeyCode::Left => { editor.action(Action::Left); status = Status::Captured; - }, + } KeyCode::Right => { editor.action(Action::Right); status = Status::Captured; - }, + } KeyCode::Up => { editor.action(Action::Up); status = Status::Captured; - }, + } KeyCode::Down => { editor.action(Action::Down); status = Status::Captured; - }, + } KeyCode::Home => { editor.action(Action::Home); status = Status::Captured; - }, + } KeyCode::End => { editor.action(Action::End); status = Status::Captured; - }, + } KeyCode::PageUp => { editor.action(Action::PageUp); status = Status::Captured; - }, + } KeyCode::PageDown => { editor.action(Action::PageDown); status = Status::Captured; - }, + } KeyCode::Escape => { editor.action(Action::Escape); status = Status::Captured; - }, + } KeyCode::Enter => { editor.action(Action::Enter); status = Status::Captured; - }, + } KeyCode::Backspace => { editor.action(Action::Backspace); status = Status::Captured; - }, + } KeyCode::Delete => { editor.action(Action::Delete); status = Status::Captured; - }, - _ => () + } + _ => (), }, Event::Keyboard(KeyEvent::CharacterReceived(character)) => { editor.action(Action::Insert(character)); status = Status::Captured; - }, + } Event::Mouse(MouseEvent::ButtonPressed(Button::Left)) => { if layout.bounds().contains(cursor_position) { editor.action(Action::Click { - x: (cursor_position.x - layout.bounds().x) as i32 - self.padding.left as i32, + x: (cursor_position.x - layout.bounds().x) as i32 + - self.padding.left as i32, y: (cursor_position.y - layout.bounds().y) as i32 - self.padding.top as i32, }); state.is_dragging = true; status = Status::Captured; } - }, + } Event::Mouse(MouseEvent::ButtonReleased(Button::Left)) => { state.is_dragging = false; status = Status::Captured; - }, + } Event::Mouse(MouseEvent::CursorMoved { .. }) => { if state.is_dragging { editor.action(Action::Drag { - x: (cursor_position.x - layout.bounds().x) as i32 - self.padding.left as i32, + x: (cursor_position.x - layout.bounds().x) as i32 + - self.padding.left as i32, y: (cursor_position.y - layout.bounds().y) as i32 - self.padding.top as i32, }); status = Status::Captured; } - }, + } Event::Mouse(MouseEvent::WheelScrolled { delta }) => match delta { ScrollDelta::Lines { x, y } => { editor.action(Action::Scroll { lines: (-y * 6.0) as i32, }); status = Status::Captured; - }, + } _ => (), }, - _ => () + _ => (), } status } } -impl<'a, 'editor, Editor, Message, Renderer> From> for Element<'a, Message, Renderer> +impl<'a, 'editor, Editor, Message, Renderer> From> + for Element<'a, Message, Renderer> where Renderer: renderer::Renderer + image::Renderer, Renderer::Theme: StyleSheet, diff --git a/examples/editor-orbclient/src/main.rs b/examples/editor-orbclient/src/main.rs index 09f87d9..075c7c2 100644 --- a/examples/editor-orbclient/src/main.rs +++ b/examples/editor-orbclient/src/main.rs @@ -1,19 +1,14 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use cosmic_text::{ - Action, - Attrs, - Buffer, - Edit, - Family, - FontSystem, - Metrics, - SwashCache, - SyntaxEditor, + Action, Attrs, Buffer, Edit, Family, FontSystem, Metrics, SwashCache, SyntaxEditor, SyntaxSystem, }; use orbclient::{EventOption, Renderer, Window, WindowFlag}; -use std::{env, thread, time::{Duration, Instant}}; +use std::{ + env, thread, + time::{Duration, Instant}, +}; fn main() { env_logger::init(); @@ -65,20 +60,18 @@ fn main() { let mut editor = SyntaxEditor::new( Buffer::new(&font_system, font_sizes[font_size_i]), &syntax_system, - "base16-eighties.dark" - ).unwrap(); + "base16-eighties.dark", + ) + .unwrap(); #[cfg(feature = "vi")] let mut editor = cosmic_text::ViEditor::new(editor); - editor.buffer_mut().set_size( - window.width() as i32 - line_x * 2, - window.height() as i32 - ); + editor + .buffer_mut() + .set_size(window.width() as i32 - line_x * 2, window.height() as i32); - let attrs = Attrs::new() - .monospaced(true) - .family(Family::Monospace); + let attrs = Attrs::new().monospaced(true).family(Family::Monospace); match editor.load_text(&path, attrs) { Ok(()) => (), Err(err) => { @@ -212,7 +205,9 @@ fn main() { } } EventOption::Resize(event) => { - editor.buffer_mut().set_size(event.width as i32 - line_x * 2, event.height as i32); + editor + .buffer_mut() + .set_size(event.width as i32 - line_x * 2, event.height as i32); } EventOption::Scroll(event) => { editor.action(Action::Scroll { @@ -243,7 +238,7 @@ fn main() { window.set_async(window_async); } - if window_async && ! found_event { + if window_async && !found_event { // In async mode and no event found, sleep thread::sleep(Duration::from_millis(5)); } diff --git a/examples/editor-test/src/main.rs b/examples/editor-test/src/main.rs index 6dcb72f..5f70bec 100644 --- a/examples/editor-test/src/main.rs +++ b/examples/editor-test/src/main.rs @@ -54,14 +54,8 @@ fn main() { ]; let font_size_default = 1; // Body - let mut buffer = Buffer::new( - &font_system, - font_sizes[font_size_default] - ); - buffer.set_size( - window.width() as i32, - window.height() as i32 - ); + let mut buffer = Buffer::new(&font_system, font_sizes[font_size_default]); + buffer.set_size(window.width() as i32, window.height() as i32); let mut editor = Editor::new(buffer); diff --git a/examples/rich-text/src/main.rs b/examples/rich-text/src/main.rs index 0d753c8..1595f6c 100644 --- a/examples/rich-text/src/main.rs +++ b/examples/rich-text/src/main.rs @@ -1,23 +1,14 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use cosmic_text::{ - Action, - Attrs, - AttrsList, - Buffer, - BufferLine, - Color, - Edit, - Editor, - Family, - FontSystem, - Metrics, - Style, - SwashCache, - Weight, + Action, Attrs, AttrsList, Buffer, BufferLine, Color, Edit, Editor, Family, FontSystem, Metrics, + Style, SwashCache, Weight, }; use orbclient::{EventOption, Renderer, Window, WindowFlag}; -use std::{process, thread, time::{Duration, Instant}}; +use std::{ + process, thread, + time::{Duration, Instant}, +}; fn main() { env_logger::init(); @@ -47,13 +38,12 @@ fn main() { let mut editor = Editor::new(Buffer::new( &font_system, - Metrics::new(32, 44).scale(display_scale) + Metrics::new(32, 44).scale(display_scale), )); - editor.buffer_mut().set_size( - window.width() as i32, - window.height() as i32 - ); + editor + .buffer_mut() + .set_size(window.width() as i32, window.height() as i32); let attrs = Attrs::new(); let serif_attrs = attrs.family(Family::Serif); @@ -79,25 +69,37 @@ fn main() { ("Sans-Serif Normal ", attrs), ("Sans-Serif Bold ", attrs.weight(Weight::BOLD)), ("Sans-Serif Italic ", attrs.style(Style::Italic)), - ("Sans-Serif Bold Italic", attrs.weight(Weight::BOLD).style(Style::Italic)), + ( + "Sans-Serif Bold Italic", + attrs.weight(Weight::BOLD).style(Style::Italic), + ), ], &[ ("Serif Normal ", serif_attrs), ("Serif Bold ", serif_attrs.weight(Weight::BOLD)), ("Serif Italic ", serif_attrs.style(Style::Italic)), - ("Serif Bold Italic", serif_attrs.weight(Weight::BOLD).style(Style::Italic)), + ( + "Serif Bold Italic", + serif_attrs.weight(Weight::BOLD).style(Style::Italic), + ), ], &[ ("Mono Normal ", mono_attrs), ("Mono Bold ", mono_attrs.weight(Weight::BOLD)), ("Mono Italic ", mono_attrs.style(Style::Italic)), - ("Mono Bold Italic", mono_attrs.weight(Weight::BOLD).style(Style::Italic)), + ( + "Mono Bold Italic", + mono_attrs.weight(Weight::BOLD).style(Style::Italic), + ), ], &[ ("Comic Normal ", comic_attrs), ("Comic Bold ", comic_attrs.weight(Weight::BOLD)), ("Comic Italic ", comic_attrs.style(Style::Italic)), - ("Comic Bold Italic", comic_attrs.weight(Weight::BOLD).style(Style::Italic)), + ( + "Comic Bold Italic", + comic_attrs.weight(Weight::BOLD).style(Style::Italic), + ), ], &[ ("R", attrs.color(Color::rgb(0xFF, 0x00, 0x00))), @@ -121,10 +123,11 @@ fn main() { ("O", attrs.color(Color::rgb(0xFF, 0xFF, 0x00))), ("R", attrs.color(Color::rgb(0xFF, 0x7F, 0x00))), ("N", attrs.color(Color::rgb(0xFF, 0x00, 0x00))), - ], - &[ - ("生活,삶,जिंदगी 😀 FPS", attrs.color(Color::rgb(0xFF, 0x00, 0x00))) - ] + ], + &[( + "生活,삶,जिंदगी 😀 FPS", + attrs.color(Color::rgb(0xFF, 0x00, 0x00)), + )], ]; for &line in lines { let mut line_text = String::new(); @@ -135,7 +138,10 @@ fn main() { let end = line_text.len(); attrs_list.add_span(start..end, attrs); } - editor.buffer_mut().lines.push(BufferLine::new(line_text, attrs_list)); + editor + .buffer_mut() + .lines + .push(BufferLine::new(line_text, attrs_list)); } let mut swash_cache = SwashCache::new(&font_system); @@ -187,18 +193,26 @@ fn main() { mouse_x = mouse.x; mouse_y = mouse.y; if mouse_left { - editor.action(Action::Drag { x: mouse_x, y: mouse_y }); + editor.action(Action::Drag { + x: mouse_x, + y: mouse_y, + }); } - }, + } EventOption::Button(button) => { mouse_left = button.left; if mouse_left { - editor.action(Action::Click { x: mouse_x, y: mouse_y }); + editor.action(Action::Click { + x: mouse_x, + y: mouse_y, + }); } - }, + } EventOption::Resize(resize) => { - editor.buffer_mut().set_size(resize.width as i32, resize.height as i32); - }, + editor + .buffer_mut() + .set_size(resize.width as i32, resize.height as i32); + } EventOption::Quit(_) => process::exit(0), _ => (), } diff --git a/examples/terminal/src/main.rs b/examples/terminal/src/main.rs index 4c121e8..fb16071 100644 --- a/examples/terminal/src/main.rs +++ b/examples/terminal/src/main.rs @@ -1,11 +1,8 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 -use cosmic_text::{Attrs, Color, FontSystem, SwashCache, Buffer, Metrics}; +use cosmic_text::{Attrs, Buffer, Color, FontSystem, Metrics, SwashCache}; use std::cmp; -use termion::{ - color, - cursor, -}; +use termion::{color, cursor}; fn main() { // A FontSystem provides access to detected system fonts, create one per application @@ -66,11 +63,7 @@ fn main() { } // Scale by alpha (mimics blending with black) - let scale = |c: u8| { - cmp::max(0, cmp::min(255, - ((c as i32) * (a as i32)) / 255 - )) as u8 - }; + let scale = |c: u8| cmp::max(0, cmp::min(255, ((c as i32) * (a as i32)) / 255)) as u8; // Navigate to x coordinate if x > last_x { diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index c7ad93b..0000000 --- a/rustfmt.toml +++ /dev/null @@ -1 +0,0 @@ -disable_all_formatting = true diff --git a/src/attrs.rs b/src/attrs.rs index bc4ac7b..33b1979 100644 --- a/src/attrs.rs +++ b/src/attrs.rs @@ -24,12 +24,7 @@ impl Color { /// Create new color with red, green, blue, and alpha components #[inline] pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self { - Self( - ((a as u32) << 24) | - ((r as u32) << 16) | - ((g as u32) << 8) | - (b as u32) - ) + Self(((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32)) } /// Get the red component @@ -165,22 +160,20 @@ impl<'a> Attrs<'a> { /// Check if font matches pub fn matches(&self, face: &fontdb::FaceInfo) -> bool { //TODO: smarter way of including emoji - face.post_script_name.contains("Emoji") || - ( - face.style == self.style && - face.weight == self.weight && - face.stretch == self.stretch && - face.monospaced == self.monospaced - ) + face.post_script_name.contains("Emoji") + || (face.style == self.style + && face.weight == self.weight + && face.stretch == self.stretch + && face.monospaced == self.monospaced) } /// Check if this set of attributes can be shaped with another pub fn compatible(&self, other: &Self) -> bool { self.family == other.family - && self.monospaced == other.monospaced - && self.stretch == other.stretch - && self.style == other.style - && self.weight == other.weight + && self.monospaced == other.monospaced + && self.stretch == other.stretch + && self.style == other.style + && self.weight == other.weight } } @@ -268,7 +261,10 @@ impl AttrsList { /// /// This returns a span that contains the index pub fn get_span(&self, index: usize) -> Attrs { - self.spans.get(&index).map(|v| v.as_attrs()).unwrap_or(self.defaults.as_attrs()) + self.spans + .get(&index) + .map(|v| v.as_attrs()) + .unwrap_or(self.defaults.as_attrs()) } /// Split attributes list at an offset @@ -288,20 +284,19 @@ impl AttrsList { } for (key, resize) in removes { - let (range, attrs) = self.spans.get_key_value(&key.start).map(|v| (v.0.clone(), v.1.clone())).expect("attrs span not found"); + let (range, attrs) = self + .spans + .get_key_value(&key.start) + .map(|v| (v.0.clone(), v.1.clone())) + .expect("attrs span not found"); self.spans.remove(key); if resize { - new.spans.insert( - 0..range.end - index, - attrs.clone() - ); + new.spans.insert(0..range.end - index, attrs.clone()); self.spans.insert(range.start..index, attrs); } else { - new.spans.insert( - range.start - index..range.end - index, - attrs - ); + new.spans + .insert(range.start - index..range.end - index, attrs); } } new diff --git a/src/buffer.rs b/src/buffer.rs index 07d3612..a84919b 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -5,15 +5,12 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; -use core::{ - cmp, - fmt, -}; +use core::{cmp, fmt}; use unicode_segmentation::UnicodeSegmentation; -use crate::{Attrs, AttrsList, BufferLine, FontSystem, LayoutGlyph, LayoutLine, ShapeLine, Wrap}; #[cfg(feature = "swash")] use crate::Color; +use crate::{Attrs, AttrsList, BufferLine, FontSystem, LayoutGlyph, LayoutLine, ShapeLine, Wrap}; /// Current cursor location #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd)] @@ -39,7 +36,11 @@ pub struct LayoutCursor { impl LayoutCursor { pub fn new(line: usize, layout: usize, glyph: usize) -> Self { - Self { line, layout, glyph } + Self { + line, + layout, + glyph, + } } } @@ -81,13 +82,25 @@ impl<'a> LayoutRun<'a> { let cursor = Cursor::new(self.line_i, self.glyphs.last().map_or(0, |glyph| glyph.end)); if cursor >= cursor_start && cursor <= cursor_end { if x_start.is_none() { - x_start = Some(self.glyphs.last().map_or(0., |glyph| glyph.x + glyph.w * ltr_factor)); + x_start = Some( + self.glyphs + .last() + .map_or(0., |glyph| glyph.x + glyph.w * ltr_factor), + ); } - x_end = Some(self.glyphs.last().map_or(0., |glyph| glyph.x + glyph.w * ltr_factor)); + x_end = Some( + self.glyphs + .last() + .map_or(0., |glyph| glyph.x + glyph.w * ltr_factor), + ); } if let Some(x_start) = x_start { let x_end = x_end.expect("end of cursor not found"); - let (x_start, x_end) = if x_start < x_end { (x_start, x_end) } else { (x_end, x_start) }; + let (x_start, x_end) = if x_start < x_end { + (x_start, x_end) + } else { + (x_end, x_start) + }; Some((x_start, x_end - x_start)) } else { None @@ -107,14 +120,28 @@ pub struct LayoutRunIter<'a, 'b> { impl<'a, 'b> LayoutRunIter<'a, 'b> { pub fn new(buffer: &'b Buffer<'a>) -> Self { - let total_layout_lines: usize = buffer.lines.iter().map(|line| line.layout_opt().as_ref().map(|layout| layout.len()).unwrap_or_default()).sum(); - let top_cropped_layout_lines = total_layout_lines.saturating_sub(buffer.scroll.try_into().unwrap_or_default()); - let maximum_lines = buffer.height.checked_div(buffer.metrics.line_height).unwrap_or_default(); - let bottom_cropped_layout_lines = if top_cropped_layout_lines > maximum_lines.try_into().unwrap_or_default() { - maximum_lines.try_into().unwrap_or_default() - } else { - top_cropped_layout_lines - }; + let total_layout_lines: usize = buffer + .lines + .iter() + .map(|line| { + line.layout_opt() + .as_ref() + .map(|layout| layout.len()) + .unwrap_or_default() + }) + .sum(); + let top_cropped_layout_lines = + total_layout_lines.saturating_sub(buffer.scroll.try_into().unwrap_or_default()); + let maximum_lines = buffer + .height + .checked_div(buffer.metrics.line_height) + .unwrap_or_default(); + let bottom_cropped_layout_lines = + if top_cropped_layout_lines > maximum_lines.try_into().unwrap_or_default() { + maximum_lines.try_into().unwrap_or_default() + } else { + top_cropped_layout_lines + }; Self { buffer, line_i: 0, @@ -169,7 +196,7 @@ impl<'a, 'b> Iterator for LayoutRunIter<'a, 'b> { } } -impl<'a, 'b> ExactSizeIterator for LayoutRunIter<'a, 'b> { } +impl<'a, 'b> ExactSizeIterator for LayoutRunIter<'a, 'b> {} /// Metrics of text #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] @@ -182,7 +209,10 @@ pub struct Metrics { impl Metrics { pub const fn new(font_size: i32, line_height: i32) -> Self { - Self { font_size, line_height } + Self { + font_size, + line_height, + } } pub const fn scale(self, scale: i32) -> Self { @@ -215,10 +245,7 @@ pub struct Buffer<'a> { impl<'a> Buffer<'a> { /// Create a new [`Buffer`] with the provided [`FontSystem`] and [`Metrics`] - pub fn new( - font_system: &'a FontSystem, - metrics: Metrics, - ) -> Self { + pub fn new(font_system: &'a FontSystem, metrics: Metrics) -> Self { let mut buffer = Self { font_system, lines: Vec::new(), @@ -244,7 +271,7 @@ impl<'a> Buffer<'a> { self.font_system, self.metrics.font_size, self.width, - self.wrap + self.wrap, ); } } @@ -274,7 +301,7 @@ impl<'a> Buffer<'a> { self.font_system, self.metrics.font_size, self.width, - self.wrap + self.wrap, ); total_layout += layout.len() as i32; } @@ -307,7 +334,7 @@ impl<'a> Buffer<'a> { self.font_system, self.metrics.font_size, self.width, - self.wrap + self.wrap, ); if line_i == cursor.line { let layout_cursor = self.layout_cursor(&cursor); @@ -341,13 +368,7 @@ impl<'a> Buffer<'a> { let scroll_end = self.scroll + lines; let total_layout = self.shape_until(scroll_end); - self.scroll = cmp::max( - 0, - cmp::min( - total_layout - (lines - 1), - self.scroll, - ), - ); + self.scroll = cmp::max(0, cmp::min(total_layout - (lines - 1), self.scroll)); } pub fn layout_cursor(&self, cursor: &Cursor) -> LayoutCursor { @@ -358,40 +379,24 @@ impl<'a> Buffer<'a> { for (layout_i, layout_line) in layout.iter().enumerate() { for (glyph_i, glyph) in layout_line.glyphs.iter().enumerate() { if cursor.index == glyph.start { - return LayoutCursor::new( - cursor.line, - layout_i, - glyph_i - ); + return LayoutCursor::new(cursor.line, layout_i, glyph_i); } } match layout_line.glyphs.last() { Some(glyph) => { if cursor.index == glyph.end { - return LayoutCursor::new( - cursor.line, - layout_i, - layout_line.glyphs.len() - ); + return LayoutCursor::new(cursor.line, layout_i, layout_line.glyphs.len()); } - }, + } None => { - return LayoutCursor::new( - cursor.line, - layout_i, - 0 - ); + return LayoutCursor::new(cursor.line, layout_i, 0); } } } // Fall back to start of line //TODO: should this be the end of the line? - LayoutCursor::new( - cursor.line, - 0, - 0 - ) + LayoutCursor::new(cursor.line, 0, 0) } /// Get [`FontSystem`] used by this [`Buffer`] @@ -408,7 +413,12 @@ impl<'a> Buffer<'a> { /// Lay out the provided line index and return the result pub fn line_layout(&mut self, line_i: usize) -> Option<&[LayoutLine]> { let line = self.lines.get_mut(line_i)?; - Some(line.layout(self.font_system, self.metrics.font_size, self.width, self.wrap)) + Some(line.layout( + self.font_system, + self.metrics.font_size, + self.width, + self.wrap, + )) } /// Get the current [`Metrics`] @@ -476,11 +486,13 @@ impl<'a> Buffer<'a> { pub fn set_text(&mut self, text: &str, attrs: Attrs<'a>) { self.lines.clear(); for line in text.lines() { - self.lines.push(BufferLine::new(line.to_string(), AttrsList::new(attrs))); + self.lines + .push(BufferLine::new(line.to_string(), AttrsList::new(attrs))); } // Make sure there is always one line if self.lines.is_empty() { - self.lines.push(BufferLine::new(String::new(), AttrsList::new(attrs))); + self.lines + .push(BufferLine::new(String::new(), AttrsList::new(attrs))); } self.scroll = 0; @@ -522,9 +534,7 @@ impl<'a> Buffer<'a> { first_run = false; let new_cursor = Cursor::new(run.line_i, 0); new_cursor_opt = Some(new_cursor); - } else if y >= line_y - font_size - && y < line_y - font_size + line_height - { + } else if y >= line_y - font_size && y < line_y - font_size + line_height { let mut new_cursor_glyph = run.glyphs.len(); let mut new_cursor_char = 0; @@ -538,9 +548,7 @@ impl<'a> Buffer<'a> { new_cursor_char = 0; } } - if x >= glyph.x as i32 - && x <= (glyph.x + glyph.w) as i32 - { + if x >= glyph.x as i32 && x <= (glyph.x + glyph.w) as i32 { new_cursor_glyph = glyph_i; let cluster = &run.text[glyph.start..glyph.end]; @@ -548,9 +556,7 @@ impl<'a> Buffer<'a> { let mut egc_x = glyph.x; let egc_w = glyph.w / (total as f32); for (egc_i, egc) in cluster.grapheme_indices(true) { - if x >= egc_x as i32 - && x <= (egc_x + egc_w) as i32 - { + if x >= egc_x as i32 && x <= (egc_x + egc_w) as i32 { new_cursor_char = egc_i; let right_half = x >= (egc_x + egc_w / 2.0) as i32; @@ -578,11 +584,13 @@ impl<'a> Buffer<'a> { Some(glyph) => { // Position at glyph new_cursor.index = glyph.start + new_cursor_char; - }, - None => if let Some(glyph) = run.glyphs.last() { - // Position at end of line - new_cursor.index = glyph.end; - }, + } + None => { + if let Some(glyph) = run.glyphs.last() { + // Position at end of line + new_cursor.index = glyph.end; + } + } } new_cursor_opt = Some(new_cursor); @@ -606,7 +614,8 @@ impl<'a> Buffer<'a> { /// Draw the buffer #[cfg(feature = "swash")] pub fn draw(&self, cache: &mut crate::SwashCache, color: Color, mut f: F) - where F: FnMut(i32, i32, u32, u32, Color) + where + F: FnMut(i32, i32, u32, u32, Color), { for run in self.layout_runs() { for glyph in run.glyphs.iter() { diff --git a/src/buffer_line.rs b/src/buffer_line.rs index 242db25..428504c 100644 --- a/src/buffer_line.rs +++ b/src/buffer_line.rs @@ -1,8 +1,5 @@ #[cfg(not(feature = "std"))] -use alloc::{ - string::String, - vec::Vec, -}; +use alloc::{string::String, vec::Vec}; use crate::{AttrsList, FontSystem, LayoutLine, ShapeLine, Wrap}; @@ -39,7 +36,11 @@ impl BufferLine { /// /// Will reset shape and layout if it differs from current text and attributes list. /// Returns true if the line was reset - pub fn set_text + Into>(&mut self, text: T, attrs_list: AttrsList) -> bool { + pub fn set_text + Into>( + &mut self, + text: T, + attrs_list: AttrsList, + ) -> bool { if text.as_ref() != self.text || attrs_list != self.attrs_list { self.text = text.into(); self.attrs_list = attrs_list; @@ -102,7 +103,8 @@ impl BufferLine { if other.attrs_list.defaults() != self.attrs_list.defaults() { // If default formatting does not match, make a new span for it - self.attrs_list.add_span(len..len + other.text().len(), other.attrs_list.defaults()); + self.attrs_list + .add_span(len..len + other.text().len(), other.attrs_list.defaults()); } for (other_range, attrs) in other.attrs_list.spans() { @@ -157,15 +159,17 @@ impl BufferLine { } /// Layout line, will cache results - pub fn layout(&mut self, font_system: &FontSystem, font_size: i32, width: i32, wrap: Wrap) -> &[LayoutLine] { + pub fn layout( + &mut self, + font_system: &FontSystem, + font_size: i32, + width: i32, + wrap: Wrap, + ) -> &[LayoutLine] { if self.layout_opt.is_none() { self.wrap = wrap; let shape = self.shape(font_system); - let layout = shape.layout( - font_size, - width, - wrap - ); + let layout = shape.layout(font_size, width, wrap); self.layout_opt = Some(layout); } self.layout_opt.as_ref().expect("layout not found") diff --git a/src/edit/editor.rs b/src/edit/editor.rs index 0e7df62..2ddf9fc 100644 --- a/src/edit/editor.rs +++ b/src/edit/editor.rs @@ -5,9 +5,9 @@ use alloc::string::String; use core::{cmp, iter::once}; use unicode_segmentation::UnicodeSegmentation; -use crate::{Action, AttrsList, Buffer, BufferLine, Cursor, Edit, LayoutCursor}; #[cfg(feature = "swash")] use crate::Color; +use crate::{Action, AttrsList, Buffer, BufferLine, Cursor, Edit, LayoutCursor}; /// A wrapper of [`Buffer`] for easy editing pub struct Editor<'a> { @@ -31,14 +31,17 @@ impl<'a> Editor<'a> { } fn set_layout_cursor(&mut self, cursor: LayoutCursor) { - let layout = self.buffer.line_layout(cursor.line).expect("layout not found"); + let layout = self + .buffer + .line_layout(cursor.line) + .expect("layout not found"); let layout_line = match layout.get(cursor.layout) { Some(some) => some, None => match layout.last() { Some(some) => some, None => todo!("layout cursor in line with no layouts"), - } + }, }; let new_index = match layout_line.glyphs.get(cursor.glyph) { @@ -47,7 +50,7 @@ impl<'a> Editor<'a> { Some(glyph) => glyph.end, //TODO: is this correct? None => 0, - } + }, }; if self.cursor.line != cursor.line || self.cursor.index != new_index { @@ -217,7 +220,8 @@ impl<'a> Edit<'a> for Editor<'a> { let after_len = after.text().len(); // Collect attributes - let mut final_attrs = attrs_list.unwrap_or_else(|| AttrsList::new(line.attrs_list().get_span(line.text().len()))); + let mut final_attrs = attrs_list + .unwrap_or_else(|| AttrsList::new(line.attrs_list().get_span(line.text().len()))); // Append the inserted text, line by line // we want to see a blank entry if the string ends with a newline @@ -227,13 +231,23 @@ impl<'a> Edit<'a> for Editor<'a> { let mut these_attrs = final_attrs.split_off(data_line.len()); remaining_split_len -= data_line.len(); core::mem::swap(&mut these_attrs, &mut final_attrs); - line.append(BufferLine::new(data_line.strip_suffix(char::is_control).unwrap_or(data_line), these_attrs)); + line.append(BufferLine::new( + data_line + .strip_suffix(char::is_control) + .unwrap_or(data_line), + these_attrs, + )); } else { panic!("str::lines() did not yield any elements"); } if let Some(data_line) = lines_iter.next_back() { remaining_split_len -= data_line.len(); - let mut tmp = BufferLine::new(data_line.strip_suffix(char::is_control).unwrap_or(data_line), final_attrs.split_off(remaining_split_len)); + let mut tmp = BufferLine::new( + data_line + .strip_suffix(char::is_control) + .unwrap_or(data_line), + final_attrs.split_off(remaining_split_len), + ); tmp.append(after); self.buffer.lines.insert(insert_line, tmp); self.cursor.line += 1; @@ -242,7 +256,12 @@ impl<'a> Edit<'a> for Editor<'a> { } for data_line in lines_iter.rev() { remaining_split_len -= data_line.len(); - let tmp = BufferLine::new(data_line.strip_suffix(char::is_control).unwrap_or(data_line), final_attrs.split_off(remaining_split_len)); + let tmp = BufferLine::new( + data_line + .strip_suffix(char::is_control) + .unwrap_or(data_line), + final_attrs.split_off(remaining_split_len), + ); self.buffer.lines.insert(insert_line, tmp); self.cursor.line += 1; } @@ -278,7 +297,7 @@ impl<'a> Edit<'a> for Editor<'a> { self.buffer.set_redraw(true); } self.cursor_x_opt = None; - }, + } Action::Next => { let line = &mut self.buffer.lines[self.cursor.line]; if self.cursor.index < line.text().len() { @@ -295,9 +314,12 @@ impl<'a> Edit<'a> for Editor<'a> { self.buffer.set_redraw(true); } self.cursor_x_opt = None; - }, + } Action::Left => { - let rtl_opt = self.buffer.lines[self.cursor.line].shape_opt().as_ref().map(|shape| shape.rtl); + let rtl_opt = self.buffer.lines[self.cursor.line] + .shape_opt() + .as_ref() + .map(|shape| shape.rtl); if let Some(rtl) = rtl_opt { if rtl { self.action(Action::Next); @@ -305,9 +327,12 @@ impl<'a> Edit<'a> for Editor<'a> { self.action(Action::Previous); } } - }, + } Action::Right => { - let rtl_opt = self.buffer.lines[self.cursor.line].shape_opt().as_ref().map(|shape| shape.rtl); + let rtl_opt = self.buffer.lines[self.cursor.line] + .shape_opt() + .as_ref() + .map(|shape| shape.rtl); if let Some(rtl) = rtl_opt { if rtl { self.action(Action::Previous); @@ -315,14 +340,14 @@ impl<'a> Edit<'a> for Editor<'a> { self.action(Action::Next); } } - }, + } Action::Up => { //TODO: make this preserve X as best as possible! let mut cursor = self.buffer.layout_cursor(&self.cursor); if self.cursor_x_opt.is_none() { self.cursor_x_opt = Some( - cursor.glyph as i32 //TODO: glyph x position + cursor.glyph as i32, //TODO: glyph x position ); } @@ -338,16 +363,20 @@ impl<'a> Edit<'a> for Editor<'a> { } self.set_layout_cursor(cursor); - }, + } Action::Down => { //TODO: make this preserve X as best as possible! let mut cursor = self.buffer.layout_cursor(&self.cursor); - let layout_len = self.buffer.line_layout(cursor.line).expect("layout not found").len(); + let layout_len = self + .buffer + .line_layout(cursor.line) + .expect("layout not found") + .len(); if self.cursor_x_opt.is_none() { self.cursor_x_opt = Some( - cursor.glyph as i32 //TODO: glyph x position + cursor.glyph as i32, //TODO: glyph x position ); } @@ -363,13 +392,13 @@ impl<'a> Edit<'a> for Editor<'a> { } self.set_layout_cursor(cursor); - }, + } Action::Home => { let mut cursor = self.buffer.layout_cursor(&self.cursor); cursor.glyph = 0; self.set_layout_cursor(cursor); self.cursor_x_opt = None; - }, + } Action::End => { let mut cursor = self.buffer.layout_cursor(&self.cursor); cursor.glyph = usize::max_value(); @@ -388,10 +417,10 @@ impl<'a> Edit<'a> for Editor<'a> { } Action::PageUp => { self.action(Action::Vertical(-self.buffer.size().1)); - }, + } Action::PageDown => { self.action(Action::Vertical(self.buffer.size().1)); - }, + } Action::Vertical(px) => { // TODO more efficient let lines = px / self.buffer.metrics().line_height; @@ -404,16 +433,14 @@ impl<'a> Edit<'a> for Editor<'a> { self.action(Action::Down); } } - }, + } Action::Escape => { if self.select_opt.take().is_some() { self.buffer.set_redraw(true); } - }, + } Action::Insert(character) => { - if character.is_control() - && !['\t', '\n', '\u{92}'].contains(&character) - { + if character.is_control() && !['\t', '\n', '\u{92}'].contains(&character) { // Filter out special chars (except for tab), use Action instead log::debug!("Refusing to insert control character {:?}", character); } else if character == '\n' { @@ -423,7 +450,7 @@ impl<'a> Edit<'a> for Editor<'a> { let str_ref = character.encode_utf8(&mut str_buf); self.insert_string(str_ref, None); } - }, + } Action::Enter => { self.delete_selection(); @@ -433,7 +460,7 @@ impl<'a> Edit<'a> for Editor<'a> { self.cursor.index = 0; self.buffer.lines.insert(self.cursor.line, new_line); - }, + } Action::Backspace => { if self.delete_selection() { // Deleted selection @@ -472,7 +499,7 @@ impl<'a> Edit<'a> for Editor<'a> { line.append(old_line); } - }, + } Action::Delete => { if self.delete_selection() { // Deleted selection @@ -484,9 +511,7 @@ impl<'a> Edit<'a> for Editor<'a> { .grapheme_indices(true) .take_while(|(i, _)| *i <= self.cursor.index) .last() - .map(|(i, c)| { - i..(i + c.len()) - }); + .map(|(i, c)| i..(i + c.len())); if let Some(range) = range_opt { self.cursor.index = range.start; @@ -504,7 +529,7 @@ impl<'a> Edit<'a> for Editor<'a> { let old_line = self.buffer.lines.remove(self.cursor.line + 1); self.buffer.lines[self.cursor.line].append(old_line); } - }, + } Action::Click { x, y } => { self.select_opt = None; @@ -514,7 +539,7 @@ impl<'a> Edit<'a> for Editor<'a> { self.buffer.set_redraw(true); } } - }, + } Action::Drag { x, y } => { if self.select_opt.is_none() { self.select_opt = Some(self.cursor); @@ -527,7 +552,7 @@ impl<'a> Edit<'a> for Editor<'a> { self.buffer.set_redraw(true); } } - }, + } Action::Scroll { lines } => { let mut scroll = self.buffer.scroll(); scroll += lines; @@ -573,7 +598,10 @@ impl<'a> Edit<'a> for Editor<'a> { self.cursor_x_opt = None; } Action::LeftWord => { - let rtl_opt = self.buffer.lines[self.cursor.line].shape_opt().as_ref().map(|shape| shape.rtl); + let rtl_opt = self.buffer.lines[self.cursor.line] + .shape_opt() + .as_ref() + .map(|shape| shape.rtl); if let Some(rtl) = rtl_opt { if rtl { self.action(Action::NextWord); @@ -581,9 +609,12 @@ impl<'a> Edit<'a> for Editor<'a> { self.action(Action::PreviousWord); } } - }, + } Action::RightWord => { - let rtl_opt = self.buffer.lines[self.cursor.line].shape_opt().as_ref().map(|shape| shape.rtl); + let rtl_opt = self.buffer.lines[self.cursor.line] + .shape_opt() + .as_ref() + .map(|shape| shape.rtl); if let Some(rtl) = rtl_opt { if rtl { self.action(Action::PreviousWord); @@ -591,7 +622,7 @@ impl<'a> Edit<'a> for Editor<'a> { self.action(Action::NextWord); } } - }, + } Action::BufferStart => { self.cursor.line = 0; self.cursor.index = 0; @@ -628,7 +659,8 @@ impl<'a> Edit<'a> for Editor<'a> { /// Draw the editor #[cfg(feature = "swash")] fn draw(&self, cache: &mut crate::SwashCache, color: Color, mut f: F) - where F: FnMut(i32, i32, u32, u32, Color) + where + F: FnMut(i32, i32, u32, u32, Color), { let font_size = self.buffer.metrics().font_size; let line_height = self.buffer.metrics().line_height; @@ -664,7 +696,7 @@ impl<'a> Edit<'a> for Editor<'a> { if cursor.index == glyph.end { return Some((run.glyphs.len(), 0.0)); } - }, + } None => { return Some((0, 0.0)); } @@ -701,16 +733,14 @@ impl<'a> Edit<'a> for Editor<'a> { let c_start = glyph.start + i; let c_end = glyph.start + i + c.len(); if (start.line != line_i || c_end > start.index) - && (end.line != line_i || c_start < end.index) { + && (end.line != line_i || c_start < end.index) + { range_opt = match range_opt.take() { Some((min, max)) => Some(( cmp::min(min, c_x as i32), cmp::max(max, (c_x + c_w) as i32), )), - None => Some(( - c_x as i32, - (c_x + c_w) as i32, - )) + None => Some((c_x as i32, (c_x + c_w) as i32)), }; } else if let Some((min, max)) = range_opt.take() { f( @@ -718,14 +748,14 @@ impl<'a> Edit<'a> for Editor<'a> { line_y - font_size, cmp::max(0, max - min) as u32, line_height as u32, - Color::rgba(color.r(), color.g(), color.b(), 0x33) + Color::rgba(color.r(), color.g(), color.b(), 0x33), ); } c_x += c_w; } } - if run.glyphs.is_empty() && end.line > line_i{ + if run.glyphs.is_empty() && end.line > line_i { // Highlight all of internal empty lines range_opt = Some((0, self.buffer.size().0)); } @@ -744,7 +774,7 @@ impl<'a> Edit<'a> for Editor<'a> { line_y - font_size, cmp::max(0, max - min) as u32, line_height as u32, - Color::rgba(color.r(), color.g(), color.b(), 0x33) + Color::rgba(color.r(), color.g(), color.b(), 0x33), ); } } @@ -760,7 +790,7 @@ impl<'a> Edit<'a> for Editor<'a> { } else { (glyph.x + cursor_glyph_offset) as i32 } - }, + } None => match run.glyphs.last() { Some(glyph) => { // End of last glyph @@ -769,21 +799,15 @@ impl<'a> Edit<'a> for Editor<'a> { } else { (glyph.x + glyph.w) as i32 } - }, + } None => { // Start of empty line 0 } - } + }, }; - f( - x, - line_y - font_size, - 1, - line_height as u32, - color, - ); + f(x, line_y - font_size, 1, line_height as u32, color); } for glyph in run.glyphs.iter() { diff --git a/src/edit/mod.rs b/src/edit/mod.rs index b80a1f5..43f7f8d 100644 --- a/src/edit/mod.rs +++ b/src/edit/mod.rs @@ -1,9 +1,9 @@ #[cfg(not(feature = "std"))] use alloc::string::String; -use crate::{AttrsList, Buffer, Cursor}; #[cfg(feature = "swash")] use crate::Color; +use crate::{AttrsList, Buffer, Cursor}; pub use self::editor::*; mod editor; @@ -114,5 +114,6 @@ pub trait Edit<'a> { /// Draw the editor #[cfg(feature = "swash")] fn draw(&self, cache: &mut crate::SwashCache, color: Color, f: F) - where F: FnMut(i32, i32, u32, u32, Color); + where + F: FnMut(i32, i32, u32, u32, Color); } diff --git a/src/edit/syntect.rs b/src/edit/syntect.rs index 0c7aea1..14a41ee 100644 --- a/src/edit/syntect.rs +++ b/src/edit/syntect.rs @@ -1,41 +1,13 @@ #[cfg(not(feature = "std"))] -use alloc::{ - string::String, - vec::Vec, -}; +use alloc::{string::String, vec::Vec}; #[cfg(feature = "std")] -use std::{ - fs, - io, - path::Path, -}; +use std::{fs, io, path::Path}; use syntect::highlighting::{ - FontStyle, - Highlighter, - HighlightState, - RangedHighlightIterator, - Theme, - ThemeSet, -}; -use syntect::parsing::{ - ParseState, - ScopeStack, - SyntaxReference, - SyntaxSet, + FontStyle, HighlightState, Highlighter, RangedHighlightIterator, Theme, ThemeSet, }; +use syntect::parsing::{ParseState, ScopeStack, SyntaxReference, SyntaxSet}; -use crate::{ - Action, - AttrsList, - Buffer, - Color, - Cursor, - Edit, - Editor, - Style, - Weight, - Wrap, -}; +use crate::{Action, AttrsList, Buffer, Color, Cursor, Edit, Editor, Style, Weight, Wrap}; pub struct SyntaxSystem { pub syntax_set: SyntaxSet, @@ -69,7 +41,11 @@ impl<'a> SyntaxEditor<'a> { /// A good default theme name is "base16-eighties.dark". /// /// Returns None if theme not found - pub fn new(buffer: Buffer<'a>, syntax_system: &'a SyntaxSystem, theme_name: &str) -> Option { + pub fn new( + buffer: Buffer<'a>, + syntax_system: &'a SyntaxSystem, + theme_name: &str, + ) -> Option { let editor = Editor::new(buffer); let syntax = syntax_system.syntax_set.find_syntax_plain_text(); let theme = syntax_system.theme_set.themes.get(theme_name)?; @@ -91,7 +67,11 @@ impl<'a> SyntaxEditor<'a> { /// /// Returns an [`io::Error`] if reading the file fails #[cfg(feature = "std")] - pub fn load_text>(&mut self, path: P, attrs: crate::Attrs<'a>) -> io::Result<()> { + pub fn load_text>( + &mut self, + path: P, + attrs: crate::Attrs<'a>, + ) -> io::Result<()> { let path = path.as_ref(); let text = fs::read_to_string(path)?; @@ -119,12 +99,7 @@ impl<'a> SyntaxEditor<'a> { /// Get the default background color pub fn background_color(&self) -> Color { if let Some(background) = self.theme.settings.background { - Color::rgba( - background.r, - background.g, - background.b, - background.a, - ) + Color::rgba(background.r, background.g, background.b, background.a) } else { Color::rgb(0, 0, 0) } @@ -133,12 +108,7 @@ impl<'a> SyntaxEditor<'a> { /// Get the default foreground (text) color pub fn foreground_color(&self) -> Color { if let Some(foreground) = self.theme.settings.foreground { - Color::rgba( - foreground.r, - foreground.g, - foreground.b, - foreground.a, - ) + Color::rgba(foreground.r, foreground.g, foreground.b, foreground.a) } else { Color::rgb(0xFF, 0xFF, 0xFF) } @@ -175,21 +145,24 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> { let mut highlighted = 0; for line_i in 0..buffer.lines.len() { let line = &mut buffer.lines[line_i]; - if ! line.is_reset() && line_i < self.syntax_cache.len() { + if !line.is_reset() && line_i < self.syntax_cache.len() { continue; } highlighted += 1; - let (mut parse_state, mut highlight_state) = if line_i > 0 && line_i <= self.syntax_cache.len() { - self.syntax_cache[line_i - 1].clone() - } else { - ( - ParseState::new(self.syntax), - HighlightState::new(&self.highlighter, ScopeStack::new()) - ) - }; + let (mut parse_state, mut highlight_state) = + if line_i > 0 && line_i <= self.syntax_cache.len() { + self.syntax_cache[line_i - 1].clone() + } else { + ( + ParseState::new(self.syntax), + HighlightState::new(&self.highlighter, ScopeStack::new()), + ) + }; - let ops = parse_state.parse_line(line.text(), &self.syntax_system.syntax_set).expect("failed to parse syntax"); + let ops = parse_state + .parse_line(line.text(), &self.syntax_system.syntax_set) + .expect("failed to parse syntax"); let ranges = RangedHighlightIterator::new( &mut highlight_state, &ops, @@ -219,8 +192,7 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> { Weight::BOLD } else { Weight::NORMAL - }) - //TODO: underline + }), //TODO: underline ); } @@ -247,7 +219,11 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> { if highlighted > 0 { buffer.set_redraw(true); #[cfg(feature = "std")] - log::debug!("Syntax highlighted {} lines in {:?}", highlighted, now.elapsed()); + log::debug!( + "Syntax highlighted {} lines in {:?}", + highlighted, + now.elapsed() + ); } self.editor.shape_as_needed(); @@ -272,7 +248,8 @@ impl<'a> Edit<'a> for SyntaxEditor<'a> { /// Draw the editor #[cfg(feature = "swash")] fn draw(&self, cache: &mut crate::SwashCache, _color: Color, mut f: F) - where F: FnMut(i32, i32, u32, u32, Color) + where + F: FnMut(i32, i32, u32, u32, Color), { let size = self.buffer().size(); f(0, 0, size.0 as u32, size.1 as u32, self.background_color()); diff --git a/src/edit/vi.rs b/src/edit/vi.rs index 3a3b1b1..5df0665 100644 --- a/src/edit/vi.rs +++ b/src/edit/vi.rs @@ -2,15 +2,7 @@ use alloc::string::String; use core::cmp; use unicode_segmentation::UnicodeSegmentation; -use crate::{ - Action, - AttrsList, - Buffer, - Color, - Cursor, - Edit, - SyntaxEditor, -}; +use crate::{Action, AttrsList, Buffer, Color, Cursor, Edit, SyntaxEditor}; #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum Mode { @@ -36,7 +28,11 @@ impl<'a> ViEditor<'a> { /// Load text from a file, and also set syntax to the best option #[cfg(feature = "std")] - pub fn load_text>(&mut self, path: P, attrs: crate::Attrs<'a>) -> std::io::Result<()> { + pub fn load_text>( + &mut self, + path: P, + attrs: crate::Attrs<'a>, + ) -> std::io::Result<()> { self.editor.load_text(path, attrs) } @@ -98,12 +94,12 @@ impl<'a> Edit<'a> for ViEditor<'a> { 'a' => { self.editor.action(Action::Right); self.mode = Mode::Insert; - }, + } // Enter insert mode at end of line 'A' => { self.editor.action(Action::End); self.mode = Mode::Insert; - }, + } // Change mode 'c' => { if self.editor.select_opt().is_some() { @@ -112,7 +108,7 @@ impl<'a> Edit<'a> for ViEditor<'a> { } else { //TODO: change to next cursor movement } - }, + } // Delete mode 'd' => { if self.editor.select_opt().is_some() { @@ -120,11 +116,11 @@ impl<'a> Edit<'a> for ViEditor<'a> { } else { //TODO: delete to next cursor movement } - }, + } // Enter insert mode at cursor 'i' => { self.mode = Mode::Insert; - }, + } // Enter insert mode at start of line 'I' => { //TODO: soft home, skip whitespace @@ -136,7 +132,7 @@ impl<'a> Edit<'a> for ViEditor<'a> { self.editor.action(Action::End); self.editor.action(Action::Enter); self.mode = Mode::Insert; - }, + } // Create line before and enter insert mode 'O' => { self.editor.action(Action::Home); @@ -144,7 +140,7 @@ impl<'a> Edit<'a> for ViEditor<'a> { self.editor.shape_as_needed(); // TODO: do not require this? self.editor.action(Action::Up); self.mode = Mode::Insert; - }, + } // Left 'h' => self.editor.action(Action::Left), // Top of screen @@ -166,7 +162,7 @@ impl<'a> Edit<'a> for ViEditor<'a> { } else { self.editor.set_select_opt(Some(self.editor.cursor())); } - }, + } // Enter line visual mode 'V' => { if self.editor.select_opt().is_some() { @@ -177,7 +173,7 @@ impl<'a> Edit<'a> for ViEditor<'a> { //TODO: set cursor_x_opt to max self.editor.action(Action::End); } - }, + } // Remove character at cursor 'x' => self.editor.action(Action::Delete), // Remove character before cursor @@ -192,15 +188,15 @@ impl<'a> Edit<'a> for ViEditor<'a> { // Enter command mode ':' => { self.mode = Mode::Command; - }, + } // Enter search mode '/' => { self.mode = Mode::Search; - }, + } // Enter search backwards mode '?' => { self.mode = Mode::SearchBackwards; - }, + } _ => (), }, _ => self.editor.action(action), @@ -213,13 +209,13 @@ impl<'a> Edit<'a> for ViEditor<'a> { self.editor.action(Action::Left); } self.mode = Mode::Normal; - }, + } _ => self.editor.action(action), }, _ => { //TODO: other modes self.mode = Mode::Normal; - }, + } } if self.mode != old_mode { @@ -229,7 +225,8 @@ impl<'a> Edit<'a> for ViEditor<'a> { #[cfg(feature = "swash")] fn draw(&self, cache: &mut crate::SwashCache, color: Color, mut f: F) - where F: FnMut(i32, i32, u32, u32, Color) + where + F: FnMut(i32, i32, u32, u32, Color), { let font_size = self.buffer().metrics().font_size; let line_height = self.buffer().metrics().line_height; @@ -266,7 +263,7 @@ impl<'a> Edit<'a> for ViEditor<'a> { if cursor.index == glyph.end { return Some((run.glyphs.len(), 0.0, default_width)); } - }, + } None => { return Some((0, 0.0, default_width)); } @@ -303,16 +300,14 @@ impl<'a> Edit<'a> for ViEditor<'a> { let c_start = glyph.start + i; let c_end = glyph.start + i + c.len(); if (start.line != line_i || c_end > start.index) - && (end.line != line_i || c_start < end.index) { + && (end.line != line_i || c_start < end.index) + { range_opt = match range_opt.take() { Some((min, max)) => Some(( cmp::min(min, c_x as i32), cmp::max(max, (c_x + c_w) as i32), )), - None => Some(( - c_x as i32, - (c_x + c_w) as i32, - )) + None => Some((c_x as i32, (c_x + c_w) as i32)), }; } else if let Some((min, max)) = range_opt.take() { f( @@ -320,14 +315,14 @@ impl<'a> Edit<'a> for ViEditor<'a> { line_y - font_size, cmp::max(0, max - min) as u32, line_height as u32, - Color::rgba(color.r(), color.g(), color.b(), 0x33) + Color::rgba(color.r(), color.g(), color.b(), 0x33), ); } c_x += c_w; } } - if run.glyphs.is_empty() && end.line > line_i{ + if run.glyphs.is_empty() && end.line > line_i { // Highlight all of internal empty lines range_opt = Some((0, self.buffer().size().0)); } @@ -346,18 +341,20 @@ impl<'a> Edit<'a> for ViEditor<'a> { line_y - font_size, cmp::max(0, max - min) as u32, line_height as u32, - Color::rgba(color.r(), color.g(), color.b(), 0x33) + Color::rgba(color.r(), color.g(), color.b(), 0x33), ); } } } // Draw cursor - if let Some((cursor_glyph, cursor_glyph_offset, cursor_glyph_width)) = cursor_glyph_opt(&self.cursor()) { + if let Some((cursor_glyph, cursor_glyph_offset, cursor_glyph_width)) = + cursor_glyph_opt(&self.cursor()) + { let block_cursor = match self.mode { Mode::Normal => true, Mode::Insert => false, - _ => true /*TODO: determine block cursor in other modes*/ + _ => true, /*TODO: determine block cursor in other modes*/ }; let (start_x, end_x) = match run.glyphs.get(cursor_glyph) { @@ -366,38 +363,33 @@ impl<'a> Edit<'a> for ViEditor<'a> { if glyph.level.is_rtl() { ( (glyph.x + glyph.w - cursor_glyph_offset) as i32, - (glyph.x + glyph.w - cursor_glyph_offset - cursor_glyph_width) as i32, + (glyph.x + glyph.w - cursor_glyph_offset - cursor_glyph_width) + as i32, ) } else { ( (glyph.x + cursor_glyph_offset) as i32, - (glyph.x + cursor_glyph_offset + cursor_glyph_width) as i32 + (glyph.x + cursor_glyph_offset + cursor_glyph_width) as i32, ) } - }, + } None => match run.glyphs.last() { Some(glyph) => { // End of last glyph if glyph.level.is_rtl() { - ( - glyph.x as i32, - (glyph.x - cursor_glyph_width) as i32 - ) + (glyph.x as i32, (glyph.x - cursor_glyph_width) as i32) } else { ( (glyph.x + glyph.w) as i32, - (glyph.x + glyph.w + cursor_glyph_width) as i32 + (glyph.x + glyph.w + cursor_glyph_width) as i32, ) } - }, + } None => { // Start of empty line - ( - 0, - cursor_glyph_width as i32 - ) + (0, cursor_glyph_width as i32) } - } + }, }; if block_cursor { @@ -411,13 +403,7 @@ impl<'a> Edit<'a> for ViEditor<'a> { Color::rgba(color.r(), color.g(), color.b(), 0x33), ); } else { - f( - start_x, - line_y - font_size, - 1, - line_height as u32, - color, - ); + f(start_x, line_y - font_size, 1, line_height as u32, color); } } diff --git a/src/font/fallback/macos.rs b/src/font/fallback/macos.rs index b6dcc6f..1bd658a 100644 --- a/src/font/fallback/macos.rs +++ b/src/font/fallback/macos.rs @@ -15,9 +15,7 @@ pub fn common_fallback() -> &'static [&'static str] { // Fallbacks to never use pub fn forbidden_fallback() -> &'static [&'static str] { - &[ - ".LastResort", - ] + &[".LastResort"] } fn han_unification(locale: &str) -> &'static [&'static str] { diff --git a/src/font/fallback/mod.rs b/src/font/fallback/mod.rs index e851dd9..0ef3f5c 100644 --- a/src/font/fallback/mod.rs +++ b/src/font/fallback/mod.rs @@ -9,11 +9,7 @@ use crate::Font; use self::platform::*; -#[cfg(not(any( - target_os = "linux", - target_os = "macos", - target_os = "windows", -)))] +#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows",)))] #[path = "other.rs"] mod platform; @@ -46,7 +42,7 @@ impl<'a> FontFallbackIter<'a> { fonts: &'a [Arc>], default_families: &'a [&'a str], scripts: Vec