[−][src]Struct libzettels::Index
The heart of a Zettelkasten is the data representing the interrelations
between the zettels. All that information is bundled in the
Index
. See its Fields
for details.
A YAML-representation of an example Index might look like this:
---
files:
file1.md:
title: File 1
followups: [file2.md]
keywords: [example, first]
links: [subdir/file3.md]
file2.md:
title: File 2
followups: [subdir/file3.md]
keywords: [example, second]
links: []
subdir/file3.md:
title: File 3
followups: []
keywords: [example, third]
links: [file1.md]
timestamp:
secs_since_epoch: 1543078763
nanos_since_epoch: 449322318
The Index provides the functionality necessary to query the Zettelkasten. For that, it offers a
- Basic API, as well as an
- Extended API
Please refer to the API Introduction for info on which to use.
Basic API
Handling the Index itself
Working with Zettels
Inspect Sequences
Inspect Links
Search
Listing
Extended API
All functions of the Basic API plus the following:
Handling the Index itself
Working with Zettels
Inspect Sequences
Fields
files: BTreeMap<PathBuf, Zettel>
A key-value-store containing indexed data about the zettels.
- The keys are paths to the respective zettel file (relative to the root directory of the Zettelkasten).
- The values are
Zettel
s
timestamp: SystemTime
A timestamp that shows when the index was last updated.
Implementations
impl Index
[src]
pub fn new(cfg: &Config) -> Result<Index, Error>
[src]
Creates a new Index
with data contained in
Config
. The actual fields used are:
rootdir
: path to the root directory containing the zettel files.indexingmethod
: theIndexingMethod
used.ignorefile
: path to the gitignore-compatible file telling the program which files in the root directory to ignore.
Note: This really creates a new Index. All files in the root
directory are parsed. If you just want to load (and maybe update) an
existing index, use Index::load
and update
respectively.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::new(&cfg)?;
Note:
- If one of the files is non-text (e.g. an image) it is not added
to the index. An
info
about this is issued to logging. - If one of the files does not contain YAML-metadata, it is added to the
index with the
title
"untitled" and emptyfollowups
andkeywords
. The markdown links (if any) are still parsed andlinks
is populated as usual.
Errors
Error::BadLink
if one of the files in the root directory
links to a target that doesn't exist (both viafollowups
and via markdown link).Error::IgnoreFile
for problems applying an existing ignore file. (A missing ignore file is no problem).Error::Io
wrapping several kinds ofstd::io:Error
, e.g. problems executing grep or ripgrep, problems with the files etc.Error::NormalizePath
if one of the files or a link infollowups
orlinks
can not be expressed relative to the root directoryError::Yaml
when deserializing a Zettel from YAML failed for one of the files (but only if it contains any YAML, at all).
pub fn load(cfg: &Config) -> Result<Index, Error>
[src]
Loads an existing Index
from the file
specified in the indexfile
field of Config
.
Note: This only loads the information contained in the index file.
Changes in the zettel files since last update of the index are not
represented in the index (i.e. since
Index::new()
or
index.update()
were called).
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?;
Errors
Error::Io
for problems reading the index file specified inConfig
's fieldindexfile
.Error::Yaml
when deserializing from YAML failed.
pub fn update(&mut self, cfg: &Config) -> Result<(), Error>
[src]
Updates an existing index using the info contained in the
Config
passed as an argument. Only files
modified after the index' timestamp are inspected.
The actual Config
fields used are:
cfg.rootdir
cfg.ignorefile
cfg.indexingmethod
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let mut index = Index::load(&cfg)?; index.update(&cfg)?;
Note:
- If one of the files is non-text (e.g. an image) it is not added
to the index. An
info
about this is issued to logging. - If one of the files does not contain YAML-metadata, it is added to the
index with the
title
"untitled" and emptyfollowups
andkeywords
. The markdown links (if any) are still parsed andlinks
is populated as usual.
Errors
Error::BadLink
if one of the files links to a target that doesn't exist (both viafollowups
and via markdown link).Error::IgnoreFile
for problems applying an existing ignore file. (A missing ignore file is no problem).Error::Io
wrapping several kinds ofstd::io:Error
, e.g. problems executing grep or ripgrep, problems with the files etc.Error::NormalizePath
if one of the files or a link infollowups
orlinks
can not be expressed relative to the root directoryError::Yaml
when deserializing a Zettel from YAML failed for one of the files (but only if it contains any YAML, at all).
pub fn save(&self, cfg: &Config) -> Result<(), Error>
[src]
Write a YAML-representation to the file specified in the Config
field
indexfile
.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; index.save(&cfg) .expect("Failed to save index to file.");
Errors
Error::Io
for problems with the specified indexfile.Error::Yaml
for problems serializing to YAML.
pub fn get_zettel<P: AsRef<Path>>(&self, key: P) -> Option<&Zettel>
[src]
Returns a reference to the Zettel found at key
.
Returns None
if said key is not present.
The key
is a path to the file relative to root directory.
Internally, this function calls the method
get
of std::collections::BTreeMap
.
See documentation there for details.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; let z1 = index.get_zettel(Path::new("file1.md")); assert!(z1.is_some()); let z1 = z1.unwrap(); assert_eq!(z1.title, "File 1");
pub fn sequences(
&self,
scope: &HashSet<PathBuf>,
cfg_sequence_start: &SequenceStart
) -> HashSet<PathBuf>
[src]
&self,
scope: &HashSet<PathBuf>,
cfg_sequence_start: &SequenceStart
) -> HashSet<PathBuf>
Returns a list of all the sequences the Zettels specified by scope
is
a part of.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; let mut scope = HashSet::new(); scope.insert(PathBuf::from("file1.md")); let sequences = index.sequences(&scope, &cfg.sequencestart);
pub fn zettels_of_sequence<P: AsRef<Path>>(&self, key: P) -> HashSet<PathBuf>
[src]
Using the Zettel specified by key
as an identifier for a sequence, this
function returns a list of all the zettels that belong to that sequence.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; let seq_zettels = index.zettels_of_sequence(PathBuf::from("file1.md"));
pub fn sequence_tree(&self, scope: &HashSet<PathBuf>) -> HashSet<PathBuf>
[src]
Returns a list of zettels that are part of all sequences of which the
zettels specified by scope
are also a part of.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; let mut scope = HashSet::new(); scope.insert(PathBuf::from("file1.md")); let sequence_tree = index.sequence_tree(&scope); assert!(sequence_tree.contains(&PathBuf::from("file1.md"))); assert!(sequence_tree.contains(&PathBuf::from("file2.md"))); assert!(sequence_tree.contains(&PathBuf::from("file3.md"))); assert!(sequence_tree.contains(&PathBuf::from("subdir/file4.md")));
pub fn sequence_tree_whole(&self, scope: &HashSet<PathBuf>) -> HashSet<PathBuf>
[src]
Returns a list of zettels that are part of all sequences of which the
zettels specified by scope
are also a part of, as well as related
sequences.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; let mut scope = HashSet::new(); scope.insert(PathBuf::from("file1.md")); let sequence_tree = index.sequence_tree_whole(&scope); assert!(sequence_tree.contains(&PathBuf::from("file1.md"))); assert!(sequence_tree.contains(&PathBuf::from("file2.md"))); assert!(sequence_tree.contains(&PathBuf::from("file3.md"))); assert!(sequence_tree.contains(&PathBuf::from("subdir/file4.md"))); assert!(sequence_tree.contains(&PathBuf::from("subdir/file5.md")));
pub fn inspect_links(&self, scope: &HashSet<PathBuf>) -> HashSet<PathBuf>
[src]
Collects the outgoing links of a list of zettels specified by
linkers
.
Returns a HashSet
.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; // We want the links of one Zettel: file1.md let mut linkers = HashSet::new(); linkers.insert(PathBuf::from("file1.md")); let links = index.inspect_links(&linkers);
pub fn inspect_incoming_links(
&self,
scope: &HashSet<PathBuf>,
all: bool
) -> HashSet<PathBuf>
[src]
&self,
scope: &HashSet<PathBuf>,
all: bool
) -> HashSet<PathBuf>
Returns a list of zettels that link to the zettels specified by
zettels
. If all
is set to true, only zettels are returned that
link to all specified zettels.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; // We want zettels linking to two Zettels: file2.md and file3.md let mut targets = HashSet::new(); targets.insert(PathBuf::from("file2.md")); targets.insert(PathBuf::from("file3.md")); // What links to either of them? let incoming = index.inspect_incoming_links(&targets, false); assert_eq!(incoming.len(), 3); assert!(incoming.contains(&PathBuf::from("file1.md"))); assert!(incoming.contains(&PathBuf::from("file2.md"))); assert!(incoming.contains(&PathBuf::from("onlies/markdown-only.md"))); // What links to both of them? let incoming = index.inspect_incoming_links(&targets, true); assert_eq!(incoming.len(), 1); assert!(incoming.contains(&PathBuf::from("file1.md")));
pub fn search_keywords(
&self,
searched_keywords: Vec<String>,
all: bool
) -> HashSet<PathBuf>
[src]
&self,
searched_keywords: Vec<String>,
all: bool
) -> HashSet<PathBuf>
Takes a vector of Strings, containing keywords to be searched for.
Returns a list of zettels that have one or – if all
is true – all
of these keywords.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; let searched_keywords = vec!["first".to_string()]; let matching_zettels = index.search_keywords(searched_keywords, false); assert_eq!(matching_zettels.len(), 1); assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
pub fn search_title<T: AsRef<str>>(
&self,
search_term: T,
exact: bool
) -> HashSet<PathBuf>
[src]
&self,
search_term: T,
exact: bool
) -> HashSet<PathBuf>
Searches the index for zettels whose title matches search_term
(exactly if exact
is true).
Returns a list of matching zettels.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; let matching_zettels = index.search_title("File 1", false); assert_eq!(matching_zettels.len(), 1); assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
pub fn combi_search<T: AsRef<str>>(
&self,
searched_keywords: Vec<String>,
all: bool,
search_term: T,
exact: bool
) -> HashSet<PathBuf>
[src]
&self,
searched_keywords: Vec<String>,
all: bool,
search_term: T,
exact: bool
) -> HashSet<PathBuf>
Combines searches for keywords and title.
If exact
is true, the title must match search_term
exactly.
If all
is true, only zettels are returned that match all search
criteria.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; let searched_keywords = vec!["first".to_string()]; let matching_zettels = index.combi_search(searched_keywords, true, "File", false); assert_eq!(matching_zettels.len(), 1); assert!(matching_zettels.contains(&PathBuf::from("file1.md")));
pub fn get_keywords(&self) -> HashSet<String>
[src]
Lists all keywords present in the zettels.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; let all_keywords = index.get_keywords(); assert!(all_keywords.contains("test")); assert!(all_keywords.contains("example"));
pub fn count_keywords(&self) -> BTreeMap<String, u32>
[src]
Lists all keywords present in the zettels along with how often they occur in the whole zettelkasen.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; let keyword_count = index.count_keywords(); assert_eq!(Some(&5), keyword_count.get("example")); assert_eq!(Some(&1), keyword_count.get("test"));
pub fn empty() -> Index
[src]
Extended API
Creates a new Index with an empty file list and the current system time as timestamp.
Example - And a very elabourated one, at that.
let index = Index::empty();
pub fn from_yaml<T: AsRef<str>>(yaml: T) -> Result<Index, Error>
[src]
Extended API
Creates a new Index by deserializing it from a YAML-string. Returns an error if something went wrong with deserializing it.
Example
let yaml = "--- files: file1.md: title: File 1 followups: [subdir/file2.md] keywords: [example] links: [] subdir/file2.md: title: File 2 followups: [] keywords: [example, second] links: [file1.md] timestamp: secs_since_epoch: 1543078763 nanos_since_epoch: 449322318"; let index = Index::from_yaml(yaml)?;
Errors
Error::Yaml
when deserializing from YAML failed.
pub fn from_file<P: AsRef<Path>>(indexfile: P) -> Result<Index, Error>
[src]
Extended API
Loads an existing Index by deserializing it from a YAML-file. Returns an error if something went wrong with reading the file or deserializing it.
let file = Path::new("examples/index.yaml"); let index = Index::from_file(file)?;
Errors
Error::Io
for problems reading the file.Error::Yaml
when deserializing from YAML failed.
pub fn update_timestamp(&mut self)
[src]
Extended API
Overwrites the timestamp with the current system time.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let mut index = Index::new(&cfg)?; index.update_timestamp();
pub fn to_file<P: AsRef<Path>>(&self, indexfile: P) -> Result<(), Error>
[src]
Extended API
Write a YAML-representation of the index to file.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; index.to_file(Path::new("examples/index.yaml"))?;
Errors
Error::Io
for problems with the specified file.Error::Yaml
for problems serializing to YAML.
pub fn add_zettel<P: AsRef<Path>>(&mut self, key: P, zettel: Zettel)
[src]
Extended API
Adds a Zettel to the index with the path to the file relative to root
directory as key
. Internally,
insert
of std::collections::BTreeMap
is called. See documentation there for details. That method's return
value is disregarded, however.
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let mut index = Index::new(&cfg)?; let file = Path::new("test-zettel.md"); //relative to the root directory let zettel = Zettel::new("Empty Zettel for Testing"); index.add_zettel(file, zettel);
pub fn remove_zettel<P: AsRef<Path>>(&mut self, key: P) -> Option<Zettel>
[src]
Extended API
Removes a Zettel from the index. The key
is the path to the
corresponding file, relative to the root directory.
Returns the old Zettel found at the key or None
if it was not present
in the first place. Please note that the return value doesn't need to
be checked for success. The entry for key
is guaranteed to be gone,
regardless of the return value.
Internally,
remove
of std::collections::BTreeMap
is called. See documentation there for details.
Example 1
In most cases, you'll just disregard the return value.
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let mut index = Index::new(&cfg)?; let file = Path::new("test-zettel.md"); //relative to root directory let zettel = Zettel::new("Empty Zettel for Testing"); index.add_zettel(file, zettel); index.remove_zettel(file); // or, if you want to be very tidy: let _ = index.remove_zettel(file);
Example 2
If you want to do something with the old Zettel:
// snip let zettel = Zettel::new("Empty Zettel for Testing"); // We clone here so we have something to compare. index.add_zettel(file, zettel.clone()); let removed = index.remove_zettel(file); assert_eq!(removed, Some(zettel));
pub fn get_mut_zettel<P: AsRef<Path>>(&mut self, key: P) -> Option<&mut Zettel>
[src]
Extended API
Returns a mutable reference to the Zettel found
at key
.
Returns None
of said key is not present.
The key
is the path to the corresponding file relative to root
directory.
Note: Editing this only changes the entry in the index, not the file itself. Changes might be overwritten when the index us updated next. This method is intended for developers of frontends who want to present the metadata and the document body to their users, separately. If you use this, take care to write changes back to the file.
Internally, this function calls the method
get_mut
of std::collections::BTreeMap
.
See documentation there for details.
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let mut index = Index::load(&cfg)?; // Use an inner scope so z goes out of scope automatically. { let z = index.get_mut_zettel(Path::new("file1.md")); assert!(z.is_some()); let z = z.unwrap(); z.title = String::from("Changed Title 1"); } // Let's get it again from index to see if the changes are there. let z = index.get_zettel(Path::new("file1.md")).unwrap(); assert_eq!(z.title, "Changed Title 1");
pub fn parents_of_zettel<P: AsRef<Path>>(&self, key: P) -> HashSet<PathBuf>
[src]
Extended API
Returns the paths to all zettels in the index that list the zettel
specified by key
as their followups.
Note
In Luhmann's Zettelkasten system, a Zettel can not be a followup of more than one other Zettel. A user might approach this differently, however, so this returns a list (a HashSet, to be exact).
Example
let cfg = Config::from_file(Path::new("examples/zettels-examples.cfg.yaml"))?; let index = Index::load(&cfg)?; let parents = index.parents_of_zettel("file2.md"); for parent in parents { println!("{:?}", parent); }
Trait Implementations
impl Debug for Index
[src]
impl<'de> Deserialize<'de> for Index
[src]
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error> where
__D: Deserializer<'de>,
[src]
__D: Deserializer<'de>,
impl PartialEq<Index> for Index
[src]
impl Serialize for Index
[src]
fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error> where
__S: Serializer,
[src]
__S: Serializer,
impl StructuralPartialEq for Index
[src]
Auto Trait Implementations
impl RefUnwindSafe for Index
impl Send for Index
impl Sync for Index
impl Unpin for Index
impl UnwindSafe for Index
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> DeserializeOwned for T where
T: for<'de> Deserialize<'de>,
[src]
T: for<'de> Deserialize<'de>,
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,