diff --git a/.github/actions/check_style/action.yml b/.github/actions/check_style/action.yml index 25020e4e4c..74bb871bf5 100644 --- a/.github/actions/check_style/action.yml +++ b/.github/actions/check_style/action.yml @@ -15,6 +15,7 @@ runs: # will have more fixes & suppression for the standard lint set run: | cargo clippy --workspace --all-features --all-targets -- -A clippy::all -D clippy::dbg_macro -D clippy::todo + cargo clippy -p gpui - name: Find modified migrations shell: bash -euxo pipefail {0} diff --git a/crates/gpui/src/keymap/matcher.rs b/crates/gpui/src/keymap/matcher.rs index 88a8826e65..c2dec94a51 100644 --- a/crates/gpui/src/keymap/matcher.rs +++ b/crates/gpui/src/keymap/matcher.rs @@ -72,7 +72,7 @@ impl KeystrokeMatcher { } } - if bindings.len() == 0 && pending_key.is_none() && self.pending_keystrokes.len() > 0 { + if bindings.is_empty() && pending_key.is_none() && !self.pending_keystrokes.is_empty() { drop(keymap); self.pending_keystrokes.remove(0); return self.match_keystroke(keystroke, context_stack); diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index e623742740..900b17bb2c 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -397,7 +397,7 @@ impl PlatformInputHandler { let Some(range) = self.handler.selected_text_range(cx) else { return; }; - self.handler.replace_text_in_range(Some(range), &input, cx); + self.handler.replace_text_in_range(Some(range), input, cx); } } diff --git a/crates/gpui/src/platform/mac/text_system.rs b/crates/gpui/src/platform/mac/text_system.rs index 138a465775..3233b6c436 100644 --- a/crates/gpui/src/platform/mac/text_system.rs +++ b/crates/gpui/src/platform/mac/text_system.rs @@ -225,9 +225,7 @@ impl MacTextSystemState { } fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option { - self.fonts[font_id.0] - .glyph_for_char(ch) - .map(|glyph_id| GlyphId(glyph_id)) + self.fonts[font_id.0].glyph_for_char(ch).map(GlyphId) } fn id_for_native_font(&mut self, requested_font: CTFont) -> FontId { diff --git a/crates/gpui/src/text_system.rs b/crates/gpui/src/text_system.rs index 9662247e6f..6cc56e306b 100644 --- a/crates/gpui/src/text_system.rs +++ b/crates/gpui/src/text_system.rs @@ -172,7 +172,7 @@ impl TextSystem { self.read_metrics(font_id, |metrics| metrics.units_per_em) } - /// Get the height of a captial letter in the given font and size. + /// Get the height of a capital letter in the given font and size. pub fn cap_height(&self, font_id: FontId, font_size: Pixels) -> Pixels { self.read_metrics(font_id, |metrics| metrics.cap_height(font_size)) } diff --git a/crates/gpui/src/text_system/line.rs b/crates/gpui/src/text_system/line.rs index d4f23c9539..e4fe5aad04 100644 --- a/crates/gpui/src/text_system/line.rs +++ b/crates/gpui/src/text_system/line.rs @@ -6,19 +6,29 @@ use derive_more::{Deref, DerefMut}; use smallvec::SmallVec; use std::sync::Arc; +/// Set the text decoration for a run of text. #[derive(Debug, Clone)] pub struct DecorationRun { + /// The length of the run in utf-8 bytes. pub len: u32, + + /// The color for this run pub color: Hsla, + + /// The background color for this run pub background_color: Option, + + /// The underline style for this run pub underline: Option, } +/// A line of text that has been shaped and decorated. #[derive(Clone, Default, Debug, Deref, DerefMut)] pub struct ShapedLine { #[deref] #[deref_mut] pub(crate) layout: Arc, + /// The text that was shaped for this line. pub text: SharedString, pub(crate) decoration_runs: SmallVec<[DecorationRun; 32]>, } @@ -30,6 +40,7 @@ impl ShapedLine { self.layout.len } + /// Paint the line of text to the window. pub fn paint( &self, origin: Point, @@ -49,21 +60,25 @@ impl ShapedLine { } } +/// A line of text that has been shaped, decorated, and wrapped by the text layout system. #[derive(Clone, Default, Debug, Deref, DerefMut)] pub struct WrappedLine { #[deref] #[deref_mut] pub(crate) layout: Arc, + /// The text that was shaped for this line. pub text: SharedString, pub(crate) decoration_runs: SmallVec<[DecorationRun; 32]>, } impl WrappedLine { + /// The length of the underlying, unwrapped layout, in utf-8 bytes. #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize { self.layout.len() } + /// Paint this line of text to the window. pub fn paint( &self, origin: Point, diff --git a/crates/gpui/src/text_system/line_layout.rs b/crates/gpui/src/text_system/line_layout.rs index 166fefd26a..014c2bb1ec 100644 --- a/crates/gpui/src/text_system/line_layout.rs +++ b/crates/gpui/src/text_system/line_layout.rs @@ -8,31 +8,50 @@ use std::{ sync::Arc, }; +/// A laid out and styled line of text #[derive(Default, Debug)] pub struct LineLayout { + /// The font size for this line pub font_size: Pixels, + /// The width of the line pub width: Pixels, + /// The ascent of the line pub ascent: Pixels, + /// The descent of the line pub descent: Pixels, + /// The shaped runs that make up this line pub runs: Vec, + /// The length of the line in utf-8 bytes pub len: usize, } +/// A run of text that has been shaped . #[derive(Debug)] pub struct ShapedRun { + /// The font id for this run pub font_id: FontId, + /// The glyphs that make up this run pub glyphs: SmallVec<[ShapedGlyph; 8]>, } +/// A single glyph, ready to paint. #[derive(Clone, Debug)] pub struct ShapedGlyph { + /// The ID for this glyph, as determined by the text system. pub id: GlyphId, + + /// The position of this glyph in it's containing line. pub position: Point, + + /// The index of this glyph in the original text. pub index: usize, + + /// Whether this glyph is an emoji pub is_emoji: bool, } impl LineLayout { + /// The index for the character at the given x coordinate pub fn index_for_x(&self, x: Pixels) -> Option { if x >= self.width { None @@ -71,6 +90,7 @@ impl LineLayout { self.len } + /// The x position of the character at the given index pub fn x_for_index(&self, index: usize) -> Pixels { for run in &self.runs { for glyph in &run.glyphs { @@ -148,31 +168,44 @@ impl LineLayout { } } +/// A line of text that has been wrapped to fit a given width #[derive(Default, Debug)] pub struct WrappedLineLayout { + /// The line layout, pre-wrapping. pub unwrapped_layout: Arc, + + /// The boundaries at which the line was wrapped pub wrap_boundaries: SmallVec<[WrapBoundary; 1]>, + + /// The width of the line, if it was wrapped pub wrap_width: Option, } +/// A boundary at which a line was wrapped #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct WrapBoundary { + /// The index in the run just before the line was wrapped pub run_ix: usize, + /// The index of the glyph just before the line was wrapped pub glyph_ix: usize, } impl WrappedLineLayout { + /// The length of the underlying text, in utf8 bytes. #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize { self.unwrapped_layout.len } + /// The width of this line, in pixels, whether or not it was wrapped. pub fn width(&self) -> Pixels { self.wrap_width .unwrap_or(Pixels::MAX) .min(self.unwrapped_layout.width) } + /// The size of the whole wrapped text, for the given line_height. + /// can span multiple lines if there are multiple wrap boundaries. pub fn size(&self, line_height: Pixels) -> Size { Size { width: self.width(), @@ -180,26 +213,32 @@ impl WrappedLineLayout { } } + /// The ascent of a line in this layout pub fn ascent(&self) -> Pixels { self.unwrapped_layout.ascent } + /// The descent of a line in this layout pub fn descent(&self) -> Pixels { self.unwrapped_layout.descent } + /// The wrap boundaries in this layout pub fn wrap_boundaries(&self) -> &[WrapBoundary] { &self.wrap_boundaries } + /// The font size of this layout pub fn font_size(&self) -> Pixels { self.unwrapped_layout.font_size } + /// The runs in this layout, sans wrapping pub fn runs(&self) -> &[ShapedRun] { &self.unwrapped_layout.runs } + /// The index corresponding to a given position in this layout for the given line height. pub fn index_for_position( &self, position: Point, @@ -377,6 +416,7 @@ impl LineLayoutCache { } } +/// A run of text with a single font. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct FontRun { pub(crate) len: usize, diff --git a/crates/gpui/src/text_system/line_wrapper.rs b/crates/gpui/src/text_system/line_wrapper.rs index 1c5b2a8f99..4950d7e20e 100644 --- a/crates/gpui/src/text_system/line_wrapper.rs +++ b/crates/gpui/src/text_system/line_wrapper.rs @@ -2,6 +2,7 @@ use crate::{px, FontId, FontRun, Pixels, PlatformTextSystem}; use collections::HashMap; use std::{iter, sync::Arc}; +/// The GPUI line wrapper, used to wrap lines of text to a given width. pub struct LineWrapper { platform_text_system: Arc, pub(crate) font_id: FontId, @@ -11,6 +12,7 @@ pub struct LineWrapper { } impl LineWrapper { + /// The maximum indent that can be applied to a line. pub const MAX_INDENT: u32 = 256; pub(crate) fn new( @@ -27,6 +29,7 @@ impl LineWrapper { } } + /// Wrap a line of text to the given width with this wrapper's font and font size. pub fn wrap_line<'a>( &'a mut self, line: &'a str, @@ -122,9 +125,12 @@ impl LineWrapper { } } +/// A boundary between two lines of text. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct Boundary { + /// The index of the last character in a line pub ix: usize, + /// The indent of the next line. pub next_indent: u32, } diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index 5ffe753dc1..a02c50cb5a 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -1257,7 +1257,7 @@ impl<'a> WindowContext<'a> { } else if let Some(currently_pending) = self.window.pending_input.take() { if bindings .iter() - .all(|binding| !currently_pending.used_by_binding(&binding)) + .all(|binding| !currently_pending.used_by_binding(binding)) { self.replay_pending_input(currently_pending) } diff --git a/crates/gpui/src/window/element_cx.rs b/crates/gpui/src/window/element_cx.rs index c48374529e..f480be9cf7 100644 --- a/crates/gpui/src/window/element_cx.rs +++ b/crates/gpui/src/window/element_cx.rs @@ -8,7 +8,7 @@ //! The other main interface is the `paint_*` family of methods, which push basic drawing commands //! to the GPU. Everything in a GPUI app is drawn with these methods. //! -//! There are also several internal methds that GPUI uses, such as [`ElementContext::with_element_state`] +//! There are also several internal methods that GPUI uses, such as [`ElementContext::with_element_state`] //! to call the paint and layout methods on elements. These have been included as they're often useful //! for taking manual control of the layouting or painting of specialized elements. @@ -733,6 +733,8 @@ impl<'a> ElementContext<'a> { /// Paint a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index. /// The y component of the origin is the baseline of the glyph. + /// You should generally prefer to use the [`ShapedLine::paint`] or [`WrappedLine::paint`] methods in the [`text_system`]. + /// This method is only useful if you need to paint a single glyph that has already been shaped. pub fn paint_glyph( &mut self, origin: Point, @@ -790,6 +792,8 @@ impl<'a> ElementContext<'a> { /// Paint an emoji glyph into the scene for the next frame at the current z-index. /// The y component of the origin is the baseline of the glyph. + /// You should generally prefer to use the [`ShapedLine::paint`] or [`WrappedLine::paint`] methods in the [`text_system`]. + /// This method is only useful if you need to paint a single emoji that has already been shaped. pub fn paint_emoji( &mut self, origin: Point, @@ -1058,7 +1062,7 @@ impl<'a> ElementContext<'a> { let text_system = self.text_system().clone(); text_system.with_view(view_id, || { if self.window.next_frame.view_stack.last() == Some(&view_id) { - return f(self); + f(self) } else { self.window.next_frame.view_stack.push(view_id); let result = f(self); @@ -1074,7 +1078,7 @@ impl<'a> ElementContext<'a> { let text_system = self.text_system().clone(); text_system.with_view(view_id, || { if self.window.next_frame.view_stack.last() == Some(&view_id) { - return f(self); + f(self) } else { self.window.next_frame.view_stack.push(view_id); self.window