<commit_before>use std;
use base::*;
use super::{LoudsTrie, NodeID, LoudsPos, LinkID, INVALID_LINK_ID};

struct History<'a> {
    trie_: &'a LoudsTrie,
    node_id_: NodeID,
    louds_pos_: LoudsPos,
    link_id_: LinkID,
    key_pos_: u32,
    //key_id_: u32,
}

impl<'a> History<'a> {
    fn new(trie: &'a LoudsTrie, node_id: NodeID, louds_pos: LoudsPos,
           link_id: LinkID, key_pos: u32) -> History<'a> {
        History { trie_: trie, node_id_: node_id, louds_pos_: louds_pos,
                  link_id_: link_id, key_pos_: key_pos }
    }
}

struct State<'a> {
    history_: Vec<History<'a> >,
    key_buf_: Vec<u8>,
}

impl<'a> State<'a> {
    fn new() -> State<'a> {
        State { history_: Vec::new(), key_buf_: Vec::new() }
    }

    fn push<'b>(&mut self, key: &'b[u8], trie: &'a LoudsTrie, node_id: NodeID,
                louds_pos: LoudsPos, link_id: LinkID) {
        self.key_buf_.extend(key);
        assert!(self.key_buf_.len() <= std::u32::MAX as usize);
        self.history_.push(History::new(trie, node_id, louds_pos, link_id,
                                        self.key_buf_.len() as u32));
    }

    fn get_key(&self) -> &[u8] {
        &self.key_buf_[..]
    }

    fn pop(&mut self) -> Option<History<'a> > {
        self.history_.pop()
    }

    fn get_node_id(&self) -> NodeID {
        self.history_.last().unwrap().node_id_
    }

    fn get_link_id(&self) -> LinkID {
        self.history_.last().unwrap().link_id_
    }
}

pub struct Nav<'a> {
    state_: State<'a>,
    trie_: &'a LoudsTrie,
}

// For lookups, marisa does caching based on the input character.
// We can't do that here. May want to remove or rethink the cache
// implementation in light of this.

impl<'a> Nav<'a> {
    pub fn new(trie: &'a LoudsTrie) -> Nav<'a> {
        Nav { state_: State::new(), trie_: trie }
    }

    fn push(&mut self, node_id: NodeID, louds_pos: LoudsPos) {
        let mut trie = self.trie_;
        loop {
            if trie.link_flags_.at(node_id.0 as usize) {
                let (node_id, link_id) = trie.get_linked_ids(node_id.0
                                                             as usize);
                // Proceed either to next trie or tail
                match &trie.next_trie_ {
                    &Some(ref next_trie) => {
                        trie = &**next_trie;
                        continue;
                    },
                    &None => {
                        // FIXME: Shouldn't need this temporary vector.
                        //        'restore' should return an iterator, and
                        //        state.push should consume it.
                        let mut v = Vec::new();
                        trie.tail_.restore(node_id.0 as usize, &mut v);

                        // Not sure if these values are correct/useful.
                        // If some stuff is only needed for some nodes...
                        // should reflect that in the types we use
                        self.state_.push(&v, trie, node_id, louds_pos,
                                         link_id);
                    }
                }
            } else {
                let node_char = [ trie.bases_[node_id.0 as usize] ];
                self.state_.push(&node_char, trie, node_id, louds_pos,
                                 INVALID_LINK_ID);
            }
            break;
        }
    }
    pub fn has_child(&self) -> bool {
        self.trie_.has_child(self.state_.get_node_id())
    }
    pub fn go_to_child(&mut self) -> bool {
        let init_node_id = self.state_.get_node_id();
        if let Some((node_id, louds_pos)) = self.trie_.child_pos(init_node_id) {
            self.push(node_id, louds_pos);
            true
        } else {
            false
        }
    }
    pub fn has_prev_sibling(&self) -> bool {
        // FIXME: Is this all...?
        self.state_.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize - 1)
        }).unwrap_or(false)
    }
    pub fn go_to_prev_sibling(&mut self) -> bool {
        // pop history and string
        // decrease louds_pos and node_id by 1 if we have a sibling
        // get string (factor this out?)
        // push new history & string

        panic!("not implemented")
    }
    pub fn has_sibling(&self) -> bool {
        self.state_.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize + 1)
        }).unwrap_or(false)
    }
    pub fn go_to_sibling(&mut self) -> bool {
        if let Some(h) = self.state_.history_.pop() {
            if h.trie_.louds_.at(h.louds_pos_.0 as usize + 1) {
                // FIXME: What about LinkID?
                self.push(NodeID(h.node_id_.0 + 1),
                          LoudsPos(h.louds_pos_.0 + 1));
                true
            } else {
                false
            }
        } else {
            false
        }
    }
    pub fn has_parent(&self) -> bool {
        panic!("not implemented")
    }
    pub fn go_to_parent(&mut self) -> bool {
        // Could use LOUDS-trie select1(rank0(m)) to navigate upward (within a
        // single trie), but it's probably more efficient just to keep a stack
        // and pop to go up
        self.state_.history_.pop().is_some()
    }
    pub fn is_leaf(&self) -> bool {
        panic!("not implemented")
    }
    //pub fn get_string(&self) -> &str {
    //    panic!("not implemented")
    //}
    pub fn get_u8(&self) -> &[u8] {
        &self.state_.key_buf_[..]
    }
    pub fn is_end(&self) -> bool {
        panic!("not implemented")
    }
}

#[derive(Copy, Clone)]
enum DFT {
    ToChild,
    ToSibling,
    ToParentSibling,
    End
}

impl DFT {
    fn new() -> DFT {
        DFT::ToChild
    }
    fn depth_first_traversal_step<'a>(&mut self, nav: &mut Nav<'a>) -> bool {
        match *self {
            DFT::ToChild => {
                if nav.go_to_child() {
                    return true;
                } else {
                    *self = DFT::ToSibling;
                    return false;
                }
            },
            DFT::ToSibling => {
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                } else {
                    *self = DFT::ToParentSibling;
                    return false;
                }
            },
            DFT::ToParentSibling => {
                if !nav.go_to_parent() {
                    *self = DFT::End;
                    return false;
                }
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                }
                return false;
            },
            DFT::End => {
                return false;
            }
        }
    }
    fn next_terminal<'a, 'b>(&mut self, nav: &'b mut Nav<'a>)
      -> Option<&'b[u8]> {
        loop {
            match *self {
                DFT::End => { return None; },
                _ => (),
            }
            if self.depth_first_traversal_step(nav) {
                return Some(nav.get_u8());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use quickcheck as qc;
    use config::NumTries;
    use super::Nav;
    use super::super::LoudsTrie;

    fn restore_with_nav_prop(v: Vec<String>, num_tries: NumTries)
      -> qc::TestResult {
/*
        if v.iter().any(|x| x.is_empty()) {
            return qc::TestResult::discard();
        }
        let mut keys: Vec<Key> = v.iter().map(|s| Key::new(s.as_bytes()))
                                 .collect();
        let config = Config::new().with_num_tries(num_tries);
        let trie = LoudsTrie::build(&mut keys, &config);

        let nav = Nav::new(&trie);

                return qc::TestResult::failed();
*/
        qc::TestResult::passed()
    }

    #[test]
    fn restore_with_nav_qc() {
        panic!()

    }

    #[test]
    fn restore_with_nav_manual() {
        panic!()

    }
}

<commit_msg>initial quickcheck test for nav<commit_after>use std;
use base::*;
use super::{LoudsTrie, NodeID, LoudsPos, LinkID, INVALID_LINK_ID};

struct History<'a> {
    trie_: &'a LoudsTrie,
    node_id_: NodeID,
    louds_pos_: LoudsPos,
    link_id_: LinkID,
    key_pos_: u32,
    //key_id_: u32,
}

impl<'a> History<'a> {
    fn new(trie: &'a LoudsTrie, node_id: NodeID, louds_pos: LoudsPos,
           link_id: LinkID, key_pos: u32) -> History<'a> {
        History { trie_: trie, node_id_: node_id, louds_pos_: louds_pos,
                  link_id_: link_id, key_pos_: key_pos }
    }
}

struct State<'a> {
    history_: Vec<History<'a> >,
    key_buf_: Vec<u8>,
}

impl<'a> State<'a> {
    fn new() -> State<'a> {
        State { history_: Vec::new(), key_buf_: Vec::new() }
    }

    fn push<'b>(&mut self, key: &'b[u8], trie: &'a LoudsTrie, node_id: NodeID,
                louds_pos: LoudsPos, link_id: LinkID) {
        self.key_buf_.extend(key);
        assert!(self.key_buf_.len() <= std::u32::MAX as usize);
        self.history_.push(History::new(trie, node_id, louds_pos, link_id,
                                        self.key_buf_.len() as u32));
    }

    fn get_key(&self) -> &[u8] {
        &self.key_buf_[..]
    }

    fn pop(&mut self) -> Option<History<'a> > {
        self.history_.pop()
    }

    fn get_node_id(&self) -> NodeID {
        self.history_.last().unwrap().node_id_
    }

    fn get_link_id(&self) -> LinkID {
        self.history_.last().unwrap().link_id_
    }
}

pub struct Nav<'a> {
    state_: State<'a>,
    trie_: &'a LoudsTrie,
}

// For lookups, marisa does caching based on the input character.
// We can't do that here. May want to remove or rethink the cache
// implementation in light of this.

impl<'a> Nav<'a> {
    pub fn new(trie: &'a LoudsTrie) -> Nav<'a> {
        Nav { state_: State::new(), trie_: trie }
    }

    fn push(&mut self, node_id: NodeID, louds_pos: LoudsPos) {
        let mut trie = self.trie_;
        loop {
            if trie.link_flags_.at(node_id.0 as usize) {
                let (node_id, link_id) = trie.get_linked_ids(node_id.0
                                                             as usize);
                // Proceed either to next trie or tail
                match &trie.next_trie_ {
                    &Some(ref next_trie) => {
                        trie = &**next_trie;
                        continue;
                    },
                    &None => {
                        // FIXME: Shouldn't need this temporary vector.
                        //        'restore' should return an iterator, and
                        //        state.push should consume it.
                        let mut v = Vec::new();
                        trie.tail_.restore(node_id.0 as usize, &mut v);

                        // Not sure if these values are correct/useful.
                        // If some stuff is only needed for some nodes...
                        // should reflect that in the types we use
                        self.state_.push(&v, trie, node_id, louds_pos,
                                         link_id);
                    }
                }
            } else {
                let node_char = [ trie.bases_[node_id.0 as usize] ];
                self.state_.push(&node_char, trie, node_id, louds_pos,
                                 INVALID_LINK_ID);
            }
            break;
        }
    }
    pub fn has_child(&self) -> bool {
        self.trie_.has_child(self.state_.get_node_id())
    }
    pub fn go_to_child(&mut self) -> bool {
        let init_node_id = self.state_.get_node_id();
        if let Some((node_id, louds_pos)) = self.trie_.child_pos(init_node_id) {
            self.push(node_id, louds_pos);
            true
        } else {
            false
        }
    }
    pub fn has_prev_sibling(&self) -> bool {
        // FIXME: Is this all...?
        self.state_.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize - 1)
        }).unwrap_or(false)
    }
    pub fn go_to_prev_sibling(&mut self) -> bool {
        // pop history and string
        // decrease louds_pos and node_id by 1 if we have a sibling
        // get string (factor this out?)
        // push new history & string

        panic!("not implemented")
    }
    pub fn has_sibling(&self) -> bool {
        self.state_.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize + 1)
        }).unwrap_or(false)
    }
    pub fn go_to_sibling(&mut self) -> bool {
        if let Some(h) = self.state_.history_.pop() {
            if h.trie_.louds_.at(h.louds_pos_.0 as usize + 1) {
                // FIXME: What about LinkID?
                self.push(NodeID(h.node_id_.0 + 1),
                          LoudsPos(h.louds_pos_.0 + 1));
                true
            } else {
                false
            }
        } else {
            false
        }
    }
    pub fn has_parent(&self) -> bool {
        panic!("not implemented")
    }
    pub fn go_to_parent(&mut self) -> bool {
        // Could use LOUDS-trie select1(rank0(m)) to navigate upward (within a
        // single trie), but it's probably more efficient just to keep a stack
        // and pop to go up
        self.state_.history_.pop().is_some()
    }
    pub fn is_leaf(&self) -> bool {
        panic!("not implemented")
    }
    //pub fn get_string(&self) -> &str {
    //    panic!("not implemented")
    //}
    pub fn get_u8(&self) -> &[u8] {
        &self.state_.key_buf_[..]
    }
    pub fn is_end(&self) -> bool {
        panic!("not implemented")
    }
}

#[derive(Copy, Clone)]
enum DFT {
    ToChild,
    ToSibling,
    ToParentSibling,
    End
}

impl DFT {
    fn new() -> DFT {
        DFT::ToChild
    }
    fn depth_first_traversal_step<'a>(&mut self, nav: &mut Nav<'a>) -> bool {
        match *self {
            DFT::ToChild => {
                if nav.go_to_child() {
                    return true;
                } else {
                    *self = DFT::ToSibling;
                    return false;
                }
            },
            DFT::ToSibling => {
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                } else {
                    *self = DFT::ToParentSibling;
                    return false;
                }
            },
            DFT::ToParentSibling => {
                if !nav.go_to_parent() {
                    *self = DFT::End;
                    return false;
                }
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                }
                return false;
            },
            DFT::End => {
                return false;
            }
        }
    }
    fn next_terminal<'a, 'b>(&mut self, nav: &'b mut Nav<'a>)
      -> Option<&'b[u8]> {
        loop {
            match *self {
                DFT::End => { return None; },
                _ => (),
            }
            if self.depth_first_traversal_step(nav) {
                return Some(nav.get_u8());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use env_logger;
    use std::cmp::Ordering;
    use quickcheck as qc;
    use config::{Config, NumTries};
    use key::Key;
    use super::{DFT, Nav};
    use super::super::LoudsTrie;

    fn restore_with_nav_prop(v: Vec<String>, num_tries: NumTries)
      -> qc::TestResult {
        if v.iter().any(|x| x.is_empty()) {
            return qc::TestResult::discard();
        }
        let mut keys: Vec<Key> = v.iter().map(|s| Key::new(s.as_bytes()))
                                 .collect();
        let config = Config::new().with_num_tries(num_tries);
        let trie = LoudsTrie::build(&mut keys, &config);

        let mut nav = Nav::new(&trie);
        let mut dft = DFT::new();

        let mut vv1: Vec<Vec<u8>> = v.iter().map(|s| From::from(s.as_bytes()))
                                    .collect();

        let mut vv2: Vec<Vec<u8>> = Vec::new();
        while let Some(s) = dft.next_terminal(&mut nav) {
            vv2.push(From::from(s));
        }

        vv1.sort();
        vv2.sort();
        qc::TestResult::from_bool(vv1.cmp(&vv2) == Ordering::Equal)
    }

    #[test]
    fn restore_with_nav_qc() {
        let _ = env_logger::init();
        qc::quickcheck(restore_with_nav_prop as fn(Vec<String>, NumTries)
                       -> qc::TestResult);
    }

    #[test]
    fn restore_with_nav_manual() {
        panic!()

    }
}

<|endoftext|>


<commit_before>///
/// Convert a number between two bases.
///
/// A number is any slice of digits.
/// A digit is any unsigned integer (e.g. u8, u16, u32, u64, or usize).
/// Bases are specified as unsigned integers.
///
/// Return an `Err(.)` if the conversion is impossible.
/// The tests do not test for specific values inside the `Err(.)`.
///
///
/// You are allowed to change the function signature as long as all test still pass.
///
///
/// Example:
/// Input
///   number: &[4, 2]
///   from_base: 10
///   to_base: 2
/// Result
///   Ok(vec![1, 0, 1, 0, 1, 0])
///
/// The example corresponds to converting the number 42 from decimal
/// which is equivalent to 101010 in binary.
///
///
/// Notes:
///  * The empty slice ( "[]" ) is equal to the number 0.
///  * Never output leading 0 digits. However, your function must be able to
///     process input with leading 0 digits.
///
#[allow(unused_variables)]
pub fn convert(number: &[u32], from_base: u32, to_base: u32) -> Result<Vec<u32>, ()> {
    if number.into_iter().any(|&x| x >= from_base) {
        return Err(());
    }

    if from_base < 2 || to_base < 2 {
        return Err(());
    }

    let mut r = number.into_iter().fold(0, |acc, &x| acc * from_base + x);

    let mut result = (0..)
        .take_while(move |&x| r >= to_base.pow(x as u32))
        .map(|x| {
            let d = r % to_base;
            r /= to_base;
            d
        })
        .collect::<Vec<_>>();

    result.reverse();

    Ok(result)
}
<commit_msg>Clean up rust code for all-your-base<commit_after>pub fn convert(number: &[u32], from_base: u32, to_base: u32) -> Result<Vec<u32>, ()> {
    if from_base < 2 || to_base < 2 {
        return Err(());
    }

    if number.iter().any(|&x| x >= from_base) {
        return Err(());
    }

    let limit = number.iter().fold(0, |acc, &x| acc * from_base + x);
    let mut r = limit;

    let mut result = (0..)
        .take_while(|&x| limit >= to_base.pow(x as u32))
        .map(|_| {
            let d = r % to_base;
            r /= to_base;
            d
        })
        .collect::<Vec<_>>();

    result.reverse();

    Ok(result)
}
<|endoftext|>


<commit_before>#[cfg(test)]
mod tests {
    // Uncomment this to use items from the containing module.
    // use super::*;
    #[test]
    fn it_works() {
        let result = 2 + 2;
        assert_eq!(result, 4);
    }
}
<commit_msg>fixed issue with formats_source<commit_after>#[cfg(test)]
mod tests {
  // Uncomment this to use items from the containing module.
  // use super::*;
  #[test]
  fn it_works() {
    let result = 2 + 2;
    assert_eq!(result, 4);
  }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::iter;
use std::path::Path;

/*
#[doc(hidden)]
#[macro_export]
macro_rules! count {
    () => { proc_macro_call_0!() };
    (!) => { proc_macro_call_1!() };
    (!!) => { proc_macro_call_2!() };
    ...
}
*/

fn main() {
    // Tell Cargo not to rerun on src/lib.rs changes.
    println!("cargo:rerun-if-changed=build.rs");

    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("count.rs");

    let mut content = String::new();
    content += "
        #[doc(hidden)]
        #[macro_export]
        macro_rules! count {
    ";
    for i in 0..=64 {
        let bangs = iter::repeat("!").take(i).collect::<String>();
        content += &format!("({}) => {{ proc_macro_call_{}!() }};", bangs, i);
    }
    content += "
            ($(!)+) => {
                compile_error!(\"this macro does not support >64 nested macro invocations\")
            };
        }
    ";

    fs::write(dest_path, content).unwrap();
}
<commit_msg>Avoid bumping count.rs filetime if content is up to date<commit_after>use std::env;
use std::fs;
use std::iter;
use std::path::Path;

/*
#[doc(hidden)]
#[macro_export]
macro_rules! count {
    () => { proc_macro_call_0!() };
    (!) => { proc_macro_call_1!() };
    (!!) => { proc_macro_call_2!() };
    ...
}
*/

fn main() {
    // Tell Cargo not to rerun on src/lib.rs changes.
    println!("cargo:rerun-if-changed=build.rs");

    let mut content = String::new();
    content += "
        #[doc(hidden)]
        #[macro_export]
        macro_rules! count {
    ";
    for i in 0..=64 {
        let bangs = iter::repeat("!").take(i).collect::<String>();
        content += &format!("({}) => {{ proc_macro_call_{}!() }};", bangs, i);
    }
    content += "
            ($(!)+) => {
                compile_error!(\"this macro does not support >64 nested macro invocations\")
            };
        }
    ";

    let content = content.as_bytes();
    let out_dir = env::var("OUT_DIR").unwrap();
    let ref dest_path = Path::new(&out_dir).join("count.rs");

    // Avoid bumping filetime if content is up to date. Possibly related to
    // https://github.com/dtolnay/proc-macro-hack/issues/56 ...?
    if fs::read(dest_path)
        .map(|existing| existing != content)
        .unwrap_or(true)
    {
        fs::write(dest_path, content).unwrap();
    }
}
<|endoftext|>


<commit_before>use syntax::ast::{Expr, Lit, TokenTree, TtDelimited, TtToken};
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
use syntax::parse;
use syntax::parse::parser::Parser as RustParser;
use syntax::parse::token;
use syntax::ptr::P;

use super::render::{Escape, Renderer};

macro_rules! dollar {
    () => (TtToken(_, token::Dollar))
}
macro_rules! dot {
    () => (TtToken(_, token::Dot))
}
macro_rules! eq {
    () => (TtToken(_, token::Eq))
}
macro_rules! not {
    () => (TtToken(_, token::Not))
}
macro_rules! question {
    () => (TtToken(_, token::Question))
}
macro_rules! semi {
    () => (TtToken(_, token::Semi))
}
macro_rules! minus {
    () => (TtToken(_, token::BinOp(token::Minus)))
}
macro_rules! slash {
    () => (TtToken(_, token::BinOp(token::Slash)))
}
macro_rules! literal {
    () => (TtToken(_, token::Literal(..)))
}
macro_rules! ident {
    ($x:pat) => (ident!(_, $x));
    ($sp:pat, $x:pat) => (TtToken($sp, token::Ident($x, token::IdentStyle::Plain)))
}

pub fn parse(cx: &ExtCtxt, input: &[TokenTree], sp: Span) -> P<Expr> {
    let mut render = Renderer::new(cx);
    Parser {
        in_attr: false,
        input: input,
        span: sp,
        render: &mut render,
    }.markups();
    render.into_expr()
}

struct Parser<'cx: 'r, 's: 'cx, 'i, 'r> {
    in_attr: bool,
    input: &'i [TokenTree],
    span: Span,
    render: &'r mut Renderer<'cx, 's>,
}

impl<'cx, 's, 'i, 'r> Parser<'cx, 's, 'i, 'r> {
    /// Consume `n` items from the input.
    fn shift(&mut self, n: usize) {
        self.input = &self.input[n..];
    }

    /// Construct a Rust AST parser from the given token tree.
    fn new_rust_parser(&self, tts: Vec<TokenTree>) -> RustParser<'s> {
        parse::tts_to_parser(self.render.cx.parse_sess, tts, self.render.cx.cfg.clone())
    }

    fn markups(&mut self) {
        loop {
            match self.input {
                [] => return,
                [semi!(), ..] => self.shift(1),
                [_, ..] => if !self.markup() { return },
            }
        }
    }

    fn markup(&mut self) -> bool {
        match self.input {
            // Literal
            [minus!(), ref tt @ literal!(), ..] => {
                self.shift(2);
                self.literal(tt, true)
            },
            [ref tt @ literal!(), ..] => {
                self.shift(1);
                self.literal(tt, false)
            },
            // Splice
            [ref tt @ dollar!(), dollar!(), ..] => {
                self.shift(2);
                let expr = self.splice(tt.get_span());
                self.render.splice(expr, Escape::PassThru);
            },
            [ref tt @ dollar!(), ..] => {
                self.shift(1);
                let expr = self.splice(tt.get_span());
                self.render.splice(expr, Escape::Escape);
            },
            // Element
            [ident!(sp, name), ..] => {
                self.shift(1);
                self.element(name.as_str(), sp)
            },
            // Block
            [TtDelimited(sp, ref d), ..] if d.delim == token::DelimToken::Brace => {
                self.shift(1);
                self.block(sp, &d.tts)
            },
            // ???
            _ => {
                if let [ref tt, ..] = self.input {
                    self.render.cx.span_err(tt.get_span(), "invalid syntax");
                } else {
                    self.render.cx.span_err(self.span, "unexpected end of block");
                }
                return false;
            },
        }
        true
    }

    fn literal(&mut self, tt: &TokenTree, minus: bool) {
        let lit = self.new_rust_parser(vec![tt.clone()]).parse_lit();
        match lit_to_string(self.render.cx, lit, minus) {
            Some(s) => self.render.string(&s, Escape::Escape),
            None => {},
        }
    }

    fn splice(&mut self, sp: Span) -> P<Expr> {
        let mut tts = vec![];
        // First, munch a single token tree
        if let [ref tt, ..] = self.input {
            self.shift(1);
            tts.push(tt.clone());
        }
        loop {
            match self.input {
                // Munch attribute lookups e.g. `$person.address.street`
                [ref dot @ dot!(), ref ident @ ident!(_), ..] => {
                    self.shift(2);
                    tts.push(dot.clone());
                    tts.push(ident.clone());
                },
                // Munch function calls `()` and indexing operations `[]`
                [TtDelimited(sp, ref d), ..] if d.delim != token::DelimToken::Brace => {
                    self.shift(1);
                    tts.push(TtDelimited(sp, d.clone()));
                },
                _ => break,
            }
        }
        if tts.is_empty() {
            self.render.cx.span_fatal(sp, "expected expression for this splice");
        } else {
            self.new_rust_parser(tts).parse_expr()
        }
    }

    fn element(&mut self, name: &str, sp: Span) {
        if self.in_attr {
            self.render.cx.span_err(sp, "unexpected element, you silly bumpkin");
            return;
        }
        self.render.element_open_start(name);
        self.attrs();
        self.render.element_open_end();
        if let [slash!(), ..] = self.input {
            self.shift(1);
        } else {
            self.markup();
            self.render.element_close(name);
        }
    }

    fn attrs(&mut self) {
        loop { match self.input {
            [ident!(name), eq!(), ..] => {
                // Non-empty attribute
                self.shift(2);
                self.render.attribute_start(name.as_str());
                {
                    // Parse a value under an attribute context
                    let old_in_attr = self.in_attr;
                    self.in_attr = true;
                    self.markup();
                    self.in_attr = old_in_attr;
                }
                self.render.attribute_end();
            },
            [ident!(name), question!(), ..] => {
                // Empty attribute
                self.shift(2);
                if let [ref tt @ eq!(), ..] = self.input {
                    // Toggle the attribute based on a boolean expression
                    self.shift(1);
                    let cond = self.splice(tt.get_span());
                    self.render.attribute_empty_if(name.as_str(), cond);
                } else {
                    // Write the attribute unconditionally
                    self.render.attribute_empty(name.as_str());
                }
            },
            _ => return,
        }}
    }

    fn block(&mut self, sp: Span, tts: &[TokenTree]) {
        Parser {
            in_attr: self.in_attr,
            input: tts,
            span: sp,
            render: self.render,
        }.markups();
    }
}

/// Convert a literal to a string.
fn lit_to_string(cx: &ExtCtxt, lit: Lit, minus: bool) -> Option<String> {
    use syntax::ast::Lit_::*;
    let mut result = String::new();
    if minus {
        result.push('-');
    }
    match lit.node {
        LitStr(s, _) => result.push_str(s.get()),
        LitBinary(..) | LitByte(..) => {
            cx.span_err(lit.span, "cannot splice binary data");
            return None;
        },
        LitChar(c) => result.push(c),
        LitInt(x, _) => result.push_str(&x.to_string()),
        LitFloat(s, _) | LitFloatUnsuffixed(s) => result.push_str(s.get()),
        LitBool(b) => result.push_str(if b { "true" } else { "false" }),
    };
    Some(result)
}
<commit_msg>Make span always the first parameter<commit_after>use syntax::ast::{Expr, Lit, TokenTree, TtDelimited, TtToken};
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;
use syntax::parse;
use syntax::parse::parser::Parser as RustParser;
use syntax::parse::token;
use syntax::ptr::P;

use super::render::{Escape, Renderer};

macro_rules! dollar {
    () => (TtToken(_, token::Dollar))
}
macro_rules! dot {
    () => (TtToken(_, token::Dot))
}
macro_rules! eq {
    () => (TtToken(_, token::Eq))
}
macro_rules! not {
    () => (TtToken(_, token::Not))
}
macro_rules! question {
    () => (TtToken(_, token::Question))
}
macro_rules! semi {
    () => (TtToken(_, token::Semi))
}
macro_rules! minus {
    () => (TtToken(_, token::BinOp(token::Minus)))
}
macro_rules! slash {
    () => (TtToken(_, token::BinOp(token::Slash)))
}
macro_rules! literal {
    () => (TtToken(_, token::Literal(..)))
}
macro_rules! ident {
    ($x:pat) => (ident!(_, $x));
    ($sp:pat, $x:pat) => (TtToken($sp, token::Ident($x, token::IdentStyle::Plain)))
}

pub fn parse(cx: &ExtCtxt, input: &[TokenTree], sp: Span) -> P<Expr> {
    let mut render = Renderer::new(cx);
    Parser {
        in_attr: false,
        input: input,
        span: sp,
        render: &mut render,
    }.markups();
    render.into_expr()
}

struct Parser<'cx: 'r, 's: 'cx, 'i, 'r> {
    in_attr: bool,
    input: &'i [TokenTree],
    span: Span,
    render: &'r mut Renderer<'cx, 's>,
}

impl<'cx, 's, 'i, 'r> Parser<'cx, 's, 'i, 'r> {
    /// Consume `n` items from the input.
    fn shift(&mut self, n: usize) {
        self.input = &self.input[n..];
    }

    /// Construct a Rust AST parser from the given token tree.
    fn new_rust_parser(&self, tts: Vec<TokenTree>) -> RustParser<'s> {
        parse::tts_to_parser(self.render.cx.parse_sess, tts, self.render.cx.cfg.clone())
    }

    fn markups(&mut self) {
        loop {
            match self.input {
                [] => return,
                [semi!(), ..] => self.shift(1),
                [_, ..] => if !self.markup() { return },
            }
        }
    }

    fn markup(&mut self) -> bool {
        match self.input {
            // Literal
            [minus!(), ref tt @ literal!(), ..] => {
                self.shift(2);
                self.literal(tt, true)
            },
            [ref tt @ literal!(), ..] => {
                self.shift(1);
                self.literal(tt, false)
            },
            // Splice
            [ref tt @ dollar!(), dollar!(), ..] => {
                self.shift(2);
                let expr = self.splice(tt.get_span());
                self.render.splice(expr, Escape::PassThru);
            },
            [ref tt @ dollar!(), ..] => {
                self.shift(1);
                let expr = self.splice(tt.get_span());
                self.render.splice(expr, Escape::Escape);
            },
            // Element
            [ident!(sp, name), ..] => {
                self.shift(1);
                self.element(sp, name.as_str())
            },
            // Block
            [TtDelimited(sp, ref d), ..] if d.delim == token::DelimToken::Brace => {
                self.shift(1);
                self.block(sp, &d.tts)
            },
            // ???
            _ => {
                if let [ref tt, ..] = self.input {
                    self.render.cx.span_err(tt.get_span(), "invalid syntax");
                } else {
                    self.render.cx.span_err(self.span, "unexpected end of block");
                }
                return false;
            },
        }
        true
    }

    fn literal(&mut self, tt: &TokenTree, minus: bool) {
        let lit = self.new_rust_parser(vec![tt.clone()]).parse_lit();
        match lit_to_string(self.render.cx, lit, minus) {
            Some(s) => self.render.string(&s, Escape::Escape),
            None => {},
        }
    }

    fn splice(&mut self, sp: Span) -> P<Expr> {
        let mut tts = vec![];
        // First, munch a single token tree
        if let [ref tt, ..] = self.input {
            self.shift(1);
            tts.push(tt.clone());
        }
        loop {
            match self.input {
                // Munch attribute lookups e.g. `$person.address.street`
                [ref dot @ dot!(), ref ident @ ident!(_), ..] => {
                    self.shift(2);
                    tts.push(dot.clone());
                    tts.push(ident.clone());
                },
                // Munch function calls `()` and indexing operations `[]`
                [TtDelimited(sp, ref d), ..] if d.delim != token::DelimToken::Brace => {
                    self.shift(1);
                    tts.push(TtDelimited(sp, d.clone()));
                },
                _ => break,
            }
        }
        if tts.is_empty() {
            self.render.cx.span_fatal(sp, "expected expression for this splice");
        } else {
            self.new_rust_parser(tts).parse_expr()
        }
    }

    fn element(&mut self, sp: Span, name: &str) {
        if self.in_attr {
            self.render.cx.span_err(sp, "unexpected element, you silly bumpkin");
            return;
        }
        self.render.element_open_start(name);
        self.attrs();
        self.render.element_open_end();
        if let [slash!(), ..] = self.input {
            self.shift(1);
        } else {
            self.markup();
            self.render.element_close(name);
        }
    }

    fn attrs(&mut self) {
        loop { match self.input {
            [ident!(name), eq!(), ..] => {
                // Non-empty attribute
                self.shift(2);
                self.render.attribute_start(name.as_str());
                {
                    // Parse a value under an attribute context
                    let old_in_attr = self.in_attr;
                    self.in_attr = true;
                    self.markup();
                    self.in_attr = old_in_attr;
                }
                self.render.attribute_end();
            },
            [ident!(name), question!(), ..] => {
                // Empty attribute
                self.shift(2);
                if let [ref tt @ eq!(), ..] = self.input {
                    // Toggle the attribute based on a boolean expression
                    self.shift(1);
                    let cond = self.splice(tt.get_span());
                    self.render.attribute_empty_if(name.as_str(), cond);
                } else {
                    // Write the attribute unconditionally
                    self.render.attribute_empty(name.as_str());
                }
            },
            _ => return,
        }}
    }

    fn block(&mut self, sp: Span, tts: &[TokenTree]) {
        Parser {
            in_attr: self.in_attr,
            input: tts,
            span: sp,
            render: self.render,
        }.markups();
    }
}

/// Convert a literal to a string.
fn lit_to_string(cx: &ExtCtxt, lit: Lit, minus: bool) -> Option<String> {
    use syntax::ast::Lit_::*;
    let mut result = String::new();
    if minus {
        result.push('-');
    }
    match lit.node {
        LitStr(s, _) => result.push_str(s.get()),
        LitBinary(..) | LitByte(..) => {
            cx.span_err(lit.span, "cannot splice binary data");
            return None;
        },
        LitChar(c) => result.push(c),
        LitInt(x, _) => result.push_str(&x.to_string()),
        LitFloat(s, _) | LitFloatUnsuffixed(s) => result.push_str(s.get()),
        LitBool(b) => result.push_str(if b { "true" } else { "false" }),
    };
    Some(result)
}
<|endoftext|>


<commit_before>use num::rational::Ratio;

use std::f32::{atan2, sqrt, sin, cos, tan};
use std::f32::consts::PI;
use std::fmt::{Show, Formatter, Result};

//hack
use sfml::system::vector2::{Vector2f, Vector2i};

pub type Coord = f32;
pub type RawAngle = f32;

#[derive(Clone)]
pub struct Vector2 {
	x: Coord,
	y: Coord,
}

impl Vector2 {
	pub fn null() -> Vector2 {
		Vector2 { x: 0 as Coord , y: 0 as Coord }
	}

	pub fn new(x: Coord, y: Coord) -> Vector2 {
		Vector2 { x: x, y: y }
	}

	pub fn from_sfml_f(v: &Vector2f) -> Vector2 {
		Vector2 { x: v.x, y: v.y }
	}

	/*pub fn from_sfml_i(v: &Vector2i) -> Vector2 {
		Vector2 { x: v.x, y: v.y }
	}*/

	pub fn normalize(&self) -> Vector2 {
		let len = self.len();

		match len {
			0. => Vector2::null(),
			_ => Vector2 {x: self.x / len, y : self.y / len}
		}
	}

	pub fn len_squared(&self) -> f32 {
		self.x * self.x + self.y * self.y
	}

	pub fn len(&self) -> f32 {
		sqrt(self.len_squared())
	}

	pub fn polar(&self) -> Polar{
		Polar::new(Angle::rad(atan2(self.y, self.x)), self.len())
	}

	pub fn to_sfml_f(&self) -> Vector2f {
		Vector2f { x: self.x, y: self.y }
	}

	/*pub fn to_sfml_i(&self) -> Vector2i {
		Vector2i { self.x as isize, self.y as isize }
	}*/

}

impl Add<Vector2, Vector2> for Vector2 {
	fn add(&self, rhs: &Vector2) -> Vector2 {
		Vector2 { x : self.x + rhs.x,  y : self.y + rhs.y }
	}
}

impl Sub<Vector2, Vector2> for Vector2 {
	fn sub(&self, rhs: &Vector2) -> Vector2 {
		Vector2 { x : self.x - rhs.x,  y : self.y - rhs.y }
	}
}

impl Mul<f32, Vector2> for Vector2 {
	fn mul(&self, rhs: &f32) -> Vector2 {
		Vector2 { x : self.x * (*rhs),  y : self.y * (*rhs) }
	}
}

impl Div<f32, Vector2> for Vector2{
	fn div(&self, rhs: &f32) -> Vector2 {
		Vector2 { x : self.x / (*rhs),  y : self.y / (*rhs) }
	}
}

impl Neg<Vector2> for Vector2 {
	fn neg(&self) -> Vector2 {
		Vector2 { x: -self.x, y: -self.y }
	}
}

impl Eq for Vector2{
	fn eq(&self, other: &Vector2) -> bool {
		self.x == other.x && self.y == other.y
	}

	fn ne(&self, other: &Vector2) -> bool {
		self.x != other.x || self.y != other.y
	}
}

impl Show for Vector2 {
	fn fmt(&self, formatter: &mut Formatter) -> Result {
		let dirStr = angle_to_dir_str(&self.polar().angle);
		write!(formatter.buf, "{{ {} | x: {:.2}, y:{:.2} }}", dirStr, self.x, self.y)
	}
}

pub fn dot(v1: Vector2, v2: Vector2) -> f32 {
	v1.x * v2.x + v1.y * v2.y
}

//Angle---
#[derive(Clone)]
pub struct Angle {
	//in radians
	theta: RawAngle,
}

impl Angle {

	//constructors---
	pub fn deg(deg: RawAngle) -> Angle {
		Angle { theta: Angle::clamp(deg.to_radians()) }
	}
	pub fn rad(rad: RawAngle) -> Angle{
		Angle { theta: Angle::clamp(rad) }
	}

	pub fn sin(&self) -> f32 {
		sin(self.theta)
	}

	pub fn cos(&self) -> f32 {
		cos(self.theta)
	}

	pub fn tan(&self) -> f32 {
		tan(self.theta)
	}

	fn clamp(rad: RawAngle) -> RawAngle {
		let tolerance = 2 as RawAngle;
		let limit = (PI as RawAngle) *  tolerance;

		if rad > limit || rad < -limit {
			angle_to_principal_domain(rad);
		}
		rad
	}
}

impl Add<Angle, Angle> for Angle {
	fn add(&self, rhs: &Angle) -> Angle {
		Angle { theta : Angle::clamp(self.theta + rhs.theta) }
	}
}

impl Sub<Angle, Angle> for Angle {
	fn sub(&self, rhs: &Angle) -> Angle {
		Angle { theta : Angle::clamp(self.theta - rhs.theta) }
	}
}

impl Mul<f32, Angle> for Angle {
	fn mul(&self, rhs: &f32) -> Angle {
		Angle { theta : Angle::clamp(self.theta * *rhs) }
	}
}

impl Div<f32, Angle> for Angle{
	fn div(&self, rhs: &f32) -> Angle {
		//clamp if divided by negative values
		Angle { theta : Angle::clamp(self.theta / *rhs) }
	}
}

impl Neg<Angle> for Angle {
	fn neg(&self) -> Angle {
		Angle { theta : Angle::clamp(-self.theta) }
	}
}

impl Show for Angle {
	fn fmt(&self, formatter: &mut Formatter) -> Result {

		let normalizedAngle = angle_to_principal_domain(self.theta);
		let simplificationFactor = 6;
		let simplifiedNumerator = (normalizedAngle / PI * simplificationFactor as f32).round() as isize;
		let ratio = Ratio::new(simplifiedNumerator, simplificationFactor);

		let n = *ratio.numer();
		let d = *ratio.denom();

		let degrees = self.theta * (180f32 / PI);

		let radStr = match (n, d) {
			(0, _) => "0".to_string(),
			(1, 1) => "π".to_string(),
			(1, _) => format!("π/{}", d),
			(_, 1) => format!("{}π", n),
			_ => format!("{}π/{}", n, d),
		};

		let dirStr = angle_to_dir_str(self);

		write!(formatter.buf, "{{ {} | rad: {} | {:.2}° }}", dirStr, radStr, degrees)

	}
}

fn angle_to_dir_str(angle : &Angle) -> String {
	let principal_angle = angle_to_principal_domain(angle.theta);
	let degrees = principal_angle * (180f32 / PI);

	match (degrees / 45.).floor() as isize {
		0 => "→".to_string(),
		1 => "↗".to_string(),
		2 => "↑".to_string(),
		3 => "↖".to_string(),
		4 => "←".to_string(),
		5 => "↙".to_string(),
		6 => "↓".to_string(),
		7 => "↘".to_string(),
		_ => "⟳".to_string()
	}
}

//polar Coordinates-----------------

#[derive(Debug)]
pub struct Polar {
	angle: Angle,
	len: f32
}

impl Polar {
	pub fn new(angle: Angle, len: f32) -> Polar {
		Polar { angle: angle, len: len }
	}

	pub fn unit(angle: Angle) -> Polar {
		Polar { angle: angle, len: 1. }
	}

	pub fn unit_rad(rad: f32) -> Polar {
		Polar { angle: Angle::rad(rad), len: 1. }
	}

	pub fn unit_deg(deg: f32) -> Polar {
		Polar { angle: Angle::deg(deg), len: 1. }
	}

	//member functions-----
	pub fn cartesian(&self) -> Vector2 {
		Vector2::new(self.angle.cos() * self.len, self.angle.sin() * self.len)
	}

	pub fn normalize(&self) -> Polar {
		Polar { angle: self.angle, len: 1.}
	}
}

//polar by polar multiplication
impl Mul<Polar, Polar> for Polar {
	fn mul(&self, rhs: &Polar) -> Polar {
		Polar { angle: self.angle + rhs.angle, len: self.len * rhs.len }
	}
}

impl Div<Polar, Polar> for Polar{
	fn div(&self, rhs: &Polar) -> Polar {
		Polar { angle: self.angle - rhs.angle, len: self.len / rhs.len }
	}
}

impl Neg<Polar> for Polar {
	fn neg(&self) -> Polar {
		Polar { angle : -self.angle, len: self.len }
	}
}

//auxiliary helper functions--------------------------------
fn angle_to_principal_domain(rad: RawAngle) -> RawAngle{
	let twoPi = (2. * PI) as RawAngle;

	let mut clamped : RawAngle = rad % twoPi;

	if clamped < 0. {
		clamped += twoPi;
	}

	assert!(clamped >= 0 as RawAngle && clamped < twoPi);
	clamped
}

//tests

#[test]
fn test_vector_cons() {
	let v1 = Vector2::null();
	let v2 = Vector2::new(3.0, 4.0);

	assert!(v1.x == 0. && v1.y == 0.);
	assert!(v2.x == 3. && v2.y == 4.);
}

#[test]
fn test_vector_normalize() {
	let v1 = Vector2::null();
	let v2 = Vector2::new(3.0, 4.0);
	let v3 = Vector2::new(1.0, 0.0);

	assert!(v1.normalize() == v1);
	assert!(v3.normalize() == v3);

	assert!(v2.normalize().x == 3.0 / 5.0 && v2.normalize().y == 4.0 / 5.0)
}

#[test]
fn test_vector_len() {
	let v1 = Vector2::null();
	let v2 = Vector2::new(3.0, 4.0);
	let v3 = Vector2::new(1.0, 0.0);
	let v4 = Vector2::new(1.0, 1.0);

	assert!(v1.len() == 0. && v1.len_squared() == 0.);
	assert!(v2.len() == 5.);
	assert!(v3.len_squared() == 1. && v3.len() == 1.);
	assert!(v4.len_squared() == 2.);
}

#[test]
fn test_vector_operators() {
	let v1 = Vector2::null();
	let v2 = Vector2::new(3.0, 4.0);
	let v3 = Vector2::new(1.0, 0.0);
	let v4 = Vector2::new(1.0, 1.0);
	let v5 = Vector2::new(0.0, 1.0);

	assert!(v1 + v2 == v2);
	assert!(v1 + v1 == v1);
	assert!(v4 + v4 == v4 * 2.);
	assert!(v3 + v4 == Vector2::new(2.0, 1.0));

	assert!(v2 - v1 == v2);
	assert!(v2 - v2 == v1);
	assert!(v4 - v3 == Vector2::new(0.0, 1.0));

	assert!(v2 != v1);
	assert!(v3 != v4 && v5 != v4 && v5 != v3);
}

#[test]
fn test_cartesian_polar() {
	let v1 = Vector2::null();
	let a1 = v1.polar();

	assert!(a1.len == 0.);
	assert!(a1.cartesian() == v1);

	let a1 = Polar::new(Angle::deg(90.), 2.);

	assert!(a1.cartesian().len() == 2.);
	assert!(a1.cartesian().polar() == a1);
	assert!(a1.cartesian().y == 2. && a1.cartesian().x == 0.);

}
<commit_msg>Fix several different api errors<commit_after>use num::rational::Ratio;

use std::f32;
use std::f32::consts::PI;
use std::fmt::{Formatter, Result};

//hack
use sfml::system::{Vector2f, Vector2i};

pub type Coord = f32;
pub type RawAngle = f32;

#[derive(Clone)]
pub struct Vector2 {
	x: Coord,
	y: Coord,
}

impl Vector2 {
	pub fn null() -> Vector2 {
		Vector2 { x: 0 as Coord , y: 0 as Coord }
	}

	pub fn new(x: Coord, y: Coord) -> Vector2 {
		Vector2 { x: x, y: y }
	}

	pub fn from_sfml_f(v: &Vector2f) -> Vector2 {
		Vector2 { x: v.x, y: v.y }
	}

	/*pub fn from_sfml_i(v: &Vector2i) -> Vector2 {
		Vector2 { x: v.x, y: v.y }
	}*/

	pub fn normalize(&self) -> Vector2 {
		let len = self.len();

		match len {
			0. => Vector2::null(),
			_ => Vector2 {x: self.x / len, y : self.y / len}
		}
	}

	pub fn len_squared(&self) -> f32 {
		self.x * self.x + self.y * self.y
	}

	pub fn len(&self) -> f32 {
		sqrt(self.len_squared())
	}

	pub fn polar(&self) -> Polar{
		Polar::new(Angle::rad(self.y.atan2(self.x)), self.len())
	}

	pub fn to_sfml_f(&self) -> Vector2f {
		Vector2f { x: self.x, y: self.y }
	}

	/*pub fn to_sfml_i(&self) -> Vector2i {
		Vector2i { self.x as isize, self.y as isize }
	}*/

}

impl Add<Vector2, Vector2> for Vector2 {
	fn add(&self, rhs: &Vector2) -> Vector2 {
		Vector2 { x : self.x + rhs.x,  y : self.y + rhs.y }
	}
}

impl Sub<Vector2, Vector2> for Vector2 {
	fn sub(&self, rhs: &Vector2) -> Vector2 {
		Vector2 { x : self.x - rhs.x,  y : self.y - rhs.y }
	}
}

impl Mul<f32, Vector2> for Vector2 {
	fn mul(&self, rhs: &f32) -> Vector2 {
		Vector2 { x : self.x * (*rhs),  y : self.y * (*rhs) }
	}
}

impl Div<f32, Vector2> for Vector2{
	fn div(&self, rhs: &f32) -> Vector2 {
		Vector2 { x : self.x / (*rhs),  y : self.y / (*rhs) }
	}
}

impl Neg<Vector2> for Vector2 {
	fn neg(&self) -> Vector2 {
		Vector2 { x: -self.x, y: -self.y }
	}
}

impl Eq for Vector2{
	fn eq(&self, other: &Vector2) -> bool {
		self.x == other.x && self.y == other.y
	}

	fn ne(&self, other: &Vector2) -> bool {
		self.x != other.x || self.y != other.y
	}
}

impl Show for Vector2 {
	fn fmt(&self, formatter: &mut Formatter) -> Result {
		let dirStr = angle_to_dir_str(&self.polar().angle);
		write!(formatter.buf, "{{ {} | x: {:.2}, y:{:.2} }}", dirStr, self.x, self.y)
	}
}

pub fn dot(v1: Vector2, v2: Vector2) -> f32 {
	v1.x * v2.x + v1.y * v2.y
}

//Angle---
#[derive(Clone)]
pub struct Angle {
	//in radians
	theta: RawAngle,
}

impl Angle {

	//constructors---
	pub fn deg(deg: RawAngle) -> Angle {
		Angle { theta: Angle::clamp(deg.to_radians()) }
	}
	pub fn rad(rad: RawAngle) -> Angle{
		Angle { theta: Angle::clamp(rad) }
	}

	pub fn sin(&self) -> f32 {
		sin(self.theta)
	}

	pub fn cos(&self) -> f32 {
		cos(self.theta)
	}

	pub fn tan(&self) -> f32 {
		tan(self.theta)
	}

	fn clamp(rad: RawAngle) -> RawAngle {
		let tolerance = 2 as RawAngle;
		let limit = (PI as RawAngle) *  tolerance;

		if rad > limit || rad < -limit {
			angle_to_principal_domain(rad);
		}
		rad
	}
}

impl Add<Angle, Angle> for Angle {
	fn add(&self, rhs: &Angle) -> Angle {
		Angle { theta : Angle::clamp(self.theta + rhs.theta) }
	}
}

impl Sub<Angle, Angle> for Angle {
	fn sub(&self, rhs: &Angle) -> Angle {
		Angle { theta : Angle::clamp(self.theta - rhs.theta) }
	}
}

impl Mul<f32, Angle> for Angle {
	fn mul(&self, rhs: &f32) -> Angle {
		Angle { theta : Angle::clamp(self.theta * *rhs) }
	}
}

impl Div<f32, Angle> for Angle{
	fn div(&self, rhs: &f32) -> Angle {
		//clamp if divided by negative values
		Angle { theta : Angle::clamp(self.theta / *rhs) }
	}
}

impl Neg<Angle> for Angle {
	fn neg(&self) -> Angle {
		Angle { theta : Angle::clamp(-self.theta) }
	}
}

impl Show for Angle {
	fn fmt(&self, formatter: &mut Formatter) -> Result {

		let normalizedAngle = angle_to_principal_domain(self.theta);
		let simplificationFactor = 6;
		let simplifiedNumerator = (normalizedAngle / PI * simplificationFactor as f32).round() as isize;
		let ratio = Ratio::new(simplifiedNumerator, simplificationFactor);

		let n = *ratio.numer();
		let d = *ratio.denom();

		let degrees = self.theta * (180f32 / PI);

		let radStr = match (n, d) {
			(0, _) => "0".to_string(),
			(1, 1) => "π".to_string(),
			(1, _) => format!("π/{}", d),
			(_, 1) => format!("{}π", n),
			_ => format!("{}π/{}", n, d),
		};

		let dirStr = angle_to_dir_str(self);

		write!(formatter.buf, "{{ {} | rad: {} | {:.2}° }}", dirStr, radStr, degrees)

	}
}

fn angle_to_dir_str(angle : &Angle) -> String {
	let principal_angle = angle_to_principal_domain(angle.theta);
	let degrees = principal_angle * (180f32 / PI);

	match (degrees / 45.).floor() as isize {
		0 => "→".to_string(),
		1 => "↗".to_string(),
		2 => "↑".to_string(),
		3 => "↖".to_string(),
		4 => "←".to_string(),
		5 => "↙".to_string(),
		6 => "↓".to_string(),
		7 => "↘".to_string(),
		_ => "⟳".to_string()
	}
}

//polar Coordinates-----------------

#[derive(Debug)]
pub struct Polar {
	angle: Angle,
	len: f32
}

impl Polar {
	pub fn new(angle: Angle, len: f32) -> Polar {
		Polar { angle: angle, len: len }
	}

	pub fn unit(angle: Angle) -> Polar {
		Polar { angle: angle, len: 1. }
	}

	pub fn unit_rad(rad: f32) -> Polar {
		Polar { angle: Angle::rad(rad), len: 1. }
	}

	pub fn unit_deg(deg: f32) -> Polar {
		Polar { angle: Angle::deg(deg), len: 1. }
	}

	//member functions-----
	pub fn cartesian(&self) -> Vector2 {
		Vector2::new(self.angle.cos() * self.len, self.angle.sin() * self.len)
	}

	pub fn normalize(&self) -> Polar {
		Polar { angle: self.angle, len: 1.}
	}
}

//polar by polar multiplication
impl Mul<Polar, Polar> for Polar {
	fn mul(&self, rhs: &Polar) -> Polar {
		Polar { angle: self.angle + rhs.angle, len: self.len * rhs.len }
	}
}

impl Div<Polar, Polar> for Polar{
	fn div(&self, rhs: &Polar) -> Polar {
		Polar { angle: self.angle - rhs.angle, len: self.len / rhs.len }
	}
}

impl Neg<Polar> for Polar {
	fn neg(&self) -> Polar {
		Polar { angle : -self.angle, len: self.len }
	}
}

//auxiliary helper functions--------------------------------
fn angle_to_principal_domain(rad: RawAngle) -> RawAngle{
	let twoPi = (2. * PI) as RawAngle;

	let mut clamped : RawAngle = rad % twoPi;

	if clamped < 0. {
		clamped += twoPi;
	}

	assert!(clamped >= 0 as RawAngle && clamped < twoPi);
	clamped
}

//tests

#[test]
fn test_vector_cons() {
	let v1 = Vector2::null();
	let v2 = Vector2::new(3.0, 4.0);

	assert!(v1.x == 0. && v1.y == 0.);
	assert!(v2.x == 3. && v2.y == 4.);
}

#[test]
fn test_vector_normalize() {
	let v1 = Vector2::null();
	let v2 = Vector2::new(3.0, 4.0);
	let v3 = Vector2::new(1.0, 0.0);

	assert!(v1.normalize() == v1);
	assert!(v3.normalize() == v3);

	assert!(v2.normalize().x == 3.0 / 5.0 && v2.normalize().y == 4.0 / 5.0)
}

#[test]
fn test_vector_len() {
	let v1 = Vector2::null();
	let v2 = Vector2::new(3.0, 4.0);
	let v3 = Vector2::new(1.0, 0.0);
	let v4 = Vector2::new(1.0, 1.0);

	assert!(v1.len() == 0. && v1.len_squared() == 0.);
	assert!(v2.len() == 5.);
	assert!(v3.len_squared() == 1. && v3.len() == 1.);
	assert!(v4.len_squared() == 2.);
}

#[test]
fn test_vector_operators() {
	let v1 = Vector2::null();
	let v2 = Vector2::new(3.0, 4.0);
	let v3 = Vector2::new(1.0, 0.0);
	let v4 = Vector2::new(1.0, 1.0);
	let v5 = Vector2::new(0.0, 1.0);

	assert!(v1 + v2 == v2);
	assert!(v1 + v1 == v1);
	assert!(v4 + v4 == v4 * 2.);
	assert!(v3 + v4 == Vector2::new(2.0, 1.0));

	assert!(v2 - v1 == v2);
	assert!(v2 - v2 == v1);
	assert!(v4 - v3 == Vector2::new(0.0, 1.0));

	assert!(v2 != v1);
	assert!(v3 != v4 && v5 != v4 && v5 != v3);
}

#[test]
fn test_cartesian_polar() {
	let v1 = Vector2::null();
	let a1 = v1.polar();

	assert!(a1.len == 0.);
	assert!(a1.cartesian() == v1);

	let a1 = Polar::new(Angle::deg(90.), 2.);

	assert!(a1.cartesian().len() == 2.);
	assert!(a1.cartesian().polar() == a1);
	assert!(a1.cartesian().y == 2. && a1.cartesian().x == 0.);

}
<|endoftext|>


<commit_before>use std::rc::Rc;

use grid::Grid;
use cell::Cell;

const NEIGHBORS_COUNT: usize = 8;

type Neighbors<C> = [Option<Rc<C>>; NEIGHBORS_COUNT];

pub struct MooreSquareGrid<C: Cell> {
    cells: Vec<Rc<C>>,
    neighbors: Vec<Neighbors<C>>,
    rows: usize,
    cols: usize
}

impl<C: Cell + Clone> MooreSquareGrid<C> {

    pub fn new(rows: usize, cols: usize, initial: C) -> Self {

        let len = rows * cols;
        let cells = vec![Rc::new(initial); len];
        let neighbors = Vec::with_capacity(len);

        let mut grid = MooreSquareGrid {
            cells: cells,
            neighbors: neighbors,
            rows: rows,
            cols: cols
        };
        grid.init_neighbors();

        grid
    }

    /// 0 | 1 | 2
    /// 3 | x | 4
    /// 5 | 6 | 7
    fn init_neighbors(&mut self) {

        let len = self.cells.len() as i32;
        let cols = self.cols as i32;

        for (offset, cell) in self.cells.iter().enumerate() {

            for serial in 0 .. NEIGHBORS_COUNT {

                let neighbor_index: i32;

                {
                    let offset = offset as i32;
                    let serial = serial as i32;

                    neighbor_index = match serial {
                        i @ 0 ... 2 => offset - cols - (i - 1),
                        3 => offset - 1,
                        4 => offset + 1,
                        i @ 5 ... 7 => offset + cols - (i - 1),
                        // such values will be ignored later
                        _ => len
                    };
                }

                if neighbor_index >= 0 && neighbor_index < len {
                    self.neighbors[offset][serial] = Some(cell.clone());
                }
                else {
                    self.neighbors[offset][serial] = None;
                }
            }
        }
    }
}

impl<C: Cell> Grid for MooreSquareGrid<C> {
    fn step(&self) {}
}
<commit_msg>More clean solution.<commit_after>use std::rc::Rc;

use grid::Grid;
use cell::Cell;

const NEIGHBORS_COUNT: usize = 8;

type Neighbors<C> = [Option<Rc<C>>; NEIGHBORS_COUNT];

pub struct MooreSquareGrid<C: Cell> {
    cells: Vec<Rc<C>>,
    neighbors: Vec<Neighbors<C>>,
    rows: usize,
    cols: usize
}

impl<C: Cell + Clone> MooreSquareGrid<C> {

    pub fn new(rows: usize, cols: usize, initial: C) -> Self {

        let len = rows * cols;
        let cells = vec![Rc::new(initial); len];
        let neighbors = Vec::with_capacity(len);

        let mut grid = MooreSquareGrid {
            cells: cells,
            neighbors: neighbors,
            rows: rows,
            cols: cols
        };
        grid.init_neighbors();

        grid
    }

    /// 0 | 1 | 2
    /// 3 | x | 4
    /// 5 | 6 | 7
    fn init_neighbors(&mut self) {

        let len = self.cells.len() as i32;
        let cols = self.cols as i32;

        for (offset, cell) in self.cells.iter().enumerate() {

            for serial in 0 .. NEIGHBORS_COUNT {

                let neighbor_index: Option<i32>;

                {
                    let offset = offset as i32;
                    let serial = serial as i32;

                    neighbor_index = match serial {
                        i @ 0 ... 2 => Some(offset - cols - (i - 1)),
                        3 => Some(offset - 1),
                        4 => Some(offset + 1),
                        i @ 5 ... 7 => Some(offset + cols - (i - 1)),
                        _ => None
                    };
                }

                if let Some(index) = neighbor_index {
                    if index >= 0 && index < len {
                        self.neighbors[offset][serial] = Some(cell.clone());
                    }
                }
            }
        }
    }
}

impl<C: Cell> Grid for MooreSquareGrid<C> {
    fn step(&self) {}
}
<|endoftext|>


<commit_before>use input::Input;
use buffer::Direction;
use keyboard::Key;
use view::View;
use frontends::{Frontend, EditorEvent};
use modes::Mode;
use overlay::{Overlay, OverlayType, OverlayEvent};

use command::Command as Cmd;
use command::{Action, BuilderEvent, Operation, Instruction};

use textobject::{TextObject, Kind, Offset};

#[derive(Copy, Debug, PartialEq, Eq)]
pub enum Command {
    SaveBuffer,
    ExitEditor,

    MoveCursor(Direction, usize),
    LineEnd,
    LineStart,

    Delete(Direction, usize),
    InsertTab,
    InsertChar(char),

    SetOverlay(OverlayType),

    Undo,
    Redo,

    Unknown,
    None,
}

impl Command {
    #[inline]
    pub fn from_str(string: &str) -> Command {
        match string {
            "q" | "quit"  => Command::ExitEditor,
            "w" | "write" => Command::SaveBuffer,

            _             => Command::Unknown,
        }
    }
}

/// The main Editor structure
///
/// This is the top-most structure in Iota.
pub struct Editor<'e, T: Frontend> {
    view: View<'e>,
    running: bool,
    frontend: T,
    mode: Box<Mode + 'e>,
}

impl<'e, T: Frontend> Editor<'e, T> {
    /// Create a new Editor instance
    pub fn new(source: Input, mode: Box<Mode + 'e>, frontend: T) -> Editor<'e, T> {
        let height = frontend.get_window_height();
        let width = frontend.get_window_width();
        let view = View::new(source, width, height);

        Editor {
            view: view,
            running: true,
            frontend: frontend,
            mode: mode,
        }
    }

    /// Handle key events
    ///
    /// Key events can be handled in an Overlay, OR in the current Mode.
    ///
    /// If there is an active Overlay, the key event is sent there, which gives
    /// back an OverlayEvent. We then parse this OverlayEvent and determine if
    /// the Overlay is finished and can be cleared. The response from the
    /// Overlay is then converted to a Command and sent off to be handled.
    ///
    /// If there is no active Overlay, the key event is sent to the current
    /// Mode, which returns a Command which we dispatch to handle_command.
    fn handle_key_event(&mut self, key: Option<Key>) {
        let key = match key {
            Some(k) => k,
            None => return
        };

        let mut remove_overlay = false;
        let command = match self.view.overlay {
            Overlay::None => self.mode.handle_key_event(key),
            _             => {
                let event = self.view.overlay.handle_key_event(key);
                match event {
                    OverlayEvent::Finished(response) => {
                        remove_overlay = true;
                        self.handle_overlay_response(response)
                    }

                    _ => { BuilderEvent::Incomplete }
                }
            }
        };

        if remove_overlay {
            self.view.overlay = Overlay::None;
            self.view.clear(&mut self.frontend);
        }

        if let BuilderEvent::Complete(c) = command {
            self.handle_command(c);
        }
    }

    /// Translate the response from an Overlay to a Command
    ///
    /// In most cases, we will just want to convert the response directly to
    /// a Command, however in some cases we will want to perform other actions
    /// first, such as in the case of Overlay::SavePrompt.
    fn handle_overlay_response(&mut self, response: Option<String>) -> BuilderEvent {
        // FIXME: This entire method neext to be updated
        match response {
            Some(data) => {
                match self.view.overlay {

                    // FIXME: this is just a temporary fix
                    Overlay::Prompt { .. } => {
                        match Command::from_str(&*data) {
                            Command::ExitEditor => {
                                return BuilderEvent::Complete(Cmd {
                                    action:Action::Instruction(Instruction::ExitEditor),
                                    number: 0,
                                    object: TextObject {
                                        kind: Kind::Char,
                                        offset: Offset::Absolute(0),
                                    },
                                })
                            }
                            _ => BuilderEvent::Incomplete
                        }
                    }

                    Overlay::SavePrompt { .. } => {
                        let path = Path::new(&*data);
                        self.view.buffer.file_path = Some(path);
                        // Command::SaveBuffer
                        BuilderEvent::Complete(Cmd {
                            action:Action::Instruction(Instruction::SaveBuffer),
                            number: 0,
                            object: TextObject {
                                kind: Kind::Char,
                                offset: Offset::Absolute(0),
                            },
                        })
                    }
                    _ => BuilderEvent::Incomplete,
                }
            }
            None => BuilderEvent::Incomplete
        }
    }

    /// Handle resize events
    ///
    /// width and height represent the new height of the window.
    fn handle_resize_event(&mut self, width: usize, height: usize) {
        self.view.resize(width, height);
    }

    /// Draw the current view to the frontend
    fn draw(&mut self) {
        self.view.draw(&mut self.frontend);
    }

    /// Handle the given command, performing the associated action
    fn handle_command(&mut self, command: Cmd) {
        match command.action {
            Action::Instruction(i) => self.handle_instruction(i, command),
            Action::Operation(o) => self.handle_operation(o, command),
        }

        // match command {
        //     // Editor Commands
        //     Command::SaveBuffer         => self.view.try_save_buffer(),
        //     Command::SetOverlay(o)      => self.view.set_overlay(o),

        //     // Navigation
        //     Command::MoveCursor(dir, n) => self.view.move_cursor(dir, n),
        //     Command::LineEnd            => self.view.move_cursor_to_line_end(),
        //     Command::LineStart          => self.view.move_cursor_to_line_start(),

        //     // Editing
        //     Command::Delete(dir, n)     => self.view.delete_chars(dir, n),
        //     Command::InsertTab          => self.view.insert_tab(),
        //     Command::InsertChar(c)      => self.view.insert_char(c),
        //     Command::Redo               => self.view.redo(),
        //     Command::Undo               => self.view.undo(),

        //     _ => {},
        // }
    }

    fn handle_instruction(&mut self, instruction: Instruction, command: Cmd) {
        match instruction {
            Instruction::SaveBuffer => { self.view.try_save_buffer() }
            Instruction::ExitEditor => { self.running = false; }
            Instruction::SetMark(mark) => {
                let (mut dir, n) = match command.object.offset {
                    Offset::Backward(n, _) => (Direction::Left, n),
                    Offset::Forward(n, _) => (Direction::Right, n),

                    // FIXME
                    Offset::Absolute(n) => (Direction::Right, 0)
                };

                if let Kind::Line(_) = command.object.kind {
                    if dir == Direction::Left {
                        dir = Direction::Up
                    } else {
                        dir = Direction::Down
                    }
                }

                self.view.move_cursor(dir, n)
            }
            Instruction::SetOverlay(overlay_type) => {
                self.view.set_overlay(overlay_type)
            }
        }
    }

    fn handle_operation(&mut self, operation: Operation, command: Cmd) {
        match operation {
            Operation::Insert => {}
            Operation::Delete => {}
            Operation::Undo => {}
            Operation::Redo => {}
        }
    }

    /// Start Iota!
    pub fn start(&mut self) {
        while self.running {
            self.draw();
            self.frontend.present();
            let event = self.frontend.poll_event();

            match event {
                EditorEvent::KeyEvent(key)         => self.handle_key_event(key),
                EditorEvent::Resize(width, height) => self.handle_resize_event(width, height),

                _ => {}
            }
        }
    }
}
<commit_msg>Added basic delete operation<commit_after>use input::Input;
use buffer::Direction;
use keyboard::Key;
use view::View;
use frontends::{Frontend, EditorEvent};
use modes::Mode;
use overlay::{Overlay, OverlayType, OverlayEvent};

use command::Command as Cmd;
use command::{Action, BuilderEvent, Operation, Instruction};

use textobject::{TextObject, Kind, Offset};

#[derive(Copy, Debug, PartialEq, Eq)]
pub enum Command {
    SaveBuffer,
    ExitEditor,

    MoveCursor(Direction, usize),
    LineEnd,
    LineStart,

    Delete(Direction, usize),
    InsertTab,
    InsertChar(char),

    SetOverlay(OverlayType),

    Undo,
    Redo,

    Unknown,
    None,
}

impl Command {
    #[inline]
    pub fn from_str(string: &str) -> Command {
        match string {
            "q" | "quit"  => Command::ExitEditor,
            "w" | "write" => Command::SaveBuffer,

            _             => Command::Unknown,
        }
    }
}

/// The main Editor structure
///
/// This is the top-most structure in Iota.
pub struct Editor<'e, T: Frontend> {
    view: View<'e>,
    running: bool,
    frontend: T,
    mode: Box<Mode + 'e>,
}

impl<'e, T: Frontend> Editor<'e, T> {
    /// Create a new Editor instance
    pub fn new(source: Input, mode: Box<Mode + 'e>, frontend: T) -> Editor<'e, T> {
        let height = frontend.get_window_height();
        let width = frontend.get_window_width();
        let view = View::new(source, width, height);

        Editor {
            view: view,
            running: true,
            frontend: frontend,
            mode: mode,
        }
    }

    /// Handle key events
    ///
    /// Key events can be handled in an Overlay, OR in the current Mode.
    ///
    /// If there is an active Overlay, the key event is sent there, which gives
    /// back an OverlayEvent. We then parse this OverlayEvent and determine if
    /// the Overlay is finished and can be cleared. The response from the
    /// Overlay is then converted to a Command and sent off to be handled.
    ///
    /// If there is no active Overlay, the key event is sent to the current
    /// Mode, which returns a Command which we dispatch to handle_command.
    fn handle_key_event(&mut self, key: Option<Key>) {
        let key = match key {
            Some(k) => k,
            None => return
        };

        let mut remove_overlay = false;
        let command = match self.view.overlay {
            Overlay::None => self.mode.handle_key_event(key),
            _             => {
                let event = self.view.overlay.handle_key_event(key);
                match event {
                    OverlayEvent::Finished(response) => {
                        remove_overlay = true;
                        self.handle_overlay_response(response)
                    }

                    _ => { BuilderEvent::Incomplete }
                }
            }
        };

        if remove_overlay {
            self.view.overlay = Overlay::None;
            self.view.clear(&mut self.frontend);
        }

        if let BuilderEvent::Complete(c) = command {
            self.handle_command(c);
        }
    }

    /// Translate the response from an Overlay to a Command
    ///
    /// In most cases, we will just want to convert the response directly to
    /// a Command, however in some cases we will want to perform other actions
    /// first, such as in the case of Overlay::SavePrompt.
    fn handle_overlay_response(&mut self, response: Option<String>) -> BuilderEvent {
        // FIXME: This entire method neext to be updated
        match response {
            Some(data) => {
                match self.view.overlay {

                    // FIXME: this is just a temporary fix
                    Overlay::Prompt { .. } => {
                        match Command::from_str(&*data) {
                            Command::ExitEditor => {
                                return BuilderEvent::Complete(Cmd {
                                    action:Action::Instruction(Instruction::ExitEditor),
                                    number: 0,
                                    object: TextObject {
                                        kind: Kind::Char,
                                        offset: Offset::Absolute(0),
                                    },
                                })
                            }
                            _ => BuilderEvent::Incomplete
                        }
                    }

                    Overlay::SavePrompt { .. } => {
                        let path = Path::new(&*data);
                        self.view.buffer.file_path = Some(path);
                        // Command::SaveBuffer
                        BuilderEvent::Complete(Cmd {
                            action:Action::Instruction(Instruction::SaveBuffer),
                            number: 0,
                            object: TextObject {
                                kind: Kind::Char,
                                offset: Offset::Absolute(0),
                            },
                        })
                    }
                    _ => BuilderEvent::Incomplete,
                }
            }
            None => BuilderEvent::Incomplete
        }
    }

    /// Handle resize events
    ///
    /// width and height represent the new height of the window.
    fn handle_resize_event(&mut self, width: usize, height: usize) {
        self.view.resize(width, height);
    }

    /// Draw the current view to the frontend
    fn draw(&mut self) {
        self.view.draw(&mut self.frontend);
    }

    /// Handle the given command, performing the associated action
    fn handle_command(&mut self, command: Cmd) {
        match command.action {
            Action::Instruction(i) => self.handle_instruction(i, command),
            Action::Operation(o) => self.handle_operation(o, command),
        }

        // match command {
        //     // Editor Commands
        //     Command::SaveBuffer         => self.view.try_save_buffer(),
        //     Command::SetOverlay(o)      => self.view.set_overlay(o),

        //     // Navigation
        //     Command::MoveCursor(dir, n) => self.view.move_cursor(dir, n),
        //     Command::LineEnd            => self.view.move_cursor_to_line_end(),
        //     Command::LineStart          => self.view.move_cursor_to_line_start(),

        //     // Editing
        //     Command::Delete(dir, n)     => self.view.delete_chars(dir, n),
        //     Command::InsertTab          => self.view.insert_tab(),
        //     Command::InsertChar(c)      => self.view.insert_char(c),
        //     Command::Redo               => self.view.redo(),
        //     Command::Undo               => self.view.undo(),

        //     _ => {},
        // }
    }

    fn handle_instruction(&mut self, instruction: Instruction, command: Cmd) {
        match instruction {
            Instruction::SaveBuffer => { self.view.try_save_buffer() }
            Instruction::ExitEditor => { self.running = false; }
            Instruction::SetMark(mark) => {
                let (mut dir, n) = match command.object.offset {
                    Offset::Backward(n, _) => (Direction::Left, n),
                    Offset::Forward(n, _) => (Direction::Right, n),

                    // FIXME
                    Offset::Absolute(n) => (Direction::Right, 0)
                };

                if let Kind::Line(_) = command.object.kind {
                    if dir == Direction::Left {
                        dir = Direction::Up
                    } else {
                        dir = Direction::Down
                    }
                }

                self.view.move_cursor(dir, n)
            }
            Instruction::SetOverlay(overlay_type) => {
                self.view.set_overlay(overlay_type)
            }
        }
    }

    fn handle_operation(&mut self, operation: Operation, command: Cmd) {
        match operation {
            Operation::Insert => {}
            Operation::Delete => {
                // FIXME: update to delete lines
                let obj = command.object;

                let (dir, n) = match obj.offset {
                    Offset::Forward(n, _) => (Direction::Right, n),
                    Offset::Backward(n, _) => (Direction::Left, n),

                    Offset::Absolute(n) => (Direction::Right, 0),
                };

                self.view.delete_chars(dir, n)
            }
            Operation::Undo => {}
            Operation::Redo => {}
        }
    }

    /// Start Iota!
    pub fn start(&mut self) {
        while self.running {
            self.draw();
            self.frontend.present();
            let event = self.frontend.poll_event();

            match event {
                EditorEvent::KeyEvent(key)         => self.handle_key_event(key),
                EditorEvent::Resize(width, height) => self.handle_resize_event(width, height),

                _ => {}
            }
        }
    }
}
<|endoftext|>