aboutsummaryrefslogtreecommitdiff
path: root/src/bibiman.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bibiman.rs')
-rw-r--r--src/bibiman.rs233
1 files changed, 169 insertions, 64 deletions
diff --git a/src/bibiman.rs b/src/bibiman.rs
index c90905f..ea9dbf5 100644
--- a/src/bibiman.rs
+++ b/src/bibiman.rs
@@ -15,6 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
/////
+use crate::app::expand_home;
use crate::bibiman::entries::EntryTableColumn;
use crate::bibiman::{bibisetup::*, search::BibiSearch};
use crate::cliargs::CLIArgs;
@@ -24,10 +25,11 @@ use crate::tui::Tui;
use crate::{app, cliargs};
use crate::{bibiman::entries::EntryTable, bibiman::keywords::TagList};
use arboard::Clipboard;
-use color_eyre::eyre::Result;
+use color_eyre::eyre::{Error, Result};
use editor_command::EditorBuilder;
use ratatui::widgets::ScrollbarState;
use regex::Regex;
+use std::ffi::OsString;
use std::fs::{self, read_to_string};
use std::fs::{File, OpenOptions};
use std::io::Write;
@@ -89,7 +91,7 @@ impl Bibiman {
main_bibfiles.append(cfg.general.bibfiles.as_mut().unwrap())
};
let main_bibfiles = cliargs::parse_files(main_bibfiles);
- let main_biblio = BibiSetup::new(&main_bibfiles);
+ let main_biblio = BibiSetup::new(&main_bibfiles, cfg);
let tag_list = TagList::new(main_biblio.keyword_list.clone());
let search_struct = BibiSearch::default();
let entry_table = EntryTable::new(main_biblio.entry_list.clone());
@@ -118,6 +120,7 @@ impl Bibiman {
self.popup_area.popup_kind = Some(PopupKind::Help);
}
+ /// Close all current popups and select former tab of main app
pub fn close_popup(&mut self) {
// Reset all popup fields to default values
self.popup_area = PopupArea::default();
@@ -133,8 +136,112 @@ impl Bibiman {
self.former_area = None;
}
- pub fn update_lists(&mut self) {
- self.main_biblio = BibiSetup::new(&self.main_bibfiles);
+ /// Open a popup
+ ///
+ /// Necessary arguments are:
+ ///
+ /// - `popup_kind`: a valid value of the `PopupKind` `enum`. This determines the
+ /// further behaviour of the popup.
+ /// - `message`: A message shown in the popup. This is needed for the `PopupKind`
+ /// values `MessageConfirm` and `MessageError`. If not needed, set it to `None`.
+ /// - `object`: An object passed as `&str` which might explain the current popup
+ /// action. Its not needed, but very useful. Can be used with the `PopupKind`
+ /// values `MessageConfirm`, `MessageError` and `YankItem`. If not needed, set it
+ /// to `None`.
+ /// - `items`: A vector of items which are needed if a selectable list is rendered.
+ /// The vector consists of tuples including a pair of `String`. The second item of
+ /// the tuple is considered kind of an object which can be used e.g. to open
+ /// the given filepath etc. If not needed, set it to `None`.
+ ///
+ /// The function will panic if a needed argument for the particular `PopupKind`
+ /// is missing
+ pub fn open_popup(
+ &mut self,
+ popup_kind: PopupKind,
+ message: Option<&str>,
+ object: Option<&str>,
+ items: Option<Vec<(String, String)>>,
+ ) -> Result<()> {
+ if let CurrentArea::EntryArea = self.current_area {
+ self.former_area = Some(FormerArea::EntryArea);
+ } else if let CurrentArea::TagArea = self.current_area {
+ self.former_area = Some(FormerArea::TagArea);
+ }
+ self.popup_area.is_popup = true;
+ self.current_area = CurrentArea::PopupArea;
+
+ match popup_kind {
+ PopupKind::Help => {
+ self.popup_area.popup_kind = Some(PopupKind::Help);
+ Ok(())
+ }
+ PopupKind::MessageConfirm => {
+ self.popup_area.popup_kind = Some(PopupKind::MessageConfirm);
+ if object.is_some() && message.is_some() {
+ self.popup_area.popup_message = message.unwrap().to_owned() + object.unwrap();
+ Ok(())
+ } else if object.is_none() && message.is_some() {
+ self.popup_area.popup_message = message.unwrap().to_owned();
+ Ok(())
+ } else {
+ Err(Error::msg("You need to past at least a message via Some(&str) to create a message popup"))
+ }
+ }
+ PopupKind::MessageError => {
+ self.popup_area.popup_kind = Some(PopupKind::MessageError);
+ if object.is_some() && message.is_some() {
+ self.popup_area.popup_message = message.unwrap().to_owned() + object.unwrap();
+ Ok(())
+ } else if object.is_none() && message.is_some() {
+ self.popup_area.popup_message = message.unwrap().to_owned();
+ Ok(())
+ } else {
+ Err(Error::msg("You need to past at least a message via Some(&str) to create a message popup"))
+ }
+ }
+ PopupKind::OpenRes => {
+ if items.is_some() {
+ self.popup_area.popup_kind = Some(PopupKind::OpenRes);
+ self.popup_area.popup_selection(items.unwrap());
+ self.popup_area.popup_state.select(Some(0));
+ Ok(())
+ } else {
+ Err(Error::msg(
+ "No Vec<(String, String)> passed as argument to generate the items list",
+ ))
+ }
+ }
+ PopupKind::AppendToFile => {
+ if items.is_some() {
+ self.popup_area.popup_kind = Some(PopupKind::AppendToFile);
+ Ok(())
+ } else {
+ Err(Error::msg(
+ "No Vec<(String, String)> passed as argument to generate the items list",
+ ))
+ }
+ }
+ PopupKind::AddEntry => {
+ self.popup_area.popup_kind = Some(PopupKind::AddEntry);
+ Ok(())
+ }
+ PopupKind::YankItem => {
+ if items.is_some() {
+ self.popup_area.popup_kind = Some(PopupKind::YankItem);
+ self.popup_area.popup_selection(items.unwrap());
+ self.popup_area.popup_state.select(Some(0));
+ Ok(())
+ } else {
+ Err(Error::msg(
+ "No Vec<(String, String)> passed as argument to generate the items list",
+ ))
+ }
+ }
+ }
+ }
+
+ pub fn update_lists(&mut self, cfg: &BibiConfig) {
+ self.main_biblio = BibiSetup::new(&self.main_bibfiles, cfg);
self.tag_list = TagList::new(self.main_biblio.keyword_list.clone());
self.entry_table = EntryTable::new(self.main_biblio.entry_list.clone());
}
@@ -397,7 +504,7 @@ impl Bibiman {
tui.terminal.clear()?;
// Update the database and the lists to show changes
- Self::update_lists(self);
+ Self::update_lists(self, cfg);
// Select entry which was selected before entering editor
self.select_entry_by_citekey(citekey);
@@ -418,7 +525,7 @@ impl Bibiman {
///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, doi_string: &str) {
+ pub fn handle_new_entry_submission(&mut self, doi_string: &str) -> Result<()> {
let doi_string = if doi_string.starts_with("10.") {
"https://doi.org/".to_string() + doi_string
} else {
@@ -442,31 +549,39 @@ impl Bibiman {
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);
+ self.open_popup(
+ PopupKind::MessageError,
+ Some("Can't find DOI: "),
+ Some(&doi_string),
+ None,
+ )?;
+ // self.popup_area
+ // .popup_message("Can't find DOI: ", &doi_string, false);
}
+ Ok(())
}
pub fn append_to_file(&mut self) {
- let mut items = vec!["Create new file".to_owned()];
+ let mut items = vec![("Create new file".to_owned(), "".to_string())];
if self.main_bibfiles.len() > 1 {
for f in self.main_bibfiles.clone() {
- items.push(f.to_str().unwrap().to_owned());
+ items.push(("File: ".into(), f.to_str().unwrap().to_owned()));
}
} else {
- items.push(
+ items.push((
+ "File: ".into(),
self.main_bibfiles
.first()
.unwrap()
.to_str()
.unwrap()
.to_owned(),
- );
+ ));
}
self.popup_area.popup_selection(items);
}
- pub fn append_entry_to_file(&mut self) -> Result<()> {
+ pub fn append_entry_to_file(&mut self, cfg: &BibiConfig) -> Result<()> {
// Index of selected popup field
let popup_idx = self.popup_area.popup_state.selected().unwrap();
@@ -482,7 +597,10 @@ impl Bibiman {
.to_string();
// Check if new file or existing file was choosen
- let mut file = if self.popup_area.popup_list[popup_idx].contains("Create new file") {
+ let mut file = if self.popup_area.popup_list[popup_idx]
+ .0
+ .contains("Create new file")
+ {
let citekey = PathBuf::from(&citekey);
// Get path of current files
let path: PathBuf = if self.main_bibfiles[0].is_file() {
@@ -535,7 +653,7 @@ impl Bibiman {
// Write content to file
file.write_all(self.popup_area.popup_sel_item.as_bytes())?;
// Update the database and the lists to reflect the new content
- self.update_lists();
+ self.update_lists(cfg);
self.close_popup();
// Select newly created entry
@@ -550,73 +668,60 @@ impl Bibiman {
// Index of selected popup field
let popup_idx = self.popup_area.popup_state.selected().unwrap();
+ let popup_entry = self.popup_area.popup_list[popup_idx].1.clone();
// Choose ressource depending an selected popup field
- if self.popup_area.popup_list[popup_idx].contains("Weblink") {
+ if self.popup_area.popup_list[popup_idx].0.contains("Weblink") {
let object = self.entry_table.entry_table_items[entry_idx].doi_url();
let url = app::prepare_weblink(object);
app::open_connected_link(cfg, &url)?;
- } else if self.popup_area.popup_list[popup_idx].contains("File") {
- let object = self.entry_table.entry_table_items[entry_idx].filepath();
- app::open_connected_file(cfg, object)?;
+ self.close_popup();
+ } else if self.popup_area.popup_list[popup_idx].0.contains("File") {
+ // TODO: Selection for multiple files
+ // let object = self.entry_table.entry_table_items[entry_idx].filepath()[0];
+ let file = expand_home(&PathBuf::from(popup_entry.clone()));
+ let object: OsString = popup_entry.into();
+ if file.is_file() {
+ app::open_connected_file(cfg, &object)?;
+ self.close_popup();
+ } else {
+ self.open_popup(
+ PopupKind::MessageError,
+ Some("No valid file path: "),
+ Some(object.to_str().unwrap()),
+ None,
+ )?;
+ }
} else {
eprintln!("Unable to find ressource to open");
};
// run command to open file/Url
- self.close_popup();
Ok(())
}
pub fn yank_entry_field(&mut self) -> Result<()> {
- // Index of selected entry
- let entry_idx = self.entry_table.entry_table_state.selected().unwrap();
-
// Index of selected popup field
let popup_idx = self.popup_area.popup_state.selected().unwrap();
+ let popup_entry = self.popup_area.popup_list[popup_idx].1.clone();
- match self.popup_area.popup_list[popup_idx]
+ let kind = self.popup_area.popup_list[popup_idx]
+ .0
.to_lowercase()
- .as_str()
- {
- "citekey" => {
- let citekey = &self.entry_table.entry_table_items[entry_idx].citekey;
- Bibiman::yank_text(citekey);
- self.popup_area.popup_message(
- "Yanked citekey to clipboard: ",
- citekey, // self.bibiman.get_selected_citekey(),
- true,
- );
- }
- "weblink" => {
- let link = &self.entry_table.entry_table_items[entry_idx].doi_url;
- if let Some(l) = link {
- Bibiman::yank_text(l);
- self.popup_area.popup_message(
- "Yanked weblink to clipboard: ",
- l, // self.bibiman.get_selected_link(),
- true,
- );
- }
- }
- "filepath" => {
- let path = self.entry_table.entry_table_items[entry_idx]
- .filepath
- .clone();
- if let Some(p) = path {
- let p = p.as_os_str().to_str();
- if let Some(p) = p {
- Bibiman::yank_text(p);
- self.popup_area.popup_message(
- "Yanked filepath to clipboard: ",
- p, // self.bibiman.get_selected_link(),
- true,
- );
- }
- }
- }
- _ => {}
- };
+ .split(":")
+ .next()
+ .unwrap()
+ .to_owned();
+
+ let msg = format!("Yanked {} to clipboard: ", &kind);
+
+ Bibiman::yank_text(&popup_entry);
+ self.open_popup(
+ PopupKind::MessageConfirm,
+ Some(&msg),
+ Some(&popup_entry),
+ None,
+ )?;
Ok(())
}