pull/6/head
dvkt 5 years ago
parent e6bc272ea9
commit add433141a

@ -1,18 +1,11 @@
#![allow(unused_must_use)]
extern crate termion;
use std::collections::HashMap;
use std::io::{stdin, stdout, Read, Write};
use termion::event::Key;
use termion::input::TermRead;
use termion::raw::IntoRawMode;
mod fetch;
mod page;
mod types;
mod ui;
use ui::*;
fn main() {
let args: Vec<String> = std::env::args().collect();
@ -30,7 +23,7 @@ fn main() {
return;
}
let mut ui = UI::new();
let mut ui = ui::UI::new();
ui.load(host, port, selector);
ui.run();
}

@ -2,6 +2,23 @@ use std::io;
use std::io::{Read, Write};
use std::net::TcpStream;
use types::Type;
use ui::{Action, Key, View};
#[derive(Debug)]
pub struct PageView {
pub input: String, // user's inputted value
pub page: Page, // data
pub line: usize, // selected line
pub scroll: usize, // scrolling offset
}
#[derive(Debug)]
pub struct Page {
lines: Vec<Line>, // lines
typ: Type, // entry type
raw: String, // raw gopher response
url: String, // gopher url
}
#[derive(Debug)]
pub struct Line {
@ -13,15 +30,111 @@ pub struct Line {
typ: Type,
}
#[derive(Debug)]
pub struct Page {
typ: Type, // entry type
raw: String, // raw gopher response
url: String, // gopher url
lines: Vec<Line>, // lines
line: usize, // selected line
input: String, // user's inputted value
offset: usize, // scrolling position
impl View for PageView {
fn process_input(&mut self, key: Key) -> Action {
match key {
Key::Char('\n') => return Action::Open,
Key::Backspace => {
if self.input.is_empty() {
Action::Back
} else {
self.input.pop();
Action::None
}
}
Key::Delete => {
self.input.pop();
Action::None
}
Key::Backspace => {
if self.input.is_empty() {
Action::Back
} else {
self.input.pop();
Action::None
}
}
Key::Delete => {
self.input.pop();
Action::None
}
Key::Ctrl('c') => {
if self.input.len() > 0 {
self.input.clear();
Action::None
} else {
Action::Quit
}
}
Key::Char('-') => {
if self.input.is_empty() {
Action::PageUp
} else {
self.input.push('-');
Action::None
}
}
Key::Char(' ') => {
if self.input.is_empty() {
return Action::PageDown;
} else {
self.input.push(' ');
Action::None
}
}
Key::Char(c) => {
self.input.push(c);
for (i, link) in self.page.lines.iter().enumerate() {
// jump to number
let count = self.page.lines.len();
if count < 10 && c == '1' && i == 0 {
return Action::FollowLink(i);
} else if count < 20 && c == '2' && i == 1 {
return Action::FollowLink(i);
} else if count < 30 && c == '3' && i == 2 {
return Action::FollowLink(i);
} else if count < 40 && c == '4' && i == 3 {
return Action::FollowLink(i);
} else if count < 50 && c == '5' && i == 4 {
return Action::FollowLink(i);
} else if count < 60 && c == '6' && i == 5 {
return Action::FollowLink(i);
} else if count < 70 && c == '7' && i == 6 {
return Action::FollowLink(i);
} else if count < 80 && c == '8' && i == 7 {
return Action::FollowLink(i);
} else if count < 90 && c == '9' && i == 8 {
return Action::FollowLink(i);
} else if self.input.len() > 1 && self.input == (i + 1).to_string() {
return Action::FollowLink(i);
} else if self.input.len() == 1 && self.input == (i + 1).to_string() {
return Action::FollowLink(i);
} else {
if link
.name
.to_ascii_lowercase()
.contains(&self.input.to_ascii_lowercase())
{
return Action::FollowLink(i);
}
}
}
Action::None
}
_ => Action::None,
}
}
}
impl PageView {
pub fn from(page: Page) -> PageView {
PageView {
page,
input: String::new(),
line: 0,
scroll: 0,
}
}
}
impl Page {
@ -119,10 +232,7 @@ impl Page {
raw,
url,
lines,
line: 0,
typ: Type::Menu,
input: String::new(),
offset: 0,
}
}
}

@ -1,11 +1,38 @@
use page::Page;
use page::{Page, PageView};
use std::io;
use std::io::{stdin, stdout, Write};
use termion::input::TermRead;
use termion::raw::IntoRawMode;
pub type Key = termion::event::Key;
pub type Error = io::Error;
#[derive(Debug)]
pub struct UI {
pages: Vec<Page>,
pages: Vec<PageView>,
page: usize,
}
#[derive(Debug)]
pub enum Action {
None,
Up,
Down,
PageUp,
PageDown,
Back,
Forward,
Open,
FollowLink(usize),
Quit,
Unknown,
}
pub trait View {
fn process_input(&mut self, c: Key) -> Action;
}
impl UI {
pub fn new() -> UI {
UI {
@ -14,7 +41,7 @@ impl UI {
}
}
pub fn run(&self) {
pub fn run(&mut self) {
loop {
self.print();
self.respond_to_user();
@ -27,12 +54,13 @@ impl UI {
}
pub fn render(&self) -> String {
// let (cols, rows) = termion::terminal_size().expect("can't get terminal size");
String::new()
}
pub fn load(&mut self, host: &str, port: &str, selector: &str) {
match Page::load(host, port, selector) {
Ok(page) => self.add_page(page),
Ok(page) => self.add_page(PageView::from(page)),
Err(e) => {
eprintln!(
"\x1B[91merror loading \x1b[93m{}:{}{}: \x1B[0m{}",
@ -43,12 +71,46 @@ impl UI {
}
}
fn add_page(&mut self, page: Page) {
fn add_page(&mut self, page: PageView) {
self.pages.push(page);
if self.pages.len() > 1 {
self.page += 1;
}
}
fn respond_to_user(&self) {}
// Get a mutable reference to the currently loaded view.
fn mut_view(&mut self) -> Option<&mut PageView> {
if self.pages.len() > 0 && self.page < self.pages.len() {
Some(self.pages.get_mut(self.page).unwrap())
} else {
None
}
}
fn respond_to_user(&mut self) {
self.process_input();
}
fn process_input(&mut self) -> Action {
let stdin = stdin();
let mut stdout = stdout().into_raw_mode().unwrap();
stdout.flush().unwrap();
let mut page = self.mut_view().expect("expected page to be loaded");
for c in stdin.keys() {
let key = c.expect("UI error on stdin.keys");
match page.process_input(key) {
Action::Unknown => match key {
Key::Ctrl('q') => return Action::Quit,
Key::Up | Key::Ctrl('p') => return Action::Up,
Key::Down | Key::Ctrl('n') => return Action::Down,
Key::Left => return Action::Back,
Key::Right => return Action::Forward,
_ => {}
},
action => return action,
}
}
Action::None
}
}

Loading…
Cancel
Save