-- Leo's gemini proxy

-- Connecting to typed-hole.org:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini

commit 110fa1541eb3710ec5783f8dafca3e394e0f7e37

Author: Julien Blanchard <julien@sideburns.eu>

Date: Sun Dec 22 15:47:47 2019 +0100


Extract GUI stuff, use Arc, display current URL in bar


diff --git a/src/gui.rs b/src/gui.rs

new file mode 100644

index 0000000..bbda792

--- /dev/null

+++ b/src/gui.rs

@@ -0,0 +1,70 @@

+use gtk::prelude::*;

+use gtk::{ApplicationWindow, Button, Entry, TextView};

+

+

+pub struct Gui {

+ window: ApplicationWindow,

+ url_bar: Entry,

+ content_view: TextView,

+ back_button: Button,

+}

+

+impl Gui {

+ pub fn new() -> Gui {

+ // Initialize the UI from the Glade XML.

+ let glade_src = include_str!("castor.glade");

+ let builder = gtk::Builder::new_from_string(glade_src);

+

+ // Get handles for the various controls we need to use.

+ let window: ApplicationWindow = builder.get_object("window").expect("Couldn't get window");

+ let url_bar: Entry = builder.get_object("url_bar").expect("Couldn't get url_bar");

+ let content_view: TextView = builder.get_object("content_view").expect("Couldn't get content_view");

+ let back_button: Button = builder.get_object("back_button").expect("Couldn't get back_button");

+

+ Gui {

+ window,

+ url_bar,

+ content_view,

+ back_button,

+ }

+ }

+

+ // Set up naming for the window and show it to the user.

+ pub fn start(&self) {

+ glib::set_application_name("Castor");

+ self.window.set_wmclass("Castor", "Castor");

+ self.window.connect_delete_event(|_, _| { gtk::main_quit(); Inhibit(false) });

+ self.window.show_all();

+ }

+

+ // pub fn update_from(&self, state: &State) {

+ // if let Some(ref err) = state.error {

+ // self.error_label.set_text(

+ // &format!("The dice expression entered is not valid:\n{}", err)

+ // );

+ // self.popover.show_all();

+ // } else {

+ // // The popover will hide itself anyway when the user clicks

+ // // outside of it, but we shouldn't leave an error indicator in it.

+ // self.error_label.set_text("");

+ // }

+

+ // self.result.set_text(&format!("{}", state.value));

+ // }

+

+ pub fn window(&self) -> &ApplicationWindow {

+ &self.window

+ }

+

+ pub fn url_bar(&self) -> &Entry {

+ &self.url_bar

+ }

+

+ pub fn content_view(&self) -> &TextView {

+ &self.content_view

+ }

+

+ pub fn back_button(&self) -> &Button {

+ &self.back_button

+ }

+}

diff --git a/src/main.rs b/src/main.rs

index 27ffa46..c214307 100644

--- a/src/main.rs

+++ b/src/main.rs

@@ -6,22 +6,22 @@ extern crate gtk;

extern crate lazy_static;


-use gio::prelude::*;

+use std::sync::Arc;

+

use glib::clone;

use gtk::prelude::*;

-use gtk::{ApplicationWindow, Builder, Button, Entry, TextBuffer, TextBufferExt, TextView};

-

-use std::env::args;

+use gtk::{TextBuffer, TextBufferExt};


extern crate regex;

use regex::Regex;


-mod content;

+mod gui;

+use gui::Gui;

mod absolute;

+mod content;

mod history;

-mod tags;

mod link;

-use link::Link;

+mod tags;


const LINK_REGEX: &str = r"^=>\s*(\S*)\s*(.*)?$";

const H1_REGEX: &str = r"^#\s+(.*)$";

@@ -29,79 +29,87 @@ const H2_REGEX: &str = r"^##\s+(.*)$";

const H3_REGEX: &str = r"^###\s+(.*)$";

const UL_REGEX: &str = r"^\s*\*\s+(.*)$";


-fn build_ui(application: &gtk::Application) {

- let glade_src = include_str!("castor.glade");

- let builder = Builder::new_from_string(glade_src);

-

- let window: ApplicationWindow = builder.get_object("window").expect("Couldn't get window");

- window.set_application(Some(application));

- let url_bar: Entry = builder.get_object("url_bar").expect("Couldn't get url_bar");

- let content_view: TextView = builder.get_object("content_view").expect("Couldn't get content_view");

- let back_button: Button = builder.get_object("back_button").expect("Couldn't get back_button");


- tags::apply_tags(&content_view.get_buffer().unwrap());

-

- url_bar.connect_activate(clone!(@weak content_view => move |bar| {

- let url = bar.get_text().expect("get_text failed").to_string();

- let full_url = if url.starts_with("gemini://") {

- url

- } else {

- format!("gemini://{}", url)

- };

+fn main() {

+ // Start up the GTK3 subsystem.

+ gtk::init().expect("Unable to start GTK3. Error");


- let new_content = visit_url(full_url, &content_view);

- }));

+ // Create the main window.

+ let gui = Arc::new(Gui::new());

+ let content_view = gui.content_view();


- back_button.connect_clicked(clone!(@weak content_view => move |_| {

- go_back(&content_view);

- }));

+ // Bind back button

+ {

+ let button = gui.back_button();

+ let gui = gui.clone();

+ button.connect_clicked(clone!(@weak content_view => move |_| {

+ go_back(&gui);

+ }));

+ }


- window.show_all();

-}

+ // Bind URL bar

+ {

+ let gui2 = gui.clone();

+ let url_bar = gui.url_bar();

+ url_bar.connect_activate(clone!(@weak content_view => move |bar| {

+ let url = bar.get_text().expect("get_text failed").to_string();

+ let full_url = if url.starts_with("gemini://") {

+ url

+ } else {

+ format!("gemini://{}", url)

+ };


-fn main() {

- let application =

- gtk::Application::new(Some("org.typed-hole.castor"), Default::default())

- .expect("Initialization failed...");

+ let new_content = visit_url(full_url, &gui2);

+ }));

+ }


- application.connect_activate(|app| {

- build_ui(app);

- });

+ // Create Pango tags

+ tags::apply_tags(&content_view.get_buffer().unwrap());


- application.run(&args().collect::<Vec<_>>());

+ gui.start();

+ gtk::main();

}


-fn go_back(view: &TextView) {

+fn go_back(gui: &Arc<Gui>) {

let previous = history::get_previous_url();

if let Some(url) = previous {

- visit_url(url.to_string(), view)

+ visit_url(url.to_string(), gui)

}

}


-fn visit_url(url: String, view: &TextView) {

+fn update_url_field(url: &str, gui: &Arc<Gui>) -> () {

+ let url_bar = gui.url_bar();

+ url_bar.get_buffer().set_text(url);

+}

+

+fn visit_url(url: String, gui: &Arc<Gui>) {

{

- println!("{:?}", url);

+ let content_view = gui.content_view();

+

match absolute::make(url.as_str()) {

Ok(url) => match content::get_data(&url) {

Ok((_meta, new_content)) => {

history::append(url.as_str());

+ update_url_field(url.as_str(), &gui);

let content_str = String::from_utf8_lossy(&new_content).to_string();

- clear_buffer(&view);

- parse_gemini(content_str, &view);

- view.show_all();

+

+ clear_buffer(&content_view);

+

+ parse_gemini(content_str, &gui);

+ content_view.show_all();

}

Err(_) => {

- let buffer = view.get_buffer().unwrap();

+ let buffer = content_view.get_buffer().unwrap();

let mut end_iter = buffer.get_end_iter();


- clear_buffer(&view);

+ clear_buffer(&content_view);


buffer.insert_markup(

&mut end_iter,

"<span foreground=\"red\" size=\"x-large\">ERROR</span>\n",

);

}

- }

+ },

Err(_) => {

println!("Could not parse {}", url.as_str());

}

@@ -109,13 +117,14 @@ fn visit_url(url: String, view: &TextView) {

}

}


-fn parse_gemini(content: String, view: &TextView) -> TextBuffer {

+fn parse_gemini(content: String, gui: &Arc<Gui>) -> TextBuffer {

let link_regexp = Regex::new(LINK_REGEX).unwrap();

let h1_regexp = Regex::new(H1_REGEX).unwrap();

let h2_regexp = Regex::new(H2_REGEX).unwrap();

let h3_regexp = Regex::new(H3_REGEX).unwrap();

let ul_regexp = Regex::new(UL_REGEX).unwrap();

- let buffer = view.get_buffer().unwrap();

+ let content_view = gui.content_view();

+ let buffer = content_view.get_buffer().unwrap();

let mut i = 0;


for line in content.lines() {

@@ -132,14 +141,14 @@ fn parse_gemini(content: String, view: &TextView) -> TextBuffer {


let button = gtk::Button::new_with_label(&button_label);


- button.connect_clicked(clone!(@weak view => move |button| {

+ button.connect_clicked(clone!(@weak gui => move |button| {

let new_url = absolute::make(&dest.clone()).unwrap().to_string();

- visit_url(new_url, &view);

+ visit_url(new_url, &gui);

}));


let mut start_iter = buffer.get_iter_at_line(i);

let anchor = buffer.create_child_anchor(&mut start_iter).unwrap();

- view.add_child_at_anchor(&button, &anchor);

+ content_view.add_child_at_anchor(&button, &anchor);

let mut end_iter = buffer.get_end_iter();

buffer.insert(&mut end_iter, "\n");

} else if h1_regexp.is_match(line) {



---

Served by Pollux Gemini Server.

-- Response ended

-- Page fetched on Sun May 19 07:57:27 2024