<commit_before>//! Layout handling

// remove
#![allow(unused)]

use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::VIEW_MAXIMIZED;
use std::rc::{Rc, Weak};
use std::fmt::{Debug, Formatter};
use std::fmt::Result as FmtResult;
use std::cell::RefCell;

pub type Node = Rc<RefCell<Container>>;

#[derive(Debug, Clone)]
enum Handle {
    View(WlcView),
    Output(WlcOutput)
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A Container, houses views and other containers
    Container,
    /// A view (window)
    View
}

/// Layout mode for a container
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

#[derive(Clone)]
pub struct Container {
    handle: Option<Handle>,
    parent: Option<Weak<RefCell<Container>>>,
    children: Vec<Node>,
    container_type: ContainerType,
    layout: Layout,
    width: u32,
    height: u32,
    x: i32,
    y: i32,
    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

/// Like i3, everything (workspaces, containers, views) are containable.
impl Container {

    /// Makes the root container. There should be only one of these
    /// Does not ensure that this is the only root container
    // NOTE Need to find a way to ensure there is only one of these things
    // Perhaps set a static global variable
    pub fn new_root() -> Node {
        trace!("Root created");
        Rc::new(RefCell::new(Container {
            handle: None,
            parent: None,
            children: vec!(),
            container_type: ContainerType::Root,
            layout: Layout::None,
            width: 0,
            height: 0,
            x: 0,
            y: 0,
            visible: false,
            is_focused: false,
            is_floating: false
        }))
    }

    /// Makes a new workspace container. This should only be called by root
    /// since it will properly initialize the right number and properly put
    /// them in the main tree.
    pub fn new_workspace(root: &mut Node) -> Node {
        if ! root.borrow().is_root() {
            panic!("Only workspaces can be added to the root node");
        }
        let workspace: Node =
            Rc::new(RefCell::new(Container {
                // NOTE Give this an output
                handle: None,
                parent: Some(Rc::downgrade(&root)),
                children: vec!(),
                container_type: ContainerType::Workspace,
                // NOTE Change this to some other default
                layout: Layout::None,
                // NOTE Figure out how to initialize these properly
                width: 0,
                height: 0,
                x: 0,
                y: 0,
                visible: false,
                is_focused: false,
                is_floating: false,
                }));
        root.borrow_mut().add_child(workspace.clone());
        workspace
    }

    /// Makes a new container. These hold views and other containers.
    /// Container hold information about specific parts of the tree in some
    /// workspace and the layout of the views within.
    pub fn new_container(parent_: &mut Node, output: WlcOutput) -> Node {
        let mut parent = parent_.borrow_mut();
        if parent.is_root() {
            panic!("Container cannot be a direct child of root");
        }
        let container = Rc::new(RefCell::new(Container {
            handle: Some(Handle::Output(output)),
            parent: Some(Rc::downgrade(&parent_)),
            children: vec!(),
            container_type: ContainerType::Container,
            // NOTE Get default, either from config or from workspace
            layout: Layout::None,
            // NOTE Get this information from somewhere, or set it later
            width: 0,
            height: 0,
            x: 0,
            y: 0,
            visible: false,
            is_focused: false,
            is_floating: false,
        }));
        parent.add_child(container.clone());
        container
    }

    /// Makes a new view. A view holds either a Wayland or an X Wayland window.
    pub fn new_view(parent_: &mut Node, view: WlcView) -> Node {
        let mut parent = parent_.borrow_mut();
        let geometry = view.get_geometry().unwrap().clone();
        if parent.is_root() {
            panic!("View cannot be a direct child of root");
        }
        let container = Rc::new(RefCell::new(Container {
            handle: Some(Handle::View(view)),
            parent: Some(Rc::downgrade(&parent_)),
            children: vec!(),
            container_type: ContainerType::View,
            layout: Layout::None,
            width: geometry.size.w,
            height: geometry.size.h,
            x: geometry.origin.x,
            y: geometry.origin.y,
            visible: false,
            is_focused: false,
            is_floating: false
        }));
        if parent.get_type() == ContainerType::Workspace {
            // Case of focused workspace, just create a child of it
            parent.add_child(container.clone());
        } else {
            // Regular case, create as sibling of current container
            // parent.add_sibling(container);
        }
        container
    }

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    pub fn get_parent(&self) -> Option<Node> {
        if self.is_root() {
            None
        } else {
            // NOTE Clone has to be done here because we have to store the
            // parent as an option since the `Weak::new` is unstable
            if let Some(parent) = self.parent.clone() {
                parent.upgrade()
            } else {
                None
            }
        }
    }

    pub fn add_child(&mut self, container: Node) {
        if self.get_type() == ContainerType::Workspace
            && container.borrow().get_type() == ContainerType::Workspace {
            panic!("Only containers can be children of a workspace");
        }
        // NOTE check to make sure we are not adding a duplicate
        self.children.push(container);
    }

    /// Removes this container and all of its children.
    /// You MUST call this function while `borrow`ing, a mutable borrow will
    /// cause it to panic at run time
    pub fn remove_container(&self) -> Result<(), &'static str> {
        if self.is_root() {
            return Err("Cannot remove root container");
        } else if self.get_type() == ContainerType::Workspace  {
            return Err("Cannot remove workspace container");
        }
        if let Some(parent) = self.get_parent() {
            // NOTE Add check here to ensure we can borrow mutably once that
            // feature stabilizes
            parent.borrow_mut().remove_child(self);
        }
        Ok(())
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    pub fn get_children(&self) -> Option<&[Node]> {
        if self.get_type() == ContainerType::View {
            None
        }
        else {
            Some(self.children.as_slice())
        }
    }

    /// Gets the type of the container
    pub fn get_type(&self) -> ContainerType {
        self.container_type
    }

    /// Returns true if this container is focused.
    pub fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes the child at the specified index
    pub fn remove_child_at(&mut self, index: usize) -> Result<Node, &'static str> {
        // NOTE Add check here to ensure we can borrow once that
        // feature stabilizes
        if self.children[index].borrow().get_type() == ContainerType::Workspace {
            return Err("Cannot remove workspace")
        }
        Ok(self.children.remove(index))
    }

    /// Removes the given child from this container's children.
    /// If the child is not present, then an error is returned
    pub fn remove_child(&mut self, node: &Container) -> Result<Node, &'static str> {
        for (index, child) in self.children.clone().iter().enumerate() {
            // NOTE Add check here to ensure we can borrow once that
            // feature stabilizes
            if *child.borrow() == *node {
                if child.borrow().get_type() == ContainerType::Workspace {
                    return Err("Can not remove workspace");
                }
                return Ok(self.children.remove(index));
            }
        }
        return Err("Could not find child in container");//format!("Could not find child {:?} in {:?}", node, self));
    }

    /// Sets this container (and everything in it) to given visibility
    pub fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the visibility of the container
    pub fn get_visibility(&self) -> bool {
        self.visible
    }

    /// Gets the X and Y dimensions of the container
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    pub fn get_position(&self) -> (i32, i32) {
        (self.x, self.y)
    }

    /// Returns true if this container is a parent of the child
    pub fn is_parent_of(&self, child: Node) -> bool {
        if self.is_root() {
            true
        } else {
            while ! child.borrow().is_root() {
                let parent = child.borrow().get_parent().unwrap();
                if child == parent {
                    return true
                }
            }
            return false;
        }
    }

    /// Returns true if this container is a child is an decedent of the parent
    pub fn is_child_of(&self, parent: Node) -> bool {
        parent.borrow().is_parent_of(Rc::new(RefCell::new(self.clone())))
    }

    pub fn is_root(&self) -> bool {
        self.get_type() == ContainerType::Root
    }

    /// Finds a parent container with the given type, if there is any
    pub fn get_parent_by_type(&self, container_type: ContainerType) -> Option<Node> {
        let mut container = self.get_parent();
        loop {
            if let Some(parent) = container {
                if parent.borrow().get_type() == container_type {
                    return Some(parent);
                }
                container = parent.borrow().get_parent();
            } else {
                return None;
            }
        }
    }
}

impl PartialEq for Container {
    fn eq(&self, other: &Container) -> bool {
        self.get_type() == other.get_type()
    }
}

impl Eq for Container { }

impl Debug for Container {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        f.debug_struct("Containable")
            .field("type", &self.get_type())
            //.field("parent", &self.get_parent())
            .field("children", &self.get_children())
            .field("focused", &self.is_focused())
            .finish()
    }
}
<commit_msg>Added add_sibling, updated new_view<commit_after>//! Layout handling

// remove
#![allow(unused)]

use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::VIEW_MAXIMIZED;
use std::rc::{Rc, Weak};
use std::fmt::{Debug, Formatter};
use std::fmt::Result as FmtResult;
use std::cell::RefCell;

pub type Node = Rc<RefCell<Container>>;

#[derive(Debug, Clone)]
enum Handle {
    View(WlcView),
    Output(WlcOutput)
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A Container, houses views and other containers
    Container,
    /// A view (window)
    View
}

/// Layout mode for a container
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

#[derive(Clone)]
pub struct Container {
    handle: Option<Handle>,
    parent: Option<Weak<RefCell<Container>>>,
    children: Vec<Node>,
    container_type: ContainerType,
    layout: Layout,
    width: u32,
    height: u32,
    x: i32,
    y: i32,
    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

/// Like i3, everything (workspaces, containers, views) are containable.
impl Container {

    /// Makes the root container. There should be only one of these
    /// Does not ensure that this is the only root container
    // NOTE Need to find a way to ensure there is only one of these things
    // Perhaps set a static global variable
    pub fn new_root() -> Node {
        trace!("Root created");
        Rc::new(RefCell::new(Container {
            handle: None,
            parent: None,
            children: vec!(),
            container_type: ContainerType::Root,
            layout: Layout::None,
            width: 0,
            height: 0,
            x: 0,
            y: 0,
            visible: false,
            is_focused: false,
            is_floating: false
        }))
    }

    /// Makes a new workspace container. This should only be called by root
    /// since it will properly initialize the right number and properly put
    /// them in the main tree.
    pub fn new_workspace(root: &mut Node) -> Node {
        if ! root.borrow().is_root() {
            panic!("Only workspaces can be added to the root node");
        }
        let workspace: Node =
            Rc::new(RefCell::new(Container {
                // NOTE Give this an output
                handle: None,
                parent: Some(Rc::downgrade(&root)),
                children: vec!(),
                container_type: ContainerType::Workspace,
                // NOTE Change this to some other default
                layout: Layout::None,
                // NOTE Figure out how to initialize these properly
                width: 0,
                height: 0,
                x: 0,
                y: 0,
                visible: false,
                is_focused: false,
                is_floating: false,
                }));
        root.borrow_mut().add_child(workspace.clone());
        workspace
    }

    /// Makes a new container. These hold views and other containers.
    /// Container hold information about specific parts of the tree in some
    /// workspace and the layout of the views within.
    pub fn new_container(parent_: &mut Node, output: WlcOutput) -> Node {
        let mut parent = parent_.borrow_mut();
        if parent.is_root() {
            panic!("Container cannot be a direct child of root");
        }
        let container = Rc::new(RefCell::new(Container {
            handle: Some(Handle::Output(output)),
            parent: Some(Rc::downgrade(&parent_)),
            children: vec!(),
            container_type: ContainerType::Container,
            // NOTE Get default, either from config or from workspace
            layout: Layout::None,
            // NOTE Get this information from somewhere, or set it later
            width: 0,
            height: 0,
            x: 0,
            y: 0,
            visible: false,
            is_focused: false,
            is_floating: false,
        }));
        parent.add_child(container.clone());
        container
    }

    /// Makes a new view. A view holds either a Wayland or an X Wayland window.
    pub fn new_view(parent_: &mut Node, view: WlcView) -> Node {
        let mut parent = parent_.borrow_mut();
        let geometry = view.get_geometry().unwrap().clone();
        if parent.is_root() {
            panic!("View cannot be a direct child of root");
        }
        let container = Rc::new(RefCell::new(Container {
            handle: Some(Handle::View(view)),
            parent: Some(Rc::downgrade(&parent_)),
            children: vec!(),
            container_type: ContainerType::View,
            layout: Layout::None,
            width: geometry.size.w,
            height: geometry.size.h,
            x: geometry.origin.x,
            y: geometry.origin.y,
            visible: false,
            is_focused: false,
            is_floating: false
        }));
        if parent.get_type() == ContainerType::Workspace {
            // Case of focused workspace, just create a child of it
            parent.add_child(container.clone());
        } else {
            // Regular case, create as sibling of current container
            parent.add_sibling(container.clone());
        }
        container
    }

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    pub fn get_parent(&self) -> Option<Node> {
        if self.is_root() {
            None
        } else {
            // NOTE Clone has to be done here because we have to store the
            // parent as an option since the `Weak::new` is unstable
            if let Some(parent) = self.parent.clone() {
                parent.upgrade()
            } else {
                None
            }
        }
    }

    pub fn add_child(&mut self, container: Node) {
        if self.get_type() == ContainerType::Workspace
            && container.borrow().get_type() == ContainerType::Workspace {
            panic!("Only containers can be children of a workspace");
        }
        // NOTE check to make sure we are not adding a duplicate
        self.children.push(container);
    }

    pub fn add_sibling(&mut self, container: Node) {
        if self.is_root() {
            panic!("Root has no sibling, cannot add sibling to root");
        }
        let parent = self.get_parent().unwrap();
        parent.borrow_mut().add_child(container);
    }

    /// Removes this container and all of its children.
    /// You MUST call this function while `borrow`ing, a mutable borrow will
    /// cause it to panic at run time
    pub fn remove_container(&self) -> Result<(), &'static str> {
        if self.is_root() {
            return Err("Cannot remove root container");
        } else if self.get_type() == ContainerType::Workspace  {
            return Err("Cannot remove workspace container");
        }
        if let Some(parent) = self.get_parent() {
            // NOTE Add check here to ensure we can borrow mutably once that
            // feature stabilizes
            parent.borrow_mut().remove_child(self);
        }
        Ok(())
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    pub fn get_children(&self) -> Option<&[Node]> {
        if self.get_type() == ContainerType::View {
            None
        }
        else {
            Some(self.children.as_slice())
        }
    }

    /// Gets the type of the container
    pub fn get_type(&self) -> ContainerType {
        self.container_type
    }

    /// Returns true if this container is focused.
    pub fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes the child at the specified index
    pub fn remove_child_at(&mut self, index: usize) -> Result<Node, &'static str> {
        // NOTE Add check here to ensure we can borrow once that
        // feature stabilizes
        if self.children[index].borrow().get_type() == ContainerType::Workspace {
            return Err("Cannot remove workspace")
        }
        Ok(self.children.remove(index))
    }

    /// Removes the given child from this container's children.
    /// If the child is not present, then an error is returned
    pub fn remove_child(&mut self, node: &Container) -> Result<Node, &'static str> {
        for (index, child) in self.children.clone().iter().enumerate() {
            // NOTE Add check here to ensure we can borrow once that
            // feature stabilizes
            if *child.borrow() == *node {
                if child.borrow().get_type() == ContainerType::Workspace {
                    return Err("Can not remove workspace");
                }
                return Ok(self.children.remove(index));
            }
        }
        return Err("Could not find child in container");//format!("Could not find child {:?} in {:?}", node, self));
    }

    /// Sets this container (and everything in it) to given visibility
    pub fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the visibility of the container
    pub fn get_visibility(&self) -> bool {
        self.visible
    }

    /// Gets the X and Y dimensions of the container
    pub fn get_dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    pub fn get_position(&self) -> (i32, i32) {
        (self.x, self.y)
    }

    /// Returns true if this container is a parent of the child
    pub fn is_parent_of(&self, child: Node) -> bool {
        if self.is_root() {
            true
        } else {
            while ! child.borrow().is_root() {
                let parent = child.borrow().get_parent().unwrap();
                if child == parent {
                    return true
                }
            }
            return false;
        }
    }

    /// Returns true if this container is a child is an decedent of the parent
    pub fn is_child_of(&self, parent: Node) -> bool {
        parent.borrow().is_parent_of(Rc::new(RefCell::new(self.clone())))
    }

    pub fn is_root(&self) -> bool {
        self.get_type() == ContainerType::Root
    }

    /// Finds a parent container with the given type, if there is any
    pub fn get_parent_by_type(&self, container_type: ContainerType) -> Option<Node> {
        let mut container = self.get_parent();
        loop {
            if let Some(parent) = container {
                if parent.borrow().get_type() == container_type {
                    return Some(parent);
                }
                container = parent.borrow().get_parent();
            } else {
                return None;
            }
        }
    }
}

impl PartialEq for Container {
    fn eq(&self, other: &Container) -> bool {
        self.get_type() == other.get_type()
    }
}

impl Eq for Container { }

impl Debug for Container {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        f.debug_struct("Containable")
            .field("type", &self.get_type())
            //.field("parent", &self.get_parent())
            .field("children", &self.get_children())
            .field("focused", &self.is_focused())
            .finish()
    }
}
<|endoftext|>


<commit_before><commit_msg>handle docs that don't use spaces in doc comments<commit_after><|endoftext|>


<commit_before>use std::fs::File;
use std::path::{ Path, PathBuf };

use download;
use extract;
use verify;
use find_package;
use find_package::Package;

fn _install_package(package: &Package, path: &Path) -> Result<bool, String> {
    let mut download_path = PathBuf::new();
        download_path.push(path);
        download_path.push(format!("download/{}", package.name));

    if !download_path.exists() {
        try!(download::download_file(&package.url, download_path.as_path()));
    }

    let mut tar_path = PathBuf::new();
        tar_path.push(path);
        tar_path.push(format!("download/{}.tar", package.name));

    if !tar_path.exists() {
        try!(extract::extract_gz(download_path.as_path(), tar_path.as_path()));
    }

    let mut install_path = PathBuf::new();
        tar_path.push(path);
        tar_path.push(format!("install/{}", package.name));

    if !install_path.exists() {
        try!(extract::extract_tar(tar_path.as_path(), install_path.as_path()));
    }

    return Ok(true)
}

pub fn install_package(name: &str, path: &Path) -> Result<bool, String> {
    let found_packages = try!(find_package::find_package(name, path));

    if !found_packages.is_empty() && found_packages.len() > 1 {
        for (i, package) in found_packages.iter().enumerate() {
            let mut install_path = PathBuf::new();
                install_path.push(path);
                install_path.push(format!("installed/{}", package.name));

            if !install_path.exists() {
                println!("Package {}: {}", i, package.name);
            }
        }

        //TODO: Accept user input and install user-chosen package.
        return _install_package(&found_packages[0], path)
    } else {
        return _install_package(&found_packages[0], path)
    }
}
<commit_msg>Return false if package is already installed<commit_after>use std::fs::File;
use std::path::{ Path, PathBuf };

use download;
use extract;
use verify;
use find_package;
use find_package::Package;

fn _install_package(package: &Package, path: &Path) -> Result<bool, String> {
    let mut download_path = PathBuf::new();
        download_path.push(path);
        download_path.push(format!("download/{}", package.name));

    if !download_path.exists() {
        try!(download::download_file(&package.url, download_path.as_path()));
    }

    let mut tar_path = PathBuf::new();
        tar_path.push(path);
        tar_path.push(format!("download/{}.tar", package.name));

    if !tar_path.exists() {
        try!(extract::extract_gz(download_path.as_path(), tar_path.as_path()));
    }

    let mut install_path = PathBuf::new();
        tar_path.push(path);
        tar_path.push(format!("install/{}", package.name));

    if !install_path.exists() {
        try!(extract::extract_tar(tar_path.as_path(), install_path.as_path()));
    } else {
        return Ok(false)
    }

    return Ok(true)
}

pub fn install_package(name: &str, path: &Path) -> Result<bool, String> {
    let found_packages = try!(find_package::find_package(name, path));

    if !found_packages.is_empty() && found_packages.len() > 1 {
        for (i, package) in found_packages.iter().enumerate() {
            let mut install_path = PathBuf::new();
                install_path.push(path);
                install_path.push(format!("installed/{}", package.name));

            if !install_path.exists() {
                println!("Package {}: {}", i, package.name);
            }
        }

        //TODO: Accept user input and install user-chosen package.
        return _install_package(&found_packages[0], path)
    } else {
        return _install_package(&found_packages[0], path)
    }
}
<|endoftext|>


<commit_before>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use extra::getopts;

struct Shell {
    cmd_prompt: ~str,
    history: ~[~str],
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            history: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");
            self.history.push(cmd_line.clone());
            match program.slice_from(program.len() - 2) {
                " &"    => { self.run_background(program, cmd_line); }
                _       => { continue; }
            }
            match program {
                ""           =>  { continue; }
                "exit"       =>  { return; }
		        "cd"	     =>  { self.run_cd(cmd_line); }
                "history"    =>  { self.run_history(); }
                _            =>  { self.run_cmdline(cmd_line); }
            }
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {
            let program: ~str = argv.remove(0);
            self.run_cmd(program, argv);
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str]) {
        if self.cmd_exists(program) {
            run::process_status(program, argv);
        } else {
            println!("{:s}: command not found", program);
        }
    }

    fn run_cd(&mut self, program: &str) {
        let mut argv: ~[~str] =
            program.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

    	let mut programs : ~str = ~"";
            if argv.len() > 0 {
                programs = argv.remove(1);
            }
    	os::change_dir(&Path::new(programs.clone()));
    }

    fn run_history(&mut self) {
        for c in range(0, self.history.len()) {
            println!("{:s}", self.history[c]);
        }
    }

    fn run_background(&mut self, program: &str, cmd_line: &str) {
            spawn(proc() {
                match program {
                    ""           =>  { }
                    "exit"       =>  { return; }
                    "cd"         =>  { self.run_cd(cmd_line); }
                    "history"    =>  { self.run_history(); }
                    _            =>  { self.run_cmdline(cmd_line); }
                }
            });
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<commit_msg>Run in background works I guess<commit_after>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use extra::getopts;

struct Shell {
    cmd_prompt: ~str,
    history: ~[~str],
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
            history: ~[],
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");
            self.history.push(cmd_line.clone());
            match cmd_line.slice_from(cmd_line.len() - 2) {
                " &"    => { self.run_background(program, cmd_line);
				continue; }
                _       => { }
            }
            match program {
		""           =>  { continue; }
		"exit"       =>  { return; }
		"cd"	     =>  { self.run_cd(cmd_line); }
		"history"    =>  { self.run_history(); }
		_            =>  { self.run_cmdline(cmd_line); }
            }
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {
            let program: ~str = argv.remove(0);
            self.run_cmd(program, argv);
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str]) {
        if self.cmd_exists(program) {
            run::process_status(program, argv);
        } else {
            println!("{:s}: command not found", program);
        }
    }

    fn run_cd(&mut self, program: &str) {
        let mut argv: ~[~str] =
            program.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

    	let mut programs : ~str = ~"";
            if argv.len() > 0 {
                programs = argv.remove(1);
            }
    	os::change_dir(&Path::new(programs.clone()));
    }

    fn run_history(&mut self) {
        for c in range(0, self.history.len()) {
            println!("{:s}", self.history[c]);
        }
    }

    fn run_background(&mut self, program: &str, cmd_line: &str) {
		let (portSelf, chanSelf): (Port<~Shell>, Chan<~Shell>) = Chan::new();
		let (portProg, chanProg): (Port<~str>, Chan<~str>) = Chan::new();
		let (portLine, chanLine): (Port<~str>, Chan<~str>) = Chan::new();

		chanSelf.send(~(Shell::new("gash > ")));
		chanProg.send(program.to_owned());
		chanLine.send(cmd_line.to_owned());
            do spawn {
		let program : ~str = portProg.recv();
		let cmd_line : ~str = portLine.recv();
		let mut selfV : ~Shell = portSelf.recv();
                match program {
             	   ~""           =>  { }
              	  ~"exit"       =>  { }
		  ~"cd"	     =>  { selfV.run_cd(cmd_line); }
                  ~"history"    =>  { selfV.run_history(); }
                  _            =>  { selfV.run_cmdline(cmd_line); }
                }
            };
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
                                                Some(cmd_str) => {cmd_str.to_owned()},
                                                None => {~""}
                                              };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<|endoftext|>


<commit_before>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use extra::getopts;
use std::io::File;
// use std::run::Process;
// use std::run::ProcessOptions;
// use std::libc;
// extra::future;
// use std::task::task;

struct Shell {
    cmd_prompt: ~str,
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());
        let mut cmd_history = ~[];

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");
            let args = cmd_line.split(' ').skip(1);

            cmd_history.push(cmd_line.clone());

            match args.clone().last() {
                Some("&") => {
                    let arg_list: ~[~str] =
                        args.clone().filter_map(|x| if x != "&" { Some(x.to_owned()) } else { None }).to_owned_vec();
                    let prog = program.to_owned();
                    spawn(proc() { run::process_status(prog, arg_list); });
                    continue;
                }
                _ => {}
            }

            // fix needed: support for command ./zhttpto > zlog.txt &
            let mut iter = args.clone();
            match iter.find(|&x| x==">") {
                Some(">") => {
                    let mut arg_list: ~[~str] = ~[];
                    args.clone().advance(|x| if x != ">" { arg_list.push(x.to_owned()); true } else { false });
                    let buffer = run::process_output(program, arg_list);
                    let path = &Path::new(iter.next().unwrap());
                    let output = File::open_mode(path, io::Truncate, io::Write);
                    match output {
                        Some(mut file) => file.write(buffer.unwrap().output),
                        None => fail!("Error: Could not write to file.")
                    }
                    continue;
                }
                _ => {}
            }

            // note: ambiguity on stdin redirection
            let mut iter = args.clone();
            match iter.find(|&x| x=="<") {
                Some("<") => {
                    let mut arg_list: ~[~str] = ~[];
                    args.clone().advance(|x| if x != "<" { arg_list.push(x.to_owned()); true } else { false });
                    // let file = File::open(&Path::new(iter.next().unwrap()));
                    // match file {
                    //     Some(f) => arg_list.push(f),
                    //     _ => fail!("Error: File not found")
                    // }
                    arg_list.push(iter.next().unwrap().to_owned());
                    run::process_status(program, arg_list);
                    continue;
                }
                _ => {}
            }

            let mut iter = args.clone();
            match iter.find(|&x| x=="|") {
                Some("|") => {
                    let mut arg_list: ~[~str] = ~[];
                    args.clone().advance(|x| if x != "|" { arg_list.push(x.to_owned()); true } else { false });
                    let buffer = run::process_output(program, arg_list);
                    let target = iter.next().unwrap();
                    arg_list = ~[];
                    iter.advance(|x| if x != "" { arg_list.push(x.to_owned()); true } else { false });
                    arg_list.push(std::str::from_utf8_owned(buffer.unwrap().output));
                    run::process_status(target, arg_list);
                    continue;
                }
                _ => {}
            }

            match program {
                ""      =>  { continue; }
                "exit"  =>  { return; }
                "cd"    =>  { self.cd(cmd_line); }
                "history"    =>  { self.history(cmd_history.clone()); }
                _       =>  { self.run_cmdline(cmd_line); }
            }
        }
    }

    fn history(&mut self, cmd_history: ~[~str]) {
        for i in range(0, cmd_history.len()) {
            println!("   {}  {:s}", i+1, cmd_history[i]);
        }
    }

    fn cd(&mut self,  cmd_line: &str) {
        let argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 1 {
            let path = &Path::new(argv[1]);
            //println!("path: {}", path.display());
            os::change_dir(path);
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {
            let program: ~str = argv.remove(0);
            self.run_cmd(program, argv);
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str]) {
        if self.cmd_exists(program) {
            run::process_status(program, argv);
        } else {
            println!("{:s}: command not found", program);
        }
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
            Some(cmd_str) => {cmd_str.to_owned()},
            None => {~""}
        };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}
<commit_msg>redone<commit_after>//
// gash.rs
//
// Starting code for PS2
// Running on Rust 0.9
//
// University of Virginia - cs4414 Spring 2014
// Weilin Xu, David Evans
// Version 0.4
//

extern mod extra;

use std::{io, run, os};
use std::io::buffered::BufferedReader;
use std::io::stdin;
use extra::getopts;
use std::io::File;
use std::io::signal::Listener;
use std::io::signal::Interrupt;

struct Shell {
    cmd_prompt: ~str,
}

impl Shell {
    fn new(prompt_str: &str) -> Shell {
        Shell {
            cmd_prompt: prompt_str.to_owned(),
        }
    }

    fn run(&mut self) {
        let mut stdin = BufferedReader::new(stdin());
        let mut cmd_history = ~[];

        loop {
            print(self.cmd_prompt);
            io::stdio::flush();

            let line = stdin.read_line().unwrap();
            let cmd_line = line.trim().to_owned();
            let program = cmd_line.splitn(' ', 1).nth(0).expect("no program");
            let args = cmd_line.split(' ').skip(1);

            cmd_history.push(cmd_line.clone());

            match program {
                ""      =>  { continue; }
                "exit"  =>  { return; }
                "cd"    =>  { self.cd(cmd_line); }
                "history"    =>  { self.history(cmd_history.clone()); }
                _ => {}
            }

            match args.clone().last() {
                Some("&") => {
                    spawn(proc() {
                        let mut listener = Listener::new();
                        listener.register(Interrupt);
                        loop {
                            match listener.port.recv() {
                                Interrupt => (),
                                _ => (),
                            }
                        }
                    });
                    println("found & symbol");
                    let mut iter = args.clone();
                    let mut past = ~[];
                    let mut prog = program;
                    loop {
                        let token = iter.next();
                        let x = token.unwrap();
                        if x == "&" {
                            // let prog2 = prog;
                            // let past2 = past;
                            // spawn(proc() { run::process_status(prog2, past2) });
                            break;
                        }
                        match x {
                            "<" => {
                                let mut arg_list: ~[~str] = past.clone();
                                arg_list.push(iter.next().unwrap().to_owned());
                                let buffer = run::process_output(prog, arg_list);
                                past = ~[];
                                past.push(std::str::from_utf8_owned(buffer.unwrap().output));
                                continue;
                            }
                            ">" => {
                                let arg_list: ~[~str] = past.clone();
                                let buffer = run::process_output(prog, arg_list);
                                let path = &Path::new(iter.next().unwrap());
                                let output = File::open_mode(path, io::Truncate, io::Write);
                                match output {
                                    Some(mut file) => file.write(buffer.unwrap().output),
                                    None => fail!("Error: Could not write to file.")
                                }
                                continue;
                            }
                            "|" => {
                                println("found | symbol");
                                let arg_list: ~[~str] = past.clone();
                                let buffer = run::process_output(prog, arg_list);
                                past = ~[];
                                past.push(std::str::from_utf8_owned(buffer.unwrap().output));
                                prog = iter.next().unwrap();
                                continue;
                            }
                            _ => past.push(x.to_owned())
                        }
                    }
                    continue;
                }
                _ => {
                    let mut iter = args.clone();
                    let mut past = ~[];
                    let mut prog = program;
                    loop {
                        let token = iter.next();
                        if token == None {
                            run::process_status(prog, past);
                            break;
                        }
                        let x = token.unwrap();
                        match x {
                            "<" => {
                                let mut arg_list: ~[~str] = past.clone();
                                let y = iter.next().unwrap();
                                print("filename: ");
                                println(y);
                                arg_list.push(y.to_owned());
                                // let buffer = run::process_output(prog, arg_list);
                                // past = ~[];
                                // past.push(std::str::from_utf8_owned(buffer.unwrap().output));
                                continue;
                            }
                            ">" => {
                                let arg_list: ~[~str] = past.clone();
                                let buffer = run::process_output(prog, arg_list);
                                let path = &Path::new(iter.next().unwrap());
                                let output = File::open_mode(path, io::Truncate, io::Write);
                                match output {
                                    Some(mut file) => file.write(buffer.unwrap().output),
                                    None => fail!("Error: Could not write to file.")
                                }
                                continue;
                            }
                            "|" => {
                                let arg_list: ~[~str] = past.clone();
                                let buffer = run::process_output(prog, arg_list);
                                past = ~[];
                                let path = &Path::new("temp.txt");
                                File::create(path).write(buffer.unwrap().output);
                                past.push(~"temp.txt");
                                prog = iter.next().unwrap();
                                continue;
                            }
                            _ => past.push(x.to_owned())
                        }
                    }
                    continue;
                }
            }

        }
    }

    fn history(&mut self, cmd_history: ~[~str]) {
        for i in range(0, cmd_history.len()) {
            println!("   {}  {:s}", i+1, cmd_history[i]);
        }
    }

    fn cd(&mut self,  cmd_line: &str) {
        let argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 1 {
            let path = &Path::new(argv[1]);
            os::change_dir(path);
        }
    }

    fn run_cmdline(&mut self, cmd_line: &str) {
        let mut argv: ~[~str] =
            cmd_line.split(' ').filter_map(|x| if x != "" { Some(x.to_owned()) } else { None }).to_owned_vec();

        if argv.len() > 0 {
            let program: ~str = argv.remove(0);
            self.run_cmd(program, argv);
        }
    }

    fn run_cmd(&mut self, program: &str, argv: &[~str]) {
        if self.cmd_exists(program) {
            println("running command line");
            run::process_status(program, argv);
        } else {
            println!("{:s}: command not found", program);
        }
    }

    fn cmd_exists(&mut self, cmd_path: &str) -> bool {
        let ret = run::process_output("which", [cmd_path.to_owned()]);
        return ret.expect("exit code error.").status.success();
    }
}

fn get_cmdline_from_args() -> Option<~str> {
    /* Begin processing program arguments and initiate the parameters. */
    let args = os::args();

    let opts = ~[
        getopts::optopt("c")
    ];

    let matches = match getopts::getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_err_msg()) }
    };

    if matches.opt_present("c") {
        let cmd_str = match matches.opt_str("c") {
            Some(cmd_str) => {cmd_str.to_owned()},
            None => {~""}
        };
        return Some(cmd_str);
    } else {
        return None;
    }
}

fn main() {
    let opt_cmd_line = get_cmdline_from_args();

    match opt_cmd_line {
        Some(cmd_line) => Shell::new("").run_cmdline(cmd_line),
        None           => Shell::new("gash > ").run()
    }
}<|endoftext|>


<commit_before>use std::libc::*;
use rt = std::rt;
use cast = std::cast;

use ffi::*;

static mut global_main_func: Option<extern fn()> = None;

pub fn run(argc: int, argv: **u8, main_func: extern fn()) -> int
{
	unsafe
	{
		global_main_func = Some(main_func);
		al_run_main(argc as c_int, cast::transmute(argv), cast::transmute(allegro_main)) as int
	}
}

extern "C"
fn allegro_main(argc: int, argv: **u8) -> c_int
{
	rt::start(argc, argv, rust_main) as c_int
}

fn rust_main()
{
	unsafe
	{
		(global_main_func.unwrap())();
		al_uninstall_system();
	}
}
<commit_msg>Swithc to native::start... hopefully it works<commit_after>extern mod native;

use std::libc::*;
use cast = std::cast;

use ffi::*;

static mut global_main_func: Option<extern fn()> = None;

pub fn run(argc: int, argv: **u8, main_func: extern fn()) -> int
{
	unsafe
	{
		global_main_func = Some(main_func);
		al_run_main(argc as c_int, cast::transmute(argv), cast::transmute(allegro_main)) as int
	}
}

extern "C"
fn allegro_main(argc: int, argv: **u8) -> c_int
{
	native::start(argc, argv, rust_main) as c_int
}

fn rust_main()
{
	unsafe
	{
		(global_main_func.unwrap())();
		al_uninstall_system();
	}
}
<|endoftext|>


<commit_before><commit_msg>Fix a new compile-time warning<commit_after><|endoftext|>


<commit_before>/*! A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 *
 * All represented positions are *absolute* positions within the codemap,
 * not relative positions within a single file.
 */

use dvec::DVec;
use std::serialization::{Serializable,
                         Deserializable,
                         Serializer,
                         Deserializer};

trait Pos {
    static pure fn from_uint(n: uint) -> self;
    pure fn to_uint(&self) -> uint;
}

pub enum BytePos = uint;
pub enum CharPos = uint;

impl BytePos: Pos {
    static pure fn from_uint(n: uint) -> BytePos { BytePos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl BytePos: cmp::Eq {
    pure fn eq(other: &BytePos) -> bool {
        *self == **other
    }
    pure fn ne(other: &BytePos) -> bool { !self.eq(other) }
}

impl BytePos: cmp::Ord {
    pure fn lt(other: &BytePos) -> bool { *self < **other }
    pure fn le(other: &BytePos) -> bool { *self <= **other }
    pure fn ge(other: &BytePos) -> bool { *self >= **other }
    pure fn gt(other: &BytePos) -> bool { *self > **other }
}

impl BytePos: Num {
    pure fn add(other: &BytePos) -> BytePos {
        BytePos(*self + **other)
    }
    pure fn sub(other: &BytePos) -> BytePos {
        BytePos(*self - **other)
    }
    pure fn mul(other: &BytePos) -> BytePos {
        BytePos(*self * (**other))
    }
    pure fn div(other: &BytePos) -> BytePos {
        BytePos(*self / **other)
    }
    pure fn modulo(other: &BytePos) -> BytePos {
        BytePos(*self % **other)
    }
    pure fn neg() -> BytePos {
        BytePos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> BytePos { BytePos(n as uint) }
}

impl BytePos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

impl CharPos: Pos {
    static pure fn from_uint(n: uint) -> CharPos { CharPos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl CharPos: cmp::Eq {
    pure fn eq(other: &CharPos) -> bool {
        *self == **other
    }
    pure fn ne(other: &CharPos) -> bool { !self.eq(other) }
}

impl CharPos: cmp::Ord {
    pure fn lt(other: &CharPos) -> bool { *self < **other }
    pure fn le(other: &CharPos) -> bool { *self <= **other }
    pure fn ge(other: &CharPos) -> bool { *self >= **other }
    pure fn gt(other: &CharPos) -> bool { *self > **other }
}

impl CharPos: Num {
    pure fn add(other: &CharPos) -> CharPos {
        CharPos(*self + **other)
    }
    pure fn sub(other: &CharPos) -> CharPos {
        CharPos(*self - **other)
    }
    pure fn mul(other: &CharPos) -> CharPos {
        CharPos(*self * (**other))
    }
    pure fn div(other: &CharPos) -> CharPos {
        CharPos(*self / **other)
    }
    pure fn modulo(other: &CharPos) -> CharPos {
        CharPos(*self % **other)
    }
    pure fn neg() -> CharPos {
        CharPos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> CharPos { CharPos(n as uint) }
}

impl CharPos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

pub struct span {
    lo: CharPos,
    hi: CharPos,
    expn_info: Option<@ExpnInfo>
}

impl span : cmp::Eq {
    pure fn eq(other: &span) -> bool {
        return self.lo == (*other).lo && self.hi == (*other).hi;
    }
    pure fn ne(other: &span) -> bool { !self.eq(other) }
}

impl<S: Serializer> span: Serializable<S> {
    /* Note #1972 -- spans are serialized but not deserialized */
    fn serialize(&self, _s: &S) { }
}

impl<D: Deserializer> span: Deserializable<D> {
    static fn deserialize(_d: &D) -> span {
        ast_util::dummy_sp()
    }
}

pub struct Loc<A: Pos> {
    file: @FileMap, line: uint, col: A
}

/// An absolute offset within the CodeMap (not a relative offset within a
/// a single FileMap)
pub struct FilePos {
    ch: CharPos, byte: BytePos
}

impl FilePos : cmp::Eq {
    pure fn eq(other: &FilePos) -> bool {
        self.ch == (*other).ch && self.byte == (*other).byte
    }
    pure fn ne(other: &FilePos) -> bool { !self.eq(other) }
}

pub enum ExpnInfo {
    ExpandedFrom({call_site: span,
                  callie: {name: ~str, span: Option<span>}})
}

pub type FileName = ~str;

pub type LookupFn = pure fn(FilePos) -> uint;

pub struct FileLines {
    file: @FileMap,
    lines: ~[uint]
}

pub enum FileSubstr {
    pub FssNone,
    pub FssInternal(span),
    pub FssExternal({filename: ~str, line: uint, col: CharPos})
}

pub struct FileMap {
    name: FileName,
    substr: FileSubstr,
    src: @~str,
    start_pos: FilePos,
    mut lines: ~[FilePos]
}

pub impl FileMap {
    static fn new_w_substr(+filename: FileName, +substr: FileSubstr,
                           src: @~str,
                           +start_pos: FilePos)
        -> FileMap {
        return FileMap {
            name: filename, substr: substr, src: src,
            start_pos: start_pos,
            mut lines: ~[]
        };
    }

    static fn new(+filename: FileName, src: @~str,
                  +start_pos: FilePos)
        -> FileMap {
        return FileMap::new_w_substr(filename, FssNone, src,
                                     start_pos);
    }

    fn next_line(&self, +pos: FilePos) {
        self.lines.push(pos);
    }

    pub fn get_line(&self, line: int) -> ~str unsafe {
        let begin: BytePos = self.lines[line].byte - self.start_pos.byte;
        let begin = begin.to_uint();
        let end = match str::find_char_from(*self.src, '\n', begin) {
            Some(e) => e,
            None => str::len(*self.src)
        };
        str::slice(*self.src, begin, end)
    }

}

pub struct CodeMap {
    files: DVec<@FileMap>
}

pub impl CodeMap {
    static pub fn new() -> CodeMap {
        CodeMap {
            files: DVec()
        }
    }

    pub fn add_filemap(&self, filemap: @FileMap) {
        let expected_byte_pos = if self.files.len() == 0 {
            0
        } else {
            let last_start = self.files.last().start_pos.byte.to_uint();
            let last_len = self.files.last().src.len();
            last_start + last_len
        };
        let actual_byte_pos = filemap.start_pos.byte.to_uint();
        debug!("codemap: adding filemap: %s", filemap.name);
        debug!("codemap: expected offset: %u", expected_byte_pos);
        debug!("codemap: actual offset: %u", actual_byte_pos);
        assert expected_byte_pos == actual_byte_pos;
        self.files.push(filemap);
    }

    pub fn mk_substr_filename(&self, sp: span) -> ~str {
        let pos = self.lookup_char_pos(sp.lo);
        return fmt!("<%s:%u:%u>", pos.file.name,
                    pos.line, pos.col.to_uint());
    }

    pub fn lookup_char_pos(&self, +pos: CharPos) -> Loc<CharPos> {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        return self.lookup_pos(pos, lookup);
    }

    pub fn lookup_byte_pos(&self, +pos: BytePos) -> Loc<BytePos> {
        pure fn lookup(pos: FilePos) -> uint { return pos.byte.to_uint(); }
        return self.lookup_pos(pos, lookup);
    }

    pub fn lookup_char_pos_adj(&self, +pos: CharPos)
        -> {filename: ~str, line: uint, col: CharPos, file: Option<@FileMap>}
    {
        let loc = self.lookup_char_pos(pos);
        match (loc.file.substr) {
            FssNone => {
                {filename: /* FIXME (#2543) */ copy loc.file.name,
                 line: loc.line,
                 col: loc.col,
                 file: Some(loc.file)}
            }
            FssInternal(sp) => {
                self.lookup_char_pos_adj(
                    sp.lo + (pos - loc.file.start_pos.ch))
            }
            FssExternal(eloc) => {
                {filename: /* FIXME (#2543) */ copy eloc.filename,
                 line: eloc.line + loc.line - 1u,
                 col: if loc.line == 1u {eloc.col + loc.col} else {loc.col},
                 file: None}
            }
        }
    }

    pub fn adjust_span(&self, sp: span) -> span {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        let line = self.lookup_line(sp.lo, lookup);
        match (line.fm.substr) {
            FssNone => sp,
            FssInternal(s) => {
                self.adjust_span(span {
                    lo: s.lo + (sp.lo - line.fm.start_pos.ch),
                    hi: s.lo + (sp.hi - line.fm.start_pos.ch),
                    expn_info: sp.expn_info
                })
            }
            FssExternal(_) => sp
        }
    }

    pub fn span_to_str(&self, sp: span) -> ~str {
        let lo = self.lookup_char_pos_adj(sp.lo);
        let hi = self.lookup_char_pos_adj(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.filename,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }

    pub fn span_to_filename(&self, sp: span) -> FileName {
        let lo = self.lookup_char_pos(sp.lo);
        return /* FIXME (#2543) */ copy lo.file.name;
    }

    pub fn span_to_lines(&self, sp: span) -> @FileLines {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        let mut lines = ~[];
        for uint::range(lo.line - 1u, hi.line as uint) |i| {
            lines.push(i);
        };
        return @FileLines {file: lo.file, lines: lines};
    }

    fn lookup_byte_offset(&self, +chpos: CharPos)
        -> {fm: @FileMap, pos: BytePos} {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        let {fm, line} = self.lookup_line(chpos, lookup);
        let line_offset = fm.lines[line].byte - fm.start_pos.byte;
        let col = chpos - fm.lines[line].ch;
        let col_offset = str::count_bytes(*fm.src,
                                          line_offset.to_uint(),
                                          col.to_uint());
        {fm: fm, pos: line_offset + BytePos(col_offset)}
    }

    pub fn span_to_snippet(&self, sp: span) -> ~str {
        let begin = self.lookup_byte_offset(sp.lo);
        let end = self.lookup_byte_offset(sp.hi);
        assert begin.fm.start_pos == end.fm.start_pos;
        return str::slice(*begin.fm.src,
                          begin.pos.to_uint(), end.pos.to_uint());
    }

    pub fn get_filemap(&self, filename: ~str) -> @FileMap {
        for self.files.each |fm| { if fm.name == filename { return *fm; } }
        //XXjdm the following triggers a mismatched type bug
        //      (or expected function, found _|_)
        fail; // ("asking for " + filename + " which we don't know about");
    }

}

priv impl CodeMap {
    fn lookup_line<A: Pos>(&self, pos: A, lookup: LookupFn)
        -> {fm: @FileMap, line: uint}
    {
        let len = self.files.len();
        let mut a = 0u;
        let mut b = len;
        while b - a > 1u {
            let m = (a + b) / 2u;
            if lookup(self.files[m].start_pos) > pos.to_uint() {
                b = m;
            } else {
                a = m;
            }
        }
        if (a >= len) {
            fail fmt!("position %u does not resolve to a source location",
                      pos.to_uint())
        }
        let f = self.files[a];
        a = 0u;
        b = vec::len(f.lines);
        while b - a > 1u {
            let m = (a + b) / 2u;
            if lookup(f.lines[m]) > pos.to_uint() { b = m; } else { a = m; }
        }
        return {fm: f, line: a};
    }

    fn lookup_pos<A: Pos Num>(&self, pos: A, lookup: LookupFn) -> Loc<A> {
        let {fm: f, line: a} = self.lookup_line(pos, lookup);
        return Loc {
            file: f,
            line: a + 1u,
            col: pos - from_uint(lookup(f.lines[a]))
        };
    }

    fn span_to_str_no_adj(&self, sp: span) -> ~str {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.file.name,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<commit_msg>Remove CodeMap.lookup_byte_pos<commit_after>/*! A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 *
 * All represented positions are *absolute* positions within the codemap,
 * not relative positions within a single file.
 */

use dvec::DVec;
use std::serialization::{Serializable,
                         Deserializable,
                         Serializer,
                         Deserializer};

trait Pos {
    static pure fn from_uint(n: uint) -> self;
    pure fn to_uint(&self) -> uint;
}

pub enum BytePos = uint;
pub enum CharPos = uint;

impl BytePos: Pos {
    static pure fn from_uint(n: uint) -> BytePos { BytePos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl BytePos: cmp::Eq {
    pure fn eq(other: &BytePos) -> bool {
        *self == **other
    }
    pure fn ne(other: &BytePos) -> bool { !self.eq(other) }
}

impl BytePos: cmp::Ord {
    pure fn lt(other: &BytePos) -> bool { *self < **other }
    pure fn le(other: &BytePos) -> bool { *self <= **other }
    pure fn ge(other: &BytePos) -> bool { *self >= **other }
    pure fn gt(other: &BytePos) -> bool { *self > **other }
}

impl BytePos: Num {
    pure fn add(other: &BytePos) -> BytePos {
        BytePos(*self + **other)
    }
    pure fn sub(other: &BytePos) -> BytePos {
        BytePos(*self - **other)
    }
    pure fn mul(other: &BytePos) -> BytePos {
        BytePos(*self * (**other))
    }
    pure fn div(other: &BytePos) -> BytePos {
        BytePos(*self / **other)
    }
    pure fn modulo(other: &BytePos) -> BytePos {
        BytePos(*self % **other)
    }
    pure fn neg() -> BytePos {
        BytePos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> BytePos { BytePos(n as uint) }
}

impl BytePos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

impl CharPos: Pos {
    static pure fn from_uint(n: uint) -> CharPos { CharPos(n) }
    pure fn to_uint(&self) -> uint { **self }
}

impl CharPos: cmp::Eq {
    pure fn eq(other: &CharPos) -> bool {
        *self == **other
    }
    pure fn ne(other: &CharPos) -> bool { !self.eq(other) }
}

impl CharPos: cmp::Ord {
    pure fn lt(other: &CharPos) -> bool { *self < **other }
    pure fn le(other: &CharPos) -> bool { *self <= **other }
    pure fn ge(other: &CharPos) -> bool { *self >= **other }
    pure fn gt(other: &CharPos) -> bool { *self > **other }
}

impl CharPos: Num {
    pure fn add(other: &CharPos) -> CharPos {
        CharPos(*self + **other)
    }
    pure fn sub(other: &CharPos) -> CharPos {
        CharPos(*self - **other)
    }
    pure fn mul(other: &CharPos) -> CharPos {
        CharPos(*self * (**other))
    }
    pure fn div(other: &CharPos) -> CharPos {
        CharPos(*self / **other)
    }
    pure fn modulo(other: &CharPos) -> CharPos {
        CharPos(*self % **other)
    }
    pure fn neg() -> CharPos {
        CharPos(-*self)
    }
    pure fn to_int() -> int { *self as int }
    static pure fn from_int(+n: int) -> CharPos { CharPos(n as uint) }
}

impl CharPos: to_bytes::IterBytes {
    pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
        (*self).iter_bytes(lsb0, f)
    }
}

pub struct span {
    lo: CharPos,
    hi: CharPos,
    expn_info: Option<@ExpnInfo>
}

impl span : cmp::Eq {
    pure fn eq(other: &span) -> bool {
        return self.lo == (*other).lo && self.hi == (*other).hi;
    }
    pure fn ne(other: &span) -> bool { !self.eq(other) }
}

impl<S: Serializer> span: Serializable<S> {
    /* Note #1972 -- spans are serialized but not deserialized */
    fn serialize(&self, _s: &S) { }
}

impl<D: Deserializer> span: Deserializable<D> {
    static fn deserialize(_d: &D) -> span {
        ast_util::dummy_sp()
    }
}

pub struct Loc<A: Pos> {
    file: @FileMap, line: uint, col: A
}

/// An absolute offset within the CodeMap (not a relative offset within a
/// a single FileMap)
pub struct FilePos {
    ch: CharPos, byte: BytePos
}

impl FilePos : cmp::Eq {
    pure fn eq(other: &FilePos) -> bool {
        self.ch == (*other).ch && self.byte == (*other).byte
    }
    pure fn ne(other: &FilePos) -> bool { !self.eq(other) }
}

pub enum ExpnInfo {
    ExpandedFrom({call_site: span,
                  callie: {name: ~str, span: Option<span>}})
}

pub type FileName = ~str;

pub type LookupFn = pure fn(FilePos) -> uint;

pub struct FileLines {
    file: @FileMap,
    lines: ~[uint]
}

pub enum FileSubstr {
    pub FssNone,
    pub FssInternal(span),
    pub FssExternal({filename: ~str, line: uint, col: CharPos})
}

pub struct FileMap {
    name: FileName,
    substr: FileSubstr,
    src: @~str,
    start_pos: FilePos,
    mut lines: ~[FilePos]
}

pub impl FileMap {
    static fn new_w_substr(+filename: FileName, +substr: FileSubstr,
                           src: @~str,
                           +start_pos: FilePos)
        -> FileMap {
        return FileMap {
            name: filename, substr: substr, src: src,
            start_pos: start_pos,
            mut lines: ~[]
        };
    }

    static fn new(+filename: FileName, src: @~str,
                  +start_pos: FilePos)
        -> FileMap {
        return FileMap::new_w_substr(filename, FssNone, src,
                                     start_pos);
    }

    fn next_line(&self, +pos: FilePos) {
        self.lines.push(pos);
    }

    pub fn get_line(&self, line: int) -> ~str unsafe {
        let begin: BytePos = self.lines[line].byte - self.start_pos.byte;
        let begin = begin.to_uint();
        let end = match str::find_char_from(*self.src, '\n', begin) {
            Some(e) => e,
            None => str::len(*self.src)
        };
        str::slice(*self.src, begin, end)
    }

}

pub struct CodeMap {
    files: DVec<@FileMap>
}

pub impl CodeMap {
    static pub fn new() -> CodeMap {
        CodeMap {
            files: DVec()
        }
    }

    pub fn add_filemap(&self, filemap: @FileMap) {
        let expected_byte_pos = if self.files.len() == 0 {
            0
        } else {
            let last_start = self.files.last().start_pos.byte.to_uint();
            let last_len = self.files.last().src.len();
            last_start + last_len
        };
        let actual_byte_pos = filemap.start_pos.byte.to_uint();
        debug!("codemap: adding filemap: %s", filemap.name);
        debug!("codemap: expected offset: %u", expected_byte_pos);
        debug!("codemap: actual offset: %u", actual_byte_pos);
        assert expected_byte_pos == actual_byte_pos;
        self.files.push(filemap);
    }

    pub fn mk_substr_filename(&self, sp: span) -> ~str {
        let pos = self.lookup_char_pos(sp.lo);
        return fmt!("<%s:%u:%u>", pos.file.name,
                    pos.line, pos.col.to_uint());
    }

    pub fn lookup_char_pos(&self, +pos: CharPos) -> Loc<CharPos> {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        return self.lookup_pos(pos, lookup);
    }

    pub fn lookup_char_pos_adj(&self, +pos: CharPos)
        -> {filename: ~str, line: uint, col: CharPos, file: Option<@FileMap>}
    {
        let loc = self.lookup_char_pos(pos);
        match (loc.file.substr) {
            FssNone => {
                {filename: /* FIXME (#2543) */ copy loc.file.name,
                 line: loc.line,
                 col: loc.col,
                 file: Some(loc.file)}
            }
            FssInternal(sp) => {
                self.lookup_char_pos_adj(
                    sp.lo + (pos - loc.file.start_pos.ch))
            }
            FssExternal(eloc) => {
                {filename: /* FIXME (#2543) */ copy eloc.filename,
                 line: eloc.line + loc.line - 1u,
                 col: if loc.line == 1u {eloc.col + loc.col} else {loc.col},
                 file: None}
            }
        }
    }

    pub fn adjust_span(&self, sp: span) -> span {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        let line = self.lookup_line(sp.lo, lookup);
        match (line.fm.substr) {
            FssNone => sp,
            FssInternal(s) => {
                self.adjust_span(span {
                    lo: s.lo + (sp.lo - line.fm.start_pos.ch),
                    hi: s.lo + (sp.hi - line.fm.start_pos.ch),
                    expn_info: sp.expn_info
                })
            }
            FssExternal(_) => sp
        }
    }

    pub fn span_to_str(&self, sp: span) -> ~str {
        let lo = self.lookup_char_pos_adj(sp.lo);
        let hi = self.lookup_char_pos_adj(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.filename,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }

    pub fn span_to_filename(&self, sp: span) -> FileName {
        let lo = self.lookup_char_pos(sp.lo);
        return /* FIXME (#2543) */ copy lo.file.name;
    }

    pub fn span_to_lines(&self, sp: span) -> @FileLines {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        let mut lines = ~[];
        for uint::range(lo.line - 1u, hi.line as uint) |i| {
            lines.push(i);
        };
        return @FileLines {file: lo.file, lines: lines};
    }

    fn lookup_byte_offset(&self, +chpos: CharPos)
        -> {fm: @FileMap, pos: BytePos} {
        pure fn lookup(pos: FilePos) -> uint { return pos.ch.to_uint(); }
        let {fm, line} = self.lookup_line(chpos, lookup);
        let line_offset = fm.lines[line].byte - fm.start_pos.byte;
        let col = chpos - fm.lines[line].ch;
        let col_offset = str::count_bytes(*fm.src,
                                          line_offset.to_uint(),
                                          col.to_uint());
        {fm: fm, pos: line_offset + BytePos(col_offset)}
    }

    pub fn span_to_snippet(&self, sp: span) -> ~str {
        let begin = self.lookup_byte_offset(sp.lo);
        let end = self.lookup_byte_offset(sp.hi);
        assert begin.fm.start_pos == end.fm.start_pos;
        return str::slice(*begin.fm.src,
                          begin.pos.to_uint(), end.pos.to_uint());
    }

    pub fn get_filemap(&self, filename: ~str) -> @FileMap {
        for self.files.each |fm| { if fm.name == filename { return *fm; } }
        //XXjdm the following triggers a mismatched type bug
        //      (or expected function, found _|_)
        fail; // ("asking for " + filename + " which we don't know about");
    }

}

priv impl CodeMap {
    fn lookup_line<A: Pos>(&self, pos: A, lookup: LookupFn)
        -> {fm: @FileMap, line: uint}
    {
        let len = self.files.len();
        let mut a = 0u;
        let mut b = len;
        while b - a > 1u {
            let m = (a + b) / 2u;
            if lookup(self.files[m].start_pos) > pos.to_uint() {
                b = m;
            } else {
                a = m;
            }
        }
        if (a >= len) {
            fail fmt!("position %u does not resolve to a source location",
                      pos.to_uint())
        }
        let f = self.files[a];
        a = 0u;
        b = vec::len(f.lines);
        while b - a > 1u {
            let m = (a + b) / 2u;
            if lookup(f.lines[m]) > pos.to_uint() { b = m; } else { a = m; }
        }
        return {fm: f, line: a};
    }

    fn lookup_pos<A: Pos Num>(&self, pos: A, lookup: LookupFn) -> Loc<A> {
        let {fm: f, line: a} = self.lookup_line(pos, lookup);
        return Loc {
            file: f,
            line: a + 1u,
            col: pos - from_uint(lookup(f.lines[a]))
        };
    }

    fn span_to_str_no_adj(&self, sp: span) -> ~str {
        let lo = self.lookup_char_pos(sp.lo);
        let hi = self.lookup_char_pos(sp.hi);
        return fmt!("%s:%u:%u: %u:%u", lo.file.name,
                    lo.line, lo.col.to_uint(), hi.line, hi.col.to_uint())
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<|endoftext|>


<commit_before>#![allow(dead_code)]

//! A first person camera.

use std::num::{ Float, FromPrimitive };
use std::marker::Reflect;
use event::GenericEvent;
use input::Button;
use { input, Camera };
use vecmath::consts::Radians;

bitflags!(flags Keys: u8 {
    const MOVE_FORWARD  = 0b00000001,
    const MOVE_BACKWARD = 0b00000010,
    const STRAFE_LEFT   = 0b00000100,
    const STRAFE_RIGHT  = 0b00001000,
    const FLY_UP        = 0b00010000,
    const FLY_DOWN      = 0b00100000
});

/// First person camera settings.
pub struct FirstPersonSettings<T=f32> {
    /// Which button to press to move forward.
    pub move_forward_button: input::Button,
    /// Which button to press to move backward.
    pub move_backward_button: input::Button,
    /// Which button to press to strafe left.
    pub strafe_left_button: input::Button,
    /// Which button to press to strafe right.
    pub strafe_right_button: input::Button,
    /// Which button to press to fly up.
    pub fly_up_button: input::Button,
    /// Which button to press to fly down.
    pub fly_down_button: input::Button,
    /// Which button to press to move faster.
    pub move_faster_button: input::Button,
    /// The horizontal movement speed.
    ///
    /// This is measured in units per second.
    pub speed_horizontal: T,
    /// The vertical movement speed.
    ///
    /// This is measured in units per second.
    pub speed_vertical: T,
}

impl<T: Float> FirstPersonSettings<T> {
    /// Creates new first person camera settings with wasd defaults.
    pub fn keyboard_wasd() -> FirstPersonSettings<T> {
        use input::Button::Keyboard;
        use input::keyboard::Key;

        FirstPersonSettings {
            move_forward_button: Keyboard(Key::W),
            move_backward_button: Keyboard(Key::S),
            strafe_left_button: Keyboard(Key::A),
            strafe_right_button: Keyboard(Key::D),
            fly_up_button: Keyboard(Key::Space),
            fly_down_button: Keyboard(Key::LShift),
            move_faster_button: Keyboard(Key::LCtrl),
            speed_horizontal: Float::one(),
            speed_vertical: Float::one(),
        }
    }

    /// Creates a new first person camera settings with esdf defaults.
    pub fn keyboard_esdf() -> FirstPersonSettings<T> {
        use input::Button::Keyboard;
        use input::keyboard::Key;

        FirstPersonSettings {
            move_forward_button: Keyboard(Key::E),
            move_backward_button: Keyboard(Key::D),
            strafe_left_button: Keyboard(Key::S),
            strafe_right_button: Keyboard(Key::F),
            fly_up_button: Keyboard(Key::Space),
            fly_down_button: Keyboard(Key::Z),
            move_faster_button: Keyboard(Key::LShift),
            speed_horizontal: Float::one(),
            speed_vertical: Float::one(),
        }
    }
}

/// Models a flying first person camera.
pub struct FirstPerson<T=f32> {
    /// The first person camera settings.
    pub settings: FirstPersonSettings<T>,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The direction we are heading.
    pub direction: [T; 3],
    /// The position of the camera.
    pub position: [T; 3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
    /// The keys that are pressed.
    keys: Keys,
}

impl<T: Float + FromPrimitive + Copy + Radians>
FirstPerson<T> {

    /// Creates a new first person camera.
    pub fn new(
        position: [T; 3],
        settings: FirstPersonSettings<T>
    ) -> FirstPerson<T> {
        let _0: T = Float::zero();
        FirstPerson {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            position: position,
            velocity: Float::one(),
        }
    }

    /// Computes camera.
    pub fn camera(&self, dt: f64) -> Camera<T> {
        let dt: T = FromPrimitive::from_f64(dt).unwrap();
        let dh = dt * self.velocity * self.settings.speed_horizontal;
        let (dx, dy, dz) = (self.direction[0], self.direction[1], self.direction[2]);
        let (s, c) = (self.yaw.sin(), self.yaw.cos());
        let mut camera = Camera::new([
            self.position[0] + (s * dx - c * dz) * dh,
            self.position[1] + dy * dt * self.settings.speed_vertical,
            self.position[2] + (s * dz + c * dx) * dh
        ]);
        camera.set_yaw_pitch(self.yaw, self.pitch);
        camera
    }

    /// Handles game event and updates camera.
    pub fn event<E>(&mut self, e: &E) where E: GenericEvent + Reflect {
        use event::{ MouseRelativeEvent, PressEvent, ReleaseEvent, UpdateEvent };

        e.update(|args| {
            let cam = self.camera(args.dt);
            self.position = cam.position;
        });

        let &mut FirstPerson {
            ref mut yaw,
            ref mut pitch,
            ref mut keys,
            ref mut direction,
            ref mut velocity,
            ref settings,
            ..
        } = self;

        let pi: T = Radians::_180();
        let sqrt2: T = Float::sqrt(FromPrimitive::from_f64(2f64).unwrap());
        let _0: T = Float::zero();
        let _1: T = Float::one();
        let _2: T = FromPrimitive::from_isize(2).unwrap();
        let _3: T = FromPrimitive::from_isize(3).unwrap();
        let _4: T = FromPrimitive::from_isize(4).unwrap();
        let _360: T = FromPrimitive::from_isize(360).unwrap();
        e.mouse_relative(|dx, dy| {
            let dx: T = FromPrimitive::from_f64(dx).unwrap();
            let dy: T = FromPrimitive::from_f64(dy).unwrap();
            *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
            *pitch = *pitch + dy / _360 * pi / _4;
            *pitch = (*pitch).min(pi / _2).max(-pi / _2);
        });
        e.press(|button| {
            let (dx, dy, dz) = (direction[0], direction[1], direction[2]);
            let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
            let mut set = |k, x: T, y: T, z: T| {
                let (x, z) = (sgn(x), sgn(z));
                let (x, z) = if x != _0 && z != _0 {
                    (x / sqrt2, z / sqrt2)
                } else {
                    (x, z)
                };
                *direction = [x, y, z];
                keys.insert(k);
            };
            match button {
                x if x == settings.move_forward_button =>
                    set(MOVE_FORWARD, -_1, dy, dz),
                x if x == settings.move_backward_button =>
                    set(MOVE_BACKWARD, _1, dy, dz),
                x if x == settings.strafe_left_button =>
                    set(STRAFE_LEFT, dx, dy, _1),
                x if x == settings.strafe_right_button =>
                    set(STRAFE_RIGHT, dx, dy, -_1),
                x if x == settings.fly_up_button =>
                    set(FLY_UP, dx, _1, dz),
                x if x == settings.fly_down_button =>
                    set(FLY_DOWN, dx, -_1, dz),
                x if x == settings.move_faster_button => *velocity = _2,
                _ => {}
            }
        });
        e.release(|button| {
            let (dx, dy, dz) = (direction[0], direction[1], direction[2]);
            let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
            let mut set = |x: T, y: T, z: T| {
                let (x, z) = (sgn(x), sgn(z));
                let (x, z) = if x != _0 && z != _0 {
                    (x / sqrt2, z / sqrt2)
                } else {
                    (x, z)
                };
                *direction = [x, y, z];
            };
            let mut release = |key, rev_key, rev_val| {
                keys.remove(key);
                if keys.contains(rev_key) { rev_val } else { _0 }
            };
            match button {
                x if x == settings.move_forward_button =>
                    set(release(MOVE_FORWARD, MOVE_BACKWARD, _1), dy, dz),
                x if x == settings.move_backward_button =>
                    set(release(MOVE_BACKWARD, MOVE_FORWARD, -_1), dy, dz),
                x if x == settings.strafe_left_button =>
                    set(dx, dy, release(STRAFE_LEFT, STRAFE_RIGHT, -_1)),
                x if x == settings.strafe_right_button =>
                    set(dx, dy, release(STRAFE_RIGHT, STRAFE_LEFT, _1)),
                x if x == settings.fly_up_button =>
                    set(dx, release(FLY_UP, FLY_DOWN, -_1), dz),
                x if x == settings.fly_down_button =>
                    set(dx, release(FLY_DOWN, FLY_UP, _1), dz),
                x if x == settings.move_faster_button => *velocity = _1,
                _ => {}
            }
        });
    }
}
<commit_msg>Remove unnecessary Reflect constraints<commit_after>#![allow(dead_code)]

//! A first person camera.

use std::num::{ Float, FromPrimitive };
use event::GenericEvent;
use input::Button;
use { input, Camera };
use vecmath::consts::Radians;

bitflags!(flags Keys: u8 {
    const MOVE_FORWARD  = 0b00000001,
    const MOVE_BACKWARD = 0b00000010,
    const STRAFE_LEFT   = 0b00000100,
    const STRAFE_RIGHT  = 0b00001000,
    const FLY_UP        = 0b00010000,
    const FLY_DOWN      = 0b00100000
});

/// First person camera settings.
pub struct FirstPersonSettings<T=f32> {
    /// Which button to press to move forward.
    pub move_forward_button: input::Button,
    /// Which button to press to move backward.
    pub move_backward_button: input::Button,
    /// Which button to press to strafe left.
    pub strafe_left_button: input::Button,
    /// Which button to press to strafe right.
    pub strafe_right_button: input::Button,
    /// Which button to press to fly up.
    pub fly_up_button: input::Button,
    /// Which button to press to fly down.
    pub fly_down_button: input::Button,
    /// Which button to press to move faster.
    pub move_faster_button: input::Button,
    /// The horizontal movement speed.
    ///
    /// This is measured in units per second.
    pub speed_horizontal: T,
    /// The vertical movement speed.
    ///
    /// This is measured in units per second.
    pub speed_vertical: T,
}

impl<T: Float> FirstPersonSettings<T> {
    /// Creates new first person camera settings with wasd defaults.
    pub fn keyboard_wasd() -> FirstPersonSettings<T> {
        use input::Button::Keyboard;
        use input::keyboard::Key;

        FirstPersonSettings {
            move_forward_button: Keyboard(Key::W),
            move_backward_button: Keyboard(Key::S),
            strafe_left_button: Keyboard(Key::A),
            strafe_right_button: Keyboard(Key::D),
            fly_up_button: Keyboard(Key::Space),
            fly_down_button: Keyboard(Key::LShift),
            move_faster_button: Keyboard(Key::LCtrl),
            speed_horizontal: Float::one(),
            speed_vertical: Float::one(),
        }
    }

    /// Creates a new first person camera settings with esdf defaults.
    pub fn keyboard_esdf() -> FirstPersonSettings<T> {
        use input::Button::Keyboard;
        use input::keyboard::Key;

        FirstPersonSettings {
            move_forward_button: Keyboard(Key::E),
            move_backward_button: Keyboard(Key::D),
            strafe_left_button: Keyboard(Key::S),
            strafe_right_button: Keyboard(Key::F),
            fly_up_button: Keyboard(Key::Space),
            fly_down_button: Keyboard(Key::Z),
            move_faster_button: Keyboard(Key::LShift),
            speed_horizontal: Float::one(),
            speed_vertical: Float::one(),
        }
    }
}

/// Models a flying first person camera.
pub struct FirstPerson<T=f32> {
    /// The first person camera settings.
    pub settings: FirstPersonSettings<T>,
    /// The yaw angle (in radians).
    pub yaw: T,
    /// The pitch angle (in radians).
    pub pitch: T,
    /// The direction we are heading.
    pub direction: [T; 3],
    /// The position of the camera.
    pub position: [T; 3],
    /// The velocity we are moving in the direction.
    pub velocity: T,
    /// The keys that are pressed.
    keys: Keys,
}

impl<T: Float + FromPrimitive + Copy + Radians>
FirstPerson<T> {

    /// Creates a new first person camera.
    pub fn new(
        position: [T; 3],
        settings: FirstPersonSettings<T>
    ) -> FirstPerson<T> {
        let _0: T = Float::zero();
        FirstPerson {
            settings: settings,
            yaw: _0,
            pitch: _0,
            keys: Keys::empty(),
            direction: [_0, _0, _0],
            position: position,
            velocity: Float::one(),
        }
    }

    /// Computes camera.
    pub fn camera(&self, dt: f64) -> Camera<T> {
        let dt: T = FromPrimitive::from_f64(dt).unwrap();
        let dh = dt * self.velocity * self.settings.speed_horizontal;
        let (dx, dy, dz) = (self.direction[0], self.direction[1], self.direction[2]);
        let (s, c) = (self.yaw.sin(), self.yaw.cos());
        let mut camera = Camera::new([
            self.position[0] + (s * dx - c * dz) * dh,
            self.position[1] + dy * dt * self.settings.speed_vertical,
            self.position[2] + (s * dz + c * dx) * dh
        ]);
        camera.set_yaw_pitch(self.yaw, self.pitch);
        camera
    }

    /// Handles game event and updates camera.
    pub fn event<E>(&mut self, e: &E) where E: GenericEvent {
        use event::{ MouseRelativeEvent, PressEvent, ReleaseEvent, UpdateEvent };

        e.update(|args| {
            let cam = self.camera(args.dt);
            self.position = cam.position;
        });

        let &mut FirstPerson {
            ref mut yaw,
            ref mut pitch,
            ref mut keys,
            ref mut direction,
            ref mut velocity,
            ref settings,
            ..
        } = self;

        let pi: T = Radians::_180();
        let sqrt2: T = Float::sqrt(FromPrimitive::from_f64(2f64).unwrap());
        let _0: T = Float::zero();
        let _1: T = Float::one();
        let _2: T = FromPrimitive::from_isize(2).unwrap();
        let _3: T = FromPrimitive::from_isize(3).unwrap();
        let _4: T = FromPrimitive::from_isize(4).unwrap();
        let _360: T = FromPrimitive::from_isize(360).unwrap();
        e.mouse_relative(|dx, dy| {
            let dx: T = FromPrimitive::from_f64(dx).unwrap();
            let dy: T = FromPrimitive::from_f64(dy).unwrap();
            *yaw = (*yaw - dx / _360 * pi / _4) % (_2 * pi);
            *pitch = *pitch + dy / _360 * pi / _4;
            *pitch = (*pitch).min(pi / _2).max(-pi / _2);
        });
        e.press(|button| {
            let (dx, dy, dz) = (direction[0], direction[1], direction[2]);
            let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
            let mut set = |k, x: T, y: T, z: T| {
                let (x, z) = (sgn(x), sgn(z));
                let (x, z) = if x != _0 && z != _0 {
                    (x / sqrt2, z / sqrt2)
                } else {
                    (x, z)
                };
                *direction = [x, y, z];
                keys.insert(k);
            };
            match button {
                x if x == settings.move_forward_button =>
                    set(MOVE_FORWARD, -_1, dy, dz),
                x if x == settings.move_backward_button =>
                    set(MOVE_BACKWARD, _1, dy, dz),
                x if x == settings.strafe_left_button =>
                    set(STRAFE_LEFT, dx, dy, _1),
                x if x == settings.strafe_right_button =>
                    set(STRAFE_RIGHT, dx, dy, -_1),
                x if x == settings.fly_up_button =>
                    set(FLY_UP, dx, _1, dz),
                x if x == settings.fly_down_button =>
                    set(FLY_DOWN, dx, -_1, dz),
                x if x == settings.move_faster_button => *velocity = _2,
                _ => {}
            }
        });
        e.release(|button| {
            let (dx, dy, dz) = (direction[0], direction[1], direction[2]);
            let sgn = |x: T| if x == _0 { _0 } else { x.signum() };
            let mut set = |x: T, y: T, z: T| {
                let (x, z) = (sgn(x), sgn(z));
                let (x, z) = if x != _0 && z != _0 {
                    (x / sqrt2, z / sqrt2)
                } else {
                    (x, z)
                };
                *direction = [x, y, z];
            };
            let mut release = |key, rev_key, rev_val| {
                keys.remove(key);
                if keys.contains(rev_key) { rev_val } else { _0 }
            };
            match button {
                x if x == settings.move_forward_button =>
                    set(release(MOVE_FORWARD, MOVE_BACKWARD, _1), dy, dz),
                x if x == settings.move_backward_button =>
                    set(release(MOVE_BACKWARD, MOVE_FORWARD, -_1), dy, dz),
                x if x == settings.strafe_left_button =>
                    set(dx, dy, release(STRAFE_LEFT, STRAFE_RIGHT, -_1)),
                x if x == settings.strafe_right_button =>
                    set(dx, dy, release(STRAFE_RIGHT, STRAFE_LEFT, _1)),
                x if x == settings.fly_up_button =>
                    set(dx, release(FLY_UP, FLY_DOWN, -_1), dz),
                x if x == settings.fly_down_button =>
                    set(dx, release(FLY_DOWN, FLY_UP, _1), dz),
                x if x == settings.move_faster_button => *velocity = _1,
                _ => {}
            }
        });
    }
}
<|endoftext|>