aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlukeflo2024-12-25 21:16:19 +0100
committerlukeflo2024-12-25 21:16:19 +0100
commitdc537b3865b59da28de0e754fe9a79efcaf618f6 (patch)
tree1654885189bf1ea486c0f50cbc753951a8ca3d49
parent67f875962af5ea71da56fa709575d3331de5ba58 (diff)
downloadbibiman-dc537b3865b59da28de0e754fe9a79efcaf618f6.tar.gz
bibiman-dc537b3865b59da28de0e754fe9a79efcaf618f6.zip
Bugfix: Handle citekey duplicates
+ When adding an entry via DOI check if created citekey is already used + If so, loop over alphabetic chars and append it to citekey + When a unique combination is found, break loop and replace original citekey
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--src/bibiman.rs133
3 files changed, 90 insertions, 47 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1bf0ac3..37b48be 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -86,7 +86,7 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bibiman"
-version = "0.9.0"
+version = "0.9.1"
dependencies = [
"arboard",
"biblatex",
diff --git a/Cargo.toml b/Cargo.toml
index bf3a680..3e28ba2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "bibiman"
-version = "0.9.0"
+version = "0.9.1"
authors = ["lukeflo <lukeflo_git@posteo.de>"]
license = "GPL-3.0-or-later"
repository = "https://codeberg.org/lukeflo/bibiman"
diff --git a/src/bibiman.rs b/src/bibiman.rs
index 5c2b666..7fd98cd 100644
--- a/src/bibiman.rs
+++ b/src/bibiman.rs
@@ -27,7 +27,7 @@ use color_eyre::eyre::Result;
use editor_command::EditorBuilder;
use ratatui::widgets::ScrollbarState;
use regex::Regex;
-use std::fs;
+use std::fs::{self, read_to_string};
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::path::PathBuf;
@@ -113,48 +113,6 @@ impl Bibiman {
self.popup_area.popup_kind = Some(PopupKind::Help);
}
- pub fn add_entry(&mut self) {
- if let CurrentArea::EntryArea = self.current_area {
- self.former_area = Some(FormerArea::EntryArea);
- }
- self.popup_area.is_popup = true;
- self.current_area = CurrentArea::PopupArea;
- self.popup_area.popup_kind = Some(PopupKind::AddEntry);
- }
-
- ///Try to resolve entered DOI. If successfull, choose file where to append
- ///the new entry via `append_to_file()` function. If not, show error popup
- ///
- ///The method needs two arguments: the CLIArgs struct and the `str` containing the DOI
- pub fn handle_new_entry_submission(&mut self, args: &CLIArgs, doi_string: &str) {
- let doi_string = if doi_string.starts_with("10.") {
- "https://doi.org/".to_string() + doi_string
- } else {
- doi_string.to_owned()
- };
-
- // Send GET request to doi resolver
- let doi_entry = ureq::get(&doi_string)
- .set("Accept", "application/x-bibtex")
- .call();
-
- if let Ok(entry) = doi_entry {
- // Save generated bibtex entry in structs field
- let entry = entry
- .into_string()
- .expect("Couldn't parse fetched entry into string");
- self.popup_area.popup_sel_item = entry;
- self.popup_area.popup_kind = Some(PopupKind::AppendToFile);
- self.append_to_file(args);
- self.former_area = Some(FormerArea::EntryArea);
- self.current_area = CurrentArea::PopupArea;
- self.popup_area.popup_state.select(Some(0))
- } else {
- self.popup_area
- .popup_message("Can't find DOI: ", &doi_string, false);
- }
- }
-
pub fn close_popup(&mut self) {
// Reset all popup fields to default values
self.popup_area = PopupArea::default();
@@ -441,6 +399,48 @@ impl Bibiman {
Ok(())
}
+ pub fn add_entry(&mut self) {
+ if let CurrentArea::EntryArea = self.current_area {
+ self.former_area = Some(FormerArea::EntryArea);
+ }
+ self.popup_area.is_popup = true;
+ self.current_area = CurrentArea::PopupArea;
+ self.popup_area.popup_kind = Some(PopupKind::AddEntry);
+ }
+
+ ///Try to resolve entered DOI. If successfull, choose file where to append
+ ///the new entry via `append_to_file()` function. If not, show error popup
+ ///
+ ///The method needs two arguments: the CLIArgs struct and the `str` containing the DOI
+ pub fn handle_new_entry_submission(&mut self, args: &CLIArgs, doi_string: &str) {
+ let doi_string = if doi_string.starts_with("10.") {
+ "https://doi.org/".to_string() + doi_string
+ } else {
+ doi_string.to_owned()
+ };
+
+ // Send GET request to doi resolver
+ let doi_entry = ureq::get(&doi_string)
+ .set("Accept", "application/x-bibtex")
+ .call();
+
+ if let Ok(entry) = doi_entry {
+ // Save generated bibtex entry in structs field
+ let entry = entry
+ .into_string()
+ .expect("Couldn't parse fetched entry into string");
+ self.popup_area.popup_sel_item = entry;
+ self.popup_area.popup_kind = Some(PopupKind::AppendToFile);
+ self.append_to_file(args);
+ self.former_area = Some(FormerArea::EntryArea);
+ self.current_area = CurrentArea::PopupArea;
+ self.popup_area.popup_state.select(Some(0))
+ } else {
+ self.popup_area
+ .popup_message("Can't find DOI: ", &doi_string, false);
+ }
+ }
+
pub fn append_to_file(&mut self, args: &CLIArgs) {
let mut items = vec!["Create new file".to_owned()];
if args.files.len() > 1 {
@@ -487,6 +487,34 @@ impl Bibiman {
File::create_new(newfile).unwrap()
} else {
let file_path = &args.files[popup_idx - 1];
+
+ // Check if similar citekey already exists
+ let file_string = read_to_string(&file_path).unwrap();
+
+ // If choosen file contains entry with fetched citekey, append an
+ // char to the citekey so no dublettes are created
+ if file_string.contains(&citekey) {
+ let mut new_citekey = String::new();
+
+ // Loop over ASCII alpabetic chars and check again if citekey with
+ // appended char exists. If yes, move to next char and test again.
+ // If the citekey is free, use it and break the loop
+ for c in b'a'..=b'z' {
+ let append_char = (c as char).to_string();
+ new_citekey = citekey.clone() + &append_char;
+ if !file_string.contains(&new_citekey) {
+ break;
+ }
+ }
+
+ let new_entry_string_clone = self.popup_area.popup_sel_item.clone();
+
+ // Replace the double citekey with newly created
+ self.popup_area.popup_sel_item = pattern
+ .replace(&new_entry_string_clone, format!("{{{},", &new_citekey))
+ .to_string();
+ }
+
OpenOptions::new().append(true).open(file_path).unwrap()
};
// Optionally, add a newline before the content
@@ -842,6 +870,8 @@ impl Bibiman {
#[cfg(test)]
mod tests {
+ use regex::Captures;
+
use super::*;
#[test]
@@ -857,8 +887,21 @@ mod tests {
let bibstring = String::from("@article{citekey77_2001:!?, author = {Hanks, Tom}, title = {A great book}, year = {2001}}");
- let result = re.captures(&bibstring).unwrap();
+ let citekey = re.captures(&bibstring).unwrap().get(1).unwrap().as_str();
+
+ assert_eq!(citekey, "citekey77_2001:!?");
- assert_eq!(result.get(1).unwrap().as_str(), "citekey77_2001:!?")
+ if bibstring.contains(&citekey) {
+ let append_char = "a";
+ let new_entry_string_clone = bibstring.clone();
+
+ let updated_bibstring = re
+ .replace(&new_entry_string_clone, |caps: &Captures| {
+ format!("{{{}{},", &caps[1], &append_char)
+ })
+ .to_string();
+
+ assert_eq!(updated_bibstring, "@article{citekey77_2001:!?a, author = {Hanks, Tom}, title = {A great book}, year = {2001}}")
+ }
}
}