diff --git a/crates/typst-ide/src/complete.rs b/crates/typst-ide/src/complete.rs index 946795521..a05be9f83 100644 --- a/crates/typst-ide/src/complete.rs +++ b/crates/typst-ide/src/complete.rs @@ -1178,7 +1178,7 @@ impl<'a> CompletionContext<'a> { parens: bool, docs: Option<&str>, ) { - let at = label.as_deref().map_or(false, |field| !is_ident(field)); + let at = label.as_deref().is_some_and(|field| !is_ident(field)); let label = label.unwrap_or_else(|| value.repr()); let detail = docs.map(Into::into).or_else(|| match value { diff --git a/crates/typst-pdf/src/outline.rs b/crates/typst-pdf/src/outline.rs index adb0df2f7..a060c175f 100644 --- a/crates/typst-pdf/src/outline.rs +++ b/crates/typst-pdf/src/outline.rs @@ -55,7 +55,7 @@ pub(crate) fn write_outline(ctx: &mut PdfContext) -> Option { // exists), or at most as deep as its actual nesting level in Typst // (not exceeding whichever is the most restrictive depth limit // of those two). - while children.last().map_or(false, |last| { + while children.last().is_some_and(|last| { last_skipped_level.map_or(true, |l| last.level < l) && last.level < leaf.level }) { diff --git a/crates/typst-syntax/src/ast.rs b/crates/typst-syntax/src/ast.rs index df9cef0cc..26a26160f 100644 --- a/crates/typst-syntax/src/ast.rs +++ b/crates/typst-syntax/src/ast.rs @@ -601,12 +601,12 @@ impl<'a> Raw<'a> { let is_whitespace = |line: &&str| line.chars().all(char::is_whitespace); // Trims a sequence of whitespace followed by a newline at the start. - if lines.first().map_or(false, is_whitespace) { + if lines.first().is_some_and(is_whitespace) { lines.remove(0); } // Trims a newline followed by a sequence of whitespace at the end. - if lines.last().map_or(false, is_whitespace) { + if lines.last().is_some_and(is_whitespace) { lines.pop(); } } diff --git a/crates/typst-syntax/src/lexer.rs b/crates/typst-syntax/src/lexer.rs index cd1998a6b..300a83537 100644 --- a/crates/typst-syntax/src/lexer.rs +++ b/crates/typst-syntax/src/lexer.rs @@ -341,7 +341,7 @@ impl Lexer<'_> { fn in_word(&self) -> bool { let wordy = |c: Option| { - c.map_or(false, |c| { + c.is_some_and(|c| { c.is_alphanumeric() && !matches!( c.script(), @@ -538,7 +538,7 @@ impl Lexer<'_> { // Make sure not to confuse a range for the decimal separator. if c != '.' && !self.s.at("..") - && !self.s.scout(1).map_or(false, is_id_start) + && !self.s.scout(1).is_some_and(is_id_start) && self.s.eat_if('.') && base == 10 { @@ -740,7 +740,7 @@ pub fn is_ident(string: &str) -> bool { let mut chars = string.chars(); chars .next() - .map_or(false, |c| is_id_start(c) && chars.all(is_id_continue)) + .is_some_and(|c| is_id_start(c) && chars.all(is_id_continue)) } /// Whether a character can start an identifier. diff --git a/crates/typst-syntax/src/parser.rs b/crates/typst-syntax/src/parser.rs index 0a740b62b..f4bb19e1c 100644 --- a/crates/typst-syntax/src/parser.rs +++ b/crates/typst-syntax/src/parser.rs @@ -1709,7 +1709,7 @@ impl<'s> Parser<'s> { fn unskip(&mut self) { if self.lexer.mode() != LexMode::Markup && self.prev_end != self.current_start { - while self.nodes.last().map_or(false, |last| last.kind().is_trivia()) { + while self.nodes.last().is_some_and(|last| last.kind().is_trivia()) { self.nodes.pop(); } diff --git a/crates/typst/src/engine.rs b/crates/typst/src/engine.rs index a5408d293..f42ea1927 100644 --- a/crates/typst/src/engine.rs +++ b/crates/typst/src/engine.rs @@ -139,7 +139,7 @@ impl<'a> Route<'a> { impl<'a> Route<'a> { /// Whether the given id is part of the route. pub fn contains(&self, id: FileId) -> bool { - self.id == Some(id) || self.outer.map_or(false, |outer| outer.contains(id)) + self.id == Some(id) || self.outer.is_some_and(|outer| outer.contains(id)) } /// Whether the route's depth is less than or equal to the given depth. diff --git a/crates/typst/src/foundations/auto.rs b/crates/typst/src/foundations/auto.rs index 05f776d17..5711b1f6a 100644 --- a/crates/typst/src/foundations/auto.rs +++ b/crates/typst/src/foundations/auto.rs @@ -80,6 +80,17 @@ impl Smart { matches!(self, Self::Custom(_)) } + /// Whether this is a `Smart::Custom(x)` and `f(x)` is true. + pub fn is_custom_and(self, f: F) -> bool + where + F: Fn(T) -> bool, + { + match self { + Self::Auto => false, + Self::Custom(x) => f(x), + } + } + /// Returns a `Smart<&T>` borrowing the inner `T`. pub fn as_ref(&self) -> Smart<&T> { match self { @@ -88,9 +99,12 @@ impl Smart { } } - /// Returns a reference the contained custom value. - /// If the value is [`Smart::Auto`], `None` is returned. - pub fn as_custom(self) -> Option { + /// Returns the contained custom value. + /// + /// If the value is [`Smart::Auto`], returns `None`. + /// + /// Equivalently, this just converts `Smart` to `Option`. + pub fn custom(self) -> Option { match self { Self::Auto => None, Self::Custom(x) => Some(x), diff --git a/crates/typst/src/foundations/datetime.rs b/crates/typst/src/foundations/datetime.rs index faef8f7fb..053aa4226 100644 --- a/crates/typst/src/foundations/datetime.rs +++ b/crates/typst/src/foundations/datetime.rs @@ -306,7 +306,7 @@ impl Datetime { ) -> StrResult { Ok(engine .world - .today(offset.as_custom()) + .today(offset.custom()) .ok_or("unable to get the current date")?) } diff --git a/crates/typst/src/foundations/selector.rs b/crates/typst/src/foundations/selector.rs index d97c3408a..747ae1a96 100644 --- a/crates/typst/src/foundations/selector.rs +++ b/crates/typst/src/foundations/selector.rs @@ -140,7 +140,7 @@ impl Selector { Self::Label(label) => target.label() == Some(*label), Self::Regex(regex) => target .to_packed::() - .map_or(false, |elem| regex.is_match(elem.text())), + .is_some_and(|elem| regex.is_match(elem.text())), Self::Can(cap) => target.func().can_type_id(*cap), Self::Or(selectors) => { selectors.iter().any(move |sel| sel.matches(target, styles)) diff --git a/crates/typst/src/foundations/str.rs b/crates/typst/src/foundations/str.rs index 48b5baf4f..e1c5d8b09 100644 --- a/crates/typst/src/foundations/str.rs +++ b/crates/typst/src/foundations/str.rs @@ -114,7 +114,7 @@ impl Str { .and_then(|v| usize::try_from(v).ok()) .filter(|&v| v <= self.0.len()); - if resolved.map_or(false, |i| !self.0.is_char_boundary(i)) { + if resolved.is_some_and(|i| !self.0.is_char_boundary(i)) { return Err(not_a_char_boundary(index)); } @@ -308,7 +308,7 @@ impl Str { ) -> bool { match pattern { StrPattern::Str(pat) => self.0.starts_with(pat.as_str()), - StrPattern::Regex(re) => re.find(self).map_or(false, |m| m.start() == 0), + StrPattern::Regex(re) => re.find(self).is_some_and(|m| m.start() == 0), } } diff --git a/crates/typst/src/foundations/styles.rs b/crates/typst/src/foundations/styles.rs index 07793e82c..95fb96fc0 100644 --- a/crates/typst/src/foundations/styles.rs +++ b/crates/typst/src/foundations/styles.rs @@ -381,7 +381,7 @@ impl Recipe { pub fn applicable(&self, target: &Content, styles: StyleChain) -> bool { self.selector .as_ref() - .map_or(false, |selector| selector.matches(target, Some(styles))) + .is_some_and(|selector| selector.matches(target, Some(styles))) } /// Apply the recipe to the given content. diff --git a/crates/typst/src/introspection/counter.rs b/crates/typst/src/introspection/counter.rs index 5c3e573ae..121611a2f 100644 --- a/crates/typst/src/introspection/counter.rs +++ b/crates/typst/src/introspection/counter.rs @@ -367,7 +367,7 @@ impl Counter { styles: Option, ) -> SourceResult { let numbering = numbering - .as_custom() + .custom() .or_else(|| { let styles = styles?; let CounterKey::Selector(Selector::Elem(func, _)) = self.0 else { diff --git a/crates/typst/src/layout/flow.rs b/crates/typst/src/layout/flow.rs index 662cf6804..5023ec244 100644 --- a/crates/typst/src/layout/flow.rs +++ b/crates/typst/src/layout/flow.rs @@ -493,7 +493,7 @@ impl<'a> FlowLayouter<'a> { while self .items .last() - .map_or(false, |item| matches!(item, FlowItem::Absolute(_, true))) + .is_some_and(|item| matches!(item, FlowItem::Absolute(_, true))) { self.items.pop(); } @@ -685,7 +685,7 @@ impl FlowLayouter<'_> { // together). if !force && (k == 0 || movable) - && frames.first().map_or(false, Frame::is_empty) + && frames.first().is_some_and(Frame::is_empty) { // Remove existing footnotes attempts because we need to // move the item to the next page. diff --git a/crates/typst/src/layout/inline/linebreak.rs b/crates/typst/src/layout/inline/linebreak.rs index 3c3416ed4..a62cda910 100644 --- a/crates/typst/src/layout/inline/linebreak.rs +++ b/crates/typst/src/layout/inline/linebreak.rs @@ -78,7 +78,7 @@ pub(super) fn breakpoints<'a>( let (link, _) = link_prefix(tail); let end = last + link.len(); linebreak_link(link, |i| f(last + i, Breakpoint::Normal)); - while iter.peek().map_or(false, |&p| p < end) { + while iter.peek().is_some_and(|&p| p < end) { iter.next(); } } diff --git a/crates/typst/src/layout/inline/mod.rs b/crates/typst/src/layout/inline/mod.rs index f579b8a3a..2802bbcb2 100644 --- a/crates/typst/src/layout/inline/mod.rs +++ b/crates/typst/src/layout/inline/mod.rs @@ -655,7 +655,7 @@ fn add_cjk_latin_spacing(items: &mut [Item]) { }); // Case 1: CJ followed by a Latin character - if glyph.is_cj_script() && next.map_or(false, |g| g.is_letter_or_number()) { + if glyph.is_cj_script() && next.is_some_and(|g| g.is_letter_or_number()) { // The spacing is default to 1/4 em, and can be shrunk to 1/8 em. glyph.x_advance += Em::new(0.25); glyph.adjustability.shrinkability.1 += Em::new(0.125); @@ -663,7 +663,7 @@ fn add_cjk_latin_spacing(items: &mut [Item]) { } // Case 2: Latin followed by a CJ character - if glyph.is_cj_script() && prev.map_or(false, |g| g.is_letter_or_number()) { + if glyph.is_cj_script() && prev.is_some_and(|g| g.is_letter_or_number()) { glyph.x_advance += Em::new(0.25); glyph.x_offset += Em::new(0.25); glyph.adjustability.shrinkability.0 += Em::new(0.125); @@ -1374,7 +1374,7 @@ fn reorder<'a>(line: &'a Line<'a>) -> (Vec<&Item<'a>>, bool) { // Compute the reordered ranges in visual order (left to right). let (levels, runs) = line.bidi.visual_runs(para, line.trimmed.clone()); - let starts_rtl = levels.first().map_or(false, |level| level.is_rtl()); + let starts_rtl = levels.first().is_some_and(|level| level.is_rtl()); // Collect the reordered items. for run in runs { diff --git a/crates/typst/src/layout/inline/shaping.rs b/crates/typst/src/layout/inline/shaping.rs index 6b1e2e93d..b558d5adf 100644 --- a/crates/typst/src/layout/inline/shaping.rs +++ b/crates/typst/src/layout/inline/shaping.rs @@ -680,7 +680,7 @@ fn shape_segment<'a>( let mut buffer = UnicodeBuffer::new(); buffer.push_str(text); buffer.set_language(language(ctx.styles)); - if let Some(script) = TextElem::script_in(ctx.styles).as_custom().and_then(|script| { + if let Some(script) = TextElem::script_in(ctx.styles).custom().and_then(|script| { rustybuzz::Script::from_iso15924_tag(Tag::from_bytes(script.as_bytes())) }) { buffer.set_script(script) @@ -751,7 +751,7 @@ fn shape_segment<'a>( } else { // First, search for the end of the tofu sequence. let k = i; - while infos.get(i + 1).map_or(false, |info| info.glyph_id == 0) { + while infos.get(i + 1).is_some_and(|info| info.glyph_id == 0) { i += 1; } @@ -781,7 +781,7 @@ fn shape_segment<'a>( // Trim half-baked cluster. let remove = base + start..base + end; - while ctx.glyphs.last().map_or(false, |g| remove.contains(&g.range.start)) { + while ctx.glyphs.last().is_some_and(|g| remove.contains(&g.range.start)) { ctx.glyphs.pop(); } @@ -866,7 +866,7 @@ fn track_and_space(ctx: &mut ShapingContext) { if glyphs .peek() - .map_or(false, |next| glyph.range.start != next.range.start) + .is_some_and(|next| glyph.range.start != next.range.start) { glyph.x_advance += tracking; } diff --git a/crates/typst/src/layout/page.rs b/crates/typst/src/layout/page.rs index 04e7dd60d..f5727d57e 100644 --- a/crates/typst/src/layout/page.rs +++ b/crates/typst/src/layout/page.rs @@ -360,7 +360,7 @@ impl Packed { let two_sided = margin.two_sided.unwrap_or(false); let margin = margin .sides - .map(|side| side.and_then(Smart::as_custom).unwrap_or(default)) + .map(|side| side.and_then(Smart::custom).unwrap_or(default)) .resolve(styles) .relative_to(size); diff --git a/crates/typst/src/layout/place.rs b/crates/typst/src/layout/place.rs index 61b07308d..176eaf472 100644 --- a/crates/typst/src/layout/place.rs +++ b/crates/typst/src/layout/place.rs @@ -101,7 +101,7 @@ impl Packed { let alignment = self.alignment(styles); if float - && alignment.map_or(false, |align| { + && alignment.is_custom_and(|align| { matches!(align.y(), None | Some(VAlignment::Horizon)) }) { diff --git a/crates/typst/src/math/spacing.rs b/crates/typst/src/math/spacing.rs index 1e8090168..6f3dc8ccc 100644 --- a/crates/typst/src/math/spacing.rs +++ b/crates/typst/src/math/spacing.rs @@ -31,8 +31,7 @@ pub(super) fn spacing( let width = size_ref.font_size().map_or(Abs::zero(), |size| v.at(size)); Some(SpacingFragment { width, weak: false }.into()) }; - let script = - |f: &MathFragment| f.math_size().map_or(false, |s| s <= MathSize::Script); + let script = |f: &MathFragment| f.math_size().is_some_and(|s| s <= MathSize::Script); match (l.class(), r.class()) { // No spacing before punctuation; thin spacing after punctuation, unless diff --git a/crates/typst/src/model/bibliography.rs b/crates/typst/src/model/bibliography.rs index ab14ab497..19fc44ea1 100644 --- a/crates/typst/src/model/bibliography.rs +++ b/crates/typst/src/model/bibliography.rs @@ -779,7 +779,7 @@ impl<'a> Generator<'a> { let citations = self.display_citations(rendered); let references = self.display_references(rendered); let hanging_indent = - rendered.bibliography.as_ref().map_or(false, |b| b.hanging_indent); + rendered.bibliography.as_ref().is_some_and(|b| b.hanging_indent); Ok(Works { citations, references, hanging_indent }) } diff --git a/crates/typst/src/model/outline.rs b/crates/typst/src/model/outline.rs index 355c9c09e..cb8d55638 100644 --- a/crates/typst/src/model/outline.rs +++ b/crates/typst/src/model/outline.rs @@ -231,7 +231,7 @@ impl Show for Packed { while ancestors .last() .and_then(|ancestor| ancestor.with::()) - .map_or(false, |last| last.level() >= *level) + .is_some_and(|last| last.level() >= *level) { ancestors.pop(); } diff --git a/crates/typst/src/realize/behaviour.rs b/crates/typst/src/realize/behaviour.rs index 747ce30c2..533185552 100644 --- a/crates/typst/src/realize/behaviour.rs +++ b/crates/typst/src/realize/behaviour.rs @@ -153,7 +153,7 @@ impl<'a> BehavedBuilder<'a> { // Store a suffix map for the next element if it has the same style // chain. - if iter.peek().map_or(false, |&(_, s2)| s == s2) { + if iter.peek().is_some_and(|&(_, s2)| s == s2) { reuse = Some(suffix.clone()); } diff --git a/crates/typst/src/realize/mod.rs b/crates/typst/src/realize/mod.rs index e9eaae600..5409cc253 100644 --- a/crates/typst/src/realize/mod.rs +++ b/crates/typst/src/realize/mod.rs @@ -161,7 +161,7 @@ impl<'a, 'v, 't> Builder<'a, 'v, 't> { let keep = content .to_packed::() - .map_or(false, |pagebreak| !pagebreak.weak(styles)); + .is_some_and(|pagebreak| !pagebreak.weak(styles)); self.interrupt_page(keep.then_some(styles), false)?; @@ -427,7 +427,7 @@ impl<'a> ParBuilder<'a> { || content.is::() || content .to_packed::() - .map_or(false, |elem| !elem.block(styles)) + .is_some_and(|elem| !elem.block(styles)) || content.is::() { self.0.push(content, styles); diff --git a/crates/typst/src/text/deco.rs b/crates/typst/src/text/deco.rs index 201b80a30..7f0b9e467 100644 --- a/crates/typst/src/text/deco.rs +++ b/crates/typst/src/text/deco.rs @@ -439,7 +439,7 @@ pub(crate) fn decorate( // Only do the costly segments intersection test if the line // intersects the bounding box. - let intersect = bbox.map_or(false, |bbox| { + let intersect = bbox.is_some_and(|bbox| { let y_min = -text.font.to_em(bbox.y_max).at(text.size); let y_max = -text.font.to_em(bbox.y_min).at(text.size); offset >= y_min && offset <= y_max diff --git a/crates/typst/src/text/mod.rs b/crates/typst/src/text/mod.rs index eab010666..13049b12b 100644 --- a/crates/typst/src/text/mod.rs +++ b/crates/typst/src/text/mod.rs @@ -952,7 +952,7 @@ cast! { TextDir, self => self.0.into_value(), v: Smart => { - if v.map_or(false, |dir| dir.axis() == Axis::Y) { + if v.is_custom_and(|dir| dir.axis() == Axis::Y) { bail!("text direction must be horizontal"); } Self(v) diff --git a/crates/typst/src/util/mod.rs b/crates/typst/src/util/mod.rs index 3a81bf553..802399fb8 100644 --- a/crates/typst/src/util/mod.rs +++ b/crates/typst/src/util/mod.rs @@ -152,7 +152,7 @@ pub fn option_eq(left: Option, other: R) -> bool where L: PartialEq, { - left.map_or(false, |v| v == other) + left.is_some_and(|v| v == other) } /// A container around a static reference that is cheap to clone and hash. diff --git a/docs/src/lib.rs b/docs/src/lib.rs index 0bb9fc86b..9ec5b087d 100644 --- a/docs/src/lib.rs +++ b/docs/src/lib.rs @@ -351,7 +351,7 @@ fn func_model( let mut self_ = false; let mut params = func.params().unwrap(); - if params.first().map_or(false, |first| first.name == "self") { + if params.first().is_some_and(|first| first.name == "self") { self_ = true; params = ¶ms[1..]; } diff --git a/docs/src/link.rs b/docs/src/link.rs index f4d803c37..537dee77a 100644 --- a/docs/src/link.rs +++ b/docs/src/link.rs @@ -95,7 +95,7 @@ fn resolve_definition(head: &str, base: &str) -> StrResult { } else if value .clone() .cast::() - .map_or(false, |func| func.param(next).is_some()) + .is_ok_and(|func| func.param(next).is_some()) { route.push_str("#parameters-"); route.push_str(next); diff --git a/tests/src/tests.rs b/tests/src/tests.rs index 2be5bc180..4c3975bbb 100644 --- a/tests/src/tests.rs +++ b/tests/src/tests.rs @@ -805,7 +805,7 @@ fn test_diagnostics<'a>( let mut actual_diagnostics = HashSet::new(); for diagnostic in diagnostics { // Ignore diagnostics from other files. - if diagnostic.span.id().map_or(false, |id| id != source.id()) { + if diagnostic.span.id().is_some_and(|id| id != source.id()) { continue; }