diff options
| author | lukeflo | 2025-08-23 21:29:35 +0200 |
|---|---|---|
| committer | lukeflo | 2025-08-23 21:29:35 +0200 |
| commit | 71632fca42977560aaf77dd521b0b6b51319ec17 (patch) | |
| tree | 651d5cbaf8cc94a5eb05c84866b0f05a720ca0f0 | |
| parent | 2c1e8342b29b36e09ec90a1cb3d5819c7143273c (diff) | |
| download | bibiman-71632fca42977560aaf77dd521b0b6b51319ec17.tar.gz bibiman-71632fca42977560aaf77dd521b0b6b51319ec17.zip | |
implement a customizable fourth column for `EntryTable`
+ Now one can select a fourth column to be displayed in the config file
+ Possible values: journaltitle, organization, institution, publisher, pubtype
+ Defaults to pubtype
| -rw-r--r-- | src/bibiman/bibisetup.rs | 101 | ||||
| -rw-r--r-- | src/bibiman/entries.rs | 29 | ||||
| -rw-r--r-- | src/bibiman/search.rs | 6 | ||||
| -rw-r--r-- | src/config.rs | 10 | ||||
| -rw-r--r-- | src/tui/ui.rs | 14 | ||||
| -rw-r--r-- | tests/test-config.toml | 5 |
6 files changed, 140 insertions, 25 deletions
diff --git a/src/bibiman/bibisetup.rs b/src/bibiman/bibisetup.rs index 1f8a912..ed189ce 100644 --- a/src/bibiman/bibisetup.rs +++ b/src/bibiman/bibisetup.rs @@ -19,6 +19,7 @@ use biblatex::{self, Bibliography}; use biblatex::{ChunksExt, Type}; use color_eyre::owo_colors::OwoColorize; use itertools::Itertools; +use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::ffi::{OsStr, OsString}; use std::{fs, path::PathBuf}; @@ -28,6 +29,24 @@ use crate::app; use crate::cliargs::{self}; use crate::config::BibiConfig; +/// Custom field used for the fourth column of the `EntryTable` +#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)] +pub enum CustomField { + #[serde(alias = "journaltitle")] + Journaltitle, + #[serde(alias = "organization")] + Organization, + #[serde(alias = "institution")] + Institution, + #[serde(alias = "series")] + Series, + #[serde(alias = "publisher")] + Publisher, + #[serde(alias = "pubtype")] + #[default] + Pubtype, +} + // Set necessary fields // TODO: can surely be made more efficient/simpler #[derive(Debug)] @@ -47,7 +66,7 @@ pub struct BibiData { pub short_author: String, pub title: String, pub year: String, - pub pubtype: String, + pub custom_field: (CustomField, String), pub keywords: String, pub citekey: String, pub abstract_text: String, @@ -64,14 +83,14 @@ pub struct BibiRow<'a> { pub authors: &'a str, pub title: &'a str, pub year: &'a str, - pub pubtype: &'a str, + pub custom_field_value: &'a str, pub symbols: &'a [Option<String>; 3], } impl BibiData { // 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(&mut self, cfg: &BibiConfig) -> BibiRow { + pub fn ref_vec(&mut self, cfg: &BibiConfig) -> BibiRow<'_> { self.short_author = match self.authors.split_once(",") { Some((first, _rest)) => { if self.authors().contains("(ed.)") { @@ -111,7 +130,7 @@ impl BibiData { }, title: self.title(), year: self.year(), - pubtype: self.pubtype(), + custom_field_value: self.custom_field_value(), symbols: &self.symbols, } } @@ -132,8 +151,8 @@ impl BibiData { &self.year } - pub fn pubtype(&self) -> &str { - &self.pubtype + pub fn custom_field_value(&self) -> &str { + &self.custom_field.1 } pub fn citekey(&self) -> &str { @@ -281,7 +300,10 @@ impl BibiSetup { short_author: String::new(), title: Self::get_title(k, bibliography), year: Self::get_year(k, bibliography), - pubtype: Self::get_pubtype(k, bibliography), + custom_field: ( + cfg.general.custom_column.clone(), + Self::get_custom_field(k, bibliography, &cfg.general.custom_column), + ), keywords: Self::get_keywords(k, bibliography), citekey: k.to_owned(), abstract_text: Self::get_abstract(k, bibliography), @@ -385,8 +407,69 @@ impl BibiSetup { } } - pub fn get_pubtype(citekey: &str, biblio: &Bibliography) -> String { - biblio.get(citekey).unwrap().entry_type.to_string() + pub fn get_custom_field( + citekey: &str, + biblio: &Bibliography, + custom_field: &CustomField, + ) -> String { + match custom_field { + CustomField::Journaltitle => { + if let Ok(val) = biblio + .get(citekey) + .expect(&format!("Citekey {} not found in bibliography", citekey)) + .journal_title() + { + val.format_verbatim() + } else { + "empty".to_string() + } + } + CustomField::Organization => { + if let Ok(val) = biblio.get(citekey).expect("").organization() { + let values: Vec<String> = val + .iter() + .map(|i| i.get(0).unwrap().v.get().to_string()) + .collect(); + values.join("; ") + } else { + "empty".to_string() + } + } + CustomField::Institution => { + if let Ok(val) = biblio.get(citekey).unwrap().institution() { + let values = val + .into_iter() + .map(|i| i.v.get().to_owned()) + .collect::<Vec<_>>(); + values.join("; ") + } else { + "empty".to_string() + } + } + CustomField::Series => { + if let Ok(val) = biblio.get(citekey).expect("").series() { + let values = val + .into_iter() + .map(|i| i.v.get().to_owned()) + .collect::<Vec<_>>(); + values.join("; ") + } else { + "empty".to_string() + } + } + CustomField::Publisher => { + if let Ok(val) = biblio.get(citekey).expect("").publisher() { + let values: Vec<String> = val + .iter() + .map(|i| i.get(0).unwrap().v.get().to_string()) + .collect(); + values.join("; ") + } else { + "empty".to_string() + } + } + CustomField::Pubtype => biblio.get(citekey).expect("").entry_type.to_string(), + } } pub fn get_keywords(citekey: &str, biblio: &Bibliography) -> String { diff --git a/src/bibiman/entries.rs b/src/bibiman/entries.rs index 8f678bc..db6d6bf 100644 --- a/src/bibiman/entries.rs +++ b/src/bibiman/entries.rs @@ -106,9 +106,11 @@ impl EntryTable { EntryTableColumn::Year => self .entry_table_items .sort_by(|a, b| b.year.to_lowercase().cmp(&a.year.to_lowercase())), - EntryTableColumn::Pubtype => self - .entry_table_items - .sort_by(|a, b| b.pubtype.to_lowercase().cmp(&a.pubtype.to_lowercase())), + EntryTableColumn::Pubtype => self.entry_table_items.sort_by(|a, b| { + b.custom_field_value() + .to_lowercase() + .cmp(&a.custom_field_value().to_lowercase()) + }), } } else if !self.entry_table_reversed_sort { match self.entry_table_selected_column { @@ -121,9 +123,11 @@ impl EntryTable { EntryTableColumn::Year => self .entry_table_items .sort_by(|a, b| a.year.to_lowercase().cmp(&b.year.to_lowercase())), - EntryTableColumn::Pubtype => self - .entry_table_items - .sort_by(|a, b| a.pubtype.to_lowercase().cmp(&b.pubtype.to_lowercase())), + EntryTableColumn::Pubtype => self.entry_table_items.sort_by(|a, b| { + a.custom_field_value() + .to_lowercase() + .cmp(&b.custom_field_value().to_lowercase()) + }), } } } @@ -132,7 +136,10 @@ impl EntryTable { #[cfg(test)] mod tests { use crate::{ - bibiman::{bibisetup::BibiRow, BibiData}, + bibiman::{ + bibisetup::{BibiRow, CustomField}, + BibiData, + }, cliargs::CLIArgs, config::BibiConfig, }; @@ -157,7 +164,7 @@ mod tests { short_author: String::new(), title: "A title".to_string(), year: "2000".to_string(), - pubtype: "article".to_string(), + custom_field: (CustomField::Pubtype, "article".to_string()), keywords: "key1, key2".to_string(), citekey: "miller_2000".to_string(), abstract_text: "An abstract".to_string(), @@ -177,7 +184,7 @@ mod tests { short_author: String::new(), title: "A title".to_string(), year: "2000".to_string(), - pubtype: "article".to_string(), + custom_field: (CustomField::Pubtype, "article".to_string()), keywords: "key1, key2".to_string(), citekey: "miller_2000".to_string(), abstract_text: "An abstract".to_string(), @@ -197,7 +204,7 @@ mod tests { authors: "Miller et al.", title: "A title", year: "2000", - pubtype: "article", + custom_field_value: "article", symbols: &[None, None, None] } ); @@ -207,7 +214,7 @@ mod tests { authors: "Miller et al. (ed.)", title: "A title", year: "2000", - pubtype: "article", + custom_field_value: "article", symbols: &[None, None, None] } ) diff --git a/src/bibiman/search.rs b/src/bibiman/search.rs index f6679a4..e0c5f17 100644 --- a/src/bibiman/search.rs +++ b/src/bibiman/search.rs @@ -37,7 +37,7 @@ impl BibiSearch { &inner_vec.authors, &inner_vec.title, &inner_vec.year, - &inner_vec.pubtype, + &inner_vec.custom_field_value(), &inner_vec.keywords, &inner_vec.citekey ) @@ -119,6 +119,8 @@ pub fn search_pattern_in_file<'a>(pattern: &str, file: &'a PathBuf) -> Option<&' mod tests { use std::ffi::OsString; + use crate::bibiman::bibisetup::CustomField; + use super::*; #[test] @@ -129,7 +131,7 @@ mod tests { short_author: "".to_string(), title: "Title".to_string(), year: "1999".to_string(), - pubtype: "article".to_string(), + custom_field: (CustomField::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(), diff --git a/src/config.rs b/src/config.rs index 4e46fdd..e3798e4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -30,7 +30,7 @@ use figment::{ use ratatui::style::Color; use serde::{Deserialize, Serialize}; -use crate::cliargs::CLIArgs; +use crate::{bibiman::bibisetup::CustomField, cliargs::CLIArgs}; const DEFAULT_CONFIG: &str = r##" # [general] @@ -67,6 +67,11 @@ const DEFAULT_CONFIG: &str = r##" # file_symbol = "F" # link_symbol = "L" +## Select a custom column beside standard "author", "title" and "year" +## Possible values are "journaltitle", "organization", "instituion", "publisher" +## and "pubtype" (which is the default) +# custom_column = "pubtype" + # [colors] ## Default values for dark-themed terminal ## Possible values are: @@ -113,6 +118,7 @@ pub struct General { pub note_symbol: String, pub file_symbol: String, pub link_symbol: String, + pub custom_column: CustomField, } /// Substruct [colors] in config.toml @@ -152,6 +158,7 @@ impl Default for BibiConfig { note_symbol: String::from("N"), file_symbol: String::from("F"), link_symbol: String::from("L"), + custom_column: CustomField::Pubtype, }, colors: Self::dark_colors(), } @@ -173,6 +180,7 @@ impl BibiConfig { note_symbol: String::from("N"), file_symbol: String::from("F"), link_symbol: String::from("L"), + custom_column: CustomField::Pubtype, }, colors: if args.light_theme { Self::light_colors() diff --git a/src/tui/ui.rs b/src/tui/ui.rs index 69ca058..2180838 100644 --- a/src/tui/ui.rs +++ b/src/tui/ui.rs @@ -18,6 +18,7 @@ use std::path::PathBuf; use super::popup::{PopupArea, PopupItem}; +use crate::bibiman::bibisetup::CustomField; use crate::bibiman::entries::EntryTableColumn; use crate::bibiman::{CurrentArea, FormerArea}; use crate::cliargs::CLIArgs; @@ -623,6 +624,15 @@ pub fn render_entrytable(app: &mut App, cfg: &BibiConfig, frame: &mut Frame, rec .fg(cfg.colors.main_text_color) .bg(cfg.colors.bar_bg_color); + let custom_col_title: &str = match cfg.general.custom_column { + CustomField::Journaltitle => "Journaltitle", + CustomField::Organization => "Organization", + CustomField::Institution => "Institution", + CustomField::Series => "Series", + CustomField::Publisher => "Publisher", + CustomField::Pubtype => "Pubtype", + }; + let header = Row::new(vec![ Cell::from(Line::from("Res.")).bg(cfg.colors.bar_bg_color), Cell::from( @@ -705,7 +715,7 @@ pub fn render_entrytable(app: &mut App, cfg: &BibiConfig, frame: &mut Frame, rec ), ), Cell::from( - Line::from(vec![{ Span::raw("Pubtype") }, { + Line::from(vec![{ Span::raw(custom_col_title) }, { if let Some(EntryTableColumn::Pubtype) = app.bibiman.entry_table.entry_table_sorted_by_col { @@ -786,7 +796,7 @@ pub fn render_entrytable(app: &mut App, cfg: &BibiConfig, frame: &mut Frame, rec Cell::from(Line::from(item.authors)), Cell::from(Line::from(item.title)), Cell::from(Line::from(item.year)), - Cell::from(Line::from(item.pubtype)), + Cell::from(Line::from(item.custom_field_value)), ]); // let row = item diff --git a/tests/test-config.toml b/tests/test-config.toml index 1d29043..0b93cf3 100644 --- a/tests/test-config.toml +++ b/tests/test-config.toml @@ -32,6 +32,11 @@ file_symbol = " " link_symbol = " " note_symbol = "" +## Select a custom column beside standard "author", "title" and "year" +## Possible values are "journaltitle", "organization", "instituion", "publisher" +## and "pubtype" (which is the default) +custom_column = "publisher" + # [colors] ## Default values for dark-themed terminal ## Possible values are: |
