diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/bib.rs | 279 | ||||
| -rw-r--r-- | src/backend/cliargs.rs | 89 | ||||
| -rw-r--r-- | src/backend/search.rs | 137 |
3 files changed, 0 insertions, 505 deletions
diff --git a/src/backend/bib.rs b/src/backend/bib.rs deleted file mode 100644 index a7df951..0000000 --- a/src/backend/bib.rs +++ /dev/null @@ -1,279 +0,0 @@ -// bibiman - a TUI for managing BibLaTeX databases -// Copyright (C) 2024 lukeflo -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -///// - -use biblatex::{self, Bibliography}; -use biblatex::{ChunksExt, Type}; -use itertools::Itertools; -use std::{fs, path::PathBuf}; - -#[derive(Debug)] -pub enum FileFormat { - BibLatex, - Hayagriva, -} - -// Set necessary fields -// TODO: can surely be made more efficient/simpler -#[derive(Debug)] -pub struct BibiMain { - pub bibfile: PathBuf, // path to bibfile - pub bibfile_format: FileFormat, // Format of passed file - pub bibfilestring: String, // content of bibfile as string - pub bibliography: Bibliography, // parsed bibliography - pub citekeys: Vec<String>, // list of all citekeys - pub keyword_list: Vec<String>, // list of all available keywords - pub entry_list: Vec<BibiData>, // List of all entries -} - -#[derive(Debug, Clone)] -pub struct BibiData { - pub authors: String, - pub title: String, - pub year: String, - pub pubtype: String, - pub keywords: String, - pub citekey: String, - pub abstract_text: String, - pub doi_url: String, - pub filepath: String, -} - -impl BibiMain { - pub fn new(main_bibfile: PathBuf) -> Self { - // TODO: Needs check for config file path as soon as config file is impl - let bibfile_format = Self::check_file_format(&main_bibfile); - let bibfile = main_bibfile; - let bibfilestring = fs::read_to_string(&bibfile).unwrap(); - let bibliography = biblatex::Bibliography::parse(&bibfilestring).unwrap(); - let citekeys = Self::get_citekeys(&bibliography); - let keyword_list = Self::collect_tag_list(&citekeys, &bibliography); - let entry_list = Self::create_entry_list(&citekeys, &bibliography); - Self { - bibfile, - bibfile_format, - bibfilestring, - bibliography, - citekeys, - keyword_list, - entry_list, - } - } - - // Check which file format the passed file has - fn check_file_format(main_bibfile: &PathBuf) -> FileFormat { - let extension = main_bibfile.extension().unwrap().to_str(); - - match extension { - Some("yml") => FileFormat::Hayagriva, - Some("yaml") => FileFormat::Hayagriva, - Some("bib") => FileFormat::BibLatex, - Some(_) => panic!("The extension {:?} is no valid bibfile", extension.unwrap()), - None => panic!("The given path {:?} holds no valid file", main_bibfile), - } - } - - fn create_entry_list(citekeys: &[String], bibliography: &Bibliography) -> Vec<BibiData> { - citekeys - .into_iter() - .map(|k| BibiData { - authors: Self::get_authors(&k, &bibliography), - title: Self::get_title(&k, &bibliography), - year: Self::get_year(&k, &bibliography), - pubtype: Self::get_pubtype(&k, &bibliography), - keywords: Self::get_keywords(&k, &bibliography), - citekey: k.to_owned(), - abstract_text: Self::get_abstract(&k, &bibliography), - doi_url: Self::get_weblink(&k, &bibliography), - filepath: Self::get_filepath(&k, &bibliography), - }) - .collect() - } - - // get list of citekeys from the given bibfile - // this list is the base for further operations on the bibentries - // since it is the entry point of the biblatex crate. - pub fn get_citekeys(bibstring: &Bibliography) -> Vec<String> { - let citekeys: Vec<String> = bibstring.keys().map(|k| k.to_owned()).collect(); - citekeys - } - - // collect all keywords present in the bibliography - // sort them and remove duplicates - // this list is for fast filtering entries by topics/keyowrds - pub fn collect_tag_list(citekeys: &[String], biblio: &Bibliography) -> Vec<String> { - // Initialize vector collecting all keywords - let mut keyword_list = vec![]; - - // Loop over entries and collect all keywords - for i in citekeys { - if biblio.get(&i).unwrap().keywords().is_ok() { - let items = biblio - .get(&i) - .unwrap() - .keywords() - .unwrap() - .format_verbatim(); - // Split keyword string into slices, trim leading and trailing - // whitespaces, remove empty slices, and collect them - let mut key_vec: Vec<String> = items - .split(',') - .map(|s| s.trim().to_string()) - .filter(|s| !s.is_empty()) - .collect(); - // Append keywords to vector - keyword_list.append(&mut key_vec); - } - } - - // Sort the vector and remove duplicates - keyword_list.sort_by(|a, b| a.to_lowercase().cmp(&b.to_lowercase())); - keyword_list.dedup(); - keyword_list - } - - pub fn get_authors(citekey: &str, biblio: &Bibliography) -> String { - if biblio.get(&citekey).unwrap().author().is_ok() { - let authors = biblio.get(&citekey).unwrap().author().unwrap(); - if authors.len() > 1 { - let all_authors = authors.iter().map(|a| &a.name).join(", "); - all_authors - } else if authors.len() == 1 { - let authors = authors[0].name.to_string(); - authors - } else { - let editors_authors = format!("empty"); - editors_authors - } - } else { - if !biblio.get(&citekey).unwrap().editors().unwrap().is_empty() { - let editors = biblio.get(&citekey).unwrap().editors().unwrap(); - if editors[0].0.len() > 1 { - // let editors = format!("{} (ed.) et al.", editors[0].0[0].name); - let mut editors = editors[0].0.iter().map(|e| &e.name).join(", "); - editors.push_str(" (ed.)"); - editors - } else if editors[0].0.len() == 1 { - let editors = format!("{} (ed.)", editors[0].0[0].name); - editors - } else { - let editors_authors = format!("empty"); - editors_authors - } - } else { - let editors_authors = format!("empty"); - editors_authors - } - } - } - - pub fn get_title(citekey: &str, biblio: &Bibliography) -> String { - let title = { - if biblio.get(&citekey).unwrap().title().is_ok() { - let title = biblio - .get(&citekey) - .unwrap() - .title() - .unwrap() - .format_verbatim(); - title - } else { - let title = format!("no title"); - title - } - }; - title - } - - pub fn get_year(citekey: &str, biblio: &Bibliography) -> String { - let year = biblio.get(&citekey).unwrap(); - let year = { - if year.date().is_ok() { - let year = year.date().unwrap().to_chunks().format_verbatim(); - let year = year[..4].to_string(); - year - } else { - let year = format!("n.d."); - year - } - }; - year - } - - pub fn get_pubtype(citekey: &str, biblio: &Bibliography) -> String { - let pubtype = biblio.get(&citekey).unwrap().entry_type.to_string(); - pubtype - } - - pub fn get_keywords(citekey: &str, biblio: &Bibliography) -> String { - let keywords = { - if biblio.get(&citekey).unwrap().keywords().is_ok() { - let keywords = biblio - .get(&citekey) - .unwrap() - .keywords() - .unwrap() - .format_verbatim(); - keywords - } else { - let keywords = String::from(""); - keywords - } - }; - keywords - } - - pub fn get_abstract(citekey: &str, biblio: &Bibliography) -> String { - let text = { - if biblio.get(&citekey).unwrap().abstract_().is_ok() { - let abstract_text = biblio - .get(&citekey) - .unwrap() - .abstract_() - .unwrap() - .format_verbatim(); - abstract_text - } else { - let abstract_text = format!("No abstract"); - abstract_text - } - }; - text - } - - pub fn get_weblink(citekey: &str, biblio: &Bibliography) -> String { - if let true = biblio.get(&citekey).unwrap().doi().is_ok() { - let url = biblio.get(&citekey).unwrap().doi().unwrap(); - url - } else if let true = biblio.get(&citekey).unwrap().url().is_ok() { - let url = biblio.get(&citekey).unwrap().url().unwrap(); - url - } else { - let url = "".to_string(); - url - } - } - - pub fn get_filepath(citekey: &str, biblio: &Bibliography) -> String { - if let true = biblio.get(&citekey).unwrap().file().is_ok() { - let file = biblio.get(&citekey).unwrap().file().unwrap(); - file - } else { - let file = "".to_string(); - file - } - } -} diff --git a/src/backend/cliargs.rs b/src/backend/cliargs.rs deleted file mode 100644 index d3a4652..0000000 --- a/src/backend/cliargs.rs +++ /dev/null @@ -1,89 +0,0 @@ -// bibiman - a TUI for managing BibLaTeX databases -// Copyright (C) 2024 lukeflo -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <https://www.gnu.org/licenses/>. -///// - -use std::path::PathBuf; - -use sarge::prelude::*; - -sarge! { - // Name of the struct - ArgumentsCLI, - - // Show help and exit. - 'h' help: bool, - - // Show version and exit. - 'v' version: bool, -} - -// struct for CLIArgs -pub struct CLIArgs { - pub helparg: bool, - pub versionarg: bool, - pub bibfilearg: PathBuf, -} - -impl CLIArgs { - pub fn new() -> Self { - let (cli_args, pos_args) = ArgumentsCLI::parse().expect("Could not parse CLI arguments"); - let bibfilearg = if pos_args.len() > 1 { - PathBuf::from(&pos_args[1]) - // pos_args[1].to_string() - } else { - PathBuf::new() - }; - Self { - helparg: cli_args.help, - versionarg: cli_args.version, - bibfilearg, - } - } -} - -pub fn help_func() -> String { - let help = format!( - "\ -{} {} - -USAGE: - bibiman [FLAGS] [file] - -POSITIONAL ARGS: - <file> Path to .bib file - -FLAGS: - -h, --help Show this help and exit - -v, --version Show the version and exit", - env!("CARGO_PKG_NAME"), - env!("CARGO_PKG_VERSION"), - ); - help -} - -pub fn version_func() -> String { - let version = format!( - "\ -{} {} -{} -{}", - env!("CARGO_PKG_NAME"), - env!("CARGO_PKG_VERSION"), - env!("CARGO_PKG_AUTHORS"), - env!("CARGO_PKG_LICENSE") - ); - version -} diff --git a/src/backend/search.rs b/src/backend/search.rs deleted file mode 100644 index 65d97d7..0000000 --- a/src/backend/search.rs +++ /dev/null @@ -1,137 +0,0 @@ -use nucleo_matcher::{ - pattern::{CaseMatching, Normalization, Pattern}, - Config, Matcher, -}; -use std::collections::HashMap; - -use crate::frontend::entries::EntryTableItem; - -#[derive(Debug)] -pub struct BibiSearch { - pub search_string: String, // Search string show in footer, used for search - pub inner_search: bool, // True, if we trigger a search for already filtered list - pub filtered_tag_list: Vec<String>, -} - -impl Default for BibiSearch { - fn default() -> Self { - Self { - search_string: String::new(), - inner_search: false, - filtered_tag_list: Vec::new(), - } - } -} - -impl BibiSearch { - // Stringify EntryTableItem by joining/concat - fn convert_to_string(inner_vec: &EntryTableItem) -> String { - let entry_table_item_str = { - format!( - "{} {} {} {} {} {}", - &inner_vec.authors, - &inner_vec.title, - &inner_vec.year, - &inner_vec.pubtype, - &inner_vec.keywords, - &inner_vec.citekey - ) - }; - entry_table_item_str - } - - // Return a filtered entry list - pub fn search_entry_list( - search_pattern: &str, - orig_list: Vec<EntryTableItem>, - ) -> Vec<EntryTableItem> { - // Create a hashmap to connect stingified entry with entry vec - let mut entry_string_hm: HashMap<String, EntryTableItem> = HashMap::new(); - - // Convert all entries to string and insert them into the hashmap - // next to the original inner Vec<String> of the entry list - for entry in orig_list { - entry_string_hm.insert(Self::convert_to_string(&entry), entry); - } - - // Set up matcher (TODO: One time needed only, move to higher level) - let mut matcher = Matcher::new(Config::DEFAULT); - - // Filter the stringified entries and collect them into a vec - let filtered_matches: Vec<String> = { - let matches = - Pattern::parse(search_pattern, CaseMatching::Ignore, Normalization::Smart) - .match_list(entry_string_hm.keys(), &mut matcher); - matches.into_iter().map(|f| f.0.to_string()).collect() - }; - - // Create filtered entry list and push the inner entry vec's to it - // Use the filtered stringified hm-key as index - let mut filtered_list: Vec<EntryTableItem> = Vec::new(); - for m in filtered_matches { - filtered_list.push(entry_string_hm[&m].to_owned()); - } - filtered_list.sort(); - filtered_list - } - - pub fn search_tag_list(search_pattern: &str, orig_list: Vec<String>) -> Vec<String> { - // Set up matcher (TODO: One time needed only) - let mut matcher = Matcher::new(Config::DEFAULT); - - // Filter the list items by search pattern - let filtered_matches: Vec<String> = { - let matches = - Pattern::parse(search_pattern, CaseMatching::Ignore, Normalization::Smart) - .match_list(orig_list, &mut matcher); - matches.into_iter().map(|f| f.0.to_string()).collect() - }; - filtered_matches - } - - pub fn filter_entries_by_tag( - keyword: &str, - orig_list: &Vec<EntryTableItem>, - ) -> Vec<EntryTableItem> { - let mut filtered_list: Vec<EntryTableItem> = Vec::new(); - - // Loop over the whole given entry table - // Check if the selected keyword is present in the current entry - // If present, push the entry to the filtered list - for e in orig_list { - if e.keywords.contains(keyword) { - filtered_list.push(e.to_owned()); - } - } - - filtered_list - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_vector_join() { - let bibvec: EntryTableItem = EntryTableItem { - authors: "Author".to_string(), - short_author: "".to_string(), - title: "Title".to_string(), - year: "1999".to_string(), - pubtype: "article".to_string(), - keywords: "hello, bye".to_string(), - citekey: "author_1999".to_string(), - abstract_text: "An abstract with multiple sentences. Here is the second".to_string(), - doi_url: "https://www.bibiman.org".to_string(), - filepath: "/home/file/path.pdf".to_string(), - }; - - let joined_vec = BibiSearch::convert_to_string(&bibvec); - - assert_eq!( - joined_vec, - "Author Title 1999 article hello, bye author_1999" - ) - } -} |
