Browse Source

Refactor history, add going forward

openbsd
Michael Beaumont 9 months ago
parent
commit
5a2cda5887
1 changed files with 181 additions and 33 deletions
  1. 181
    33
      src/history.rs

+ 181
- 33
src/history.rs View File

@@ -2,56 +2,204 @@ use std::sync::Mutex;
2 2
 use url::Url;
3 3
 
4 4
 lazy_static! {
5
-    static ref HISTORY: Mutex<Vec<Url>> = Mutex::new(vec![]);
5
+    static ref HISTORY: Mutex<History> = Mutex::new(History::new());
6
+}
7
+
8
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9
+struct History {
10
+    past: Vec<Url>,
11
+    current: Option<Url>,
12
+    future: Vec<Url>,
13
+}
14
+
15
+impl History {
16
+    fn new() -> Self {
17
+        History {
18
+            past: vec![],
19
+            current: None,
20
+            future: vec![],
21
+        }
22
+    }
23
+
24
+    fn get_previous_url(&mut self) -> Option<Url> {
25
+        let p = self.past.pop();
26
+        if p.is_some() {
27
+            if let Some(c) = self.current.take() {
28
+                self.future.push(c);
29
+            }
30
+            self.current = None;
31
+        };
32
+        p
33
+    }
34
+
35
+    fn get_next_url(&mut self) -> Option<Url> {
36
+        let f = self.future.pop();
37
+        if f.is_some() {
38
+            if let Some(c) = self.current.take() {
39
+                self.past.push(c);
40
+            }
41
+            self.current = None;
42
+        };
43
+        f
44
+    }
45
+
46
+    fn append(&mut self, url: &str) {
47
+        let url = Url::parse(url).unwrap();
48
+        if let Some(c) = self.current.replace(url) {
49
+            self.past.push(c);
50
+            self.future = vec![]
51
+        };
52
+    }
53
+
54
+    fn current(&self) -> Option<&Url> {
55
+        self.current.as_ref()
56
+    }
6 57
 }
7 58
 
8 59
 pub fn append(url: &str) {
9
-    let url = Url::parse(url).unwrap();
10
-    HISTORY.lock().unwrap().push(url)
60
+    HISTORY.lock().unwrap().append(url)
11 61
 }
12 62
 
13 63
 pub fn get_current_host() -> Option<String> {
14
-    let history = HISTORY.lock().unwrap();
15
-    match history.last() {
16
-        Some(current_url) => match current_url.host_str() {
17
-            Some(host) => Some(String::from(host)),
18
-            None => None,
19
-        },
20
-        None => None,
21
-    }
64
+    HISTORY
65
+        .lock()
66
+        .unwrap()
67
+        .current()
68
+        .and_then(|u| u.host_str())
69
+        .map(String::from)
22 70
 }
23 71
 
24 72
 pub fn get_current_url() -> Option<String> {
25
-    let history = HISTORY.lock().unwrap();
26
-    match history.last() {
27
-        Some(current_url) => {
28
-            let current_path = current_url.join("./");
29
-            match current_path {
30
-                Ok(path) => Some(path.to_string()),
31
-                Err(_) => None,
32
-            }
33
-        }
34
-        None => None,
35
-    }
73
+    HISTORY
74
+        .lock()
75
+        .unwrap()
76
+        .current()
77
+        .and_then(|u| u.join("./").ok())
78
+        .map(|p| p.to_string())
36 79
 }
37 80
 
38 81
 pub fn get_previous_url() -> Option<Url> {
39 82
     let mut history = HISTORY.lock().unwrap();
40 83
 
41
-    if history.len() > 1 {
42
-        history.pop(); // remove current
84
+    history.get_previous_url()
85
+}
43 86
 
44
-        if history.len() > 1 {
45
-            history.pop() // return previous
46
-        } else {
47
-            history.iter().cloned().last()
48
-        }
49
-    } else {
50
-        None
51
-    }
87
+pub fn get_next_url() -> Option<Url> {
88
+    let mut history = HISTORY.lock().unwrap();
89
+
90
+    history.get_next_url()
52 91
 }
53 92
 
54 93
 #[cfg(test)]
55 94
 pub(crate) fn clear() -> () {
56
-    HISTORY.lock().unwrap().clear();
95
+    *HISTORY.lock().unwrap() = History::new();
96
+}
97
+
98
+#[test]
99
+fn test_append_simple() {
100
+    crate::history::clear();
101
+
102
+    *HISTORY.lock().unwrap() = History {
103
+        past: vec![],
104
+        current: Some(Url::parse("gemini://typed-hole.org/foo").unwrap()),
105
+        future: vec![],
106
+    };
107
+
108
+    append("gemini://typed-hole.org");
109
+
110
+    assert_eq!(
111
+        *HISTORY.lock().unwrap(),
112
+        History {
113
+            past: vec![Url::parse("gemini://typed-hole.org/foo").unwrap()],
114
+            current: Some(Url::parse("gemini://typed-hole.org").unwrap()),
115
+            future: vec![],
116
+        },
117
+    );
118
+}
119
+
120
+#[test]
121
+fn test_append_clear_future() {
122
+    crate::history::clear();
123
+
124
+    *HISTORY.lock().unwrap() = History {
125
+        past: vec![],
126
+        current: Some(Url::parse("gemini://typed-hole.org").unwrap()),
127
+        future: vec![Url::parse("gemini://typed-hole.org/foo").unwrap()],
128
+    };
129
+
130
+    append("gemini://typed-hole.org/bar");
131
+
132
+    assert_eq!(
133
+        *HISTORY.lock().unwrap(),
134
+        History {
135
+            past: vec![Url::parse("gemini://typed-hole.org").unwrap()],
136
+            current: Some(Url::parse("gemini://typed-hole.org/bar").unwrap()),
137
+            future: vec![],
138
+        },
139
+    );
140
+}
141
+
142
+#[test]
143
+fn test_append_no_current() {
144
+    crate::history::clear();
145
+
146
+    *HISTORY.lock().unwrap() = History {
147
+        past: vec![],
148
+        current: None,
149
+        future: vec![Url::parse("gemini://typed-hole.org/foo").unwrap()],
150
+    };
151
+
152
+    append("gemini://typed-hole.org");
153
+
154
+    assert_eq!(
155
+        *HISTORY.lock().unwrap(),
156
+        History {
157
+            past: vec![],
158
+            current: Some(Url::parse("gemini://typed-hole.org").unwrap()),
159
+            future: vec![Url::parse("gemini://typed-hole.org/foo").unwrap()],
160
+        },
161
+    );
162
+}
163
+
164
+#[test]
165
+fn test_get_previous_url_simple() {
166
+    crate::history::clear();
167
+
168
+    *HISTORY.lock().unwrap() = History {
169
+        past: vec![Url::parse("gemini://typed-hole.org").unwrap()],
170
+        current: Some(Url::parse("gemini://typed-hole.org/foo").unwrap()),
171
+        future: vec![],
172
+    };
173
+
174
+    let previous = get_previous_url();
175
+
176
+    assert_eq!(
177
+        previous,
178
+        Some(Url::parse("gemini://typed-hole.org").unwrap())
179
+    );
180
+    assert_eq!(
181
+        *HISTORY.lock().unwrap(),
182
+        History {
183
+            past: vec![],
184
+            current: None,
185
+            future: vec![Url::parse("gemini://typed-hole.org/foo").unwrap()]
186
+        },
187
+    );
188
+}
189
+
190
+#[test]
191
+fn test_get_previous_url_no_past() {
192
+    crate::history::clear();
193
+
194
+    let simple = History {
195
+        past: vec![],
196
+        current: Some(Url::parse("gemini://typed-hole.org/foo").unwrap()),
197
+        future: vec![],
198
+    };
199
+    *HISTORY.lock().unwrap() = simple.clone();
200
+
201
+    let previous = get_previous_url();
202
+
203
+    assert_eq!(previous, None);
204
+    assert_eq!(*HISTORY.lock().unwrap(), simple);
57 205
 }

Loading…
Cancel
Save