Skip to main content

Crate kimun_core

Crate kimun_core 

Source
Expand description

Core of the Kimün note-taking app: all file operations, indexing, and note manipulation, with no presentation concerns.

The public surface is the NoteVault facade. A vault is a directory of Markdown notes on disk; NoteVault owns the operations over it (create, read, write, rename, search, browse) and is cheap to clone.

A few conventions shape this crate:

  • VaultPath for vault-internal paths. Everything addressed inside the vault uses VaultPath, a case-insensitive, /-separated, OS-agnostic path. OS path types are reserved for configuration values (the workspace root) and for converting back to a real filesystem location when a caller needs one.
  • The index is a cache. Search, backlinks, suggestions, and listings are served from a SQLite index that mirrors the notes on disk. It can be rebuilt at any time from the files, which remain the source of truth.
  • nfs and system own the filesystem. Every direct std::fs/tokio::fs call lives in one of them: nfs for vault-scoped work (notes, addressed by VaultPath) and system for host-scoped work (the app’s own directories, cross-volume moves). The rest of the crate goes through them.

§Example

Create a vault in a temporary directory, write a note, and read it back:

use kimun_core::{NoteVault, SystemPath, VaultConfig};
use kimun_core::nfs::VaultPath;

let dir = tempfile::tempdir().unwrap();
let root = SystemPath::try_absolute(dir.path()).unwrap();
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
    let vault = NoteVault::new(VaultConfig::new(root)).await.unwrap();
    let path = VaultPath::new("/hello.md");
    vault.create_note(&path, "# Hello\n").await.unwrap();
    let text = vault.get_note_text(&path).await.unwrap();
    assert_eq!(text, "# Hello\n");
});

Re-exports§

pub use nfs::saved_searches::saved_search_name_matches;
pub use nfs::saved_searches::SavedSearch;
pub use nfs::vault_id::VaultId;
pub use nfs::EntryKind;
pub use system::Host;
pub use system::SystemPath;

Modules§

error
Error types returned across the crate’s public API.
nfs
Vault-scoped filesystem layer: notes, attachments and backups inside one workspace, addressed by the VaultPath vault-internal path type. Paired with system, which owns host-scoped paths and operations.
note
Note model: parsing Markdown into details, chunks, links, and tags.
system
Host-scoped paths and file operations: the machine kimün runs on, its directories, and the file operations carrying OS-specific knowledge. Host-scoped paths and file operations: the machine kimün runs on.

Structs§

AttachmentDetails
Read-only details of an attachment, for the attachment view: its identity, size, last-modified time, extension, and previewable content.
DirectoryDetails
A directory entry within the vault.
IndexDiff
The diff a vault sync walk produces and NoteIndex::apply consumes in one atomic operation — the currency crossing the index’s interface. The order of to_add and to_modify is non-deterministic: they are populated by parallel walker threads and entries land in the order each thread completes its file read.
IndexFile
A workspace’s index file on this machine — the whole artifact, sidecars included.
IndexReport
Timing summary of an indexing pass.
NoteSuggestion
A note suggestion for the autocomplete popup.
NoteVault
Facade over a vault: a directory of Markdown notes plus its searchable index. Cheap to clone — clones share the index pool and per-note locks.
QueryTokenSpan
One classified span of a query string. range indexes the original string (byte offsets), so spans can be styled in place.
ReplacePreview
Result of a dry-run replace (NoteVault::preview_replace): how many matches would be replaced, and the note’s content after the replacement. Nothing is written to disk.
SearchResult
A single entry produced by browsing the vault: a note, directory, or attachment, identified by its path.
SearchTerms
A search query string decomposed into the typed buckets the index turns into an FTS query. Each prefix in the DSL routes a token into one of these fields; bare tokens are full-text terms. This is the boundary the TUI builds (often via with_order_directive / quote_query_term) and the index consumes, so the DSL syntax lives entirely in core.
TagSuggestion
A tag suggestion for the autocomplete popup. usage_count is computed per-query via COUNT(*) GROUP BY name over the labels table.
VaultBrowseOptions
Options to traverse the Notes You need a sync::mpsc::Sender to use a channel to receive the entries
VaultBrowseOptionsBuilder
Builder for VaultBrowseOptions; see NoteVault::browse_vault.
VaultConfig
Configuration passed to NoteVault::new.

Enums§

AttachmentContent
The previewable content of an attachment.
NoteChange
A note change reported by the NoteIndex the moment it is recorded, for consumers outside core (the RAG client). Thin by design — it carries a path, a content hash, and the kind of change, never chunk text.
NotesValidation
How thoroughly a sync pass checks whether each note has changed before updating its index entry.
OrderBy
A parsed or:/^ order directive: the column to sort by together with its direction. Produced by the query parser when it encounters an order token; OrderField is the direction-free counterpart used by callers that carry the asc/desc choice separately.
OrderField
The field a query can be ordered by. The asc/desc choice is carried separately by callers; this names only the column.
QueryTokenClass
Token class of a span in a query string, for syntax highlighting. Mirrors the grammar QueryTermExtractor::extract_and_consume consumes — the two must stay in step (see the lexer_agrees_with_parser_* tests).
ResultType
Kind of a SearchResult.

Constants§

DEFAULT_ASSETS_PATH
Default directory for attachments (see NoteVault::default_attachments_path).
DEFAULT_INBOX_PATH
Default directory for quick-capture notes (see NoteVault::quick_note).
DEFAULT_JOURNAL_PATH
Default directory for journal entries, one note per day.
MAX_CONFLICT_ATTEMPTS
How many incremented names (VaultPath::get_name_on_conflict) a conflict-avoiding create tries before giving up. High enough that no real vault reaches it, low enough to bound the work when something pathological (a name every increment collides with) would otherwise spin forever. Shared by NoteVault::free_note_path and NoteVault::create_note_avoiding_conflicts so the name they pick agrees.

Traits§

IndexObserver
Observer of index mutations, registered zero-or-one on a vault via NoteVault::set_index_observer. The index calls on_change synchronously right after a write commits, so an implementation must be cheap and non-blocking — no network, no await; fold the event into a queue and drain it elsewhere.

Functions§

expand_bare_note_prefixes
Return query with every bare note-targeting prefix — < / > / =, their long forms lk: / fwd: / name:, and the - exclusion variants — expanded to <prefix><target>. A prefix is bare when the whole token is exactly the prefix. Tokenization follows the parser’s grammar: an unquoted token ends at an ASCII space (only — a tab or NBSP is part of the token, exactly as the parser reads it), a quote is honored only at a value start (the start of a token or right after a prefix), and a quoted value may span spaces. Everything else, including whitespace, is preserved verbatim, so the result is the same query with only the bare prefixes rewritten.
query_has_unterminated_quote
True if query ends in an unterminated quoted value — the only real parse error the lenient grammar produces (the parser silently drops the rest of the string).
query_token_spans
Lex query into classified spans for syntax highlighting. Whitespace is not covered by any span. The lexer follows the parser’s grammar exactly: tokens split on ASCII space, a prefix is recognized at a token start, a quote is honored only at a value start, and an unterminated quote swallows the rest of the string (classified QueryTokenClass::Unterminated).
quote_query_term
Wrap term in the search DSL’s quote characters when it contains whitespace, so a multi-word value (e.g. a note name with spaces) is parsed as a single token instead of being split across terms. Values without whitespace are returned unchanged. Note names can never contain " (invalid on Windows/macOS/Linux filesystems alike), so no escaping is needed.
strip_order_directive
Return query with any order directive (or:/-or:/^/-^, in any position) removed. Other tokens keep their order; whitespace is normalised to single spaces. The DSL knowledge lives here in core so the TUI never hardcodes the directive syntax.
with_order_directive
Return query with its order directive replaced by field/asc.