🚀 meta: initial commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
1065
Cargo.lock
generated
Normal file
1065
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
Cargo.toml
Normal file
23
Cargo.toml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[package]
|
||||||
|
name = "obsidian-searcher"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ahash = { version = "0.8.6", features = ["serde"] }
|
||||||
|
async-channel = "2.1.1"
|
||||||
|
crossterm = "0.27.0"
|
||||||
|
error-stack = "0.4.1"
|
||||||
|
pathdiff = "0.2.1"
|
||||||
|
petgraph = { version = "0.6.4", features = ["serde-1"] }
|
||||||
|
postcard = { version = "1.0.8", features = ["alloc", "use-std"] }
|
||||||
|
ratatui = "0.24.0"
|
||||||
|
regex = "1.10.2"
|
||||||
|
serde = { version = "1.0.193", features = ["derive"] }
|
||||||
|
thiserror = "1.0.51"
|
||||||
|
tokio = { version = "1.35.1", features = ["rt-multi-thread", "macros", "fs"] }
|
||||||
|
tracing = "0.1.40"
|
||||||
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||||
|
walkdir = "2.4.0"
|
126
src/bin/build-index.rs
Normal file
126
src/bin/build-index.rs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
use std::{
|
||||||
|
env,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
thread,
|
||||||
|
};
|
||||||
|
|
||||||
|
use ahash::AHashMap;
|
||||||
|
use regex::Regex;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct DiscoveredFile {
|
||||||
|
path: PathBuf,
|
||||||
|
note_name_unique: String,
|
||||||
|
note_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn discover_all_files(directory: &Path, callback: async_channel::Sender<DiscoveredFile>) {
|
||||||
|
let span = tracing::debug_span!("entry");
|
||||||
|
|
||||||
|
for entry in WalkDir::new(directory) {
|
||||||
|
let entered = span.enter();
|
||||||
|
|
||||||
|
let entry = entry.unwrap();
|
||||||
|
let path = entry.path();
|
||||||
|
let path = path.to_owned();
|
||||||
|
|
||||||
|
let is_markdown = path.extension().map(|ext| ext == "md").unwrap_or_default();
|
||||||
|
if !is_markdown {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let relative = pathdiff::diff_paths(&path, &directory);
|
||||||
|
|
||||||
|
tracing::debug!(?path, ?directory, ?relative);
|
||||||
|
|
||||||
|
let relative = relative.unwrap();
|
||||||
|
|
||||||
|
let is_dotfile = relative.to_str().unwrap().starts_with(".");
|
||||||
|
if is_dotfile {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let note_name_unique = relative.with_extension("");
|
||||||
|
let note_name_unique = note_name_unique.to_string_lossy();
|
||||||
|
let note_name_unique = note_name_unique.into_owned();
|
||||||
|
let note_name_unique = note_name_unique.replace("\\", "/");
|
||||||
|
|
||||||
|
tracing::debug!(?note_name_unique);
|
||||||
|
|
||||||
|
let note_name = path.file_stem();
|
||||||
|
let note_name = note_name.unwrap();
|
||||||
|
let note_name = note_name.to_string_lossy();
|
||||||
|
let note_name = note_name.into_owned();
|
||||||
|
|
||||||
|
tracing::debug!(?note_name);
|
||||||
|
|
||||||
|
let discovered = DiscoveredFile {
|
||||||
|
path,
|
||||||
|
note_name,
|
||||||
|
note_name_unique,
|
||||||
|
};
|
||||||
|
|
||||||
|
callback.send_blocking(discovered).unwrap();
|
||||||
|
|
||||||
|
drop(entered);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
let mut graph = petgraph::graph::DiGraph::<String, ()>::new();
|
||||||
|
|
||||||
|
let obsidian_vault_location = env::var("OBSIDIAN_VAULT").unwrap();
|
||||||
|
let obsidian_vault_location = PathBuf::from(obsidian_vault_location);
|
||||||
|
|
||||||
|
let (tx, rx) = async_channel::bounded(64);
|
||||||
|
|
||||||
|
let handle = thread::spawn(move || discover_all_files(&obsidian_vault_location, tx));
|
||||||
|
|
||||||
|
let wikilink_regex = r"\[\[(?P<link>[^\]\|]+)(?:\|(?P<title>[^\]]+))?\]\]";
|
||||||
|
let wikilink_regex = Regex::new(wikilink_regex).unwrap();
|
||||||
|
|
||||||
|
let mut note_name_unique_to_index = AHashMap::new();
|
||||||
|
|
||||||
|
while let Ok(discovered) = rx.recv().await {
|
||||||
|
tracing::debug!(?discovered);
|
||||||
|
|
||||||
|
let note_name_unique = discovered.note_name_unique;
|
||||||
|
|
||||||
|
let index = note_name_unique_to_index
|
||||||
|
.entry(note_name_unique.clone())
|
||||||
|
.or_insert_with(|| graph.add_node(note_name_unique));
|
||||||
|
|
||||||
|
let index = *index;
|
||||||
|
|
||||||
|
let contents = tokio::fs::read_to_string(discovered.path).await;
|
||||||
|
let contents = contents.unwrap();
|
||||||
|
|
||||||
|
tracing::debug!(?contents);
|
||||||
|
|
||||||
|
let wikilinks = wikilink_regex.captures_iter(&contents);
|
||||||
|
|
||||||
|
for wikilink in wikilinks {
|
||||||
|
tracing::info!(?wikilink);
|
||||||
|
|
||||||
|
let link = wikilink.name("link").unwrap();
|
||||||
|
|
||||||
|
tracing::info!(?wikilink);
|
||||||
|
|
||||||
|
let outgoing_index = note_name_unique_to_index
|
||||||
|
.entry(link.as_str().to_string())
|
||||||
|
.or_insert_with_key(|k| graph.add_node(k.to_owned()));
|
||||||
|
|
||||||
|
graph.add_edge(index, *outgoing_index, ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let index_file = std::fs::File::create("graph.postcard").unwrap();
|
||||||
|
|
||||||
|
postcard::to_io(&graph, index_file).unwrap();
|
||||||
|
|
||||||
|
handle.join().unwrap();
|
||||||
|
}
|
52
src/bin/path-find.rs
Normal file
52
src/bin/path-find.rs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
use ahash::AHashMap;
|
||||||
|
use petgraph::Undirected;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
let file = std::fs::read("graph.postcard").unwrap();
|
||||||
|
|
||||||
|
let graph: petgraph::graph::DiGraph<String, ()> = postcard::from_bytes(&file).unwrap();
|
||||||
|
|
||||||
|
let undirected = graph.into_edge_type::<Undirected>();
|
||||||
|
let graph = undirected;
|
||||||
|
|
||||||
|
let index = {
|
||||||
|
let mut makeshift_index = AHashMap::new();
|
||||||
|
|
||||||
|
let indices = graph.node_indices();
|
||||||
|
|
||||||
|
for index in indices {
|
||||||
|
let node = &graph[index];
|
||||||
|
makeshift_index.insert(node.as_ref(), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
makeshift_index
|
||||||
|
};
|
||||||
|
|
||||||
|
let start = "WiFi";
|
||||||
|
let end = "Bluetooth";
|
||||||
|
|
||||||
|
let start_index = *index.get(start).expect("start didn't exist");
|
||||||
|
let end_index = *index.get(end).expect("end didn't exist");
|
||||||
|
|
||||||
|
tracing::info!(?start_index);
|
||||||
|
tracing::info!(?end_index);
|
||||||
|
|
||||||
|
let ret = petgraph::algo::astar(&graph, start_index, |f| f == end_index, |_e| 1, |_e| 0);
|
||||||
|
|
||||||
|
if let Some((cost, path)) = ret {
|
||||||
|
tracing::info!(cost);
|
||||||
|
|
||||||
|
tracing::info!(?path);
|
||||||
|
|
||||||
|
for idx in path {
|
||||||
|
let node = &graph[idx];
|
||||||
|
|
||||||
|
tracing::info!(node);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tracing::error!("there's no path");
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user