Skip to content

Commit

Permalink
feat: Taglines from files (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
miampf authored Jan 18, 2024
1 parent d0ebe13 commit 047972e
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
/target

/testfiles
51 changes: 51 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ edition = "2021"
[dependencies]
pest = "2.7.6"
pest_derive = "2.7.6"
walkdir = "2.4.0"
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
/// parsers contains the relevant grammar parsers
pub mod parsers;

/// search contains functions for searching files and tags.
pub mod search;
12 changes: 10 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
fn main() {
println!("Hello, world!");
use tag::search::get_tags_from_files;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let tagged_files = get_tags_from_files("testfiles")?;

for file in tagged_files.iter() {
println!("File {} contains {:?}", file.path.display(), file.tags);
}

Ok(())
}
6 changes: 0 additions & 6 deletions src/parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,6 @@ mod tests {
expected_tags: vec!["#1", "#asdf", "#something-idk"],
expected_error: false,
},
TestCase {
name: "success_with_newline",
input: "tags:\n[\n\t#something_else\n]",
expected_tags: vec!["#something_else"],
expected_error: false,
},
TestCase {
name: "fail_no_brackets",
input: "tags:#1#2#3",
Expand Down
60 changes: 60 additions & 0 deletions src/search.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use std::{
fs,
io::{BufRead, BufReader},
path::{Path, PathBuf},
};

use pest::Parser;
use walkdir::WalkDir;

use crate::parsers::tagline::{self, TaglineParser};

/// TaggedFile is a file that contains tags.
#[derive(Clone)]
pub struct TaggedFile {
pub path: PathBuf,
pub tags: Vec<String>,
}

/// get_tags_from_file() returns a list of tags found in a file.
/// It will return an error if a file has no parsable tags.
fn get_tags_from_file(file: &Path) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let file = fs::File::open(file)?;
let mut buffer = BufReader::new(file);
let mut tagline = String::new();
let _ = buffer.read_line(&mut tagline)?;

let parsed = TaglineParser::parse(tagline::Rule::tagline, tagline.trim())?;

let mut tags = Vec::new();

for tag in parsed {
if tag.as_rule() == tagline::Rule::tag {
tags.push(tag.as_str().to_string())
}
}

Ok(tags)
}

/// get_tags_from_files() recursively retrieves the tags of all files
/// in a given directory.
pub fn get_tags_from_files(directory: &str) -> Result<Vec<TaggedFile>, Box<dyn std::error::Error>> {
let mut tagged_files = Vec::new();

for entry in WalkDir::new(directory).follow_links(true) {
let entry = entry?;

if entry.file_type().is_dir() {
continue;
}

let tags = get_tags_from_file(entry.path())?;
tagged_files.push(TaggedFile {
path: entry.path().to_owned(),
tags,
})
}

Ok(tagged_files.clone())
}
2 changes: 1 addition & 1 deletion tagline.pest
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ tag = {"#" ~ (LETTER|NUMBER|CONNECTOR_PUNCTUATION|DASH_PUNCTUATION)+}
taglist = _{"[" ~ tag* ~ "]"}
tagline = _{SOI ~ "tags:" ~ taglist ~ EOI}

WHITESPACE = _{" " | "\t" | NEWLINE}
WHITESPACE = _{" " | "\t"}

0 comments on commit 047972e

Please sign in to comment.