From c555c8666268efdff4d7107d5a527b899679559e Mon Sep 17 00:00:00 2001 From: lukeflo Date: Mon, 14 Oct 2024 22:04:26 +0200 Subject: check file format, use new keys() method of biblatex crate --- Cargo.lock | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/backend/bib.rs | 29 +++++++- src/frontend/tui.rs | 71 ++----------------- 4 files changed, 232 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d3503e..e9ff8b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,7 @@ dependencies = [ "crossterm", "editor-command", "futures", + "hayagriva", "itertools", "nucleo-matcher", "ratatui", @@ -176,6 +177,43 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "citationberg" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92fea693c83bd967604be367dc1e1b4895625eabafec2eec66c51092e18e700e" +dependencies = [ + "quick-xml", + "serde", +] + [[package]] name = "clipboard-win" version = "5.4.0" @@ -301,6 +339,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "derive-new" version = "0.6.0" @@ -312,6 +356,17 @@ dependencies = [ "syn", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dlib" version = "0.5.2" @@ -444,6 +499,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "futures" version = "0.3.31" @@ -549,6 +613,16 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.15.0" @@ -560,6 +634,27 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hayagriva" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3de14f15f4243222e84000669030b3a2fe3a0c6755fd4e38e8a92de039ec21ef" +dependencies = [ + "biblatex", + "ciborium", + "citationberg", + "indexmap", + "numerals", + "paste", + "serde", + "serde_yaml", + "thiserror", + "unic-langid", + "unicode-segmentation", + "unscanny", + "url", +] + [[package]] name = "heck" version = "0.5.0" @@ -581,6 +676,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "image" version = "0.25.2" @@ -608,6 +713,7 @@ checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", "hashbrown", + "serde", ] [[package]] @@ -944,6 +1050,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "petgraph" version = "0.6.5" @@ -1001,6 +1113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", + "serde", ] [[package]] @@ -1091,6 +1204,39 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -1266,6 +1412,15 @@ dependencies = [ "weezl", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -1378,6 +1533,31 @@ dependencies = [ "petgraph", ] +[[package]] +name = "unic-langid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dd9d1e72a73b25e07123a80776aae3e7b0ec461ef94f9151eed6ec88005a44" +dependencies = [ + "unic-langid-impl", +] + +[[package]] +name = "unic-langid-impl" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a5422c1f65949306c99240b81de9f3f15929f5a8bfe05bb44b034cc8bf593e5" +dependencies = [ + "serde", + "tinystr", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + [[package]] name = "unicode-ident" version = "1.0.13" @@ -1416,12 +1596,30 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "unscanny" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9df2af067a7953e9c3831320f35c1cc0600c30d44d9f7a12b01db1cd88d6b47" +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + [[package]] name = "valuable" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 2786247..035a7c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ color-eyre = "0.6.3" crossterm = { version = "0.28.1", features = ["event-stream"] } editor-command = "0.1.1" futures = "0.3.30" +hayagriva = "0.7.0" itertools = "0.13.0" nucleo-matcher = "0.3.1" ratatui = { version = "0.28.1", features = ["unstable-rendered-line-info"]} diff --git a/src/backend/bib.rs b/src/backend/bib.rs index bfc959d..fecb548 100644 --- a/src/backend/bib.rs +++ b/src/backend/bib.rs @@ -19,11 +19,18 @@ use biblatex::{self, Bibliography}; use biblatex::{ChunksExt, Type}; 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, // list of all citekeys @@ -33,6 +40,7 @@ pub struct BibiMain { 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(); @@ -40,6 +48,7 @@ impl BibiMain { let keyword_list = Self::collect_tag_list(&citekeys, &bibliography); Self { bibfile, + bibfile_format, bibfilestring, bibliography, citekeys, @@ -47,13 +56,27 @@ impl BibiMain { } } + // 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), + } + } + // 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 { - let mut citekeys: Vec = - bibstring.iter().map(|entry| entry.to_owned().key).collect(); - citekeys.sort_by_key(|name| name.to_lowercase()); + let citekeys: Vec = bibstring.keys().map(|k| k.to_owned()).collect(); + // let mut citekeys: Vec = + // bibstring.iter().map(|entry| entry.to_owned().key).collect(); + // citekeys.sort_by_key(|name| name.to_lowercase()); citekeys } diff --git a/src/frontend/tui.rs b/src/frontend/tui.rs index 698407d..e3c9c1a 100644 --- a/src/frontend/tui.rs +++ b/src/frontend/tui.rs @@ -24,6 +24,8 @@ use crossterm::{ terminal::{EnterAlternateScreen, LeaveAlternateScreen}, }; // use ratatui::backend::{Backend, CrosstermBackend}; +use color_eyre::eyre::{OptionExt, Result}; +use futures::{FutureExt, StreamExt}; use ratatui::backend::CrosstermBackend as Backend; use std::io::{stdout, Stdout}; use std::panic; @@ -31,10 +33,6 @@ use std::{ ops::{Deref, DerefMut}, time::Duration, }; - -use color_eyre::config::HookBuilder; -use color_eyre::eyre::{OptionExt, Result}; -use futures::{FutureExt, StreamExt}; use tokio::sync::mpsc; use tokio_util::sync::CancellationToken; @@ -51,14 +49,6 @@ pub enum Event { Resize(u16, u16), } -// pub type IO = std::io::{{crossterm_io | title_case}}; -// pub fn io() -> IO { -// std::io::{{crossterm_io}}() -// } -/// Representation of a terminal user interface. -/// -/// It is responsible for setting up the terminal, -/// initializing the interface and handling the draw events. #[derive(Debug)] pub struct Tui { /// Interface to the Terminal. @@ -73,7 +63,7 @@ pub struct Tui { } impl Tui { - /// Constructs a new instance of [`Tui`]. + // Constructs a new instance of [`Tui`]. pub fn new() -> Result { let terminal = ratatui::Terminal::new(Backend::new(stdout()))?; let (sender, receiver) = mpsc::unbounded_channel(); @@ -150,26 +140,6 @@ impl Tui { cancellation_token.cancel(); } - /// Initializes the terminal interface. - /// - /// It enables the raw mode and sets terminal properties. - // pub fn init(&mut self) -> Result<()> { - // terminal::enable_raw_mode()?; - // crossterm::execute!(io::stdout(), EnterAlternateScreen, EnableMouseCapture)?; - - // // Define a custom panic hook to reset the terminal properties. - // // This way, you won't have your terminal messed up if an unexpected error happens. - // let panic_hook = panic::take_hook(); - // panic::set_hook(Box::new(move |panic| { - // Self::reset().expect("failed to reset the terminal"); - // panic_hook(panic); - // })); - - // self.terminal.hide_cursor()?; - // self.terminal.clear()?; - // Ok(()) - // } - pub fn enter(&mut self) -> Result<()> { crossterm::terminal::enable_raw_mode()?; crossterm::execute!(stdout(), EnterAlternateScreen, cursor::Hide)?; @@ -216,10 +186,10 @@ impl Tui { Ok(()) } - /// [`Draw`] the terminal interface by [`rendering`] the widgets. - /// - /// [`Draw`]: ratatui::Terminal::draw - /// [`rendering`]: crate::ui::render + // [`Draw`] the terminal interface by [`rendering`] the widgets. + // + // [`Draw`]: ratatui::Terminal::draw + // [`rendering`]: crate::ui::render pub fn draw(&mut self, app: &mut App) -> Result<()> { // self.terminal.draw(|frame| ui::render(app, frame))?; self.terminal @@ -230,33 +200,6 @@ impl Tui { pub async fn next(&mut self) -> Result { self.receiver.recv().await.ok_or_eyre("This is an IO error") } - - pub fn init_error_hooks() -> Result<()> { - let (panic, error) = HookBuilder::default().into_hooks(); - let panic = panic.into_panic_hook(); - let error = error.into_eyre_hook(); - color_eyre::eyre::set_hook(Box::new(move |e| { - let _ = crossterm::execute!( - stdout(), - DisableMouseCapture, - LeaveAlternateScreen, - cursor::Show - ); - let _ = crossterm::terminal::disable_raw_mode(); - error(e) - }))?; - std::panic::set_hook(Box::new(move |info| { - let _ = crossterm::execute!( - stdout(), - DisableMouseCapture, - LeaveAlternateScreen, - cursor::Show - ); - let _ = crossterm::terminal::disable_raw_mode(); - panic(info) - })); - Ok(()) - } } impl Deref for Tui { -- cgit v1.2.3 From d54b08f8fbe372afdd9b4bc3e366555ebdef4372 Mon Sep 17 00:00:00 2001 From: lukeflo Date: Thu, 17 Oct 2024 13:12:16 +0200 Subject: simplify get_authors func --- src/backend/bib.rs | 51 ++++++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/src/backend/bib.rs b/src/backend/bib.rs index fecb548..8539ab3 100644 --- a/src/backend/bib.rs +++ b/src/backend/bib.rs @@ -170,39 +170,36 @@ impl BibiEntry { } pub fn get_authors(citekey: &str, biblio: &Bibliography) -> String { - let authors = { - if biblio.get(&citekey).unwrap().author().is_ok() { - let authors = biblio.get(&citekey).unwrap().author().unwrap(); - if authors.len() > 1 { - let authors = format!("{} et al.", authors[0].name); - authors - } else if authors.len() == 1 { - let authors = authors[0].name.to_string(); - authors - } else { - let editors_authors = format!("empty"); - editors_authors - } + if biblio.get(&citekey).unwrap().author().is_ok() { + let authors = biblio.get(&citekey).unwrap().author().unwrap(); + if authors.len() > 1 { + let authors = format!("{} et al.", authors[0].name); + authors + } else if authors.len() == 1 { + let authors = authors[0].name.to_string(); + authors } else { - if biblio.get(&citekey).unwrap().editors().is_ok() { - let editors = biblio.get(&citekey).unwrap().editors().unwrap(); - if editors.len() > 1 { - let editors = format!("{} (ed.) et al.", editors[0].0[0].name); - editors - } else if editors.len() == 1 { - let editors = format!("{} (ed.)", editors[0].0[0].name); - editors - } else { - let editors_authors = format!("empty"); - editors_authors - } + let editors_authors = format!("empty"); + editors_authors + } + } else { + if biblio.get(&citekey).unwrap().editors().is_ok() { + let editors = biblio.get(&citekey).unwrap().editors().unwrap(); + if editors.len() > 1 { + let editors = format!("{} (ed.) et al.", editors[0].0[0].name); + editors + } else if editors.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 } - }; - authors + } } pub fn get_title(citekey: &str, biblio: &Bibliography) -> String { -- cgit v1.2.3 From 374dd9b36dec8d122078cb7ef10dd912fef32460 Mon Sep 17 00:00:00 2001 From: lukeflo Date: Thu, 17 Oct 2024 13:49:52 +0200 Subject: testwise rewrite entry table parsing --- src/backend/search.rs | 22 +++++------ src/frontend/app.rs | 8 ++-- src/frontend/entries.rs | 100 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 82 insertions(+), 48 deletions(-) diff --git a/src/backend/search.rs b/src/backend/search.rs index f9062c8..4576d2d 100644 --- a/src/backend/search.rs +++ b/src/backend/search.rs @@ -114,17 +114,17 @@ mod tests { #[test] fn test_vector_join() { - let bibvec: EntryTableItem = EntryTableItem::new( - "Author", - "Title", - "1999", - "article", - "hello, bye", - "author_1999", - "An abstract with multiple sentences. Here is the second", - "https://www.bibiman.org", - "/home/file/path.pdf", - ); + let bibvec: EntryTableItem = EntryTableItem { + authors: "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); diff --git a/src/frontend/app.rs b/src/frontend/app.rs index 8d6454d..a035231 100644 --- a/src/frontend/app.rs +++ b/src/frontend/app.rs @@ -79,7 +79,7 @@ impl App { let biblio_data = BibiData::new(&main_biblio.bibliography, &main_biblio.citekeys); let tag_list = TagList::new(main_biblio.keyword_list.clone()); let search_struct = BibiSearch::default(); - let entry_table = EntryTable::from_iter(biblio_data.entry_list.bibentries.clone()); + let entry_table = EntryTable::new(&main_biblio.citekeys, &main_biblio.bibliography); let current_area = CurrentArea::EntryArea; Ok(Self { running, @@ -133,7 +133,8 @@ impl App { BibiData::new(&self.main_biblio.bibliography, &self.main_biblio.citekeys); // self.tag_list = TagList::from_iter(self.main_biblio.keyword_list.clone()); self.tag_list = TagList::new(self.main_biblio.keyword_list.clone()); - self.entry_table = EntryTable::from_iter(self.biblio_data.entry_list.bibentries.clone()); + self.entry_table = + EntryTable::new(&self.main_biblio.citekeys, &self.main_biblio.bibliography); } // Toggle moveable list between entries and tags @@ -157,7 +158,8 @@ impl App { } pub fn reset_current_list(&mut self) { - self.entry_table = EntryTable::from_iter(self.biblio_data.entry_list.bibentries.clone()); + self.entry_table = + EntryTable::new(&self.main_biblio.citekeys, &self.main_biblio.bibliography); self.tag_list = TagList::new(self.main_biblio.keyword_list.clone()); if let CurrentArea::TagArea = self.current_area { self.tag_list.tag_list_state.select(Some(0)) diff --git a/src/frontend/entries.rs b/src/frontend/entries.rs index 98604f9..95f6f84 100644 --- a/src/frontend/entries.rs +++ b/src/frontend/entries.rs @@ -17,7 +17,8 @@ use super::app::App; use super::tui::Tui; -use crate::backend::search::BibiSearch; +use crate::backend::{bib::BibiEntry, search::BibiSearch}; +use biblatex::Bibliography; use color_eyre::eyre::{Context, Ok, Result}; use core::panic; use editor_command::EditorBuilder; @@ -36,18 +37,49 @@ pub struct EntryTable { pub entry_info_scroll_state: ScrollbarState, } -impl FromIterator> for EntryTable { - fn from_iter>>(iter: T) -> Self { - let entry_table_items: Vec = iter +// impl FromIterator> for EntryTable { +// fn from_iter>>(iter: T) -> Self { +// let entry_table_items: Vec = iter +// .into_iter() +// .sorted() +// // 0: authors, 1: title, 2: date, 3: pubtype, 4: keywords, 5: citekey +// // 6: abstract, 7: doi/url, 8: pdf filepath +// // See backend/bib.rs BibiEntry impl +// .map(|i| { +// EntryTableItem::new( +// &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], &i[6], &i[7], &i[8], +// ) +// }) +// .collect(); +// let entry_table_state = TableState::default().with_selected(0); +// let entry_scroll_state = ScrollbarState::new(entry_table_items.len()); +// let entry_info_scroll_state = ScrollbarState::default(); +// Self { +// entry_table_items, +// entry_table_at_search_start: Vec::new(), +// entry_table_state, +// entry_scroll_state, +// entry_info_scroll: 0, +// entry_info_scroll_state, +// } +// } +// } + +impl EntryTable { + pub fn new(citekeys: &Vec, biblio: &Bibliography) -> Self { + let entry_table_items: Vec = citekeys .into_iter() .sorted() - // 0: authors, 1: title, 2: date, 3: pubtype, 4: keywords, 5: citekey - // 6: abstract, 7: doi/url, 8: pdf filepath - // See backend/bib.rs BibiEntry impl - .map(|i| { - EntryTableItem::new( - &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], &i[6], &i[7], &i[8], - ) + .map(|key| EntryTableItem { + authors: BibiEntry::get_authors(&key, &biblio), + title: BibiEntry::get_title(&key, &biblio), + year: BibiEntry::get_year(&key, &biblio), + pubtype: BibiEntry::get_pubtype(&key, &biblio), + keywords: BibiEntry::get_keywords(&key, &biblio), + citekey: key.clone(), + abstract_text: BibiEntry::get_abstract(&key, &biblio), + doi_url: BibiEntry::get_weblink(&key, &biblio), + filepath: BibiEntry::get_filepath(&key, &biblio), }) .collect(); let entry_table_state = TableState::default().with_selected(0); @@ -79,29 +111,29 @@ pub struct EntryTableItem { } impl EntryTableItem { - pub fn new( - authors: &str, - title: &str, - year: &str, - pubtype: &str, - keywords: &str, - citekey: &str, - abstract_text: &str, - doi_url: &str, - filepath: &str, - ) -> Self { - Self { - authors: authors.to_string(), - title: title.to_string(), - year: year.to_string(), - pubtype: pubtype.to_string(), - keywords: keywords.to_string(), - citekey: citekey.to_string(), - abstract_text: abstract_text.to_string(), - doi_url: doi_url.to_string(), - filepath: filepath.to_string(), - } - } + // pub fn new( + // authors: String, + // title: String, + // year: String, + // pubtype: String, + // keywords: String, + // citekey: String, + // abstract_text: String, + // doi_url: String, + // filepath: String, + // ) -> Self { + // Self { + // authors, + // title, + // year, + // pubtype, + // keywords, + // citekey, + // abstract_text, + // doi_url, + // filepath, + // } + // } // This functions decides which fields are rendered in the entry table // Fields which should be usable but not visible can be left out -- cgit v1.2.3 From 2983a94911b4ba76891ae3beaefcb5033bfc6ddd Mon Sep 17 00:00:00 2001 From: lukeflo Date: Thu, 17 Oct 2024 14:01:34 +0200 Subject: make scrollbars adapt to lists filtered by search --- src/frontend/entries.rs | 4 ++++ src/frontend/keywords.rs | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/frontend/entries.rs b/src/frontend/entries.rs index 95f6f84..fb80b46 100644 --- a/src/frontend/entries.rs +++ b/src/frontend/entries.rs @@ -288,6 +288,10 @@ impl App { let filtered_list = BibiSearch::search_entry_list(&mut self.search_struct.search_string, orig_list.clone()); self.entry_table.entry_table_items = filtered_list; + self.entry_table.entry_scroll_state = ScrollbarState::content_length( + self.entry_table.entry_scroll_state, + self.entry_table.entry_table_items.len(), + ); } // Open file connected with entry through 'file' or 'pdf' field diff --git a/src/frontend/keywords.rs b/src/frontend/keywords.rs index 9432752..98c4222 100644 --- a/src/frontend/keywords.rs +++ b/src/frontend/keywords.rs @@ -118,6 +118,10 @@ impl App { let filtered_list = BibiSearch::search_tag_list(&self.search_struct.search_string, orig_list.clone()); self.tag_list.tag_list_items = filtered_list; + self.tag_list.tag_scroll_state = ScrollbarState::content_length( + self.tag_list.tag_scroll_state, + self.tag_list.tag_list_items.len(), + ); // self.tag_list = TagList::from_iter(filtered_list) } @@ -143,6 +147,10 @@ impl App { self.search_struct.filtered_tag_list = filtered_keywords.clone(); self.tag_list.tag_list_items = filtered_keywords; + self.tag_list.tag_scroll_state = ScrollbarState::content_length( + self.tag_list.tag_scroll_state, + self.tag_list.tag_list_items.len(), + ); } // Filter the entry list by tags when hitting enter @@ -154,6 +162,11 @@ impl App { let filtered_list = BibiSearch::filter_entries_by_tag(&keyword, &orig_list); self.tag_list.selected_keyword = keyword.to_string(); self.entry_table.entry_table_items = filtered_list; + // Update scrollbar state with new lenght of itemlist + self.entry_table.entry_scroll_state = ScrollbarState::content_length( + self.entry_table.entry_scroll_state, + self.entry_table.entry_table_items.len(), + ); self.filter_tags_by_entries(); self.toggle_area(); self.entry_table.entry_table_state.select(Some(0)); -- cgit v1.2.3 From 5abdd1822a1d388feb36b0d4e62316b4671bf406 Mon Sep 17 00:00:00 2001 From: lukeflo Date: Thu, 17 Oct 2024 14:04:19 +0200 Subject: Delete old code --- src/frontend/keywords.rs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/frontend/keywords.rs b/src/frontend/keywords.rs index 98c4222..ba74b02 100644 --- a/src/frontend/keywords.rs +++ b/src/frontend/keywords.rs @@ -42,23 +42,6 @@ impl TagListItem { } } -// impl FromIterator for TagList { -// fn from_iter>(iter: I) -> Self { -// let tag_list_items: Vec = iter -// .into_iter() -// .map(|info| TagListItem::new(&info)) -// .collect(); -// let tag_list_state = ListState::default(); // for preselection: .with_selected(Some(0)); -// let tag_scroll_state = ScrollbarState::new(tag_list_items.len()); -// Self { -// tag_list_items, -// tag_list_state, -// tag_scroll_state, -// selected_keyword: String::new(), -// } -// } -// } - impl TagList { pub fn new(keyword_list: Vec) -> Self { let tag_list_items = keyword_list; @@ -118,11 +101,11 @@ impl App { let filtered_list = BibiSearch::search_tag_list(&self.search_struct.search_string, orig_list.clone()); self.tag_list.tag_list_items = filtered_list; + // Update scrollbar length after filtering list self.tag_list.tag_scroll_state = ScrollbarState::content_length( self.tag_list.tag_scroll_state, self.tag_list.tag_list_items.len(), ); - // self.tag_list = TagList::from_iter(filtered_list) } pub fn filter_tags_by_entries(&mut self) { -- cgit v1.2.3 From 1fb272e563aca3b90a82fcbef68ed1c28cb7b212 Mon Sep 17 00:00:00 2001 From: lukeflo Date: Thu, 17 Oct 2024 23:02:06 +0200 Subject: Implement sorting and remove unneccessary struct - Implement sorting of list (by authors for now) - Remove hole BibiData struct - Create entry table content directly through iterator --- src/backend/bib.rs | 55 --------------------- src/frontend/app.rs | 6 --- src/frontend/entries.rs | 126 ++++++++++++++++++++++-------------------------- src/frontend/handler.rs | 3 ++ src/frontend/ui.rs | 27 +++++++---- 5 files changed, 78 insertions(+), 139 deletions(-) diff --git a/src/backend/bib.rs b/src/backend/bib.rs index 8539ab3..aca08b3 100644 --- a/src/backend/bib.rs +++ b/src/backend/bib.rs @@ -113,61 +113,6 @@ impl BibiMain { keyword_list.dedup(); keyword_list } -} - -#[derive(Debug)] -pub struct BibiData { - pub entry_list: BibiDataSets, -} - -impl BibiData { - pub fn new(biblio: &Bibliography, citekeys: &Vec) -> Self { - Self { - entry_list: { - let bibentries = citekeys - .into_iter() - .map(|citekey| BibiEntry::new(&citekey, &biblio)) - .collect(); - BibiDataSets { bibentries } - }, - } - } -} - -// Parent struct which keeps the Vector of all bibentries -// Necessary for implementing FromIterator -#[derive(Debug)] -pub struct BibiDataSets { - pub bibentries: Vec>, -} - -// Struct which has to be created for every entry of bibdatabase -#[derive(Debug)] -pub struct BibiEntry { - pub authors: String, - pub title: String, - pub year: String, - pub pubtype: String, - pub keywords: String, - pub citekey: String, - pub weblink: String, - pub filepath: String, -} - -impl BibiEntry { - pub fn new(citekey: &str, biblio: &Bibliography) -> Vec { - vec![ - Self::get_authors(&citekey, &biblio), - Self::get_title(&citekey, &biblio), - Self::get_year(&citekey, &biblio), - Self::get_pubtype(&citekey, &biblio), - Self::get_keywords(&citekey, &biblio), - citekey.to_string(), - Self::get_abstract(&citekey, &biblio), - Self::get_weblink(&citekey, &biblio), - Self::get_filepath(&citekey, &biblio), - ] - } pub fn get_authors(citekey: &str, biblio: &Bibliography) -> String { if biblio.get(&citekey).unwrap().author().is_ok() { diff --git a/src/frontend/app.rs b/src/frontend/app.rs index a035231..10cfa9b 100644 --- a/src/frontend/app.rs +++ b/src/frontend/app.rs @@ -53,8 +53,6 @@ pub struct App { pub main_bibfile: PathBuf, // main bibliography pub main_biblio: BibiMain, - // bibliographic data - pub biblio_data: BibiData, // search struct: pub search_struct: BibiSearch, // tag list @@ -76,7 +74,6 @@ impl App { let running = true; let main_bibfile = args.bibfilearg; let main_biblio = BibiMain::new(main_bibfile.clone()); - let biblio_data = BibiData::new(&main_biblio.bibliography, &main_biblio.citekeys); let tag_list = TagList::new(main_biblio.keyword_list.clone()); let search_struct = BibiSearch::default(); let entry_table = EntryTable::new(&main_biblio.citekeys, &main_biblio.bibliography); @@ -85,7 +82,6 @@ impl App { running, main_bibfile, main_biblio, - biblio_data, tag_list, search_struct, entry_table, @@ -129,8 +125,6 @@ impl App { pub fn update_lists(&mut self) { self.main_biblio = BibiMain::new(self.main_bibfile.clone()); - self.biblio_data = - BibiData::new(&self.main_biblio.bibliography, &self.main_biblio.citekeys); // self.tag_list = TagList::from_iter(self.main_biblio.keyword_list.clone()); self.tag_list = TagList::new(self.main_biblio.keyword_list.clone()); self.entry_table = diff --git a/src/frontend/entries.rs b/src/frontend/entries.rs index fb80b46..38b1852 100644 --- a/src/frontend/entries.rs +++ b/src/frontend/entries.rs @@ -17,12 +17,11 @@ use super::app::App; use super::tui::Tui; -use crate::backend::{bib::BibiEntry, search::BibiSearch}; +use crate::backend::{bib::BibiMain, search::BibiSearch}; use biblatex::Bibliography; use color_eyre::eyre::{Context, Ok, Result}; use core::panic; use editor_command::EditorBuilder; -use itertools::Itertools; use ratatui::widgets::{ScrollbarState, TableState}; use std::process::{Command, Stdio}; @@ -31,69 +30,82 @@ use std::process::{Command, Stdio}; pub struct EntryTable { pub entry_table_items: Vec, pub entry_table_at_search_start: Vec, + pub entry_table_reversed_sort: bool, pub entry_table_state: TableState, pub entry_scroll_state: ScrollbarState, pub entry_info_scroll: u16, pub entry_info_scroll_state: ScrollbarState, } -// impl FromIterator> for EntryTable { -// fn from_iter>>(iter: T) -> Self { -// let entry_table_items: Vec = iter -// .into_iter() -// .sorted() -// // 0: authors, 1: title, 2: date, 3: pubtype, 4: keywords, 5: citekey -// // 6: abstract, 7: doi/url, 8: pdf filepath -// // See backend/bib.rs BibiEntry impl -// .map(|i| { -// EntryTableItem::new( -// &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], &i[6], &i[7], &i[8], -// ) -// }) -// .collect(); -// let entry_table_state = TableState::default().with_selected(0); -// let entry_scroll_state = ScrollbarState::new(entry_table_items.len()); -// let entry_info_scroll_state = ScrollbarState::default(); -// Self { -// entry_table_items, -// entry_table_at_search_start: Vec::new(), -// entry_table_state, -// entry_scroll_state, -// entry_info_scroll: 0, -// entry_info_scroll_state, -// } -// } -// } - impl EntryTable { pub fn new(citekeys: &Vec, biblio: &Bibliography) -> Self { - let entry_table_items: Vec = citekeys - .into_iter() - .sorted() - .map(|key| EntryTableItem { - authors: BibiEntry::get_authors(&key, &biblio), - title: BibiEntry::get_title(&key, &biblio), - year: BibiEntry::get_year(&key, &biblio), - pubtype: BibiEntry::get_pubtype(&key, &biblio), - keywords: BibiEntry::get_keywords(&key, &biblio), - citekey: key.clone(), - abstract_text: BibiEntry::get_abstract(&key, &biblio), - doi_url: BibiEntry::get_weblink(&key, &biblio), - filepath: BibiEntry::get_filepath(&key, &biblio), - }) - .collect(); + let entry_table_items = Self::set_entry_table(&citekeys, &biblio); let entry_table_state = TableState::default().with_selected(0); let entry_scroll_state = ScrollbarState::new(entry_table_items.len()); let entry_info_scroll_state = ScrollbarState::default(); Self { entry_table_items, entry_table_at_search_start: Vec::new(), + entry_table_reversed_sort: false, entry_table_state, entry_scroll_state, entry_info_scroll: 0, entry_info_scroll_state, } } + + pub fn set_entry_table(citekeys: &Vec, biblio: &Bibliography) -> Vec { + let mut entry_table: Vec = citekeys + .into_iter() + .map(|key| EntryTableItem { + authors: BibiMain::get_authors(&key, &biblio), + title: BibiMain::get_title(&key, &biblio), + year: BibiMain::get_year(&key, &biblio), + pubtype: BibiMain::get_pubtype(&key, &biblio), + keywords: BibiMain::get_keywords(&key, &biblio), + citekey: key.to_owned(), + abstract_text: BibiMain::get_abstract(&key, &biblio), + doi_url: BibiMain::get_weblink(&key, &biblio), + filepath: BibiMain::get_filepath(&key, &biblio), + }) + .collect(); + + entry_table.sort_by(|a, b| a.authors.to_lowercase().cmp(&b.authors.to_lowercase())); + entry_table + } + + // Sort entry table by specific column. + // Toggle sorting by hitting same key again + pub fn sort_entry_table(&mut self, sorting: &str) { + if self.entry_table_reversed_sort { + match sorting { + "author" => self + .entry_table_items + .sort_by(|a, b| a.authors.to_lowercase().cmp(&b.authors.to_lowercase())), + "title" => self + .entry_table_items + .sort_by(|a, b| a.title.to_lowercase().cmp(&b.title.to_lowercase())), + "year" => self + .entry_table_items + .sort_by(|a, b| a.year.to_lowercase().cmp(&b.year.to_lowercase())), + _ => {} + } + } else if !self.entry_table_reversed_sort { + match sorting { + "author" => self + .entry_table_items + .sort_by(|a, b| b.authors.to_lowercase().cmp(&a.authors.to_lowercase())), + "title" => self + .entry_table_items + .sort_by(|a, b| b.title.to_lowercase().cmp(&a.title.to_lowercase())), + "year" => self + .entry_table_items + .sort_by(|a, b| b.year.to_lowercase().cmp(&a.year.to_lowercase())), + _ => {} + } + } + self.entry_table_reversed_sort = !self.entry_table_reversed_sort; + } } // Define contents of each entry table row @@ -111,30 +123,6 @@ pub struct EntryTableItem { } impl EntryTableItem { - // pub fn new( - // authors: String, - // title: String, - // year: String, - // pubtype: String, - // keywords: String, - // citekey: String, - // abstract_text: String, - // doi_url: String, - // filepath: String, - // ) -> Self { - // Self { - // authors, - // title, - // year, - // pubtype, - // keywords, - // citekey, - // abstract_text, - // doi_url, - // filepath, - // } - // } - // This functions decides which fields are rendered in the entry table // Fields which should be usable but not visible can be left out pub fn ref_vec(&self) -> Vec<&String> { diff --git a/src/frontend/handler.rs b/src/frontend/handler.rs index c2cacf5..70ba5c7 100644 --- a/src/frontend/handler.rs +++ b/src/frontend/handler.rs @@ -121,6 +121,9 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App, tui: &mut Tui) -> R KeyCode::Char('G') | KeyCode::End => { app.select_last_entry(); } + KeyCode::Char('s') => { + app.entry_table.sort_entry_table("author"); + } KeyCode::Char('y') => { App::yank_text(&app.get_selected_citekey()); } diff --git a/src/frontend/ui.rs b/src/frontend/ui.rs index 08cebcb..1767cea 100644 --- a/src/frontend/ui.rs +++ b/src/frontend/ui.rs @@ -47,6 +47,8 @@ const SELECTED_STYLE: Style = Style::new() .add_modifier(Modifier::REVERSED); const TEXT_FG_COLOR: Color = Color::Indexed(252); const TEXT_UNSELECTED_FG_COLOR: Color = Color::Indexed(245); +const SORTED_ENTRIES: &str = "▼"; +const SORTED_ENTRIES_REVERSED: &str = "▲"; const SCROLLBAR_UPPER_CORNER: Option<&str> = Some("┓"); const SCROLLBAR_LOWER_CORNER: Option<&str> = Some("┛"); @@ -259,15 +261,22 @@ impl App { let header_style = Style::default().bold().fg(TEXT_FG_COLOR); - let header = [ - "Authors".underlined(), - "Title".underlined(), - "Year".underlined(), - "Type".underlined(), - ] - .into_iter() - .map(Cell::from) - .collect::() + let header = Row::new(vec![ + Cell::from(Line::from(vec![ + Span::raw("Author").underlined(), + Span::raw(format!( + " {}", + if self.entry_table.entry_table_reversed_sort { + SORTED_ENTRIES_REVERSED + } else { + SORTED_ENTRIES + } + )), + ])), + Cell::from("Title".to_string().underlined()), + Cell::from("Year".to_string().underlined()), + Cell::from("Type".to_string().underlined()), + ]) .style(header_style) .height(1); -- cgit v1.2.3 From 8362f2a4272cf11e54c9384b19d5c878141bf76d Mon Sep 17 00:00:00 2001 From: lukeflo Date: Thu, 17 Oct 2024 23:06:22 +0200 Subject: update README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0bd95a6..ae34818 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ updated: - [x] **Scrollbar** for better navigating. - [ ] **Open related notes file** for specific entry. - [ ] **Add Entry via DOI** as formatted code. +- [ ] **Sort Entries** by different values (partly possible for author column) - [ ] **Support Hayagriva(`.yaml.`)** format as input. - [ ] **Implement config file** for setting some default values like main bibfile, PDF-opener, or editor -- cgit v1.2.3 From 917b9c522635a304ff7c70499f05903a694696a3 Mon Sep 17 00:00:00 2001 From: lukeflo Date: Thu, 17 Oct 2024 23:24:51 +0200 Subject: correct sorting function --- src/frontend/entries.rs | 21 +++++++++++++-------- src/frontend/handler.rs | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/frontend/entries.rs b/src/frontend/entries.rs index 38b1852..63a2a1b 100644 --- a/src/frontend/entries.rs +++ b/src/frontend/entries.rs @@ -76,35 +76,37 @@ impl EntryTable { // Sort entry table by specific column. // Toggle sorting by hitting same key again - pub fn sort_entry_table(&mut self, sorting: &str) { + pub fn sort_entry_table(&mut self, sorting: &str, toggle: bool) { + if toggle { + self.entry_table_reversed_sort = !self.entry_table_reversed_sort; + } if self.entry_table_reversed_sort { match sorting { "author" => self .entry_table_items - .sort_by(|a, b| a.authors.to_lowercase().cmp(&b.authors.to_lowercase())), + .sort_by(|a, b| b.authors.to_lowercase().cmp(&a.authors.to_lowercase())), "title" => self .entry_table_items - .sort_by(|a, b| a.title.to_lowercase().cmp(&b.title.to_lowercase())), + .sort_by(|a, b| b.title.to_lowercase().cmp(&a.title.to_lowercase())), "year" => self .entry_table_items - .sort_by(|a, b| a.year.to_lowercase().cmp(&b.year.to_lowercase())), + .sort_by(|a, b| b.year.to_lowercase().cmp(&a.year.to_lowercase())), _ => {} } } else if !self.entry_table_reversed_sort { match sorting { "author" => self .entry_table_items - .sort_by(|a, b| b.authors.to_lowercase().cmp(&a.authors.to_lowercase())), + .sort_by(|a, b| a.authors.to_lowercase().cmp(&b.authors.to_lowercase())), "title" => self .entry_table_items - .sort_by(|a, b| b.title.to_lowercase().cmp(&a.title.to_lowercase())), + .sort_by(|a, b| a.title.to_lowercase().cmp(&b.title.to_lowercase())), "year" => self .entry_table_items - .sort_by(|a, b| b.year.to_lowercase().cmp(&a.year.to_lowercase())), + .sort_by(|a, b| a.year.to_lowercase().cmp(&b.year.to_lowercase())), _ => {} } } - self.entry_table_reversed_sort = !self.entry_table_reversed_sort; } } @@ -276,6 +278,9 @@ impl App { let filtered_list = BibiSearch::search_entry_list(&mut self.search_struct.search_string, orig_list.clone()); self.entry_table.entry_table_items = filtered_list; + if self.entry_table.entry_table_reversed_sort { + self.entry_table.sort_entry_table("author", false); + } self.entry_table.entry_scroll_state = ScrollbarState::content_length( self.entry_table.entry_scroll_state, self.entry_table.entry_table_items.len(), diff --git a/src/frontend/handler.rs b/src/frontend/handler.rs index 70ba5c7..ec1647e 100644 --- a/src/frontend/handler.rs +++ b/src/frontend/handler.rs @@ -122,7 +122,7 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App, tui: &mut Tui) -> R app.select_last_entry(); } KeyCode::Char('s') => { - app.entry_table.sort_entry_table("author"); + app.entry_table.sort_entry_table("author", true); } KeyCode::Char('y') => { App::yank_text(&app.get_selected_citekey()); -- cgit v1.2.3 From b5538d8c8408f1afbcfecb2a3b0407c3ad53ebe5 Mon Sep 17 00:00:00 2001 From: lukeflo Date: Fri, 18 Oct 2024 17:07:25 +0200 Subject: Handle short and long author fields --- Cargo.lock | 4 +-- Cargo.toml | 2 +- src/backend/bib.rs | 20 +++++------ src/backend/search.rs | 1 + src/frontend/entries.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++--- src/frontend/ui.rs | 21 ++++++------ src/main.rs | 6 ++-- tests/biblatex-test.bib | 2 +- 8 files changed, 114 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9ff8b6..8a84eaf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -636,9 +636,9 @@ dependencies = [ [[package]] name = "hayagriva" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de14f15f4243222e84000669030b3a2fe3a0c6755fd4e38e8a92de039ec21ef" +checksum = "7a3635c2577f77499c9dc3dceeef2e64e6c146e711b1861507a0f15b20641348" dependencies = [ "biblatex", "ciborium", diff --git a/Cargo.toml b/Cargo.toml index 035a7c8..e9b5158 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ color-eyre = "0.6.3" crossterm = { version = "0.28.1", features = ["event-stream"] } editor-command = "0.1.1" futures = "0.3.30" -hayagriva = "0.7.0" +hayagriva = "0.8.0" itertools = "0.13.0" nucleo-matcher = "0.3.1" ratatui = { version = "0.28.1", features = ["unstable-rendered-line-info"]} diff --git a/src/backend/bib.rs b/src/backend/bib.rs index aca08b3..1f5d05d 100644 --- a/src/backend/bib.rs +++ b/src/backend/bib.rs @@ -17,6 +17,7 @@ use biblatex::{self, Bibliography}; use biblatex::{ChunksExt, Type}; +use itertools::Itertools; use std::{fs, path::PathBuf}; #[derive(Debug)] @@ -74,16 +75,13 @@ impl BibiMain { // since it is the entry point of the biblatex crate. pub fn get_citekeys(bibstring: &Bibliography) -> Vec { let citekeys: Vec = bibstring.keys().map(|k| k.to_owned()).collect(); - // let mut citekeys: Vec = - // bibstring.iter().map(|entry| entry.to_owned().key).collect(); - // citekeys.sort_by_key(|name| name.to_lowercase()); 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: &Vec, biblio: &Bibliography) -> Vec { + pub fn collect_tag_list(citekeys: &[String], biblio: &Bibliography) -> Vec { // Initialize vector collecting all keywords let mut keyword_list = vec![]; @@ -118,8 +116,8 @@ impl BibiMain { if biblio.get(&citekey).unwrap().author().is_ok() { let authors = biblio.get(&citekey).unwrap().author().unwrap(); if authors.len() > 1 { - let authors = format!("{} et al.", authors[0].name); - authors + 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 @@ -128,12 +126,14 @@ impl BibiMain { editors_authors } } else { - if biblio.get(&citekey).unwrap().editors().is_ok() { + if !biblio.get(&citekey).unwrap().editors().unwrap().is_empty() { let editors = biblio.get(&citekey).unwrap().editors().unwrap(); - if editors.len() > 1 { - let editors = format!("{} (ed.) et al.", editors[0].0[0].name); + 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.len() == 1 { + } else if editors[0].0.len() == 1 { let editors = format!("{} (ed.)", editors[0].0[0].name); editors } else { diff --git a/src/backend/search.rs b/src/backend/search.rs index 4576d2d..65d97d7 100644 --- a/src/backend/search.rs +++ b/src/backend/search.rs @@ -116,6 +116,7 @@ mod tests { 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(), diff --git a/src/frontend/entries.rs b/src/frontend/entries.rs index 63a2a1b..f64e35e 100644 --- a/src/frontend/entries.rs +++ b/src/frontend/entries.rs @@ -17,7 +17,10 @@ use super::app::App; use super::tui::Tui; -use crate::backend::{bib::BibiMain, search::BibiSearch}; +use crate::backend::{ + bib::{BibiMain, FileFormat}, + search::BibiSearch, +}; use biblatex::Bibliography; use color_eyre::eyre::{Context, Ok, Result}; use core::panic; @@ -54,11 +57,12 @@ impl EntryTable { } } - pub fn set_entry_table(citekeys: &Vec, biblio: &Bibliography) -> Vec { + pub fn set_entry_table(citekeys: &[String], biblio: &Bibliography) -> Vec { let mut entry_table: Vec = citekeys .into_iter() .map(|key| EntryTableItem { authors: BibiMain::get_authors(&key, &biblio), + short_author: String::new(), title: BibiMain::get_title(&key, &biblio), year: BibiMain::get_year(&key, &biblio), pubtype: BibiMain::get_pubtype(&key, &biblio), @@ -114,6 +118,7 @@ impl EntryTable { #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct EntryTableItem { pub authors: String, + pub short_author: String, pub title: String, pub year: String, pub pubtype: String, @@ -127,8 +132,32 @@ pub struct EntryTableItem { impl EntryTableItem { // This functions decides which fields are rendered in the entry table // Fields which should be usable but not visible can be left out - pub fn ref_vec(&self) -> Vec<&String> { - vec![&self.authors, &self.title, &self.year, &self.pubtype] + pub fn ref_vec(&mut self) -> Vec<&str> { + self.short_author = match self.authors.split_once(",") { + Some((first, _rest)) => { + if self.authors.contains("(ed.)") { + let first_author = format!("{} et al. (ed.)", first); + first_author + } else { + let first_author = format!("{} et al.", first); + first_author + } + } + None => String::from(""), + }; + + vec![ + { + if self.short_author.is_empty() { + &self.authors + } else { + &self.short_author + } + }, + &self.title, + &self.year, + &self.pubtype, + ] } pub fn authors(&self) -> &str { @@ -150,6 +179,14 @@ impl EntryTableItem { pub fn citekey(&self) -> &str { &self.citekey } + + pub fn doi_url(&self) -> &str { + &self.doi_url + } + + pub fn filepath(&self) -> &str { + &self.filepath + } } impl App { @@ -355,6 +392,8 @@ impl App { #[cfg(test)] mod tests { + use super::EntryTableItem; + #[test] fn check_os() { let os = std::env::consts::OS; @@ -365,4 +404,46 @@ mod tests { std::env::consts::OS ) } + + #[test] + fn shorten_authors() { + let mut entry: EntryTableItem = EntryTableItem { + authors: "Miller, Schmitz, Bernard".to_string(), + short_author: "".to_string(), + title: "A title".to_string(), + year: "2000".to_string(), + pubtype: "article".to_string(), + keywords: "key1, key2".to_string(), + citekey: "miller_2000".to_string(), + abstract_text: "An abstract".to_string(), + doi_url: "www.text.org".to_string(), + filepath: "/home/test".to_string(), + }; + + let entry_vec = EntryTableItem::ref_vec(&mut entry); + + let mut entry_editors: EntryTableItem = EntryTableItem { + authors: "Miller, Schmitz, Bernard (ed.)".to_string(), + short_author: "".to_string(), + title: "A title".to_string(), + year: "2000".to_string(), + pubtype: "article".to_string(), + keywords: "key1, key2".to_string(), + citekey: "miller_2000".to_string(), + abstract_text: "An abstract".to_string(), + doi_url: "www.text.org".to_string(), + filepath: "/home/test".to_string(), + }; + + let entry_vec_editors = EntryTableItem::ref_vec(&mut entry_editors); + + assert_eq!( + entry_vec, + vec!["Miller et al.", "A title", "2000", "article"] + ); + assert_eq!( + entry_vec_editors, + vec!["Miller et al. (ed.)", "A title", "2000", "article"] + ) + } } diff --git a/src/frontend/ui.rs b/src/frontend/ui.rs index 1767cea..d94a654 100644 --- a/src/frontend/ui.rs +++ b/src/frontend/ui.rs @@ -28,7 +28,10 @@ use ratatui::{ }, }; -use crate::{frontend::app::App, frontend::keywords::TagListItem}; +use crate::{ + backend::bib::BibiMain, + frontend::{app::App, keywords::TagListItem}, +}; use super::app::{CurrentArea, FormerArea}; @@ -284,7 +287,7 @@ impl App { let rows = self .entry_table .entry_table_items - .iter() + .iter_mut() .enumerate() .map(|(_i, data)| { let item = data.ref_vec(); @@ -349,15 +352,16 @@ impl App { let mut lines = vec![]; lines.push(Line::from(vec![ Span::styled("Authors: ", style_value), - Span::styled(cur_entry.authors.clone(), Style::new().green()), + // Span::styled(cur_entry.authors.clone(), Style::new().green()), + Span::styled(cur_entry.authors(), Style::new().green()), ])); lines.push(Line::from(vec![ Span::styled("Title: ", style_value), - Span::styled(cur_entry.title.clone(), Style::new().magenta()), + Span::styled(cur_entry.title(), Style::new().magenta()), ])); lines.push(Line::from(vec![ Span::styled("Year: ", style_value), - Span::styled(cur_entry.year.clone(), Style::new().light_magenta()), + Span::styled(cur_entry.year(), Style::new().light_magenta()), ])); if !cur_entry.doi_url.is_empty() || !cur_entry.filepath.is_empty() { lines.push(Line::raw("")); @@ -366,7 +370,7 @@ impl App { lines.push(Line::from(vec![ Span::styled("DOI/URL: ", style_value_sec), Span::styled( - cur_entry.doi_url.clone(), + cur_entry.doi_url(), Style::default().fg(TEXT_FG_COLOR).underlined(), ), ])); @@ -374,10 +378,7 @@ impl App { if !cur_entry.filepath.is_empty() { lines.push(Line::from(vec![ Span::styled("File: ", style_value_sec), - Span::styled( - cur_entry.filepath.clone(), - Style::default().fg(TEXT_FG_COLOR), - ), + Span::styled(cur_entry.filepath(), Style::default().fg(TEXT_FG_COLOR)), ])); } lines.push(Line::from("")); diff --git a/src/main.rs b/src/main.rs index 6ef7ee1..b90aeea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,9 +42,9 @@ async fn main() -> Result<()> { std::process::exit(0); } - if !parsed_args.bibfilearg.is_file() { - panic!("No \'.bib\' file passed, aborting") - } + // if !parsed_args.bibfilearg.is_file() { + // panic!("No \'.bib\' file passed, aborting") + // } init_error_hooks()?; diff --git a/tests/biblatex-test.bib b/tests/biblatex-test.bib index 7a1c226..b89416b 100644 --- a/tests/biblatex-test.bib +++ b/tests/biblatex-test.bib @@ -15,7 +15,7 @@ publisher = {Gale}, volume = {61}, pages = {204--208}, - editor = {Matuz, Roger}, + editor = {Matuz, Roger and Miller, Helen}, keywords = {narration}, langid = {english}, langidopts = {variant=american}, -- cgit v1.2.3 From 8beb373c4a587cdcea772f725f51c2ff2db7273d Mon Sep 17 00:00:00 2001 From: lukeflo Date: Sat, 19 Oct 2024 21:30:37 +0200 Subject: reinvent BibiData, start integrating yaml --- src/backend/bib.rs | 101 +++++++++++++++++++++++++++++++++++------------- src/frontend/app.rs | 8 ++-- src/frontend/entries.rs | 30 +++++++------- 3 files changed, 93 insertions(+), 46 deletions(-) diff --git a/src/backend/bib.rs b/src/backend/bib.rs index 1f5d05d..29ce22e 100644 --- a/src/backend/bib.rs +++ b/src/backend/bib.rs @@ -17,6 +17,7 @@ use biblatex::{self, Bibliography}; use biblatex::{ChunksExt, Type}; +use hayagriva::io::from_yaml_str; use itertools::Itertools; use std::{fs, path::PathBuf}; @@ -36,6 +37,20 @@ pub struct BibiMain { pub bibliography: Bibliography, // parsed bibliography pub citekeys: Vec, // list of all citekeys pub keyword_list: Vec, // list of all available keywords + pub entry_list: Vec, // 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 { @@ -47,6 +62,7 @@ impl BibiMain { 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, &bibfile_format); Self { bibfile, bibfile_format, @@ -54,6 +70,15 @@ impl BibiMain { bibliography, citekeys, keyword_list, + entry_list, + } + } + + fn parse_bibliography(format: &FileFormat, bibfilestring: &str) -> Bibliography { + if let FileFormat::BibLatex = format { + biblatex::Bibliography::parse(bibfilestring).unwrap() + } else if let FileFormat::Hayagriva = format { + from_yaml_str(&bibfilestring).unwrap() } } @@ -70,6 +95,27 @@ impl BibiMain { } } + fn create_entry_list( + citekeys: &[String], + bibliography: &Bibliography, + format: &FileFormat, + ) -> Vec { + citekeys + .into_iter() + .map(|k| BibiData { + authors: Self::get_authors(&k, &bibliography, format), + 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. @@ -112,38 +158,41 @@ impl BibiMain { 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 + pub fn get_authors(citekey: &str, biblio: &Bibliography, format: &FileFormat) -> String { + if let FileFormat::BibLatex = format { + 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 { - let editors_authors = format!("empty"); - editors_authors + 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 + } } + } else if let FileFormat::Hayagriva = format { } } diff --git a/src/frontend/app.rs b/src/frontend/app.rs index 10cfa9b..822c6f0 100644 --- a/src/frontend/app.rs +++ b/src/frontend/app.rs @@ -76,7 +76,7 @@ impl App { let main_biblio = BibiMain::new(main_bibfile.clone()); let tag_list = TagList::new(main_biblio.keyword_list.clone()); let search_struct = BibiSearch::default(); - let entry_table = EntryTable::new(&main_biblio.citekeys, &main_biblio.bibliography); + let entry_table = EntryTable::new(main_biblio.entry_list.clone()); let current_area = CurrentArea::EntryArea; Ok(Self { running, @@ -127,8 +127,7 @@ impl App { self.main_biblio = BibiMain::new(self.main_bibfile.clone()); // self.tag_list = TagList::from_iter(self.main_biblio.keyword_list.clone()); self.tag_list = TagList::new(self.main_biblio.keyword_list.clone()); - self.entry_table = - EntryTable::new(&self.main_biblio.citekeys, &self.main_biblio.bibliography); + self.entry_table = EntryTable::new(self.main_biblio.entry_list.clone()); } // Toggle moveable list between entries and tags @@ -152,8 +151,7 @@ impl App { } pub fn reset_current_list(&mut self) { - self.entry_table = - EntryTable::new(&self.main_biblio.citekeys, &self.main_biblio.bibliography); + self.entry_table = EntryTable::new(self.main_biblio.entry_list.clone()); self.tag_list = TagList::new(self.main_biblio.keyword_list.clone()); if let CurrentArea::TagArea = self.current_area { self.tag_list.tag_list_state.select(Some(0)) diff --git a/src/frontend/entries.rs b/src/frontend/entries.rs index f64e35e..dea970e 100644 --- a/src/frontend/entries.rs +++ b/src/frontend/entries.rs @@ -18,7 +18,7 @@ use super::app::App; use super::tui::Tui; use crate::backend::{ - bib::{BibiMain, FileFormat}, + bib::{BibiData, BibiMain, FileFormat}, search::BibiSearch, }; use biblatex::Bibliography; @@ -41,8 +41,8 @@ pub struct EntryTable { } impl EntryTable { - pub fn new(citekeys: &Vec, biblio: &Bibliography) -> Self { - let entry_table_items = Self::set_entry_table(&citekeys, &biblio); + pub fn new(entry_list: Vec) -> Self { + let entry_table_items = Self::set_entry_table(entry_list); let entry_table_state = TableState::default().with_selected(0); let entry_scroll_state = ScrollbarState::new(entry_table_items.len()); let entry_info_scroll_state = ScrollbarState::default(); @@ -57,20 +57,20 @@ impl EntryTable { } } - pub fn set_entry_table(citekeys: &[String], biblio: &Bibliography) -> Vec { - let mut entry_table: Vec = citekeys + pub fn set_entry_table(entry_list: Vec) -> Vec { + let mut entry_table: Vec = entry_list .into_iter() - .map(|key| EntryTableItem { - authors: BibiMain::get_authors(&key, &biblio), + .map(|e| EntryTableItem { + authors: e.authors, short_author: String::new(), - title: BibiMain::get_title(&key, &biblio), - year: BibiMain::get_year(&key, &biblio), - pubtype: BibiMain::get_pubtype(&key, &biblio), - keywords: BibiMain::get_keywords(&key, &biblio), - citekey: key.to_owned(), - abstract_text: BibiMain::get_abstract(&key, &biblio), - doi_url: BibiMain::get_weblink(&key, &biblio), - filepath: BibiMain::get_filepath(&key, &biblio), + title: e.title, + year: e.year, + pubtype: e.pubtype, + keywords: e.keywords, + citekey: e.citekey, + abstract_text: e.abstract_text, + doi_url: e.doi_url, + filepath: e.filepath, }) .collect(); -- cgit v1.2.3 From cf6a8d0c25bba1ee767c1dcc945cfbb577dbd13c Mon Sep 17 00:00:00 2001 From: lukeflo Date: Sat, 19 Oct 2024 23:05:40 +0200 Subject: format and clean code --- src/backend/bib.rs | 74 +++++++++++++++++++------------------------------ src/frontend/entries.rs | 6 +--- src/frontend/ui.rs | 5 +--- src/main.rs | 1 - 4 files changed, 31 insertions(+), 55 deletions(-) diff --git a/src/backend/bib.rs b/src/backend/bib.rs index 29ce22e..a7df951 100644 --- a/src/backend/bib.rs +++ b/src/backend/bib.rs @@ -17,7 +17,6 @@ use biblatex::{self, Bibliography}; use biblatex::{ChunksExt, Type}; -use hayagriva::io::from_yaml_str; use itertools::Itertools; use std::{fs, path::PathBuf}; @@ -62,7 +61,7 @@ impl BibiMain { 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, &bibfile_format); + let entry_list = Self::create_entry_list(&citekeys, &bibliography); Self { bibfile, bibfile_format, @@ -74,14 +73,6 @@ impl BibiMain { } } - fn parse_bibliography(format: &FileFormat, bibfilestring: &str) -> Bibliography { - if let FileFormat::BibLatex = format { - biblatex::Bibliography::parse(bibfilestring).unwrap() - } else if let FileFormat::Hayagriva = format { - from_yaml_str(&bibfilestring).unwrap() - } - } - // Check which file format the passed file has fn check_file_format(main_bibfile: &PathBuf) -> FileFormat { let extension = main_bibfile.extension().unwrap().to_str(); @@ -95,15 +86,11 @@ impl BibiMain { } } - fn create_entry_list( - citekeys: &[String], - bibliography: &Bibliography, - format: &FileFormat, - ) -> Vec { + fn create_entry_list(citekeys: &[String], bibliography: &Bibliography) -> Vec { citekeys .into_iter() .map(|k| BibiData { - authors: Self::get_authors(&k, &bibliography, format), + authors: Self::get_authors(&k, &bibliography), title: Self::get_title(&k, &bibliography), year: Self::get_year(&k, &bibliography), pubtype: Self::get_pubtype(&k, &bibliography), @@ -158,41 +145,38 @@ impl BibiMain { keyword_list } - pub fn get_authors(citekey: &str, biblio: &Bibliography, format: &FileFormat) -> String { - if let FileFormat::BibLatex = format { - 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 - } + 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 { - 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 - } + 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 } - } else if let FileFormat::Hayagriva = format { } } diff --git a/src/frontend/entries.rs b/src/frontend/entries.rs index dea970e..6c227df 100644 --- a/src/frontend/entries.rs +++ b/src/frontend/entries.rs @@ -17,11 +17,7 @@ use super::app::App; use super::tui::Tui; -use crate::backend::{ - bib::{BibiData, BibiMain, FileFormat}, - search::BibiSearch, -}; -use biblatex::Bibliography; +use crate::backend::{bib::BibiData, search::BibiSearch}; use color_eyre::eyre::{Context, Ok, Result}; use core::panic; use editor_command::EditorBuilder; diff --git a/src/frontend/ui.rs b/src/frontend/ui.rs index d94a654..4ea275d 100644 --- a/src/frontend/ui.rs +++ b/src/frontend/ui.rs @@ -28,10 +28,7 @@ use ratatui::{ }, }; -use crate::{ - backend::bib::BibiMain, - frontend::{app::App, keywords::TagListItem}, -}; +use crate::frontend::{app::App, keywords::TagListItem}; use super::app::{CurrentArea, FormerArea}; diff --git a/src/main.rs b/src/main.rs index b90aeea..979c4cf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,6 @@ use backend::cliargs::{self, CLIArgs}; use color_eyre::eyre::Result; -use core::panic; use errorsetup::init_error_hooks; use frontend::app::App; -- cgit v1.2.3