diff options
Diffstat (limited to 'src/bibiman.rs')
| -rw-r--r-- | src/bibiman.rs | 197 |
1 files changed, 183 insertions, 14 deletions
diff --git a/src/bibiman.rs b/src/bibiman.rs index 21601e3..6d21f8c 100644 --- a/src/bibiman.rs +++ b/src/bibiman.rs @@ -20,21 +20,22 @@ use crate::bibiman::entries::EntryTableColumn; use crate::bibiman::{bibisetup::*, search::BibiSearch}; use crate::cliargs::CLIArgs; use crate::config::BibiConfig; -use crate::tui::popup::{PopupArea, PopupKind}; +use crate::tui::popup::{PopupArea, PopupItem, PopupKind}; use crate::tui::Tui; use crate::{app, cliargs}; use crate::{bibiman::entries::EntryTable, bibiman::keywords::TagList}; use arboard::Clipboard; -use color_eyre::eyre::{Error, Result}; +use color_eyre::eyre::{Context, Error, Result}; use crossterm::event::KeyCode; use editor_command::EditorBuilder; use ratatui::widgets::ScrollbarState; use regex::Regex; +use std::ffi::OsStr; use std::fs::{self, read_to_string}; use std::fs::{File, OpenOptions}; use std::io::Write; use std::path::PathBuf; -use std::process::Command; +use std::process::{Command, Stdio}; use std::result::Result::Ok; use tui_input::Input; @@ -160,7 +161,7 @@ impl Bibiman { popup_kind: PopupKind, message: Option<&str>, object: Option<&str>, - items: Option<Vec<(String, String)>>, + items: Option<Vec<(String, String, PopupItem)>>, ) -> Result<()> { if let CurrentArea::EntryArea = self.current_area { self.former_area = Some(FormerArea::EntryArea); @@ -237,6 +238,18 @@ impl Bibiman { )) } } + PopupKind::CreateNote => { + if items.is_some() { + self.popup_area.popup_kind = Some(PopupKind::CreateNote); + 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", + )) + } + } } } @@ -366,9 +379,9 @@ impl Bibiman { .entry_table_state .selected_column() .unwrap() - == 3 + == 4 { - self.entry_table.entry_table_state.select_first_column(); + self.entry_table.entry_table_state.select_column(Some(1)); } else { self.entry_table.entry_table_state.select_next_column(); } @@ -395,7 +408,7 @@ impl Bibiman { .entry_table_state .selected_column() .unwrap() - == 0 + == 1 { self.entry_table.entry_table_state.select_last_column(); } else { @@ -512,6 +525,74 @@ impl Bibiman { Ok(()) } + pub fn open_connected_note( + &mut self, + cfg: &BibiConfig, + tui: &mut Tui, + file: &OsStr, + ) -> Result<()> { + // get filecontent and citekey for calculating line number + + match std::env::var("TERM") { + Ok(sh) => { + let editor = if let Some(e) = cfg.general.editor.clone() { + e + } else if let Ok(e) = std::env::var("VISUAL") { + e + } else if let Ok(e) = std::env::var("EDITOR") { + e + } else { + String::from("vi") + }; + let _ = Command::new(sh) + .arg("-e") + .arg(editor) + .arg(file) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn() + .wrap_err("Couldn't run editor"); + // Prepare arguments to open file at specific line + // let status = note_cmd.status()?; + // if !status.success() { + // eprintln!("Spawning editor failed with status {}", status); + // } + } + Err(_e) => { + let citekey: &str = &self.entry_table.entry_table_items + [self.entry_table.entry_table_state.selected().unwrap()] + .citekey + .clone(); + // Exit TUI to enter editor + tui.exit()?; + // Use VISUAL or EDITOR. Set "vi" as last fallback + let mut note_cmd: Command = EditorBuilder::new() + .source(cfg.general.editor.clone()) + .environment() + .source(Some("vi")) + .build() + .unwrap(); + // Prepare arguments to open file at specific line + let status = note_cmd.arg(file).status()?; + if !status.success() { + eprintln!("Spawning editor failed with status {}", status); + } + + // Enter TUI again + tui.enter()?; + tui.terminal.clear()?; + + // Update the database and the lists to show changes + // Self::update_lists(self, cfg); + + // Select entry which was selected before entering editor + self.select_entry_by_citekey(citekey); + } + } + + Ok(()) + } + pub fn add_entry(&mut self) { if let CurrentArea::EntryArea = self.current_area { self.former_area = Some(FormerArea::EntryArea); @@ -562,10 +643,18 @@ impl Bibiman { } pub fn append_to_file(&mut self) { - let mut items = vec![("Create new file".to_owned(), "".to_string())]; + let mut items = vec![( + "Create new file".to_owned(), + "".to_string(), + PopupItem::Default, + )]; if self.main_bibfiles.len() > 1 { for f in self.main_bibfiles.clone() { - items.push(("File: ".into(), f.to_str().unwrap().to_owned())); + items.push(( + "File: ".into(), + f.to_str().unwrap().to_owned(), + PopupItem::Bibfile, + )); } } else { items.push(( @@ -576,6 +665,7 @@ impl Bibiman { .to_str() .unwrap() .to_owned(), + PopupItem::Bibfile, )); } self.popup_area.popup_selection(items); @@ -662,7 +752,36 @@ impl Bibiman { Ok(()) } - pub fn open_connected_res(&mut self, cfg: &BibiConfig) -> Result<()> { + pub fn create_note(&mut self, cfg: &BibiConfig) -> Result<()> { + // Index of selected entry + let entry_idx = self.entry_table.entry_table_state.selected().unwrap(); + let citekey = self.entry_table.entry_table_items[entry_idx] + .citekey + .clone(); + + // Index of selected popup field + let popup_idx = self.popup_area.popup_state.selected().unwrap(); + let ext = self.popup_area.popup_list[popup_idx].1.clone(); + + let basename = PathBuf::from(&citekey).with_extension(ext); + let path = cfg.general.note_path.as_ref().unwrap(); + + let new_file = path.join(basename); + + let new_file = if new_file.starts_with("~") { + expand_home(&new_file) + } else { + new_file + }; + + File::create_new(new_file).unwrap(); + self.close_popup(); + self.update_lists(cfg); + self.select_entry_by_citekey(&citekey); + Ok(()) + } + + pub fn open_connected_res(&mut self, cfg: &BibiConfig, tui: &mut Tui) -> Result<()> { // Index of selected entry let entry_idx = self.entry_table.entry_table_state.selected().unwrap(); @@ -671,12 +790,12 @@ impl Bibiman { 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].0.contains("Weblink") { + if let PopupItem::Link = self.popup_area.popup_list[popup_idx].2 { let object = self.entry_table.entry_table_items[entry_idx].doi_url(); let url = app::prepare_weblink(object); app::open_connected_link(cfg, &url)?; self.close_popup(); - } else if self.popup_area.popup_list[popup_idx].0.contains("File") { + } else if let PopupItem::Entryfile = self.popup_area.popup_list[popup_idx].2 { // 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())); @@ -692,6 +811,20 @@ impl Bibiman { None, )?; } + } else if let PopupItem::Notefile = self.popup_area.popup_list[popup_idx].2 { + let file = expand_home(&PathBuf::from(popup_entry.clone())); + // let object: OsString = popup_entry.into(); + if file.is_file() { + self.open_connected_note(cfg, tui, &file.into_os_string())?; + self.close_popup(); + } else { + self.open_popup( + PopupKind::MessageError, + Some("No valid file path: "), + Some(file.to_str().unwrap()), + None, + )?; + } } else { eprintln!("Unable to find ressource to open"); }; @@ -733,11 +866,17 @@ impl Bibiman { /// /// `o` -> opens the first file of the `filepath` `Vec` for the current entry /// `l` -> opens the link of the current entry + /// `n` -> opens the first note /// /// **Yanking popup** /// /// `y` -> yanks the citekey for the current entry - pub fn fast_selection(&mut self, cfg: &BibiConfig, key_code: KeyCode) -> Result<()> { + pub fn fast_selection( + &mut self, + cfg: &BibiConfig, + tui: &mut Tui, + key_code: KeyCode, + ) -> Result<()> { if let CurrentArea::PopupArea = self.current_area { let entry_idx = self.entry_table.entry_table_state.selected().unwrap(); match self.popup_area.popup_kind { @@ -747,7 +886,19 @@ impl Bibiman { .filepath .clone(); if file.is_some() { - let file = expand_home(&PathBuf::from(file.unwrap()[0].clone())); + let file = if self.entry_table.entry_table_items[entry_idx].file_field + && cfg.general.file_prefix.is_some() + { + cfg.general + .file_prefix + .clone() + .unwrap() + .join(&file.unwrap()[0]) + .into_os_string() + } else { + file.unwrap()[0].clone() + }; + let file = expand_home(&PathBuf::from(file)); // let object: OsString = popup_entry.into(); if file.is_file() { app::open_connected_file(cfg, &file.into_os_string())?; @@ -762,6 +913,24 @@ impl Bibiman { } } } + KeyCode::Char('n') => { + let file = self.entry_table.entry_table_items[entry_idx].notes.clone(); + if file.is_some() { + let file = expand_home(&PathBuf::from(file.unwrap()[0].clone())); + // let object: OsString = popup_entry.into(); + if file.is_file() { + self.open_connected_note(cfg, tui, &file.into_os_string())?; + self.close_popup(); + } else { + self.open_popup( + PopupKind::MessageError, + Some("No valid file path: "), + Some(file.to_str().unwrap()), + None, + )?; + } + } + } KeyCode::Char('l') => { if self.entry_table.entry_table_items[entry_idx] .doi_url |
