aboutsummaryrefslogtreecommitdiff
path: root/src/bibiman.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bibiman.rs')
-rw-r--r--src/bibiman.rs197
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