From 2896973024e7f5c6c9dae5cea9c6e14d168ed7ab Mon Sep 17 00:00:00 2001 From: dvkt Date: Fri, 22 Nov 2019 21:55:32 -0800 Subject: [PATCH] oh oh pee --- src/main.rs | 367 +++++++++++++++++++++++++++++----------------------- 1 file changed, 202 insertions(+), 165 deletions(-) diff --git a/src/main.rs b/src/main.rs index be9b350..dcdd72e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ extern crate termion; +use std::collections::HashMap; use std::io::{stdin, stdout, Read, Write}; use std::net::TcpStream; @@ -10,17 +11,28 @@ use termion::input::TermRead; use termion::raw::IntoRawMode; #[derive(Debug)] -struct Link<'res> { - name: &'res str, - host: &'res str, - port: &'res str, - selector: &'res str, +struct App { + pages: HashMap, + cursor: String, } -struct Cursor { - link: usize, +#[derive(Debug)] +struct Page { + body: String, + cursor: usize, + url: String, + links: Vec, } +#[derive(Debug)] +struct Link { + name: String, + host: String, + port: String, + selector: String, +} + +#[derive(Debug)] enum Action { None, Up, @@ -30,95 +42,205 @@ enum Action { } fn main() { - phetch_and_print("phkt.io", "70", "/"); + let mut app = App { + pages: HashMap::new(), + cursor: String::new(), + }; + app.load("phkt.io", "70", "/"); + loop { + app.render(); + app.respond(); + } } -fn phetch_and_print(host: &str, port: &str, selector: &str) { - let response = phetch(host, port, selector); - let links = parse_links(&response); - println!("{:?}", links); - let mut cursor = Cursor { link: 0 }; - loop { - render(&response, &cursor); - match user_input() { - Action::Up => { - if cursor.link > 0 { - cursor.link -= 1; - } - } - Action::Down => { - if cursor.link < links.len() { - cursor.link += 1; - } - } - Action::Open => { - if cursor.link > 0 && cursor.link - 1 < links.len() { - println!("OPEN: {:?}", links[cursor.link - 1]); - let link = &links[cursor.link - 1]; - phetch_and_print(link.host, link.port, link.selector); +impl App { + fn load(&mut self, host: &str, port: &str, selector: &str) { + let mut page = self.fetch(host, port, selector); + page.parse_links(); + self.pages.insert(page.url.to_string(), page); + self.cursor = format!("{}:{}{}", host, port, selector); + } + + fn render(&self) { + if let Some(page) = self.pages.get(&self.cursor) { + print!("\x1B[2J\x1B[H{}", page.draw()); + } else { + println!("{}", ""); + } + } + + fn fetch(&self, host: &str, port: &str, selector: &str) -> Page { + let mut body = String::new(); + TcpStream::connect(format!("{}:{}", host, port)) + .and_then(|mut stream| { + stream.write(format!("{}\r\n", selector).as_ref()); + Ok(stream) + }) + .and_then(|mut stream| { + stream.read_to_string(&mut body); + Ok(()) + }) + .map_err(|err| { + eprintln!("err: {}", err); + }); + Page { + body: body, + cursor: 0, + url: format!("{}:{}{}", host, port, selector), + links: Vec::new(), + } + } + + fn respond(&mut self) { + match self.pages.get_mut(&self.cursor) { + None => return, + Some(page) => match term_input() { + Action::Up => page.cursor_up(), + Action::Down => page.cursor_down(), + Action::Open => { + if page.cursor > 0 && page.cursor - 1 < page.links.len() { + println!("OPEN: {:?}", page.links[page.cursor - 1]); + std::process::exit(0); + } } - } - Action::Quit => return, - _ => {} + Action::Quit => return, + _ => {} + }, } } } -fn phetch(host: &str, port: &str, selector: &str) -> String { - let mut out = String::new(); - TcpStream::connect(format!("{}:{}", host, port)) - .and_then(|mut stream| { - stream.write(format!("{}\r\n", selector).as_ref()); - Ok(stream) - }) - .and_then(|mut stream| { - stream.read_to_string(&mut out); - Ok(()) - }) - .map_err(|err| { - eprintln!("err: {}", err); - }); - out -} +impl Page { + fn cursor_up(&mut self) { + if self.cursor > 0 { + self.cursor -= 1; + } + } + fn cursor_down(&mut self) { + if self.cursor < self.links.len() { + self.cursor += 1; + } + } -fn parse_links<'res>(response: &'res str) -> Vec { - let mut links: Vec = Vec::new(); - let mut start = true; - let mut is_link = false; - let mut link = (0, 0); - for (i, c) in response.chars().enumerate() { - if start { - match c { - '0' | '1' => { - is_link = true; - link.0 = i + 1; + fn parse_links(&mut self) { + if self.links.len() > 0 { + self.links.clear(); + } + let mut start = true; + let mut is_link = false; + let mut link = (0, 0); + for (i, c) in self.body.chars().enumerate() { + if start { + match c { + '0' | '1' => { + is_link = true; + link.0 = i + 1; + } + '\n' => continue, + _ => is_link = false, + } + start = false; + } else if c == '\n' { + start = true; + if is_link && i > link.0 { + link.1 = i; + let mut line = Vec::new(); + for s in self.body[link.0..link.1].split('\t') { + line.push(s); + } + self.links.push(Link { + name: line[0].to_string(), + selector: line[1].to_string(), + host: line[2].to_string(), + port: line[3].trim_end_matches('\r').to_string(), + }); + is_link = false; } - '\n' => continue, - _ => is_link = false, } - start = false; - } else if c == '\n' { - start = true; - if is_link && i > link.0 { - link.1 = i; - let mut line = Vec::new(); - for s in response[link.0..link.1].split('\t') { - line.push(s); + } + } + + fn draw(&self) -> String { + let mut start = true; + let mut skip_to_end = false; + let mut links = 0; + let mut out = String::with_capacity(self.body.len() * 2); + let mut prefix = ""; + for (i, c) in self.body.chars().enumerate() { + let mut is_link = false; + if start { + match c { + 'i' => { + prefix = "\x1B[93m"; + is_link = false; + } + 'h' => { + prefix = "\x1B[96m"; + links += 1; + is_link = true; + } + '0' => { + prefix = "\x1B[94m"; + links += 1; + is_link = true; + } + '1' => { + prefix = "\x1B[94m"; + links += 1; + is_link = true; + } + '.' => { + if self.body.len() > i + 2 + && self.body[i..].chars().next().unwrap() == '\r' + && self.body[i + 1..].chars().next().unwrap() == '\n' + { + continue; + } + } + '\r' => continue, + '\n' => continue, + _ => prefix = "", + } + if is_link && self.cursor > 0 && self.cursor == links { + out.push_str("\x1b[92;1m*\x1b[0m"); + } else { + out.push(' '); + } + out.push_str(" "); + if is_link { + out.push_str("\x1B[95m"); + if links < 10 { + out.push(' '); + } + out.push_str(&links.to_string()); + out.push_str(". \x1B[0m"); + } else { + out.push(' '); + out.push_str("\x1B[0m"); + out.push_str(" "); + } + out.push_str(prefix); + start = false + } else if skip_to_end { + if c == '\n' { + out.push_str("\r\n\x1B[0m"); + start = true; + skip_to_end = false; + } + } else if c == '\t' { + skip_to_end = true; + } else { + out.push(c); + if c == '\n' { + start = true; } - links.push(Link { - name: line[0], - selector: line[1], - host: line[2], - port: line[3].trim_end_matches('\r'), - }); - is_link = false; } } + out } - links } -fn user_input() -> Action { +fn term_input() -> Action { let stdin = stdin(); let mut stdout = stdout().into_raw_mode().unwrap(); let mut y = 1; @@ -163,88 +285,3 @@ fn user_input() -> Action { } Action::None } - -fn render(buf: &str, cur: &Cursor) { - // let clear = ""; - let clear = "\x1B[2J\x1B[H"; - print!("{}{}", clear, draw(buf, cur)); -} - -fn draw(buf: &str, cur: &Cursor) -> String { - let mut start = true; - let mut skip_to_end = false; - let mut links = 0; - let mut out = String::with_capacity(buf.len() * 2); - let mut prefix = ""; - for (i, c) in buf.chars().enumerate() { - let mut is_link = false; - if start { - match c { - 'i' => { - prefix = "\x1B[93m"; - is_link = false; - } - 'h' => { - prefix = "\x1B[96m"; - links += 1; - is_link = true; - } - '0' => { - prefix = "\x1B[94m"; - links += 1; - is_link = true; - } - '1' => { - prefix = "\x1B[94m"; - links += 1; - is_link = true; - } - '.' => { - if buf.len() > i + 2 - && buf[i..].chars().next().unwrap() == '\r' - && buf[i + 1..].chars().next().unwrap() == '\n' - { - continue; - } - } - '\r' => continue, - '\n' => continue, - _ => prefix = "", - } - if is_link && cur.link > 0 && cur.link == links { - out.push_str("\x1b[92;1m*\x1b[0m"); - } else { - out.push(' '); - } - out.push_str(" "); - if is_link { - out.push_str("\x1B[95m"); - if links < 10 { - out.push(' '); - } - out.push_str(&links.to_string()); - out.push_str(". \x1B[0m"); - } else { - out.push(' '); - out.push_str("\x1B[0m"); - out.push_str(" "); - } - out.push_str(prefix); - start = false - } else if skip_to_end { - if c == '\n' { - out.push_str("\r\n\x1B[0m"); - start = true; - skip_to_end = false; - } - } else if c == '\t' { - skip_to_end = true; - } else { - out.push(c); - if c == '\n' { - start = true; - } - } - } - out -}