pub struct MarkerRule { /* private fields */ }Expand description
The compiled incomplete_markers rule: one shared answer to “is this an
incomplete marker?”, used by the renderer that highlights them and by the
scanner that indexes them.
It is a newtype rather than a bare Regex so that regex stays out of this
crate’s public API, and so the two consumers cannot drift apart into two
notions of what a marker is.
§Word boundaries
Boundaries are decided per alternative, not once around the group. A
single \b on the whole alternation demands a word character on the far
side of every marker, whatever the marker ends with — so a marker configured
as TODO: would never match TODO: foo, because the byte after the colon is
a space. Symmetrically, a leading \b would stop @todo from matching at the
start of a line, and would demand a word character before the @. So a
\b is prefixed only when the marker’s first character is word-ish and
suffixed only when its last one is, where word-ish means
char::is_alphanumeric() || c == '_' — the definition the regex crate’s own
Unicode \b uses.
§Longest match
The regex crate’s alternation is leftmost-first, not leftmost-longest: in
TODO|TODOMAYBE the shorter branch would win. Alternatives are therefore
sorted longest-first at construction, which makes the result independent of
the order the markers appear in the configuration file.
§No prefilter
There is deliberately no hand-rolled pre-check of the kind [might_be_task]
performs. The two situations are not the same. [might_be_task] exists to
keep [TASK_LINE] off the regex crate’s capture-tracking engine, which is
the slow one — roughly 710ns against 70ns, as documented on [TASK_LINE]. A
MarkerRule search captures nothing, so it runs on the meta engine, which
already extracts the literal alternation and drives a SIMD prefilter over it.
A second prefilter in front of that would duplicate work the regex crate does
better, and would have to be kept in agreement with the boundary rules above.
Implementations§
Source§impl MarkerRule
impl MarkerRule
Sourcepub fn new(markers: &[String]) -> Option<Self>
pub fn new(markers: &[String]) -> Option<Self>
Compiles a rule from the configured markers, or returns None when there
is nothing to match.
Empty entries are dropped, so incomplete_markers = [""] is the same off
switch as incomplete_markers = [] — and None is the signal to skip the
pass entirely rather than to run a pattern that matches everywhere.
Markers are regex::escaped, so a marker containing metacharacters
(FIXME() is matched literally instead of breaking compilation.
Sourcepub fn cached(markers: &[String]) -> Option<Arc<Self>>
pub fn cached(markers: &[String]) -> Option<Arc<Self>>
MarkerRule::new, memoised on the marker list that produced it.
Use this on any path that runs per file or per request. Compiling the
pattern costs ~80µs — three to four times what rendering a small page
costs in total — because the regex crate builds an NFA, a lazy DFA and a
literal prefilter. The render pipeline needs a rule for every page it
renders, and mark_incomplete is on by default in server and GUI mode,
so compiling per render put that 80µs on the default path for every
request. (Callers that build a rule once and keep it — TaskIndex does
— should keep calling MarkerRule::new and own the result.)
Keyed by the marker list rather than held in a plain OnceLock because a
single process legitimately renders with more than one configuration: the
test suite does it constantly, and nothing stops a GUI from opening two
repositories whose .mbr/config.toml disagree. A None result is cached
too, so a marker list that cannot compile is not retried per page.
Entries are never evicted. The key space is the set of distinct
incomplete_markers values a process ever sees — one in production, a
handful under test — so there is nothing to bound.
Sourcepub fn block_initial_match(&self, text: &str) -> Option<usize>
pub fn block_initial_match(&self, text: &str) -> Option<usize>
Byte length of the marker text begins with, or None when it begins
with something else.
This is the renderer’s block-initial test, and the direct replacement for
the old ^(?:M1|M2)\b pattern.
Sourcepub fn find_iter<'t>(
&'t self,
text: &'t str,
) -> impl Iterator<Item = Range<usize>> + 't
pub fn find_iter<'t>( &'t self, text: &'t str, ) -> impl Iterator<Item = Range<usize>> + 't
Every marker in text, as byte ranges, ascending and non-overlapping.
Sourcepub fn find_in_line(&self, line: &str) -> Option<usize>
pub fn find_in_line(&self, line: &str) -> Option<usize>
Byte offset of the first marker in a raw source line that a reader would
actually see, or None when the line has none.
Unlike MarkerRule::find_iter this understands markdown: a marker
inside a code span, a wikilink target, a link destination or title, an
autolink or a reference definition does not count. See [MarkupCursor].
Trait Implementations§
Source§impl Clone for MarkerRule
impl Clone for MarkerRule
Auto Trait Implementations§
impl Freeze for MarkerRule
impl RefUnwindSafe for MarkerRule
impl Send for MarkerRule
impl Sync for MarkerRule
impl Unpin for MarkerRule
impl UnsafeUnpin for MarkerRule
impl UnwindSafe for MarkerRule
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);