~julienxx/asuka

1c6d9adcf392be574903ba32cd5f5227792989ea — Arav K a month ago 26daa0e master
Create a `History` structure

The goal is to move the history data out of global state and into the
user-data area provided by `cursive`.  This begins that process by
creating a self-contained structure for manipulating history.  For now,
the original module functions are provided.  Once the history structure
is embedded as user data, they will no longer be necessary.

This also changes behaviour slightly, by allowing all URLs in the
history stack to be popped off, thereby returning to the start page.
However, the content loading and drawing functions don't yet support
this, so nothing changes on the user end.
2 files changed, 52 insertions(+), 19 deletions(-)

M src/history.rs
M src/main.rs
M src/history.rs => src/history.rs +51 -18
@@ 1,32 1,65 @@
use std::sync::Mutex;
use url::Url;

/// History.
/// 
/// This structure manages all aspects of browser history.
/// 
/// Internally, URLs are stored in a first-in-last-out (FILO) stack.
/// When a URL is visited, it gets pushed on top of the stack.  To go
/// back, the topmost URL (i.e. the current one) is popped off, and
/// the previous URL becomes the current URL.  Initially, the stack is
/// empty, signifying that the current page is the startup page.
pub struct History {
    /// The URL stack.
    urls: Vec<Url>,
}

impl History {
    /// Creates a new, empty [`History`].
    pub fn new() -> History {
        History { urls: Vec::new() }
    }

    /// Retrieves the current URL, if any.
    pub fn cur(&self) -> Option<&Url> {
        self.urls.last()
    }

    /// Pushes a new URL onto the stack.
    /// 
    /// This indicates that this new URL is being visited.
    pub fn push(&mut self, url: Url) {
        self.urls.push(url)
    }

    /// Pops off the current URL, if any.
    /// 
    /// This indicates that the previous URL is being visited.
    /// 
    /// The current URL (if any) is lost.
    /// 
    /// If there is only one URL on the stack, it gets removed.  If
    /// the stack is already empty, no action occurs.
    pub fn pop(&mut self) {
        self.urls.pop();
    }
}

lazy_static! {
    static ref HISTORY: Mutex<Vec<Url>> = Mutex::new(vec![]);
    static ref HISTORY: Mutex<History> = Mutex::new(History::new());
}

pub fn append(url: &str) {
    let url = Url::parse(url).unwrap();
    HISTORY.lock().unwrap().push(url)
pub fn append(url: Url) {
    HISTORY.lock().unwrap().push(url);
}

pub fn get_current_url() -> Option<Url> {
    let history = HISTORY.lock().unwrap();
    history.last().cloned()
    HISTORY.lock().unwrap().cur().cloned()
}

pub fn get_previous_url() -> Option<Url> {
    let mut history = HISTORY.lock().unwrap();

    if history.len() > 1 {
        history.pop(); // remove current

        if history.len() > 1 {
            history.pop() // return previous
        } else {
            history.iter().cloned().last()
        }
    } else {
        None
    }
    history.pop();
    history.cur().cloned()
}

M src/main.rs => src/main.rs +1 -1
@@ 192,7 192,7 @@ fn visit_url(s: &mut Cursive, url: &Url) {

    match content::get_data(&url) {
        Ok((meta, new_content)) => {
            history::append(url.as_str());
            history::append(url.clone());
            // handle meta header
            let response = handle_response_status(s, &url, meta, new_content);
            draw_content(s, &url, response);