[][src]Struct libzettels::Index

pub struct Index {
    pub files: BTreeMap<PathBuf, Zettel>,
    pub timestamp: SystemTime,
}

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

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 Zettels
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: the IndexingMethod 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 empty followups and keywords. The markdown links (if any) are still parsed and links 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 via followups 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 of std::io:Error, e.g. problems executing grep or ripgrep, problems with the files etc.
  • Error::NormalizePath if one of the files or a link in followups or linkscan not be expressed relative to the root directory
  • Error::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 in Config's field indexfile.
  • 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 empty followups and keywords. The markdown links (if any) are still parsed and links is populated as usual.

Errors

  • Error::BadLink if one of the files links to a target that doesn't exist (both via followups 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 of std::io:Error, e.g. problems executing grep or ripgrep, problems with the files etc.
  • Error::NormalizePath if one of the files or a link in followups or linkscan not be expressed relative to the root directory
  • Error::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]

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")));

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);

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]

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]

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")));

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

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

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

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]

impl PartialEq<Index> for Index[src]

impl Serialize for Index[src]

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]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.