diff options
| author | lukeflo | 2024-10-08 22:48:53 +0200 |
|---|---|---|
| committer | lukeflo | 2024-10-12 22:41:38 +0200 |
| commit | 2aaee4d89f7d8ee683a0d50f21723d908dec3e46 (patch) | |
| tree | 973beeb3d1ff543971b7bca1aa22df361354cc25 /src | |
| parent | e425c7dcdf444de1151ab3f5347e6503cd0452b9 (diff) | |
| download | bibiman-2aaee4d89f7d8ee683a0d50f21723d908dec3e46.tar.gz bibiman-2aaee4d89f7d8ee683a0d50f21723d908dec3e46.zip | |
open URLs, DOIs and PDFs
+ Implement opening mechanism for URLs, DOIs and PDFs
+ Adding logic to reset selected item after editing to same entry as
before
Diffstat (limited to 'src')
| -rw-r--r-- | src/backend/bib.rs | 1 | ||||
| -rw-r--r-- | src/backend/cliargs.rs | 23 | ||||
| -rw-r--r-- | src/frontend/entries.rs | 92 | ||||
| -rw-r--r-- | src/frontend/handler.rs | 3 | ||||
| -rw-r--r-- | src/main.rs | 6 |
5 files changed, 95 insertions, 30 deletions
diff --git a/src/backend/bib.rs b/src/backend/bib.rs index 3e0e844..bfc959d 100644 --- a/src/backend/bib.rs +++ b/src/backend/bib.rs @@ -17,7 +17,6 @@ use biblatex::{self, Bibliography}; use biblatex::{ChunksExt, Type}; -use color_eyre::eyre::ErrReport; use std::{fs, path::PathBuf}; // Set necessary fields diff --git a/src/backend/cliargs.rs b/src/backend/cliargs.rs index 31d37f0..d3a4652 100644 --- a/src/backend/cliargs.rs +++ b/src/backend/cliargs.rs @@ -15,7 +15,6 @@ // along with this program. If not, see <https://www.gnu.org/licenses/>. ///// -use core::panic; use std::path::PathBuf; use sarge::prelude::*; @@ -45,7 +44,7 @@ impl CLIArgs { PathBuf::from(&pos_args[1]) // pos_args[1].to_string() } else { - panic!("No path to bibfile provided as argument") + PathBuf::new() }; Self { helparg: cli_args.help, @@ -55,26 +54,6 @@ impl CLIArgs { } } -// Struct for positional arguments -// TODO: Can surely be improved!! -// pub struct PosArgs { -// pub bibfilearg: PathBuf, -// } - -// impl PosArgs { -// pub fn parse_pos_args() -> Self { -// let (_, pos_args) = ArgumentsCLI::parse().expect("Could not parse positional arguments"); -// Self { -// bibfilearg: if pos_args.len() > 1 { -// PathBuf::from(&pos_args[1]) -// // pos_args[1].to_string() -// } else { -// panic!("No path to bibfile provided as argument") -// }, // bibfilearg: pos_args[1].to_string(), -// } -// } -// } - pub fn help_func() -> String { let help = format!( "\ diff --git a/src/frontend/entries.rs b/src/frontend/entries.rs index b1312ec..1f79bf4 100644 --- a/src/frontend/entries.rs +++ b/src/frontend/entries.rs @@ -19,13 +19,11 @@ use super::app::App; use super::tui::Tui; use crate::backend::search::BibiSearch; use color_eyre::eyre::{Context, Ok, Result}; +use core::panic; use editor_command::EditorBuilder; use itertools::Itertools; use ratatui::widgets::TableState; -use std::{ - io::Stderr, - process::{Command, Stdio}, -}; +use std::process::{Command, Stdio}; impl FromIterator<Vec<String>> for EntryTable { fn from_iter<T: IntoIterator<Item = Vec<String>>>(iter: T) -> Self { @@ -156,6 +154,8 @@ impl App { pub fn run_editor(&mut self, tui: &mut Tui) -> Result<()> { // get filecontent and citekey for calculating line number let citekey = self.get_selected_citekey(); + // create independent copy of citekey for finding entry after updating list + let saved_key = citekey.to_owned(); let filepath = self.main_biblio.bibfile.display().to_string(); let filecontent = self.main_biblio.bibfilestring.clone(); let mut line_count = 0; @@ -197,6 +197,23 @@ impl App { // Update the database and the lists to show changes self.update_lists(); + + // Search for entry, selected before editing, by matching citekeys + // Use earlier saved copy of citekey to match + let mut idx_count = 0; + loop { + if self.entry_table.entry_table_items[idx_count] + .citekey + .contains(&saved_key) + { + break; + } + idx_count = idx_count + 1 + } + + // Set selected entry to vec-index of match + self.entry_table.entry_table_state.select(Some(idx_count)); + Ok(()) } @@ -224,10 +241,19 @@ impl App { let filepath = &self.entry_table.entry_table_items[idx].filepath.clone(); // Build command to execute pdf-reader. 'xdg-open' is Linux standard - // TODO: need to implement for MacOS ('opener'). Windows, I don't know... - let _ = Command::new("xdg-open") + let cmd = { + match std::env::consts::OS { + "linux" => String::from("xdg-open"), + "macos" => String::from("open"), + "windows" => String::from("start"), + _ => panic!("Couldn't detect OS for setting correct opener"), + } + }; + + // Pass filepath as argument, pipe stdout and stderr to /dev/null + // to keep the TUI clean (where is it piped on Windows???) + let _ = Command::new(&cmd) .arg(&filepath) - // Pipe output produced by opener to /dev/null .stdout(Stdio::null()) .stderr(Stdio::null()) .spawn() @@ -235,4 +261,56 @@ impl App { Ok(()) } + + pub fn open_doi_url(&mut self) -> Result<()> { + let idx = self.entry_table.entry_table_state.selected().unwrap(); + let web_adress = self.entry_table.entry_table_items[idx].doi_url.clone(); + + // Resolve strings using the resolving function of dx.doi.org, so the + // terminal is not blocked by the resolving process + let url = if web_adress.starts_with("10.") { + let prefix = "https://doi.org/".to_string(); + prefix + &web_adress + } else if web_adress.starts_with("www.") { + let prefix = "https://".to_string(); + prefix + &web_adress + } else { + web_adress + }; + + // Build command to execute browser. 'xdg-open' is Linux standard + let cmd = { + match std::env::consts::OS { + "linux" => String::from("xdg-open"), + "macos" => String::from("open"), + "windows" => String::from("start"), + _ => panic!("Couldn't detect OS for setting correct opener"), + } + }; + + // Pass filepath as argument, pipe stdout and stderr to /dev/null + // to keep the TUI clean (where is it piped on Windows???) + let _ = Command::new(&cmd) + .arg(url) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .spawn() + .wrap_err("Opening file not possible"); + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn check_os() { + let os = std::env::consts::OS; + assert_eq!( + os, + "linux", + "You're not coding on linux, but on {}... Switch to linux, now!", + std::env::consts::OS + ) + } } diff --git a/src/frontend/handler.rs b/src/frontend/handler.rs index 5bb52d5..9a27b3a 100644 --- a/src/frontend/handler.rs +++ b/src/frontend/handler.rs @@ -102,6 +102,9 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App, tui: &mut Tui) -> R KeyCode::Char('o') => { app.open_connected_file()?; } + KeyCode::Char('u') => { + app.open_doi_url()?; + } KeyCode::Char('/') => { app.enter_search_area(); } diff --git a/src/main.rs b/src/main.rs index 9ff24c8..74e1252 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,8 @@ // along with this program. If not, see <https://www.gnu.org/licenses/>. ///// +use core::panic; + use backend::cliargs::{self, CLIArgs}; use color_eyre::eyre::Result; use frontend::app::App; @@ -39,6 +41,10 @@ async fn main() -> Result<()> { std::process::exit(0); } + if !parsed_args.bibfilearg.is_file() { + panic!("No \'.bib\' file passed, aborting") + } + // Create an application. let mut app = App::new(parsed_args)?; |
