From 3e86e1d11fa06dedde78621c3e0503a7492ad05e Mon Sep 17 00:00:00 2001
From: lukeflo
Date: Fri, 27 Sep 2024 14:49:37 +0200
Subject: copy citekey action, info box init
---
src/backend/bib.rs | 29 ++++++++++++---
src/frontend/app.rs | 94 +++++++++++++++++++++++++++----------------------
src/frontend/handler.rs | 9 +++++
src/frontend/ui.rs | 70 ++++++++++++++++++++++++++----------
src/main.rs | 8 +----
5 files changed, 138 insertions(+), 72 deletions(-)
(limited to 'src')
diff --git a/src/backend/bib.rs b/src/backend/bib.rs
index c520395..cbaa00e 100644
--- a/src/backend/bib.rs
+++ b/src/backend/bib.rs
@@ -23,6 +23,7 @@ use biblatex::{ChunksExt, Type};
// Set necessary fields
// TODO: can surely be made more efficient/simpler
+#[derive(Debug)]
pub struct BibiMain {
pub bibfile: PathBuf, // path to bibfile
pub bibfilestring: String, // content of bibfile as string
@@ -105,7 +106,7 @@ impl BibiEntry {
]
}
- fn get_authors(citekey: &str, biblio: &Bibliography) -> String {
+ pub fn get_authors(citekey: &str, biblio: &Bibliography) -> String {
let authors = {
if biblio.get(&citekey).unwrap().author().is_ok() {
let authors = biblio.get(&citekey).unwrap().author().unwrap();
@@ -141,7 +142,7 @@ impl BibiEntry {
authors
}
- fn get_title(citekey: &str, biblio: &Bibliography) -> String {
+ pub fn get_title(citekey: &str, biblio: &Bibliography) -> String {
let title = {
if biblio.get(&citekey).unwrap().title().is_ok() {
let title = biblio
@@ -159,7 +160,7 @@ impl BibiEntry {
title
}
- fn get_year(citekey: &str, biblio: &Bibliography) -> String {
+ pub fn get_year(citekey: &str, biblio: &Bibliography) -> String {
let year = biblio.get(&citekey).unwrap();
let year = {
if year.date().is_ok() {
@@ -174,12 +175,12 @@ impl BibiEntry {
year
}
- fn get_pubtype(citekey: &str, biblio: &Bibliography) -> String {
+ pub fn get_pubtype(citekey: &str, biblio: &Bibliography) -> String {
let pubtype = biblio.get(&citekey).unwrap().entry_type.to_string();
pubtype
}
- fn get_keywords(citekey: &str, biblio: &Bibliography) -> String {
+ pub fn get_keywords(citekey: &str, biblio: &Bibliography) -> String {
let keywords = biblio
.get(&citekey)
.unwrap()
@@ -188,4 +189,22 @@ impl BibiEntry {
.format_verbatim();
keywords
}
+
+ pub fn get_abstract(citekey: &str, biblio: &Bibliography) -> String {
+ let text = {
+ if biblio.get(&citekey).unwrap().abstract_().is_ok() {
+ let abstract_text = biblio
+ .get(&citekey)
+ .unwrap()
+ .abstract_()
+ .unwrap()
+ .format_verbatim();
+ abstract_text
+ } else {
+ let abstract_text = format!("No abstract");
+ abstract_text
+ }
+ };
+ text
+ }
}
diff --git a/src/frontend/app.rs b/src/frontend/app.rs
index d61d094..7a211e8 100644
--- a/src/frontend/app.rs
+++ b/src/frontend/app.rs
@@ -18,6 +18,7 @@
use crate::backend::bib::*;
use std::error;
+use arboard::Clipboard;
use itertools::Itertools;
use ratatui::widgets::{ListState, TableState};
@@ -37,10 +38,16 @@ pub enum CurrentArea {
pub struct App {
// Is the application running?
pub running: bool,
+ // main bibliography
+ pub main_biblio: BibiMain,
+ // bibliographic data
+ pub biblio_data: BibiData,
// list
pub tag_list: TagList,
// TODO: table items
pub entry_table: EntryTable,
+ // scroll state info buffer
+ pub scroll_info: u16,
// area
pub current_area: CurrentArea,
}
@@ -185,39 +192,35 @@ impl EntryTableItem {
}
}
-// impl Default for App {
-// fn default(bib_main: &BibiMain, bib_data: &BibiData) -> Self {
-// // TEST: read file
-// let keyword_list = BibiMain::new().citekeys;
-// let entry_vec = BibiData::new().entry_list.bibentries;
-// Self {
-// running: true,
-// tag_list: TagList::from_iter(keyword_list),
-// entry_table: EntryTable::from_iter(entry_vec),
-// current_area: CurrentArea::EntryArea,
-// }
-// }
-// }
+impl Default for App {
+ fn default() -> Self {
+ let running = true;
+ let main_biblio = BibiMain::new();
+ let biblio_data = BibiData::new(&main_biblio.bibliography, &main_biblio.citekeys);
+ let tag_list = TagList::from_iter(main_biblio.citekeys.clone());
+ let entry_table = EntryTable::from_iter(biblio_data.entry_list.bibentries.clone());
+ let current_area = CurrentArea::EntryArea;
+ Self {
+ running,
+ main_biblio,
+ biblio_data,
+ tag_list,
+ entry_table,
+ scroll_info: 0,
+ current_area,
+ }
+ }
+}
impl App {
// Constructs a new instance of [`App`].
- pub fn new(bib_main: &BibiMain, bib_data: &BibiData) -> Self {
- Self {
- running: true,
- tag_list: TagList::from_iter(bib_main.citekeys.clone()),
- entry_table: EntryTable::from_iter(bib_data.entry_list.bibentries.clone()),
- current_area: CurrentArea::EntryArea,
- }
+ pub fn new() -> Self {
+ Self::default()
}
// Handles the tick event of the terminal.
pub fn tick(&self) {}
- // TODO: Create process to do something with selected entry
- // The logic getting e.g. the citekey of the selected entry is:
- // let idx = self.entry_table.entry_table_state.selected().unwrap();
- // println!("{:#?}", self.entry_table.entry_table_items[*idx].citekey);
-
// Set running to false to quit the application.
pub fn quit(&mut self) {
self.running = false;
@@ -231,6 +234,18 @@ impl App {
}
}
+ pub fn scroll_info_down(&mut self) {
+ self.scroll_info = (self.scroll_info + 1) % 10;
+ }
+
+ pub fn scroll_info_up(&mut self) {
+ if self.scroll_info == 0 {
+ {}
+ } else {
+ self.scroll_info = (self.scroll_info - 1) % 10;
+ }
+ }
+
pub fn select_none(&mut self) {
match self.current_area {
CurrentArea::EntryArea => self.entry_table.entry_table_state.select(None),
@@ -270,22 +285,17 @@ impl App {
// self.tag_list.tag_list_state.select_last();
}
- // pub fn select_none(&mut self) {
- // self.entry_table.entry_table_state.select(None);
- // }
-
- // pub fn select_next(&mut self) {
- // self.entry_table.entry_table_state.select_next();
- // }
- // pub fn select_previous(&mut self) {
- // self.entry_table.entry_table_state.select_previous();
- // }
-
- // pub fn select_first(&mut self) {
- // self.entry_table.entry_table_state.select_first();
- // }
+ // Get the citekey of the selected entry
+ pub fn get_selected_citekey(&self) -> &str {
+ let idx = self.entry_table.entry_table_state.selected().unwrap();
+ let citekey = &self.entry_table.entry_table_items[idx].citekey;
+ citekey
+ }
- // pub fn select_last(&mut self) {
- // self.entry_table.entry_table_state.select_last();
- // }
+ // Yank the passed string to system clipboard
+ pub fn yank_text(selection: &str) {
+ let mut clipboard = Clipboard::new().unwrap();
+ let yanked_text = selection.to_string();
+ clipboard.set_text(yanked_text).unwrap();
+ }
}
diff --git a/src/frontend/handler.rs b/src/frontend/handler.rs
index cdf47e2..a9b79a0 100644
--- a/src/frontend/handler.rs
+++ b/src/frontend/handler.rs
@@ -34,6 +34,12 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
app.quit();
}
}
+ KeyCode::PageDown => {
+ app.scroll_info_down();
+ }
+ KeyCode::PageUp => {
+ app.scroll_info_up();
+ }
_ => {}
}
// Keycodes for specific areas
@@ -77,6 +83,9 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
KeyCode::Char('G') | KeyCode::End => {
app.select_last();
}
+ KeyCode::Char('y') => {
+ App::yank_text(&app.get_selected_citekey());
+ }
KeyCode::Tab | KeyCode::BackTab => {
app.toggle_area();
}
diff --git a/src/frontend/ui.rs b/src/frontend/ui.rs
index 5d17051..8d5dcd8 100644
--- a/src/frontend/ui.rs
+++ b/src/frontend/ui.rs
@@ -15,6 +15,7 @@
// along with this program. If not, see .
/////
+use biblatex::ChunksExt;
use ratatui::{
buffer::Buffer,
layout::{Constraint, Layout, Rect},
@@ -23,14 +24,17 @@ use ratatui::{
Color, Modifier, Style, Stylize,
},
symbols,
- text::{Line, Text},
+ text::{Line, Span, Text},
widgets::{
Block, Cell, HighlightSpacing, List, ListItem, Padding, Paragraph, Row, StatefulWidget,
Table, TableState, Widget, Wrap,
},
};
-use crate::frontend::app::{App, TagListItem};
+use crate::{
+ backend::bib::BibiEntry,
+ frontend::app::{App, TagListItem},
+};
use super::app::EntryTableItem;
@@ -171,24 +175,54 @@ impl App {
);
}
- pub fn render_selected_item(&self, area: Rect, buf: &mut Buffer) {
+ pub fn render_selected_item(&mut self, area: Rect, buf: &mut Buffer) {
// We get the info depending on the item's state.
- // INFO: Only a placeholder at the moment:
- let info = "Infor for selected item".to_string();
// TODO: Implement logic showin informations for selected entry:
- // let info = if let Some(i) = self.tag_list.state.selected() {
- // "Infor for selected item".to_string()
- // // match self.todo_list.items[i].status {
- // // Status::Completed => format!("✓ DONE: {}", self.todo_list.items[i].info),
- // // Status::Todo => format!("☐ TODO: {}", self.todo_list.items[i].info),
- // // }
- // } else {
- // "Nothing selected...".to_string()
- // };
+ let style_value = Style::new().bold();
+ let mut lines = vec![];
+ lines.push(Line::from(vec![
+ Span::styled("Authors: ", style_value),
+ Span::styled(
+ String::from(BibiEntry::get_authors(
+ &self.get_selected_citekey(),
+ &self.main_biblio.bibliography,
+ )),
+ Style::new().green(),
+ ),
+ ]));
+ lines.push(Line::from(vec![
+ Span::styled("Title: ", style_value),
+ Span::styled(
+ String::from(BibiEntry::get_title(
+ &self.get_selected_citekey(),
+ &self.main_biblio.bibliography,
+ )),
+ Style::new().magenta(),
+ ),
+ ]));
+ lines.push(Line::from(vec![
+ Span::styled("Year: ", style_value),
+ Span::styled(
+ String::from(BibiEntry::get_year(
+ &self.get_selected_citekey(),
+ &self.main_biblio.bibliography,
+ )),
+ Style::new().light_magenta(),
+ ),
+ ]));
+ lines.push(Line::from(""));
+ lines.push(Line::from(vec![Span::styled(
+ String::from(BibiEntry::get_abstract(
+ &self.get_selected_citekey(),
+ &self.main_biblio.bibliography,
+ )),
+ Style::default(),
+ )]));
+ let info = Text::from(lines);
// We show the list item's info under the list in this paragraph
let block = Block::bordered()
- .title(Line::raw(" Item Info ").centered())
+ .title(Line::raw(" Entry Information ").centered())
// .borders(Borders::TOP)
.border_set(symbols::border::ROUNDED)
.border_style(BOX_BORDER_STYLE_MAIN)
@@ -198,8 +232,9 @@ impl App {
// We can now render the item info
Paragraph::new(info)
.block(block)
- .fg(TEXT_FG_COLOR)
+ // .fg(TEXT_FG_COLOR)
.wrap(Wrap { trim: false })
+ .scroll((self.scroll_info, 0))
.render(area, buf);
}
@@ -208,8 +243,7 @@ impl App {
.title(Line::raw(" Tag List ").centered())
.border_set(symbols::border::ROUNDED)
.border_style(BOX_BORDER_STYLE_MAIN)
- .bg(Color::Black)
- .padding(Padding::horizontal(1));
+ .bg(Color::Black);
// Iterate through all elements in the `items` and stylize them.
let items: Vec = self
diff --git a/src/main.rs b/src/main.rs
index a07b75a..6ffff25 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -50,14 +50,8 @@ async fn main() -> AppResult<()> {
std::process::exit(0);
}
- // TODO: Implement logic for CLI arguments/options which need to be handled
- // before the TUI is started
-
- let mut bib_main = BibiMain::new();
- let mut bib_data = BibiData::new(&bib_main.bibliography, &bib_main.citekeys);
-
// Create an application.
- let mut app = App::new(&mut bib_main, &mut bib_data);
+ let mut app = App::new();
// Initialize the terminal user interface.
let backend = CrosstermBackend::new(io::stdout());
--
cgit v1.2.3