M Cargo.lock => Cargo.lock +2 -1
@@ 112,7 112,7 @@ dependencies = [
[[package]]
name = "castor"
-version = "0.8.8"
+version = "0.8.9"
dependencies = [
"ansi-parser",
"dirs",
@@ 127,6 127,7 @@ dependencies = [
"open",
"openssl",
"pango",
+ "pango-sys",
"percent-encoding",
"regex",
"serde",
M Cargo.toml => Cargo.toml +2 -1
@@ 1,6 1,6 @@
[package]
name = "castor"
-version = "0.8.8"
+version = "0.8.9"
authors = ["Julien Blanchard <julien@typed-hole.org>"]
edition = "2018"
@@ 13,6 13,7 @@ gio = "*"
glib = "*"
glib-sys = "*"
pango = "*"
+pango-sys = "*"
open = "*"
regex = "*"
native-tls = "*"
M README.md => README.md +27 -6
@@ 82,12 82,33 @@ background = "#FFC0CB"
h1 = ">"
h2 = "))"
h3 = "}}}"
-list = "🌼"
-
-[monospace]
-gemini=false
-gopher=true
-finger=true
+list = "🌼 "
+
+[fonts]
+[fonts.finger]
+ family = "monospace"
+ size = 11
+[fonts.gemini]
+ family = "serif"
+ size = 11
+[fonts.gemini.h1]
+ family = "sans"
+ size = 16
+ style = "normal"
+[fonts.gemini.h2]
+ family = "monospace"
+ size = 13
+ style = "italic"
+[fonts.gemini.h3]
+ family = "monospace"
+ size = 12
+[fonts.gemini.list]
+ family = "sans"
+ size = 11
+ style = "oblique"
+[fonts.gopher]
+ family = "monospace"
+ size = 11
```
M data/castor_settings.toml.example => data/castor_settings.toml.example +26 -5
@@ 13,9 13,30 @@ background = "#FFC0CB"
h1 = ">"
h2 = "))"
h3 = "}}}"
-list = "🌼"
+list = "🌼 "
-[monospace]
-gemini=false
-gopher=true
-finger=true
+[fonts]
+[fonts.finger]
+ family = "monospace"
+ size = 11
+[fonts.gemini]
+ family = "serif"
+ size = 11
+[fonts.gemini.h1]
+ family = "sans"
+ size = 16
+ style = "normal"
+[fonts.gemini.h2]
+ family = "monospace"
+ size = 13
+ style = "italic"
+[fonts.gemini.h3]
+ family = "monospace"
+ size = 12
+[fonts.gemini.list]
+ family = "sans"
+ size = 11
+ style = "oblique"
+[fonts.gopher]
+ family = "monospace"
+ size = 11
M src/draw.rs => src/draw.rs +40 -42
@@ 19,11 19,7 @@ pub fn gemini_content(
let buffer = content_view.get_buffer().unwrap();
let mut mono_toggle = false;
- let font_family = if crate::settings::gemini_monospace() {
- "monospace"
- } else {
- "sans"
- };
+ let font_family = crate::settings::get_gemini_text_font_family();
for el in content {
match el {
@@ 32,10 28,12 @@ pub fn gemini_content(
buffer.insert_markup(
&mut end_iter,
&format!(
- "<span foreground=\"{}\" size=\"x-large\" font_family=\"{}\">{}{}</span>\n",
- crate::settings::h1_color(),
- font_family,
- crate::settings::h1_character(),
+ "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
+ crate::settings::get_h1_color(),
+ crate::settings::get_gemini_h1_font_size(),
+ crate::settings::get_gemini_h1_font_family(),
+ crate::settings::get_gemini_h1_font_style(),
+ crate::settings::get_h1_character(),
escape_text(&header)
),
);
@@ 45,10 43,12 @@ pub fn gemini_content(
buffer.insert_markup(
&mut end_iter,
&format!(
- "<span foreground=\"{}\" size=\"large\" font_family=\"{}\">{}{}</span>\n",
- crate::settings::h2_color(),
- font_family,
- crate::settings::h2_character(),
+ "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
+ crate::settings::get_h2_color(),
+ crate::settings::get_gemini_h2_font_size(),
+ crate::settings::get_gemini_h2_font_family(),
+ crate::settings::get_gemini_h2_font_style(),
+ crate::settings::get_h2_character(),
escape_text(&header)
),
);
@@ 58,10 58,12 @@ pub fn gemini_content(
buffer.insert_markup(
&mut end_iter,
&format!(
- "<span foreground=\"{}\" size=\"medium\" font_family=\"{}\">{}{}</span>\n",
- crate::settings::h3_color(),
- font_family,
- crate::settings::h3_character(),
+ "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
+ crate::settings::get_h3_color(),
+ crate::settings::get_gemini_h3_font_size(),
+ crate::settings::get_gemini_h3_font_family(),
+ crate::settings::get_gemini_h3_font_style(),
+ crate::settings::get_h3_character(),
escape_text(&header)
),
);
@@ 71,10 73,12 @@ pub fn gemini_content(
buffer.insert_markup(
&mut end_iter,
&format!(
- "<span foreground=\"{}\" font_family=\"{}\">{} {}</span>\n",
- crate::settings::list_color(),
- font_family,
- crate::settings::list_character(),
+ "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
+ crate::settings::get_list_color(),
+ crate::settings::get_gemini_list_font_size(),
+ crate::settings::get_gemini_list_font_family(),
+ crate::settings::get_gemini_list_font_style(),
+ crate::settings::get_list_character(),
escape_text(&item)
),
);
@@ 94,8 98,9 @@ pub fn gemini_content(
buffer.insert_markup(
&mut end_iter,
&format!(
- "<span foreground=\"{}\" font_family=\"monospace\">{}</span>\n",
- crate::settings::text_color(),
+ "<span foreground=\"{}\" font_family=\"monospace\" size=\"{}\">{}</span>\n",
+ crate::settings::get_text_color(),
+ crate::settings::get_gemini_text_font_size(),
text
),
);
@@ 103,9 108,10 @@ pub fn gemini_content(
buffer.insert_markup(
&mut end_iter,
&format!(
- "<span foreground=\"{}\" font_family=\"{}\">{}</span>\n",
- crate::settings::text_color(),
+ "<span foreground=\"{}\" font_family=\"{}\" size=\"{}\">{}</span>\n",
+ crate::settings::get_text_color(),
font_family,
+ crate::settings::get_gemini_text_font_size(),
text
),
);
@@ 130,7 136,7 @@ pub fn gemini_text_content(gui: &Arc<Gui>, content: std::str::Lines) -> TextBuff
&mut end_iter,
&format!(
"<span foreground=\"{}\" font_family=\"monospace\">{}</span>\n",
- crate::settings::text_color(),
+ crate::settings::get_text_color(),
escape_text(&line)
),
);
@@ 149,11 155,6 @@ pub fn gopher_content(
match el {
Ok(crate::gopher::parser::TextElement::Text(text)) => {
let mut end_iter = buffer.get_end_iter();
- let font_family = if crate::settings::gopher_monospace() {
- "font_family=\"monospace\""
- } else {
- "font_family=\"serif\""
- };
let text = if text.contains("<span") {
text
@@ 164,9 165,10 @@ pub fn gopher_content(
buffer.insert_markup(
&mut end_iter,
&format!(
- "<span foreground=\"{}\" {}>{}</span>\n",
- crate::settings::text_color(),
- font_family,
+ "<span foreground=\"{}\" font_family=\"{}\" size=\"{}\">{}</span>\n",
+ crate::settings::get_text_color(),
+ crate::settings::get_gopher_font_family(),
+ crate::settings::get_gopher_font_size(),
text
),
);
@@ 200,18 202,14 @@ pub fn finger_content(
match el {
Ok(crate::finger::parser::TextElement::Text(text)) => {
let mut end_iter = buffer.get_end_iter();
- let font_family = if crate::settings::finger_monospace() {
- "font_family=\"monospace\""
- } else {
- "font_family=\"serif\""
- };
buffer.insert_markup(
&mut end_iter,
&format!(
- "<span foreground=\"{}\" {}>{}</span>\n",
- crate::settings::text_color(),
- font_family,
+ "<span foreground=\"{}\" font_family=\"{}\" size=\"{}\">{}</span>\n",
+ crate::settings::get_text_color(),
+ crate::settings::get_finger_font_family(),
+ crate::settings::get_finger_font_size(),
escape_text(&text)
),
);
M src/finger/client.rs => src/finger/client.rs +3 -3
@@ 37,13 37,13 @@ pub fn get_data<T: Protocol>(url: T) -> Result<(Option<Vec<u8>>, Vec<u8>), Strin
Ok((None, res))
})
- .join()
- .unwrap(),
+ .join()
+ .unwrap(),
Err(e) => Err(format!("Could not connect to {}\n{}", urlf, e)),
}
}
None => Err(format!("Could not connect to {}\n", urlf)),
- }
+ },
Err(e) => Err(format!("Could not connect to {}\n{}", urlf, e)),
}
}
M src/gemini/client.rs => src/gemini/client.rs +2 -2
@@ 31,8 31,8 @@ pub fn get_data<T: Protocol>(url: T) -> Result<(Option<Vec<u8>>, Vec<u8>), Strin
V4(ip) => V4(ip),
V6(ip) => match addrs_iter.next() {
Some(addr) => addr,
- None => V6(ip)
- }
+ None => V6(ip),
+ },
};
let stream = TcpStream::connect_timeout(&socket_addr, Duration::new(5, 0));
M src/gopher/link.rs => src/gopher/link.rs +8 -0
@@ 170,6 170,14 @@ impl FromStr for Link {
} else {
Err(ParseError)
}
+ // } else if line.contains("://") {
+ // let url = extract_url(line);
+ // let label = String::from(line);
+
+ // match make_link(String::from(url), label) {
+ // Some(link) => Ok(link),
+ // None => Err(ParseError),
+ // }
} else {
Err(ParseError)
}
M src/gopher/parser.rs => src/gopher/parser.rs +6 -1
@@ 42,7 42,12 @@ impl FromStr for TextElement {
// Text line
if line.contains("gopher://") {
Ok(TextElement::LinkItem(String::from(line)))
- } else if line.contains("http://") || line.contains("https://") || line.contains("gemini://") || line.contains("finger://") || line.contains("ftp://") {
+ } else if line.contains("http://")
+ || line.contains("https://")
+ || line.contains("gemini://")
+ || line.contains("finger://")
+ || line.contains("ftp://")
+ {
Ok(TextElement::ExternalLinkItem(String::from(line)))
} else {
Ok(TextElement::Text(colors::colorize(line)))
M src/main.rs => src/main.rs +3 -1
@@ 190,7 190,9 @@ pub fn visit_url<T: AbsoluteUrl + Protocol>(gui: &Arc<Gui>, url: T) {
let absolute_url = url.to_absolute_url();
match absolute_url {
- Ok(absolute_url) => match gemini::client::get_data(Gemini { source: absolute_url.to_string() }) {
+ Ok(absolute_url) => match gemini::client::get_data(Gemini {
+ source: absolute_url.to_string(),
+ }) {
Ok((meta, new_content)) => {
let meta_str = String::from_utf8_lossy(&meta.unwrap()).to_string();
M src/settings.rs => src/settings.rs +287 -90
@@ 12,7 12,7 @@ struct Settings {
general: Option<General>,
colors: Option<Color>,
characters: Option<Character>,
- monospace: Option<Monospace>,
+ fonts: Option<Font>,
}
#[derive(Deserialize)]
@@ 38,11 38,27 @@ struct Character {
list: Option<String>,
}
-#[derive(Deserialize)]
-struct Monospace {
- finger: Option<bool>,
- gemini: Option<bool>,
- gopher: Option<bool>,
+#[derive(Debug, Deserialize)]
+struct Font {
+ finger: Option<FontAttr>,
+ gemini: Option<GeminiFontAttr>,
+ gopher: Option<FontAttr>,
+}
+
+#[derive(Debug, Deserialize)]
+struct FontAttr {
+ family: Option<String>,
+ style: Option<String>,
+ size: Option<i32>,
+}
+
+#[derive(Debug, Deserialize)]
+struct GeminiFontAttr {
+ text: Option<FontAttr>,
+ h1: Option<FontAttr>,
+ h2: Option<FontAttr>,
+ h3: Option<FontAttr>,
+ list: Option<FontAttr>,
}
pub fn start_url() -> Option<String> {
@@ 52,130 68,311 @@ pub fn start_url() -> Option<String> {
}
}
-pub fn h1_color() -> String {
- match read().colors {
- Some(colors) => match colors.h1 {
- Some(color) => color,
- None => String::from("#9932CC"),
- },
+const DEFAULT_FONT: &str = "serif";
+const DEFAULT_FONT_STYLE: &str = "normal";
+const DEFAULT_FONT_SIZE: i32 = 11 * pango_sys::PANGO_SCALE;
+const DEFAULT_H1_FONT_SIZE: i32 = 16 * pango_sys::PANGO_SCALE;
+const DEFAULT_H2_FONT_SIZE: i32 = 13 * pango_sys::PANGO_SCALE;
+const DEFAULT_H3_FONT_SIZE: i32 = 12 * pango_sys::PANGO_SCALE;
+
+fn finger_font_family() -> Option<String> {
+ read().fonts?.finger?.family
+}
+
+fn finger_font_size() -> Option<i32> {
+ read().fonts?.finger?.size.or(Some(DEFAULT_FONT_SIZE))
+}
+
+pub fn get_finger_font_family() -> String {
+ match finger_font_family() {
+ Some(family) => family,
+ None => String::from(DEFAULT_FONT),
+ }
+}
+
+pub fn get_finger_font_size() -> i32 {
+ match finger_font_size() {
+ Some(size) => size * pango_sys::PANGO_SCALE,
+ None => DEFAULT_FONT_SIZE,
+ }
+}
+
+fn gemini_text_font_family() -> Option<String> {
+ read().fonts?.gemini?.text?.family
+}
+
+pub fn get_gemini_text_font_family() -> String {
+ match gemini_text_font_family() {
+ Some(family) => family,
+ None => String::from(DEFAULT_FONT),
+ }
+}
+
+fn gemini_text_font_size() -> Option<i32> {
+ read().fonts?.gemini?.text?.size
+}
+
+pub fn get_gemini_text_font_size() -> i32 {
+ match gemini_text_font_size() {
+ Some(size) => size * pango_sys::PANGO_SCALE,
+ None => DEFAULT_FONT_SIZE,
+ }
+}
+
+fn gemini_h1_font_family() -> Option<String> {
+ read().fonts?.gemini?.h1?.family
+}
+
+fn gemini_h1_font_size() -> Option<i32> {
+ read().fonts?.gemini?.h1?.size
+}
+
+fn gemini_h1_font_style() -> Option<String> {
+ read().fonts?.gemini?.h1?.style
+}
+
+pub fn get_gemini_h1_font_size() -> i32 {
+ match gemini_h1_font_size() {
+ Some(size) => size * pango_sys::PANGO_SCALE,
+ None => DEFAULT_H1_FONT_SIZE,
+ }
+}
+
+pub fn get_gemini_h1_font_family() -> String {
+ match gemini_h1_font_family() {
+ Some(family) => family,
+ None => String::from(DEFAULT_FONT),
+ }
+}
+
+pub fn get_gemini_h1_font_style() -> String {
+ match gemini_h1_font_style() {
+ Some(style) => style,
+ None => String::from(DEFAULT_FONT_STYLE),
+ }
+}
+
+fn gemini_h2_font_family() -> Option<String> {
+ read().fonts?.gemini?.h2?.family
+}
+
+fn gemini_h2_font_size() -> Option<i32> {
+ read().fonts?.gemini?.h2?.size
+}
+
+fn gemini_h2_font_style() -> Option<String> {
+ read().fonts?.gemini?.h2?.style
+}
+
+pub fn get_gemini_h2_font_size() -> i32 {
+ match gemini_h2_font_size() {
+ Some(size) => size * pango_sys::PANGO_SCALE,
+ None => DEFAULT_H2_FONT_SIZE,
+ }
+}
+
+pub fn get_gemini_h2_font_family() -> String {
+ match gemini_h2_font_family() {
+ Some(family) => family,
+ None => String::from(DEFAULT_FONT),
+ }
+}
+
+pub fn get_gemini_h2_font_style() -> String {
+ match gemini_h2_font_style() {
+ Some(style) => style,
+ None => String::from(DEFAULT_FONT_STYLE),
+ }
+}
+
+fn gemini_h3_font_family() -> Option<String> {
+ read().fonts?.gemini?.h3?.family
+}
+
+fn gemini_h3_font_size() -> Option<i32> {
+ read().fonts?.gemini?.h3?.size
+}
+
+fn gemini_h3_font_style() -> Option<String> {
+ read().fonts?.gemini?.h3?.style
+}
+
+pub fn get_gemini_h3_font_size() -> i32 {
+ match gemini_h3_font_size() {
+ Some(size) => size * pango_sys::PANGO_SCALE,
+ None => DEFAULT_H3_FONT_SIZE,
+ }
+}
+
+pub fn get_gemini_h3_font_family() -> String {
+ match gemini_h3_font_family() {
+ Some(family) => family,
+ None => String::from(DEFAULT_FONT),
+ }
+}
+
+pub fn get_gemini_h3_font_style() -> String {
+ match gemini_h3_font_style() {
+ Some(style) => style,
+ None => String::from(DEFAULT_FONT_STYLE),
+ }
+}
+
+fn gemini_list_font_family() -> Option<String> {
+ read().fonts?.gemini?.list?.family
+}
+
+fn gemini_list_font_size() -> Option<i32> {
+ read().fonts?.gemini?.list?.size
+}
+
+fn gemini_list_font_style() -> Option<String> {
+ read().fonts?.gemini?.list?.style
+}
+
+pub fn get_gemini_list_font_size() -> i32 {
+ match gemini_list_font_size() {
+ Some(size) => size * pango_sys::PANGO_SCALE,
+ None => DEFAULT_FONT_SIZE,
+ }
+}
+
+pub fn get_gemini_list_font_family() -> String {
+ match gemini_list_font_family() {
+ Some(family) => family,
+ None => String::from(DEFAULT_FONT),
+ }
+}
+
+pub fn get_gemini_list_font_style() -> String {
+ match gemini_list_font_style() {
+ Some(style) => style,
+ None => String::from(DEFAULT_FONT_STYLE),
+ }
+}
+
+fn gopher_font_family() -> Option<String> {
+ read().fonts?.gopher?.family
+}
+
+fn gopher_font_size() -> Option<i32> {
+ read().fonts?.gopher?.size
+}
+
+pub fn get_gopher_font_family() -> String {
+ match gopher_font_family() {
+ Some(family) => family,
+ None => String::from(DEFAULT_FONT),
+ }
+}
+
+pub fn get_gopher_font_size() -> i32 {
+ match gopher_font_size() {
+ Some(size) => size * pango_sys::PANGO_SCALE,
+ None => DEFAULT_FONT_SIZE,
+ }
+}
+
+fn h1_color() -> Option<String> {
+ read().colors?.h1
+}
+
+pub fn get_h1_color() -> String {
+ match h1_color() {
+ Some(color) => color,
None => String::from("#9932CC"),
}
}
-pub fn h2_color() -> String {
- match read().colors {
- Some(colors) => match colors.h2 {
- Some(color) => color,
- None => String::from("#FF1493"),
- },
+fn h2_color() -> Option<String> {
+ read().colors?.h2
+}
+
+pub fn get_h2_color() -> String {
+ match h2_color() {
+ Some(color) => color,
None => String::from("#FF1493"),
}
}
-pub fn h3_color() -> String {
- match read().colors {
- Some(colors) => match colors.h3 {
- Some(color) => color,
- None => String::from("#87CEFA"),
- },
+fn h3_color() -> Option<String> {
+ read().colors?.h3
+}
+
+pub fn get_h3_color() -> String {
+ match h3_color() {
+ Some(color) => color,
None => String::from("#87CEFA"),
}
}
-pub fn list_color() -> String {
- match read().colors {
- Some(colors) => match colors.list {
- Some(color) => color,
- None => String::from("green"),
- },
+fn list_color() -> Option<String> {
+ read().colors?.list
+}
+
+pub fn get_list_color() -> String {
+ match list_color() {
+ Some(color) => color,
None => String::from("green"),
}
}
-pub fn text_color() -> String {
- match read().colors {
- Some(colors) => match colors.text {
- Some(color) => color,
- None => String::from("black"),
- },
+fn text_color() -> Option<String> {
+ read().colors?.text
+}
+
+pub fn get_text_color() -> String {
+ match text_color() {
+ Some(color) => color,
None => String::from("black"),
}
}
pub fn background_color() -> Option<String> {
- match read().colors {
- Some(colors) => colors.background,
- None => None,
- }
+ read().colors?.background
}
-pub fn h1_character() -> String {
- match read().characters {
- Some(characters) => match characters.h1 {
- Some(character) => character,
- None => String::new(),
- },
- None => String::new(),
- }
+fn h1_character() -> Option<String> {
+ read().characters?.h1
}
-pub fn h2_character() -> String {
- match read().characters {
- Some(characters) => match characters.h2 {
- Some(character) => character,
- None => String::new(),
- },
+pub fn get_h1_character() -> String {
+ match h1_character() {
+ Some(char) => char,
None => String::new(),
}
}
-pub fn h3_character() -> String {
- match read().characters {
- Some(characters) => match characters.h3 {
- Some(character) => character,
- None => String::new(),
- },
+fn h2_character() -> Option<String> {
+ read().characters?.h2
+}
+
+pub fn get_h2_character() -> String {
+ match h2_character() {
+ Some(char) => char,
None => String::new(),
}
}
-pub fn list_character() -> String {
- match read().characters {
- Some(characters) => match characters.list {
- Some(character) => character,
- None => String::from("■"),
- },
- None => String::from("■"),
- }
+fn h3_character() -> Option<String> {
+ read().characters?.h3
}
-pub fn finger_monospace() -> bool {
- match read().monospace {
- Some(monospace) => match monospace.finger {
- Some(setting) => setting,
- None => true,
- },
- None => true,
+pub fn get_h3_character() -> String {
+ match h3_character() {
+ Some(char) => char,
+ None => String::new(),
}
}
-pub fn gemini_monospace() -> bool {
- match read().monospace {
- Some(monospace) => match monospace.gemini {
- Some(setting) => setting,
- None => true,
- },
- None => true,
- }
+fn list_character() -> Option<String> {
+ read().characters?.list
}
-pub fn gopher_monospace() -> bool {
- match read().monospace {
- Some(monospace) => match monospace.gopher {
- Some(setting) => setting,
- None => true,
- },
- None => true,
+pub fn get_list_character() -> String {
+ match list_character() {
+ Some(char) => char,
+ None => String::from("■"),
}
}