commit a3970084c76419c27a95164ae2f20a09dfa7c23a
parent 1127ffe3f8a250600fd40febf51aa8a2e8b6155f
Author: cy6erlion <dev@merely.tech>
Date: Tue, 12 Jan 2021 20:30:06 +0200
tui initial cursive UI intergration
Diffstat:
M | src/main.rs | | | 106 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------ |
1 file changed, 82 insertions(+), 24 deletions(-)
diff --git a/src/main.rs b/src/main.rs
@@ -1,14 +1,19 @@
use clap::{App, Arg, SubCommand};
-extern crate pager;
+use cursive::align::HAlign;
+use cursive::event::{EventResult, Key};
+use cursive::theme::{BaseColor::*, Color::*, PaletteColor::*};
+use cursive::traits::With;
+use cursive::traits::*;
+use cursive::views::{Dialog, OnEventView, Panel, SelectView, TextContent, TextView};
+use cursive::Cursive;
mod fetch;
-pub mod storage;
+mod storage;
-use pager::Pager;
use std::fs::File;
use std::io::{BufReader, Read};
-fn main() {
+fn main() -> Result<(), std::io::Error> {
let matches = App::new("ietf")
.version("0.1.0")
.about("A program to read RFCs in the terminal.")
@@ -34,13 +39,22 @@ fn main() {
.get_matches();
let storage = storage::Storage::new();
-
- // Read RFC by serial number
+ let mut siv = cursive::default();
+ siv.set_theme(cursive::theme::Theme::default().with(|theme| {
+ use cursive::theme::{BaseColor::*, Color::*, PaletteColor::*};
+ theme.palette[Background] = TerminalDefault;
+ theme.palette[Primary] = Dark(Black);
+ theme.palette[Secondary] = Rgb(255, 12, 42);
+ }));
+
+ // Read RFC by rfcnumber
if let Some(n) = matches.value_of("Number") {
let rfc_number = n.parse::<u32>().unwrap();
// check if RFC is downloaded
if !storage.is_rfc_downloaded(rfc_number).unwrap() {
+ println!("Fetching RFC...");
+
// download RFC
let rfc_data = fetch::rfc(rfc_number).unwrap();
@@ -57,9 +71,9 @@ fn main() {
.read_to_string(&mut rfc_data)
.expect("Unable to read RFC");
- Pager::with_pager("less -r").setup();
- println!("{}", &rfc_data);
- return;
+ siv.add_layer(TextView::new(rfc_data).with_name("text").scrollable());
+ siv.run();
+ return Ok(());
}
// Removes RFC by serial number
@@ -68,19 +82,19 @@ fn main() {
n.parse::<u32>()
.expect("RFC Serial Number should be a numeric value!"),
);
- return;
+ return Ok(());
}
// Update RFC index
if let Some(_matches) = matches.subcommand_matches("update") {
storage.update_index();
- return;
+ return Ok(());
}
// Remove the ietf directory
if let Some(_matches) = matches.subcommand_matches("clean") {
storage.clean();
- return;
+ return Ok(());
}
// ---------- Display RFC list view ------------
@@ -89,22 +103,66 @@ fn main() {
let mut buffer_reader = BufReader::new(index_file);
let mut read_more_dots = "";
- buffer_reader
- .read_to_string(&mut index_data)
- .expect("Unable to read INDEX");
+ // Let's put the callback in a separate function to keep it clean,
+ // but it's not required.
+ let show_next_window = move |siv: &mut Cursive, rfc_title: &str| {
+ let rfc_title: Vec<&str> = rfc_title.split(' ').collect();
- Pager::with_pager("less -r").setup();
+ let rfc_number = rfc_title[0]
+ .parse::<u32>()
+ .expect("Could not parse RFC number");
- for line in index_data.lines() {
- let line_words: Vec<&str> = line.split(' ').collect();
- let summerize: String = line.chars().skip(line_words[0].len()).take(77).collect();
+ // check if RFC is downloaded
+ if !storage.is_rfc_downloaded(rfc_number).unwrap() {
+ println!("Fetching RFC...");
+ // download RFC
+ let rfc_data = fetch::rfc(rfc_number).unwrap();
- if line.len() >= 77 {
- read_more_dots = "...";
+ // persist RFC
+ storage.persist_rfc(rfc_number, &rfc_data);
}
- println!("{} | {}{}", line_words[0], summerize, read_more_dots);
+ let rfc_file_path = format!("{}{}", storage.rfc_dir_path, rfc_number);
- read_more_dots = "";
- }
+ let mut rfc_data = String::new();
+ let index_file = File::open(&rfc_file_path).expect("Unable to open file");
+ let mut buffer_reader = BufReader::new(index_file);
+ buffer_reader
+ .read_to_string(&mut rfc_data)
+ .expect("Unable to read RFC");
+
+ siv.add_layer(TextView::new(rfc_data).with_name("text").scrollable());
+ };
+
+ buffer_reader
+ .read_to_string(&mut index_data)
+ .expect("Unable to read INDEX");
+
+ let lines = index_data.lines();
+
+ let mut select = SelectView::new()
+ // Center the text horizontally
+ .h_align(HAlign::Center)
+ // Use keyboard to jump to the pressed letters
+ .autojump();
+
+ select.add_all_str(lines);
+
+ // Sets the callback for when "Enter" is pressed.
+ select.set_on_submit(show_next_window);
+
+ // Let's override the `p` and `n` keys for navigation
+ let select = OnEventView::new(select)
+ .on_pre_event_inner('p', |s, _| {
+ let cb = s.select_up(1);
+ Some(EventResult::Consumed(Some(cb)))
+ })
+ .on_pre_event_inner('n', |s, _| {
+ let cb = s.select_down(1);
+ Some(EventResult::Consumed(Some(cb)))
+ });
+
+ siv.add_layer(Dialog::around(select.scrollable().fixed_size((30, 20))).title("IETF RFC INDEX"));
+ siv.run();
+ Ok(())
}