-- Leo's gemini proxy
-- Connecting to typed-hole.org:1965...
-- Connected
-- Sending request
-- Meta line: 20 text/gemini
commit 36c10b5e3f878c631fbdfe0fe8a9ac256c478cb3
Author: Julien Blanchard <julien@sideburns.eu>
Date: Mon Jul 29 19:01:07 2019 +0200
Improve header and links parsing
diff --git a/src/main.rs b/src/main.rs
index db5eadf..5ec1801 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,9 +1,9 @@
use cursive::align::HAlign;
+use cursive::theme::Effect;
use cursive::traits::*;
+use cursive::utils::markup::StyledString;
use cursive::view::Scrollable;
use cursive::views::{Dialog, EditView, Panel, SelectView};
-use cursive::utils::markup::StyledString;
-use cursive::theme::Effect;
use cursive::Cursive;
extern crate native_tls;
@@ -23,55 +23,67 @@ use url::Url;
struct Header {
- code: i8,
- meta: String
+ code: i16,
+ meta: String,
}
struct Link {
url: String,
- label: String
+ label: String,
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+struct ParseError;
+
+const HEADER_REGEX: &str = r"^(\d{1,3})[ \t](.*)$";
+const LINK_REGEX: &str = r"^=>\s(\S*)\s*(.*)?$";
+
impl FromStr for Header {
- type Err = std::string::ParseError;
+ type Err = ParseError;
- // Parses a string into an instance of 'Header'
+ // Parses a &str into an instance of 'Header'
fn from_str(line: &str) -> Result<Self, Self::Err> {
- let text = format!("{}", line);
- let link_regexp = Regex::new(r"^(\d*)\t(.*)$").unwrap();
+ let header_regexp = Regex::new(HEADER_REGEX).unwrap();
- let caps = link_regexp.captures(&text).unwrap();
- let code_str = caps.get(1).map_or("", |m| m.as_str());
- let meta_str = caps.get(2).map_or("", |m| m.as_str());
+ match header_regexp.captures(&line) {
+ Some(caps) => {
+ let code_str = caps.get(1).map_or("", |m| m.as_str());
+ let meta_str = caps.get(2).map_or("", |m| m.as_str());
- let code = code_str.parse::<i8>().unwrap();
- let meta = meta_str.to_string();
+ let code: i16 = code_str.parse().expect("2");
+ let meta = meta_str.to_string();
- Ok(Header {code, meta})
+ Ok(Header { code, meta })
+ }
+ None => Err(ParseError),
+ }
}
}
impl FromStr for Link {
- type Err = std::string::ParseError;
+ type Err = ParseError;
- // Parses a string into an instance of 'Link'
+ // Parses a &str into an instance of 'Link'
fn from_str(line: &str) -> Result<Self, Self::Err> {
- let text = format!("{}", line);
- let link_regexp = Regex::new(r"^=>\s(\S*)\s*(.*)?$").unwrap();
+ let link_regexp = Regex::new(LINK_REGEX).unwrap();
- let caps = link_regexp.captures(&text).unwrap();
- let url_str = caps.get(1).map_or("", |m| m.as_str());
- let label_str = caps.get(2).map_or("", |m| m.as_str());
+ match link_regexp.captures(&line) {
+ Some(caps) => {
+ let url_str = caps.get(1).map_or("", |m| m.as_str());
+ let label_str = caps.get(2).map_or("", |m| m.as_str());
- let url = url_str.to_string();
- let label = if label_str.is_empty() {
- url_str.to_string()
- } else {
- label_str.to_string()
- };
+ let url = url_str.to_string();
+ let label = if label_str.is_empty() {
+ url_str.to_string()
+ } else {
+ label_str.to_string()
+ };
- Ok(Link {url, label})
+ Ok(Link { url, label })
+ }
+ None => Err(ParseError),
+ }
}
}
@@ -95,12 +107,12 @@ fn main() {
siv.add_fullscreen_layer(
Dialog::around(Panel::new(
- select.with_id("main").scrollable().full_screen()
+ select.with_id("main").scrollable().full_screen(),
))
.title("Asuka Browser")
.h_align(HAlign::Center)
.button("Quit", |s| s.quit())
- .with_id("container")
+ .with_id("container"),
);
// We can quit by pressing q
@@ -119,11 +131,8 @@ fn prompt_for_url(s: &mut Cursive) {
.title("Enter URL")
// Padding is (left, right, top, bottom)
.padding((1, 1, 1, 0))
- .content(
- EditView::new()
- .on_submit(goto_url)
- .fixed_width(20)
- ).with_id("url_popup")
+ .content(EditView::new().on_submit(goto_url).fixed_width(20))
+ .with_id("url_popup"),
);
}
@@ -145,14 +154,12 @@ fn visit_url(s: &mut Cursive, url_s: &str) {
}
match parse_link(url_s) {
- Ok(url) => {
- match get_data(url) {
- Ok(new_content) => {
- draw_content(s, url_s, new_content);
- }
- Err(msg) => {
- s.add_layer(Dialog::info(msg));
- }
+ Ok(url) => match get_data(url) {
+ Ok(new_content) => {
+ draw_content(s, url_s, new_content);
+ }
+ Err(msg) => {
+ s.add_layer(Dialog::info(msg));
}
},
Err(_) => {
@@ -174,7 +181,7 @@ fn parse_link(url: &str) -> Result<url::Url, url::ParseError> {
};
Url::parse(&url_s)
- },
+ }
None => {
let url_s = if url.starts_with("gemini://") {
url.to_owned()
@@ -194,45 +201,31 @@ fn draw_content(s: &mut Cursive, url: &str, content: String) {
container.set_title(url);
main_view.clear();
- for line in content.lines() {
- if is_header(line) {
- // let _header = Header::from_str(line);
- } else if is_link(line) {
- let link = Link::from_str(line).unwrap();
- let mut formatted = StyledString::new();
- formatted.append(StyledString::styled(
- link.label,
- Effect::Underline,
- ));
-
- main_view.add_item(formatted, link.url)
- } else {
- main_view.add_item(line, "0".to_owned())
- }
+ match Header::from_str(content.lines().next().unwrap()) {
+ Ok(_header) => {}
+ Err(_) => {}
}
- main_view.set_on_submit(follow_link);
-}
-
-fn is_header(line: &str) -> bool {
- let text = format!("{}", line);
- let header_regexp = Regex::new(r"^(\d*)\t(\S*)$").unwrap();
-
- header_regexp.is_match(&text)
-}
+ for line in content.lines().skip(1) {
+ match Link::from_str(line) {
+ Ok(link) => {
+ let mut formatted = StyledString::new();
+ formatted.append(StyledString::styled(link.label, Effect::Underline));
-fn is_link(line: &str) -> bool {
- let text = format!("{}", line);
- let link_regexp = Regex::new(r"^=>\s(\S*)(.*)?$").unwrap();
+ main_view.add_item(formatted, link.url)
+ }
+ Err(_) => main_view.add_item(line, "0".to_owned()),
+ }
+ }
- link_regexp.is_match(&text)
+ main_view.set_on_submit(follow_link);
}
fn is_gemini_link(line: &str) -> bool {
line != "0"
}
-fn follow_link (s: &mut Cursive, line: &str) {
+fn follow_link(s: &mut Cursive, line: &str) {
if is_gemini_link(&line) {
let next_url = parse_link(&line);
visit_url(s, next_url.expect("Not an URL").as_str())
@@ -291,8 +284,8 @@ fn get_last_host() -> Option<String> {
Some(url) => {
let urlp = Url::parse(url).expect("not an URL");
Some(urlp.host_str().unwrap().to_owned())
- },
- None => None
+ }
+ None => None,
}
}
---
Served by Pollux Gemini Server.
-- Response ended
-- Page fetched on Sun May 19 10:50:44 2024