🚀 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