From 0ae240d705f76e3ce613c448dbbb7ea4fee51fff Mon Sep 17 00:00:00 2001 From: miampf Date: Sun, 21 Jan 2024 16:33:24 +0100 Subject: [PATCH 1/3] added stricter clippy lints --- Cargo.toml | 10 ++++++++++ src/main.rs | 28 +++++++++++++--------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 41c0289..a4e2a4c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ name = "tag" version = "0.1.0" edition = "2021" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] @@ -13,3 +14,12 @@ pest = "2.7.6" pest_derive = "2.7.6" textwrap = "0.16.0" walkdir = "2.4.0" + +[lints.clippy] +pedantic = "warn" +nursery = "warn" +suspicious = "warn" +cargo = "warn" +complexity = "deny" +perf = "deny" +style = "deny" diff --git a/src/main.rs b/src/main.rs index 19b97e8..d6f8dfb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::{path::PathBuf, process::Command}; +use std::{path::Path, process::Command}; use colored::Colorize; use pest::Parser; @@ -39,13 +39,13 @@ mod cli { } impl Cli { - pub fn new_and_parse() -> Cli { - Cli::parse() + pub fn new_and_parse() -> Self { + Self::parse() } } } -fn execute_command_on_file(path: PathBuf, command: String) -> String { +fn execute_command_on_file(path: &Path, command: &str) -> String { let command = command.replace("#FILE#", path.to_str().unwrap()); let output = if cfg!(target_os = "windows") { @@ -78,7 +78,7 @@ fn execute_command_on_file(path: PathBuf, command: String) -> String { output_string.unwrap().to_string() } -fn execute_filter_command_on_file(path: PathBuf, command: String) -> bool { +fn execute_filter_command_on_file(path: &Path, command: &str) -> bool { let command = command.replace("#FILE#", path.to_str().unwrap()); let output = if cfg!(target_os = "windows") { @@ -121,10 +121,10 @@ fn main() -> Result<(), Box> { let query = query.unwrap(); - for file in file_index.iter() { + for file in file_index { let ast = construct_query_ast( query.clone().next().unwrap().into_inner(), - file.tags.iter().map(|tag| tag.as_str()).collect(), + file.tags.iter().map(std::string::String::as_str).collect(), ); // skip the file if tags don't match query @@ -134,20 +134,18 @@ fn main() -> Result<(), Box> { // skip the file if filter command is unsuccessful if args.filter_command.is_some() - && !execute_filter_command_on_file( - file.path.clone(), - args.filter_command.clone().unwrap(), - ) + && !execute_filter_command_on_file(&file.path, &args.filter_command.clone().unwrap()) { continue; } println!("{}", file.path.display().to_string().green()); - let mut output = String::new(); - if args.command.is_some() { - output = execute_command_on_file(file.path.clone(), args.command.clone().unwrap()); - } + let output = if args.command.is_some() { + execute_command_on_file(&file.path, &args.command.clone().unwrap()) + } else { + String::new() + }; if !args.silent { println!("\t{}", format!("tags: {:?}", file.tags).blue()); From ec841b7a321d0248fd4924aad5907a1ff476c98e Mon Sep 17 00:00:00 2001 From: miampf Date: Sun, 21 Jan 2024 16:40:10 +0100 Subject: [PATCH 2/3] took out cargo warning + added package metadata --- Cargo.toml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a4e2a4c..5de3044 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,11 @@ name = "tag" version = "0.1.0" edition = "2021" - +description = "Search for local text files with a simple tagging system." +license = "MIT" +repository = "https://github.com/miampf/tag" +keywords = ["organization", "tagging", "plaintext", "searching"] +categories = ["command-line-utilities", "filesystem"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -19,7 +23,6 @@ walkdir = "2.4.0" pedantic = "warn" nursery = "warn" suspicious = "warn" -cargo = "warn" complexity = "deny" perf = "deny" style = "deny" From ba17143e4ceefb86d6c6c44663ca68fe94788d78 Mon Sep 17 00:00:00 2001 From: miampf Date: Sun, 21 Jan 2024 16:55:27 +0100 Subject: [PATCH 3/3] fixed remaining issues found by new config --- src/main.rs | 4 +-- src/parsers.rs | 73 ++++++++++++++++++++++++++------------------------ src/search.rs | 20 ++++++++------ 3 files changed, 52 insertions(+), 45 deletions(-) diff --git a/src/main.rs b/src/main.rs index d6f8dfb..9dbd7a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ use std::{path::Path, process::Command}; use colored::Colorize; use pest::Parser; use tag::{ - parsers::query::{construct_query_ast, evaluate_ast, QueryParser, Rule}, + parsers::searchquery::{construct_query_ast, evaluate_ast, QueryParser, Rule}, search::get_tags_from_files, }; @@ -124,7 +124,7 @@ fn main() -> Result<(), Box> { for file in file_index { let ast = construct_query_ast( query.clone().next().unwrap().into_inner(), - file.tags.iter().map(std::string::String::as_str).collect(), + &file.tags.iter().map(std::string::String::as_str).collect(), ); // skip the file if tags don't match query diff --git a/src/parsers.rs b/src/parsers.rs index b6162c0..0223fc9 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -1,14 +1,14 @@ -pub mod tagline { +pub mod onfile { use pest_derive::Parser; #[derive(Parser)] #[grammar = "tagline.pest"] - /// TaglineParser is responsible for parsing the taglines at the start of each searched file. + /// `TaglineParser` is responsible for parsing the taglines at the start of each searched file. /// The relevant rule is `tagline`. pub struct TaglineParser; } -pub mod query { +pub mod searchquery { use pest::{iterators::Pairs, pratt_parser::PrattParser}; use pest_derive::Parser; @@ -25,7 +25,7 @@ pub mod query { } /// Op is an Operation that can be used in a query. - #[derive(Debug, PartialEq, Clone)] + #[derive(Debug, PartialEq, Eq, Clone)] pub enum Op { And, Or, @@ -33,8 +33,8 @@ pub mod query { lazy_static::lazy_static! { static ref PRATT_PARSER: PrattParser = { - use pest::pratt_parser::{Assoc::*, Op}; - use Rule::*; + use pest::pratt_parser::{Assoc::Left, Op}; + use Rule::{and, or, unary_not}; PrattParser::new() // & and | are evaluated with the same precedence @@ -45,17 +45,18 @@ pub mod query { #[derive(Parser)] #[grammar = "query.pest"] - /// QueryParser is responsible for parsing the search query. + /// `QueryParser` is responsible for parsing the search query. /// The relevant rule is `tagsearch`. pub struct QueryParser; - /// construct_query_ast() creates an AST from a string of symbols - /// lexed by the QueryParser and a list of tags. - pub fn construct_query_ast(pairs: Pairs, tags: Vec<&str>) -> Expr { + /// `construct_query_ast()` creates an AST from a string of symbols + /// lexed by the `QueryParser` and a list of tags. + #[must_use] + pub fn construct_query_ast(pairs: Pairs, tags: &Vec<&str>) -> Expr { PRATT_PARSER .map_primary(|primary| match primary.as_rule() { Rule::tag => Expr::Bool(tags.contains(&primary.as_str().trim())), - Rule::expr => construct_query_ast(primary.into_inner(), tags.clone()), + Rule::expr => construct_query_ast(primary.into_inner(), tags), rule => unreachable!("Expected tag, found {:?}", rule), }) .map_infix(|lhs, op, rhs| { @@ -78,8 +79,9 @@ pub mod query { .parse(pairs) } - /// evaluate_ast() evaluates an AST created by construct_query_ast() + /// `evaluate_ast()` evaluates an AST created by `construct_query_ast()` /// and returns the result. + #[must_use] pub fn evaluate_ast(ast: Expr) -> bool { match ast { Expr::Bool(value) => value, @@ -98,14 +100,14 @@ pub mod query { #[cfg(test)] mod tests { - use crate::parsers::query::construct_query_ast; - use crate::parsers::query::evaluate_ast; - use crate::parsers::query::Expr; - use crate::parsers::query::Op; - use crate::parsers::query::QueryParser; + use crate::parsers::searchquery::construct_query_ast; + use crate::parsers::searchquery::evaluate_ast; + use crate::parsers::searchquery::Expr; + use crate::parsers::searchquery::Op; + use crate::parsers::searchquery::QueryParser; - use super::query; - use super::tagline; + use super::onfile; + use super::searchquery; use pest::Parser; @@ -151,10 +153,10 @@ mod tests { }, ]; - test_cases.iter().for_each(|test_case| { + for test_case in test_cases { println!("test_tagline_parser: \n\t{}", test_case.name); - let res = tagline::TaglineParser::parse(tagline::Rule::tagline, test_case.input); + let res = onfile::TaglineParser::parse(onfile::Rule::tagline, test_case.input); if res.is_err() { assert!(test_case.expected_error); return; @@ -163,11 +165,11 @@ mod tests { assert!(!test_case.expected_error); for (i, tag) in res.unwrap().enumerate() { - if tag.as_rule() == tagline::Rule::tag { + if tag.as_rule() == onfile::Rule::tag { assert_eq!(tag.as_str().trim(), test_case.expected_tags[i]); } } - }) + } } #[test] @@ -221,10 +223,11 @@ mod tests { }, ]; - test_cases.iter().for_each(|test_case| { + for test_case in test_cases { println!("test_query_parser: \n\t{}", test_case.name); - let res = query::QueryParser::parse(query::Rule::tagsearch, test_case.input); + let res = + searchquery::QueryParser::parse(searchquery::Rule::tagsearch, test_case.input); if res.is_err() { assert!(test_case.expected_error); return; @@ -232,8 +235,8 @@ mod tests { assert!(!test_case.expected_error); - assert_eq!(test_case.input, res.unwrap().as_str()) - }) + assert_eq!(test_case.input, res.unwrap().as_str()); + } } #[test] @@ -276,24 +279,24 @@ mod tests { }, ]; - test_cases.iter().for_each(|test_case| { + for test_case in test_cases { println!("test_construct_query_ast: \n\t{}", test_case.name); let ast = construct_query_ast( - QueryParser::parse(query::Rule::tagsearch, test_case.input_query) + QueryParser::parse(searchquery::Rule::tagsearch, test_case.input_query) .unwrap() .next() .unwrap() .into_inner(), - test_case + &test_case .input_tags .iter() - .map(|tag| tag.as_str()) + .map(std::string::String::as_str) .collect(), ); assert_eq!(test_case.expected_ast, ast); - }) + } } #[test] @@ -333,13 +336,13 @@ mod tests { }, ]; - test_cases.iter().for_each(|test_case| { + for test_case in test_cases { println!("test_evaluate_ast: \n\t{}", test_case.name); assert_eq!( test_case.expected_result, evaluate_ast(test_case.input_ast.clone()) - ) - }) + ); + } } } diff --git a/src/search.rs b/src/search.rs index 7295b92..7b8928a 100644 --- a/src/search.rs +++ b/src/search.rs @@ -7,16 +7,16 @@ use std::{ use pest::Parser; use walkdir::WalkDir; -use crate::parsers::tagline::{self, TaglineParser}; +use crate::parsers::onfile::{self, TaglineParser}; -/// TaggedFile is a file that contains tags. +/// `TaggedFile` is a file that contains tags. #[derive(Clone, Debug)] pub struct TaggedFile { pub path: PathBuf, pub tags: Vec, } -/// get_tags_from_file() returns a list of tags found in a file. +/// `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, Box> { let file = fs::File::open(file)?; @@ -24,21 +24,25 @@ fn get_tags_from_file(file: &Path) -> Result, Box Result, Box> { let mut tagged_files = Vec::new(); @@ -55,7 +59,7 @@ pub fn get_tags_from_files(directory: &str) -> Result, Box