Browse Source

Support new Quote syntax, better text wrapping

tags/0.8.14
Julien Blanchard 11 months ago
parent
commit
aa1c169810
4 changed files with 177 additions and 65 deletions
  1. 109
    64
      src/draw.rs
  2. 3
    0
      src/gemini/parser.rs
  3. 0
    1
      src/main.rs
  4. 65
    0
      src/settings.rs

+ 109
- 64
src/draw.rs View File

@@ -4,6 +4,10 @@ use gtk::TextBuffer;
4 4
 use std::str::FromStr;
5 5
 use std::sync::Arc;
6 6
 use url::Url;
7
+use std::convert::TryInto;
8
+
9
+extern crate textwrap;
10
+use textwrap::fill;
7 11
 
8 12
 use crate::absolute_url::AbsoluteUrl;
9 13
 use crate::gemini::link::Link as GeminiLink;
@@ -11,6 +15,7 @@ use crate::gopher::link::Link as GopherLink;
11 15
 use crate::gui::Gui;
12 16
 use crate::protocols::{Finger, Gemini, Gopher};
13 17
 
18
+
14 19
 pub fn gemini_content(
15 20
     gui: &Arc<Gui>,
16 21
     content: Vec<Result<crate::gemini::parser::TextElement, crate::gemini::parser::ParseError>>,
@@ -23,87 +28,108 @@ pub fn gemini_content(
23 28
 
24 29
     for el in content {
25 30
         match el {
31
+            Ok(crate::gemini::parser::TextElement::MonoText(_text)) => {
32
+                mono_toggle = !mono_toggle;
33
+            }
26 34
             Ok(crate::gemini::parser::TextElement::H1(header)) => {
27 35
                 let mut end_iter = buffer.get_end_iter();
28
-                buffer.insert_markup(
29
-                    &mut end_iter,
30
-                    &format!(
31
-                        "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
32
-                        crate::settings::get_h1_color(),
33
-                        crate::settings::get_gemini_h1_font_size(),
34
-                        crate::settings::get_gemini_h1_font_family(),
35
-                        crate::settings::get_gemini_h1_font_style(),
36
-                        crate::settings::get_h1_character(),
37
-                        escape_text(&header)
38
-                    ),
39
-                );
36
+                if mono_toggle {
37
+                    buffer.insert_markup(&mut end_iter, &mono_span(header));
38
+                } else {
39
+                  buffer.insert_markup(
40
+                      &mut end_iter,
41
+                      &format!(
42
+                          "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
43
+                          crate::settings::get_h1_color(),
44
+                          crate::settings::get_gemini_h1_font_size(),
45
+                          crate::settings::get_gemini_h1_font_family(),
46
+                          crate::settings::get_gemini_h1_font_style(),
47
+                          crate::settings::get_h1_character(),
48
+                          header
49
+                      ),
50
+                  );
51
+                }
40 52
             }
41 53
             Ok(crate::gemini::parser::TextElement::H2(header)) => {
42 54
                 let mut end_iter = buffer.get_end_iter();
43
-                buffer.insert_markup(
44
-                    &mut end_iter,
45
-                    &format!(
46
-                        "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
47
-                        crate::settings::get_h2_color(),
48
-                        crate::settings::get_gemini_h2_font_size(),
49
-                        crate::settings::get_gemini_h2_font_family(),
50
-                        crate::settings::get_gemini_h2_font_style(),
51
-                        crate::settings::get_h2_character(),
52
-                        escape_text(&header)
53
-                    ),
54
-                );
55
+                if mono_toggle {
56
+                    buffer.insert_markup(&mut end_iter, &mono_span(header));
57
+               } else {
58
+                  buffer.insert_markup(
59
+                      &mut end_iter,
60
+                      &format!(
61
+                          "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
62
+                          crate::settings::get_h2_color(),
63
+                          crate::settings::get_gemini_h2_font_size(),
64
+                          crate::settings::get_gemini_h2_font_family(),
65
+                          crate::settings::get_gemini_h2_font_style(),
66
+                          crate::settings::get_h2_character(),
67
+                          header
68
+                      ),
69
+                  );
70
+                }
55 71
             }
56 72
             Ok(crate::gemini::parser::TextElement::H3(header)) => {
57 73
                 let mut end_iter = buffer.get_end_iter();
58
-                buffer.insert_markup(
59
-                    &mut end_iter,
60
-                    &format!(
61
-                        "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
62
-                        crate::settings::get_h3_color(),
63
-                        crate::settings::get_gemini_h3_font_size(),
64
-                        crate::settings::get_gemini_h3_font_family(),
65
-                        crate::settings::get_gemini_h3_font_style(),
66
-                        crate::settings::get_h3_character(),
67
-                        escape_text(&header)
68
-                    ),
69
-                );
74
+                if mono_toggle {
75
+                    buffer.insert_markup(&mut end_iter, &mono_span(header));
76
+                } else {
77
+                    buffer.insert_markup(
78
+                        &mut end_iter,
79
+                        &format!(
80
+                            "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
81
+                            crate::settings::get_h3_color(),
82
+                            crate::settings::get_gemini_h3_font_size(),
83
+                            crate::settings::get_gemini_h3_font_family(),
84
+                            crate::settings::get_gemini_h3_font_style(),
85
+                            crate::settings::get_h3_character(),
86
+                            header
87
+                        ),
88
+                    );
89
+                }
70 90
             }
71 91
             Ok(crate::gemini::parser::TextElement::ListItem(item)) => {
72 92
                 let mut end_iter = buffer.get_end_iter();
73
-                buffer.insert_markup(
74
-                    &mut end_iter,
75
-                    &format!(
76
-                        "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
77
-                        crate::settings::get_list_color(),
78
-                        crate::settings::get_gemini_list_font_size(),
79
-                        crate::settings::get_gemini_list_font_family(),
80
-                        crate::settings::get_gemini_list_font_style(),
81
-                        crate::settings::get_list_character(),
82
-                        escape_text(&item)
83
-                    ),
84
-                );
85
-            }
86
-            Ok(crate::gemini::parser::TextElement::MonoText(_text)) => {
87
-                mono_toggle = !mono_toggle;
93
+                if mono_toggle {
94
+                    buffer.insert_markup(&mut end_iter, &mono_span(item));
95
+                } else {
96
+                    buffer.insert_markup(
97
+                      &mut end_iter,
98
+                      &format!(
99
+                          "<span foreground=\"{}\" size=\"{}\" font_family=\"{}\" style=\"{}\">{}{}</span>\n",
100
+                          crate::settings::get_list_color(),
101
+                          crate::settings::get_gemini_list_font_size(),
102
+                          crate::settings::get_gemini_list_font_family(),
103
+                          crate::settings::get_gemini_list_font_style(),
104
+                          crate::settings::get_list_character(),
105
+                          escape_text(&item)
106
+                      ),
107
+                  );
108
+                }
88 109
             }
89
-            Ok(crate::gemini::parser::TextElement::Text(text)) => {
110
+            Ok(crate::gemini::parser::TextElement::Quote(mut text)) => {
90 111
                 let mut end_iter = buffer.get_end_iter();
91
-                let text = if text.contains("<span") {
92
-                    text
93
-                } else {
94
-                    escape_text(&text)
95
-                };
96
-
97 112
                 if mono_toggle {
113
+                    buffer.insert_markup(&mut end_iter, &mono_span(text));
114
+                } else {
98 115
                     buffer.insert_markup(
99 116
                         &mut end_iter,
100 117
                         &format!(
101
-                            "<span foreground=\"{}\" font_family=\"monospace\" size=\"{}\">{}</span>\n",
102
-                            crate::settings::get_text_color(),
103
-                            crate::settings::get_gemini_text_font_size(),
104
-                            text
118
+                            "<span foreground=\"{}\" background=\"{}\" font_family=\"{}\" size=\"{}\" style=\"{}\">{}</span>\n",
119
+                            crate::settings::get_gemini_quote_foreground_color(),
120
+                            crate::settings::get_gemini_quote_background_color(),
121
+                            crate::settings::get_gemini_quote_font_family(),
122
+                            crate::settings::get_gemini_quote_font_size(),
123
+                            crate::settings::get_gemini_quote_font_style(),
124
+                            fill(&text.split_off(2), width(&gui))
105 125
                         ),
106 126
                     );
127
+                }
128
+            }
129
+            Ok(crate::gemini::parser::TextElement::Text(text)) => {
130
+                let mut end_iter = buffer.get_end_iter();
131
+                if mono_toggle {
132
+                    buffer.insert_markup(&mut end_iter, &mono_span(escape_text(&text)));
107 133
                 } else {
108 134
                     buffer.insert_markup(
109 135
                         &mut end_iter,
@@ -112,13 +138,18 @@ pub fn gemini_content(
112 138
                             crate::settings::get_text_color(),
113 139
                             font_family,
114 140
                             crate::settings::get_gemini_text_font_size(),
115
-                            text
141
+                            fill(&escape_text(&text), width(&gui))
116 142
                         ),
117 143
                     );
118 144
                 }
119 145
             }
120 146
             Ok(crate::gemini::parser::TextElement::LinkItem(link_item)) => {
121
-                gemini_link(&gui, link_item);
147
+                if mono_toggle {
148
+                    let mut end_iter = buffer.get_end_iter();
149
+                    buffer.insert_markup(&mut end_iter, &mono_span(escape_text(&link_item)));
150
+                } else {
151
+                    gemini_link(&gui, link_item);
152
+                }
122 153
             }
123 154
             Err(_) => println!("Something failed."),
124 155
         }
@@ -411,3 +442,17 @@ pub fn insert_external_button(gui: &Arc<Gui>, url: Url, label: &str) {
411 442
 fn escape_text(str: &str) -> String {
412 443
     String::from(glib::markup_escape_text(&str).as_str())
413 444
 }
445
+
446
+fn mono_span(text: String) -> String {
447
+    format!(
448
+        "<span foreground=\"{}\" font_family=\"monospace\" size=\"{}\">{}</span>\n",
449
+        crate::settings::get_text_color(),
450
+        crate::settings::get_gemini_text_font_size(),
451
+        text
452
+    )
453
+}
454
+
455
+fn width(gui: &Arc<Gui>) -> usize {
456
+    let (win_width, _) = gtk::ApplicationWindow::get_size(gui.window());
457
+    (win_width / 10).try_into().unwrap()
458
+}

+ 3
- 0
src/gemini/parser.rs View File

@@ -14,6 +14,7 @@ pub enum TextElement {
14 14
     LinkItem(String),
15 15
     Text(String),
16 16
     MonoText(String),
17
+    Quote(String),
17 18
 }
18 19
 
19 20
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -56,6 +57,8 @@ impl FromStr for TextElement {
56 57
             Ok(TextElement::LinkItem(String::from(line)))
57 58
         } else if line.starts_with("```") {
58 59
             Ok(TextElement::MonoText(String::from(line)))
60
+        } else if line.starts_with("> ") {
61
+            Ok(TextElement::Quote(String::from(line)))
59 62
         } else {
60 63
             Ok(TextElement::Text(colors::colorize(line)))
61 64
         }

+ 0
- 1
src/main.rs View File

@@ -107,7 +107,6 @@ fn main() {
107 107
 
108 108
 fn route_url(gui: &Arc<Gui>, url: String) {
109 109
     if url == "" {
110
-        return
111 110
     } else if url.starts_with("gemini://") {
112 111
         visit_url(&gui, Gemini { source: url })
113 112
     } else if url.starts_with("gopher://") {

+ 65
- 0
src/settings.rs View File

@@ -28,6 +28,7 @@ struct Color {
28 28
     list: Option<String>,
29 29
     text: Option<String>,
30 30
     background: Option<String>,
31
+    quote: Option<QuoteColor>,
31 32
 }
32 33
 
33 34
 #[derive(Deserialize)]
@@ -59,6 +60,13 @@ struct GeminiFontAttr {
59 60
     h2: Option<FontAttr>,
60 61
     h3: Option<FontAttr>,
61 62
     list: Option<FontAttr>,
63
+    quote: Option<FontAttr>,
64
+}
65
+
66
+#[derive(Debug, Deserialize)]
67
+struct QuoteColor {
68
+    foreground: Option<String>,
69
+    background: Option<String>,
62 70
 }
63 71
 
64 72
 pub fn start_url() -> Option<String> {
@@ -230,6 +238,18 @@ fn gemini_list_font_style() -> Option<String> {
230 238
     read().fonts?.gemini?.list?.style
231 239
 }
232 240
 
241
+fn gemini_quote_font_family() -> Option<String> {
242
+    read().fonts?.gemini?.quote?.family
243
+}
244
+
245
+fn gemini_quote_font_size() -> Option<i32> {
246
+    read().fonts?.gemini?.quote?.size
247
+}
248
+
249
+fn gemini_quote_font_style() -> Option<String> {
250
+    read().fonts?.gemini?.quote?.style
251
+}
252
+
233 253
 pub fn get_gemini_list_font_size() -> i32 {
234 254
     match gemini_list_font_size() {
235 255
         Some(size) => size * pango_sys::PANGO_SCALE,
@@ -251,6 +271,27 @@ pub fn get_gemini_list_font_style() -> String {
251 271
     }
252 272
 }
253 273
 
274
+pub fn get_gemini_quote_font_size() -> i32 {
275
+    match gemini_quote_font_size() {
276
+        Some(size) => size * pango_sys::PANGO_SCALE,
277
+        None => DEFAULT_FONT_SIZE,
278
+    }
279
+}
280
+
281
+pub fn get_gemini_quote_font_family() -> String {
282
+    match gemini_quote_font_family() {
283
+        Some(family) => family,
284
+        None => String::from(DEFAULT_FONT),
285
+    }
286
+}
287
+
288
+pub fn get_gemini_quote_font_style() -> String {
289
+    match gemini_quote_font_style() {
290
+        Some(style) => style,
291
+        None => String::from("italic"),
292
+    }
293
+}
294
+
254 295
 fn gopher_font_family() -> Option<String> {
255 296
     read().fonts?.gopher?.family
256 297
 }
@@ -317,6 +358,30 @@ pub fn get_list_color() -> String {
317 358
     }
318 359
 }
319 360
 
361
+fn quote_color() -> Option<QuoteColor> {
362
+    read().colors?.quote
363
+}
364
+
365
+pub fn get_gemini_quote_foreground_color() -> String {
366
+    match quote_color() {
367
+        Some(color) => match color.foreground {
368
+            Some(color) => color,
369
+            None => String::from("#e4e4e4"),
370
+        },
371
+        None => String::from("#e4e4e4"),
372
+    }
373
+}
374
+
375
+pub fn get_gemini_quote_background_color() -> String {
376
+    match quote_color() {
377
+        Some(color) => match color.foreground {
378
+            Some(color) => color,
379
+            None => String::from("grey"),
380
+        },
381
+        None => String::from("grey"),
382
+    }
383
+}
384
+
320 385
 fn text_color() -> Option<String> {
321 386
     read().colors?.text
322 387
 }

Loading…
Cancel
Save