From fffc48bfc6bb88ba04af5c68fc12e677ad92fadf Mon Sep 17 00:00:00 2001 From: dvkt Date: Thu, 19 Dec 2019 02:11:51 -0800 Subject: [PATCH] lil help menu --- README.md | 1 + src/help.rs | 37 ++++++++++++++++++++++ src/main.rs | 3 +- src/menu/menu_view.rs | 9 ++++-- src/menu/mod.rs | 4 ++- src/text.rs | 10 ++++-- src/ui.rs | 74 +++++++++++++++++++++++++------------------ 7 files changed, 101 insertions(+), 37 deletions(-) create mode 100644 src/help.rs diff --git a/README.md b/README.md index 0987828..2cc69ab 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ Just unzip/untar the `phetch` program into your $PATH and get going! ### basics - [ ] download to ~/Downloads + gopher://zaibatsu.circumlunar.space/1/~cardboard64/ - [ ] `?` to show all keyboard shortcuts - [ ] save history to file - [ ] load history from file diff --git a/src/help.rs b/src/help.rs new file mode 100644 index 0000000..609d2b4 --- /dev/null +++ b/src/help.rs @@ -0,0 +1,37 @@ +pub const GOPHERMAP: &str = " +i +i +i / / / +i ___ (___ ___ (___ ___ (___ +i| )| )|___)| | | ) +i|__/ | / |__ |__ |__ | / +i| +i +i ** keyboard shortcuts ** +i +ileft back in history +iright forward in history +iup select prev link +idown select next link +ipage up scroll page up +ipage down scroll page down +i +ictrl-g go to gopher url +ictrl-u show current gopher url +ictrl-y copy url to clipboard +ictrl-r view raw version of page +i +i ~ * ~ +i +iPress the # of a link to visit +ior select it. Use ENTER to open +ithe selected link. +i +iJust start typing to select links. +i +1text mode shortcuts /text help +1menu mode shortcuts /menu help +i +1....some of my poetry /poetry help +i +"; diff --git a/src/main.rs b/src/main.rs index 7c2c0c7..683e426 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ extern crate termion; mod gopher; +mod help; mod menu; mod text; mod ui; @@ -53,7 +54,7 @@ fn main() { let mut ui = UI::new(); if let Err(e) = ui.open(&url) { - ui.error(&e.to_string()); + ui::error(&e.to_string()); exit(1); } ui.run(); diff --git a/src/menu/menu_view.rs b/src/menu/menu_view.rs index 02313d1..2d5a130 100644 --- a/src/menu/menu_view.rs +++ b/src/menu/menu_view.rs @@ -3,7 +3,8 @@ use gopher::Type; use menu::{Line, Menu}; use std::io::stdout; use std::io::Write; -use ui::{prompt, Action, Key, View, MAX_COLS, SCROLL_LINES}; +use ui; +use ui::{Action, Key, View, MAX_COLS, SCROLL_LINES}; pub struct MenuView { pub input: String, // user's inputted value @@ -26,6 +27,10 @@ impl View for MenuView { self.render_lines() } + fn raw(&self) -> String { + self.menu.raw.to_string() + } + fn process_input(&mut self, key: Key) -> Action { self.process_key(key) } @@ -365,7 +370,7 @@ impl MenuView { let url = line.url.to_string(); let (typ, _, _, _) = gopher::parse_url(&url); if typ == Type::Search { - if let Some(query) = prompt(&format!("{}> ", line.name)) { + if let Some(query) = ui::prompt(&format!("{}> ", line.name)) { Action::Open(format!("{}?{}", url, query)) } else { Action::None diff --git a/src/menu/mod.rs b/src/menu/mod.rs index 4c06c0f..b35f355 100644 --- a/src/menu/mod.rs +++ b/src/menu/mod.rs @@ -9,6 +9,7 @@ pub struct Menu { pub lines: Vec, // lines pub links: Vec, // links (index of line in lines vec) pub longest: usize, // size of the longest line + pub raw: String, // raw response } #[derive(Debug)] @@ -85,7 +86,7 @@ impl Menu { url.push_str("/"); url.push(first_char); // add trailing / if the selector is blank - if parts.len() == 0 || parts[1].len() == 0 { + if parts.len() == 0 || parts.len() > 1 && parts[1].len() == 0 { url.push('/'); } } @@ -106,6 +107,7 @@ impl Menu { lines, links, longest, + raw, } } } diff --git a/src/text.rs b/src/text.rs index 316d458..bba3e54 100644 --- a/src/text.rs +++ b/src/text.rs @@ -2,7 +2,7 @@ use ui::{Action, Key, View, MAX_COLS, SCROLL_LINES}; pub struct TextView { url: String, - raw: String, + raw_response: String, scroll: usize, // offset lines: usize, // # of lines longest: usize, // longest line @@ -14,6 +14,10 @@ impl View for TextView { self.url.to_string() } + fn raw(&self) -> String { + self.raw_response.to_string() + } + fn set_size(&mut self, cols: usize, rows: usize) { self.size = (cols, rows); } @@ -95,7 +99,7 @@ impl View for TextView { String::from("") }; let iter = self - .raw + .raw_response .split_terminator('\n') .skip(self.scroll) .take(rows - 1); @@ -125,7 +129,7 @@ impl TextView { TextView { url, - raw: response, + raw_response: response, scroll: 0, lines, longest, diff --git a/src/ui.rs b/src/ui.rs index 5a5c942..20eaed9 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -9,6 +9,7 @@ use termion::raw::IntoRawMode; use gopher; use gopher::io_error; use gopher::Type; +use help; use menu::MenuView; use text::TextView; @@ -41,6 +42,7 @@ pub trait View { fn process_input(&mut self, c: Key) -> Action; fn render(&self) -> String; fn url(&self) -> String; + fn raw(&self) -> String; fn set_size(&mut self, cols: usize, rows: usize); } @@ -85,7 +87,7 @@ impl UI { let action = self.process_page_input(); self.process_action(action) - .map_err(|e| self.error(&e.to_string())); + .map_err(|e| error(&e.to_string())); } pub fn open(&mut self, url: &str) -> io::Result<()> { @@ -95,7 +97,7 @@ impl UI { } // gopher URL - self.status(&format!( + status(&format!( "{}Loading...{}", color::Fg(color::LightBlack), termion::cursor::Show @@ -136,32 +138,6 @@ impl UI { self.size = (cols, rows); } - // Display a status message to the user. - fn status(&self, s: &str) { - print!( - "{}{}{}{}{}", - "\x1b[93m", - termion::cursor::Goto(1, self.size.1 as u16), - termion::clear::CurrentLine, - s, - color::Fg(color::Reset) - ); - stdout().flush(); - } - - // Display an error message to the user. - pub fn error(&self, e: &str) { - print!( - "{}{}{}{}{}", - "\x1b[91m", - termion::cursor::Goto(1, self.size.1 as u16), - termion::clear::CurrentLine, - e, - color::Fg(color::Reset) - ); - stdout().flush(); - } - fn add_page(&mut self, view: T) { self.dirty = true; if !self.pages.is_empty() && self.page < self.pages.len() - 1 { @@ -209,6 +185,13 @@ impl UI { self.page += 1; } } + Action::Keypress(Key::Ctrl('r')) => { + if let Some(page) = self.pages.get(self.page) { + let url = page.url().to_string(); + let raw = page.raw().to_string(); + self.add_page(TextView::from(url, raw)); + } + } Action::Keypress(Key::Ctrl('g')) => { if let Some(url) = prompt("Go to URL: ") { if !url.contains("://") && !url.starts_with("gopher://") { @@ -218,15 +201,18 @@ impl UI { } } } + Action::Keypress(Key::Ctrl('h')) => { + self.add_page(MenuView::from("help".into(), help::GOPHERMAP.into())); + } Action::Keypress(Key::Ctrl('u')) => { if let Some(page) = self.pages.get(self.page) { - self.status(&format!("Current URL: {}", page.url())); + status(&format!("Current URL: {}", page.url())); } } Action::Keypress(Key::Ctrl('y')) => { if let Some(page) = self.pages.get(self.page) { copy_to_clipboard(&page.url())?; - self.status(&format!("Copied {} to clipboard.", page.url())); + status(&format!("Copied {} to clipboard.", page.url())); } } _ => (), @@ -329,3 +315,31 @@ pub fn prompt(prompt: &str) -> Option { None } } + +// Display a status message to the user. +pub fn status(s: &str) { + let (_cols, rows) = termion::terminal_size().unwrap(); + print!( + "{}{}{}{}{}", + "\x1b[93m", + termion::cursor::Goto(1, rows), + termion::clear::CurrentLine, + s, + color::Fg(color::Reset) + ); + stdout().flush(); +} + +// Display an error message to the user. +pub fn error(e: &str) { + let (_cols, rows) = termion::terminal_size().unwrap(); + print!( + "{}{}{}{}{}", + "\x1b[91m", + termion::cursor::Goto(1, rows), + termion::clear::CurrentLine, + e, + color::Fg(color::Reset) + ); + stdout().flush(); +}