Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add metrics to attributes #257

Merged
merged 6 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/rich-text/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ fn set_buffer_text<'a>(buffer: &mut BorrowedWithFontSystem<'a, Buffer>) {
let comic_attrs = attrs.family(Family::Name("Comic Neue"));

let spans: &[(&str, Attrs)] = &[
("Font size 64 ", attrs.metrics(Metrics::relative(64.0, 1.2))),
("Font size 8 ", attrs.metrics(Metrics::relative(8.0, 1.2))),
("Font size 20 ", attrs.metrics(Metrics::relative(20.0, 1.2))),
("Font size 14 ", attrs.metrics(Metrics::relative(14.0, 1.2))),
(
"Font size 48\n",
attrs.metrics(Metrics::relative(48.0, 1.2)),
),
("B", attrs.weight(Weight::BOLD)),
("old ", attrs),
("I", attrs.style(Style::Italic)),
Expand Down
39 changes: 38 additions & 1 deletion src/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use core::ops::Range;
use rangemap::RangeMap;

use crate::CacheKeyFlags;
use crate::{CacheKeyFlags, Metrics};

pub use fontdb::{Family, Stretch, Style, Weight};

Expand Down Expand Up @@ -101,6 +101,32 @@
}
}

/// Metrics, but implementing Eq and Hash using u32 representation of f32
//TODO: what are the edge cases of this?
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct CacheMetrics {
pub font_size_bits: u32,
jackpot51 marked this conversation as resolved.
Show resolved Hide resolved
pub line_height_bits: u32,
}

impl From<Metrics> for CacheMetrics {
fn from(metrics: Metrics) -> Self {
Self {
font_size_bits: metrics.font_size.to_bits(),
line_height_bits: metrics.line_height.to_bits(),
}
}
}

impl From<CacheMetrics> for Metrics {
fn from(metrics: CacheMetrics) -> Self {
Self {
font_size: f32::from_bits(metrics.font_size_bits),
line_height: f32::from_bits(metrics.line_height_bits),
}
}
}

/// Text attributes
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Attrs<'a> {
Expand All @@ -112,6 +138,7 @@
pub weight: Weight,
pub metadata: usize,
pub cache_key_flags: CacheKeyFlags,
pub metrics_opt: Option<CacheMetrics>,
}

impl<'a> Attrs<'a> {
Expand All @@ -127,6 +154,7 @@
weight: Weight::NORMAL,
metadata: 0,
cache_key_flags: CacheKeyFlags::empty(),
metrics_opt: None,
}
}

Expand Down Expand Up @@ -172,6 +200,12 @@
self
}

/// Set [`Metrics`], overriding values in buffer
pub fn metrics(mut self, metrics: Metrics) -> Self {
self.metrics_opt = Some(metrics.into());
self
}

/// Check if font matches
pub fn matches(&self, face: &fontdb::FaceInfo) -> bool {
//TODO: smarter way of including emoji
Expand Down Expand Up @@ -219,6 +253,7 @@
pub weight: Weight,
pub metadata: usize,
pub cache_key_flags: CacheKeyFlags,
pub metrics_opt: Option<CacheMetrics>,
}

impl AttrsOwned {
Expand All @@ -231,6 +266,7 @@
weight: attrs.weight,
metadata: attrs.metadata,
cache_key_flags: attrs.cache_key_flags,
metrics_opt: attrs.metrics_opt,
}
}

Expand All @@ -243,6 +279,7 @@
weight: self.weight,
metadata: self.metadata,
cache_key_flags: self.cache_key_flags,
metrics_opt: self.metrics_opt,
}
}
}
Expand Down Expand Up @@ -300,7 +337,7 @@
}

/// Split attributes list at an offset
pub fn split_off(&mut self, index: usize) -> Self {

Check warning on line 340 in src/attrs.rs

View workflow job for this annotation

GitHub Actions / clippy

docs for function which may panic missing `# Panics` section

warning: docs for function which may panic missing `# Panics` section --> src/attrs.rs:340:5 | 340 | pub fn split_off(&mut self, index: usize) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here --> src/attrs.rs:356:34 | 356 | let (range, attrs) = self | __________________________________^ 357 | | .spans 358 | | .get_key_value(&key.start) 359 | | .map(|v| (v.0.clone(), v.1.clone())) 360 | | .expect("attrs span not found"); | |_______________________________________________^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc note: the lint level is defined here --> src/lib.rs:88:9 | 88 | #![warn(clippy::missing_panics_doc)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^
let mut new = Self::new(self.defaults.as_attrs());
let mut removes = Vec::new();

Expand Down
96 changes: 39 additions & 57 deletions src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
pub line_y: f32,
/// Y offset to top of line
pub line_top: f32,
/// Y offset to next line
pub line_height: f32,
/// Width of line
pub line_w: f32,
}
Expand All @@ -35,7 +37,7 @@
/// and `cursor_end` within this run, or None if the cursor range does not intersect this run.
/// This may return widths of zero if `cursor_start == cursor_end`, if the run is empty, or if the
/// region's left start boundary is the same as the cursor's end boundary or vice versa.
pub fn highlight(&self, cursor_start: Cursor, cursor_end: Cursor) -> Option<(f32, f32)> {

Check warning on line 40 in src/buffer.rs

View workflow job for this annotation

GitHub Actions / clippy

docs for function which may panic missing `# Panics` section

warning: docs for function which may panic missing `# Panics` section --> src/buffer.rs:40:5 | 40 | pub fn highlight(&self, cursor_start: Cursor, cursor_end: Cursor) -> Option<(f32, f32)> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here --> src/buffer.rs:62:25 | 62 | let x_end = x_end.expect("end of cursor not found"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc
let mut x_start = None;
let mut x_end = None;
let rtl_factor = if self.rtl { 1. } else { 0. };
Expand Down Expand Up @@ -92,54 +94,25 @@
buffer: &'b Buffer,
line_i: usize,
layout_i: usize,
remaining_len: usize,
total_layout: i32,
line_top: f32,
}

impl<'b> LayoutRunIter<'b> {
pub fn new(buffer: &'b Buffer) -> Self {
let total_layout_lines: usize = buffer
.lines
.iter()
.skip(buffer.scroll.line)
.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.layout.try_into().unwrap_or_default());
let maximum_lines = if buffer.metrics.line_height == 0.0 {
0
} else {
(buffer.height / buffer.metrics.line_height) as i32
};
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: buffer.scroll.line,
layout_i: 0,
remaining_len: bottom_cropped_layout_lines,
total_layout: 0,
line_top: 0.0,
}
}
}

impl<'b> Iterator for LayoutRunIter<'b> {
type Item = LayoutRun<'b>;

fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining_len, Some(self.remaining_len))
}

fn next(&mut self) -> Option<Self::Item> {
while let Some(line) = self.buffer.lines.get(self.line_i) {
let shape = line.shape_opt().as_ref()?;
Expand All @@ -153,30 +126,33 @@
continue;
}

let line_top = self
.total_layout
.saturating_sub(self.buffer.scroll.layout)
.saturating_sub(1) as f32
* self.buffer.metrics.line_height;
let mut line_height = self.buffer.metrics.line_height;
for glyph in layout_line.glyphs.iter() {
if let Some(glyph_line_height) = glyph.line_height_opt {
line_height = line_height.max(glyph_line_height);
}
}

let line_top = self.line_top;
let glyph_height = layout_line.max_ascent + layout_line.max_descent;
let centering_offset = (self.buffer.metrics.line_height - glyph_height) / 2.0;
let centering_offset = (line_height - glyph_height) / 2.0;
let line_y = line_top + centering_offset + layout_line.max_ascent;

if line_top + centering_offset > self.buffer.height {
return None;
}

return self.remaining_len.checked_sub(1).map(|num| {
self.remaining_len = num;
LayoutRun {
line_i: self.line_i,
text: line.text(),
rtl: shape.rtl,
glyphs: &layout_line.glyphs,
line_y,
line_top,
line_w: layout_line.w,
}
self.line_top += line_height;

return Some(LayoutRun {
line_i: self.line_i,
text: line.text(),
rtl: shape.rtl,
glyphs: &layout_line.glyphs,
line_y,
line_top,
line_height,
line_w: layout_line.w,
});
}
self.line_i += 1;
Expand All @@ -187,8 +163,6 @@
}
}

impl<'b> ExactSizeIterator for LayoutRunIter<'b> {}

/// Metrics of text
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Metrics {
Expand All @@ -199,13 +173,23 @@
}

impl Metrics {
/// Create metrics with given font size and line height
pub const fn new(font_size: f32, line_height: f32) -> Self {
Self {
font_size,
line_height,
}
}

/// Create metrics with given font size and calculate line height using relative scale
pub fn relative(font_size: f32, line_height_scale: f32) -> Self {
Self {
font_size,
line_height: font_size * line_height_scale,
}
}

/// Scale font size and line height
pub fn scale(self, scale: f32) -> Self {
Self {
font_size: self.font_size * scale,
Expand All @@ -223,7 +207,7 @@
/// A buffer of text that is shaped and laid out
#[derive(Debug)]
pub struct Buffer {
/// [BufferLine]s (or paragraphs) of text in the buffer

Check warning on line 210 in src/buffer.rs

View workflow job for this annotation

GitHub Actions / clippy

item in documentation is missing backticks

warning: item in documentation is missing backticks --> src/buffer.rs:210:10 | 210 | /// [BufferLine]s (or paragraphs) of text in the buffer | ^^^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown note: the lint level is defined here --> src/lib.rs:84:9 | 84 | #![warn(clippy::doc_markdown)] | ^^^^^^^^^^^^^^^^^^^^ help: try | 210 | /// [`BufferLine`]s (or paragraphs) of text in the buffer | ~~~~~~~~~~~~
pub lines: Vec<BufferLine>,
metrics: Metrics,
width: f32,
Expand Down Expand Up @@ -328,12 +312,12 @@
}

/// Shape lines until cursor, also scrolling to include cursor in view
pub fn shape_until_cursor(
&mut self,
font_system: &mut FontSystem,
cursor: Cursor,
prune: bool,
) {

Check warning on line 320 in src/buffer.rs

View workflow job for this annotation

GitHub Actions / clippy

docs for function which may panic missing `# Panics` section

warning: docs for function which may panic missing `# Panics` section --> src/buffer.rs:315:5 | 315 | / pub fn shape_until_cursor( 316 | | &mut self, 317 | | font_system: &mut FontSystem, 318 | | cursor: Cursor, 319 | | prune: bool, 320 | | ) { | |_____^ | note: first possible panic found here --> src/buffer.rs:323:29 | 323 | let layout_cursor = self | _____________________________^ 324 | | .layout_cursor(font_system, cursor) 325 | | .expect("shape_until_cursor invalid cursor"); | |________________________________________________________^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc
let old_scroll = self.scroll;

let layout_cursor = self
Expand Down Expand Up @@ -404,7 +388,7 @@
}

/// Shape lines until scroll
pub fn shape_until_scroll(&mut self, font_system: &mut FontSystem, prune: bool) {

Check warning on line 391 in src/buffer.rs

View workflow job for this annotation

GitHub Actions / clippy

docs for function which may panic missing `# Panics` section

warning: docs for function which may panic missing `# Panics` section --> src/buffer.rs:391:5 | 391 | pub fn shape_until_scroll(&mut self, font_system: &mut FontSystem, prune: bool) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here --> src/buffer.rs:429:30 | 429 | let layout = self | ______________________________^ 430 | | .line_layout(font_system, line_i) 431 | | .expect("shape_until_scroll invalid line"); | |______________________________________________________________^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc
let old_scroll = self.scroll;

loop {
Expand Down Expand Up @@ -788,21 +772,19 @@
#[cfg(all(feature = "std", not(target_arch = "wasm32")))]
let instant = std::time::Instant::now();

let font_size = self.metrics.font_size;
let line_height = self.metrics.line_height;

let mut new_cursor_opt = None;

let mut runs = self.layout_runs().peekable();
let mut first_run = true;
while let Some(run) = runs.next() {
let line_y = run.line_y;
let line_top = run.line_top;
let line_height = run.line_height;

if first_run && y < line_y - font_size {
if first_run && y < line_top {
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_top && y < line_top + line_height {
let mut new_cursor_glyph = run.glyphs.len();
let mut new_cursor_char = 0;
let mut new_cursor_affinity = Affinity::After;
Expand Down Expand Up @@ -1118,7 +1100,7 @@
)?;
}
Motion::Vertical(px) => {
// TODO more efficient
// TODO more efficient, use layout run line height
let lines = px / self.metrics().line_height as i32;
match lines.cmp(&0) {
cmp::Ordering::Less => {
Expand Down
2 changes: 1 addition & 1 deletion src/edit/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@
F: FnMut(i32, i32, u32, u32, Color),
{
self.with_buffer(|buffer| {
let line_height = buffer.metrics().line_height;
for run in buffer.layout_runs() {
let line_i = run.line_i;
let line_y = run.line_y;
let line_top = run.line_top;
let line_height = run.line_height;

let cursor_glyph_opt = |cursor: &Cursor| -> Option<(usize, f32)> {
if cursor.line == line_i {
Expand Down Expand Up @@ -518,17 +518,17 @@

fn apply_change(&mut self, change: &Change) -> bool {
// Cannot apply changes if there is a pending change
match self.change.take() {
Some(pending) => {
if !pending.items.is_empty() {
//TODO: is this a good idea?
log::warn!("pending change caused apply_change to be ignored!");
self.change = Some(pending);
return false;
}
}
None => {}
}

Check warning on line 531 in src/edit/editor.rs

View workflow job for this annotation

GitHub Actions / clippy

you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`

warning: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` --> src/edit/editor.rs:521:9 | 521 | / match self.change.take() { 522 | | Some(pending) => { 523 | | if !pending.items.is_empty() { 524 | | //TODO: is this a good idea? ... | 530 | | None => {} 531 | | } | |_________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_match = note: `#[warn(clippy::single_match)]` on by default help: try | 521 ~ if let Some(pending) = self.change.take() { 522 + if !pending.items.is_empty() { 523 + //TODO: is this a good idea? 524 + log::warn!("pending change caused apply_change to be ignored!"); 525 + self.change = Some(pending); 526 + return false; 527 + } 528 + } |

for item in change.items.iter() {
//TODO: edit cursor if needed?
Expand Down
2 changes: 1 addition & 1 deletion src/edit/vi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,12 @@

/// Load text from a file, and also set syntax to the best option
#[cfg(feature = "std")]
pub fn load_text<P: AsRef<std::path::Path>>(
&mut self,
font_system: &mut FontSystem,
path: P,
attrs: crate::Attrs,
) -> std::io::Result<()> {

Check warning on line 218 in src/edit/vi.rs

View workflow job for this annotation

GitHub Actions / clippy

docs for function returning `Result` missing `# Errors` section

warning: docs for function returning `Result` missing `# Errors` section --> src/edit/vi.rs:213:5 | 213 | / pub fn load_text<P: AsRef<std::path::Path>>( 214 | | &mut self, 215 | | font_system: &mut FontSystem, 216 | | path: P, 217 | | attrs: crate::Attrs, 218 | | ) -> std::io::Result<()> { | |____________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc note: the lint level is defined here --> src/lib.rs:86:9 | 86 | #![warn(clippy::missing_errors_doc)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^
self.editor.load_text(font_system, path, attrs)
}

Expand Down Expand Up @@ -312,11 +312,11 @@
let size = buffer.size();
f(0, 0, size.0 as u32, size.1 as u32, background_color);
let font_size = buffer.metrics().font_size;
let line_height = buffer.metrics().line_height;
for run in buffer.layout_runs() {
let line_i = run.line_i;
let line_y = run.line_y;
let line_top = run.line_top;
let line_height = run.line_height;

let cursor_glyph_opt = |cursor: &Cursor| -> Option<(usize, f32, f32)> {
//TODO: better calculation of width
Expand Down Expand Up @@ -642,10 +642,10 @@
}
};

let has_selection = match editor.selection() {
Selection::None => false,
_ => true,
};

Check warning on line 648 in src/edit/vi.rs

View workflow job for this annotation

GitHub Actions / clippy

match expression looks like `matches!` macro

warning: match expression looks like `matches!` macro --> src/edit/vi.rs:645:29 | 645 | let has_selection = match editor.selection() { | _____________________________^ 646 | | Selection::None => false, 647 | | _ => true, 648 | | }; | |_________^ help: try: `!matches!(editor.selection(), Selection::None)` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro = note: `#[warn(clippy::match_like_matches_macro)]` on by default

self.parser.parse(key, has_selection, |event| {
log::debug!(" Event {:?}", event);
Expand Down Expand Up @@ -876,16 +876,16 @@
editor.with_buffer(|buffer| {
let text = buffer.lines[cursor.line].text();
if cursor.index < text.len() {
match text[cursor.index..]
.char_indices()
.filter(|&(i, c)| i > 0 && c == find_c)
.next()

Check warning on line 882 in src/edit/vi.rs

View workflow job for this annotation

GitHub Actions / clippy

called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead

warning: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead --> src/edit/vi.rs:879:43 | 879 | ... match text[cursor.index..] | _____________________________^ 880 | | ... .char_indices() 881 | | ... .filter(|&(i, c)| i > 0 && c == find_c) 882 | | ... .next() | |_________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#filter_next = note: `#[warn(clippy::filter_next)]` on by default help: try | 879 ~ match text[cursor.index..] 880 + .char_indices().find(|&(i, c)| i > 0 && c == find_c) |
{
Some((i, _)) => {
cursor.index += i;
}
None => {}
}

Check warning on line 888 in src/edit/vi.rs

View workflow job for this annotation

GitHub Actions / clippy

you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`

warning: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` --> src/edit/vi.rs:879:37 | 879 | / ... match text[cursor.index..] 880 | | ... .char_indices() 881 | | ... .filter(|&(i, c)| i > 0 && c == find_c) 882 | | ... .next() ... | 887 | | ... None => {} 888 | | ... } | |_______________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_match help: try | 879 ~ if let Some((i, _)) = text[cursor.index..] 880 + .char_indices() 881 + .filter(|&(i, c)| i > 0 && c == find_c) 882 + .next() { 883 + cursor.index += i; 884 + } |
}
});
editor.set_cursor(cursor);
Expand Down Expand Up @@ -982,16 +982,16 @@
editor.with_buffer(|buffer| {
let text = buffer.lines[cursor.line].text();
if cursor.index > 0 {
match text[..cursor.index]
.char_indices()
.filter(|&(_, c)| c == find_c)
.last()
{
Some((i, _)) => {
cursor.index = i;
}
None => {}
}

Check warning on line 994 in src/edit/vi.rs

View workflow job for this annotation

GitHub Actions / clippy

you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`

warning: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` --> src/edit/vi.rs:985:37 | 985 | / ... match text[..cursor.index] 986 | | ... .char_indices() 987 | | ... .filter(|&(_, c)| c == find_c) 988 | | ... .last() ... | 993 | | ... None => {} 994 | | ... } | |_______________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_match help: try | 985 ~ if let Some((i, _)) = text[..cursor.index] 986 + .char_indices() 987 + .filter(|&(_, c)| c == find_c) 988 + .last() { 989 + cursor.index = i; 990 + } |
}
});
editor.set_cursor(cursor);
Expand All @@ -1002,24 +1002,24 @@
editor.with_buffer(|buffer| {
let text = buffer.lines[cursor.line].text();
if cursor.index > 0 {
match text[..cursor.index]
.char_indices()
.filter_map(|(i, c)| {
if c == find_c {
let end = i + c.len_utf8();
if end < cursor.index {
return Some(end);
}
}
None
})
.last()
{
Some(i) => {
cursor.index = i;
}
None => {}
}

Check warning on line 1022 in src/edit/vi.rs

View workflow job for this annotation

GitHub Actions / clippy

you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`

warning: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` --> src/edit/vi.rs:1005:37 | 1005 | / ... match text[..cursor.index] 1006 | | ... .char_indices() 1007 | | ... .filter_map(|(i, c)| { 1008 | | ... if c == find_c { ... | 1021 | | ... None => {} 1022 | | ... } | |_______________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#single_match help: try | 1005 ~ if let Some(i) = text[..cursor.index] 1006 + .char_indices() 1007 + .filter_map(|(i, c)| { 1008 + if c == find_c { 1009 + let end = i + c.len_utf8(); 1010 + if end < cursor.index { 1011 + return Some(end); 1012 + } 1013 + } 1014 + None 1015 + }) 1016 + .last() { 1017 + cursor.index = i; 1018 + } |
}
});
editor.set_cursor(cursor);
Expand Down Expand Up @@ -1129,13 +1129,13 @@
let action_opt = editor.with_buffer(|buffer| {
let mut layout_runs = buffer.layout_runs();
if let Some(first) = layout_runs.next() {
if let Some(last) = layout_runs.last() {
Some(Action::Motion(Motion::GotoLine(
(last.line_i + first.line_i) / 2,
)))
} else {
None
}

Check warning on line 1138 in src/edit/vi.rs

View workflow job for this annotation

GitHub Actions / clippy

manual implementation of `Option::map`

warning: manual implementation of `Option::map` --> src/edit/vi.rs:1132:37 | 1132 | / ... if let Some(last) = layout_runs.last() { 1133 | | ... Some(Action::Motion(Motion::GotoLine( 1134 | | ... (last.line_i + first.line_i) / 2, 1135 | | ... ))) 1136 | | ... } else { 1137 | | ... None 1138 | | ... } | |_______________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_map = note: `#[warn(clippy::manual_map)]` on by default help: try | 1132 ~ layout_runs.last().map(|last| Action::Motion(Motion::GotoLine( 1133 + (last.line_i + first.line_i) / 2, 1134 + ))) |
} else {
None
}
Expand Down Expand Up @@ -1164,11 +1164,11 @@
{
/// Load text from a file, and also set syntax to the best option
#[cfg(feature = "std")]
pub fn load_text<P: AsRef<std::path::Path>>(
&mut self,
path: P,
attrs: crate::Attrs,
) -> std::io::Result<()> {

Check warning on line 1171 in src/edit/vi.rs

View workflow job for this annotation

GitHub Actions / clippy

docs for function returning `Result` missing `# Errors` section

warning: docs for function returning `Result` missing `# Errors` section --> src/edit/vi.rs:1167:5 | 1167 | / pub fn load_text<P: AsRef<std::path::Path>>( 1168 | | &mut self, 1169 | | path: P, 1170 | | attrs: crate::Attrs, 1171 | | ) -> std::io::Result<()> { | |____________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc
self.inner.load_text(self.font_system, path, attrs)
}

Expand Down
2 changes: 2 additions & 0 deletions src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
pub end: usize,
/// Font size of the glyph
pub font_size: f32,
/// Line height of the glyph, will override buffer setting
pub line_height_opt: Option<f32>,
/// Font id of the glyph
pub font_id: fontdb::ID,
/// Font id of the glyph
Expand All @@ -26,7 +28,7 @@
pub y: f32,
/// Width of hitbox
pub w: f32,
/// Unicode BiDi embedding level, character is left-to-right if `level` is divisible by 2

Check warning on line 31 in src/layout.rs

View workflow job for this annotation

GitHub Actions / clippy

item in documentation is missing backticks

warning: item in documentation is missing backticks --> src/layout.rs:31:17 | 31 | /// Unicode BiDi embedding level, character is left-to-right if `level` is divisible by 2 | ^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown help: try | 31 | /// Unicode `BiDi` embedding level, character is left-to-right if `level` is divisible by 2 | ~~~~~~
pub level: unicode_bidi::Level,
/// X offset in line
///
Expand Down Expand Up @@ -56,7 +58,7 @@

#[derive(Clone, Debug)]
pub struct PhysicalGlyph {
/// Cache key, see [CacheKey]

Check warning on line 61 in src/layout.rs

View workflow job for this annotation

GitHub Actions / clippy

item in documentation is missing backticks

warning: item in documentation is missing backticks --> src/layout.rs:61:25 | 61 | /// Cache key, see [CacheKey] | ^^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown help: try | 61 | /// Cache key, see [`CacheKey`] | ~~~~~~~~~~
pub cache_key: CacheKey,
/// Integer component of X offset in line
pub x: i32,
Expand Down
Loading
Loading