pub struct TaskIndex { /* private fields */ }Expand description
Lazy, thread-safe index of every markdown file that contains tasks.
Files with neither a task nor a marker are deliberately absent rather
than stored empty, which keeps both memory and every query’s iteration
proportional to the notes that actually have something to show. How large a
share of a repository that is depends on the configuration: with markers
enabled a note needs only the word TODO in a sentence to qualify, so the
index is no longer the small minority of files it is with checkboxes alone.
Files matching tasks_ignore_globs are absent too. Excluding them here,
at the one place the index is filled, is what makes the exclusion complete:
the panel, the folder facets, total_matches and every count all derive
from TaskIndex::snapshot.
Implementations§
Source§impl TaskIndex
impl TaskIndex
Sourcepub fn new(ignore_globs: &[String]) -> Self
pub fn new(ignore_globs: &[String]) -> Self
Creates an empty, unbuilt index that excludes files matching
ignore_globs (the tasks_ignore_globs config option).
The patterns are compiled here, once, mirroring Repo::init’s
compiled_ignore_globs: the build walks every markdown file in the
repository, so re-parsing the patterns per file would cost far more than
the matching itself.
A pattern that does not compile is dropped with a warning rather than
refused. Config::validate already
rejects one at startup, so the only way to reach here with a bad pattern
is to bypass config loading entirely.
Sourcepub fn with_markers(ignore_globs: &[String], markers: &[String]) -> Self
pub fn with_markers(ignore_globs: &[String], markers: &[String]) -> Self
TaskIndex::new, additionally indexing the incomplete markers in
markers (the incomplete_markers config option).
An empty slice disables marker scanning, the same equivalence
incomplete_markers = [] already has for the renderer — which is also
how a caller says “highlighting is off”, since a marker with no
highlight has no #mbr-marker-N anchor for the panel to link to.
The rule is compiled here, once, for the reason the ignore globs are:
the build reads every markdown file in the repository, so re-compiling a
regex per file would dwarf the matching. MarkerRule is Send + Sync
(it wraps a Regex), which is what lets the whole index be shared as an
Arc into spawn_blocking.
Sourcepub fn get(&self, abs_path: &Path) -> Option<Arc<FileTasks>>
pub fn get(&self, abs_path: &Path) -> Option<Arc<FileTasks>>
The tasks recorded for one absolute path, if any.
Sourcepub fn snapshot(&self) -> Vec<Arc<FileTasks>>
pub fn snapshot(&self) -> Vec<Arc<FileTasks>>
A cheap snapshot of every indexed file, for querying.
Clones Arcs, not data. Taking a snapshot rather than querying through
a pin guard keeps the guard off the (potentially slow) grouping pass and
gives the query a stable view even if the watcher fires mid-query.
Sourcepub async fn ensure_built(
self: &Arc<Self>,
repo: &Arc<Repo>,
) -> Result<(), TaskIndexError>
pub async fn ensure_built( self: &Arc<Self>, repo: &Arc<Repo>, ) -> Result<(), TaskIndexError>
Builds the index if it has not been built yet.
Idempotent and single-flight: concurrent callers await one build. The
work runs on spawn_blocking because it is a sequential pass of
synchronous file reads.
Individual unreadable files (permissions, invalid UTF-8, oversized) are skipped with a debug log; only a panic in the build task is an error.
Sourcepub fn invalidate_file(
&self,
abs_path: &Path,
event: &ChangeEventType,
repo: &Repo,
)
pub fn invalidate_file( &self, abs_path: &Path, event: &ChangeEventType, repo: &Repo, )
Re-scans (Created/Modified) or drops (Deleted) one file.
No-op when the index has never been built. A change arriving before anybody asked for tasks must not trigger the very build the laziness exists to avoid.
NOTE (known window): a file changed while the initial build is running is skipped here, because the build has not published itself yet, and the build may already have read that file’s previous contents. The entry then stays stale until the file changes again or the process restarts. Closing it would mean either serializing the watcher against the build (blocking edits behind a full-repo read pass) or queueing deferred invalidations forever for the common case where tasks are never opened. Neither is worth it for a window that is bounded by one build.
Call this after Repo::invalidate_file for the same event: the
url/title of a created or modified file are read back out of the repo.
Sourcepub fn rebuild_if_built(&self, repo: &Repo)
pub fn rebuild_if_built(&self, repo: &Repo)
Re-scans the whole repository, but only if the index was already built.
The watcher calls this on its full-rescan path (a change batch too large
to patch file by file), where per-file invalidation would cost more than
one read pass. Like Self::invalidate_file it does nothing when the
index has never been built, so an unused task index stays free.
Entries are replaced and stale ones pruned in a single pass at the end, so a concurrent query never observes a half-empty index — only the old contents or the new ones.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for TaskIndex
impl !RefUnwindSafe for TaskIndex
impl Send for TaskIndex
impl Sync for TaskIndex
impl Unpin for TaskIndex
impl UnsafeUnpin for TaskIndex
impl UnwindSafe for TaskIndex
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> 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);