<commit_before>extern crate argparse;
extern crate comrak;
extern crate glob;
extern crate handlebars;
extern crate lazycell;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate simple_logger;
extern crate syntect;
extern crate regex;
extern crate time;
extern crate toml;
extern crate typed_arena;
extern crate walkdir;

mod directives;
mod evaluator;
mod highlighter;
mod lex;
mod markdown;
mod page;
mod parse;
mod theme;
mod toctree;

use std::cell::RefCell;
use std::collections::HashMap;
use std::convert::From;
use std::fs::{self, File};
use std::io::{self, Read, Write};
use std::mem;
use std::path::{Path, PathBuf};
use argparse::{ArgumentParser, StoreTrue};
use evaluator::Evaluator;
use page::Page;
use toctree::TocTree;

#[derive(Debug)]
enum LinkError {
    TemplateError(handlebars::RenderError),
    IOError(io::Error),
}

impl From<handlebars::RenderError> for LinkError {
    fn from(orig: handlebars::RenderError) -> Self {
        LinkError::TemplateError(orig)
    }
}

impl From<io::Error> for LinkError {
    fn from(orig: io::Error) -> Self {
        LinkError::IOError(orig)
    }
}

#[derive(Deserialize)]
struct RawConfig {
    syntax_theme: Option<String>,
    theme: Option<PathBuf>,
    content_dir: Option<PathBuf>,
    output: Option<PathBuf>,
    templates: HashMap<String, String>,
    theme_constants: Option<serde_json::map::Map<String, serde_json::Value>>,
}

struct Project {
    verbose: bool,
    theme: theme::Theme,
    content_dir: PathBuf,
    output: PathBuf,
    templates: Vec<(glob::Pattern, String)>,
    theme_constants: serde_json::map::Map<String, serde_json::Value>,
    evaluator: Evaluator,
}

impl Project {
    fn read_toml(path: &Path) -> Result<Project, ()> {
        let mut file = File::open(path).or(Err(()))?;
        let mut data = String::new();
        file.read_to_string(&mut data).or(Err(()))?;
        let config: RawConfig = toml::from_str(&data).or(Err(()))?;

        let theme_path = config.theme.ok_or(())?;
        let theme = theme::Theme::load(&theme_path)?;

        let path_patterns: Result<Vec<_>, ()> = config
            .templates
            .iter()
            .map(|(k, v)| {
                     let pattern = match glob::Pattern::new(k) {
                         Ok(p) => p,
                         Err(_) => return Err(()),
                     };
                     Ok((pattern, v.to_owned()))
                 })
            .collect();

        let path_patterns = path_patterns.or(Err(()))?;

        let syntax_theme = config
            .syntax_theme
            .unwrap_or_else(|| highlighter::DEFAULT_SYNTAX_THEME.to_owned());
        let mut evaluator = Evaluator::new_with_options(&syntax_theme);
        evaluator.register("md", Box::new(directives::Markdown::new()));
        evaluator.register("table", Box::new(directives::Dummy::new()));
        evaluator.register("version", Box::new(directives::Version::new("3.4.0")));
        evaluator.register("note",
                           Box::new(directives::Admonition::new("Note", "note")));
        evaluator.register("warning",
                           Box::new(directives::Admonition::new("Warning", "warning")));
        evaluator.register("manual",
                           Box::new(directives::LinkTemplate::new("https://docs.mongodb.com/manual")));
        evaluator.register("definition-list",
                           Box::new(directives::DefinitionList::new()));
        evaluator.register("concat", Box::new(directives::Concat::new()));
        evaluator.register("include", Box::new(directives::Include::new()));
        evaluator.register("import", Box::new(directives::Import::new()));
        evaluator.register("null", Box::new(directives::Dummy::new()));
        evaluator.register("let", Box::new(directives::Let::new()));
        evaluator.register("define", Box::new(directives::Define::new()));
        evaluator.register("get", Box::new(directives::Get::new()));
        evaluator.register("theme-config", Box::new(directives::ThemeConfig::new()));
        evaluator.register("toctree", Box::new(directives::TocTree::new()));

        Ok(Project {
               verbose: false,
               theme: theme,
               content_dir: config
                   .content_dir
                   .unwrap_or_else(|| PathBuf::from("content")),
               output: config.output.unwrap_or_else(|| PathBuf::from("build")),
               templates: path_patterns,
               theme_constants: config
                   .theme_constants
                   .unwrap_or_else(serde_json::map::Map::new),
               evaluator: evaluator,
           })
    }

    fn build_file(&self, evaluator: &Evaluator, slug: &str, path: &Path) -> Result<Page, ()> {
        debug!("Compiling {}", slug);

        let node = match evaluator.parser.borrow_mut().parse(path) {
            Ok(n) => n,
            Err(_) => {
                error!("Failed to parse {}", path.to_string_lossy());
                return Err(());
            }
        };

        let output = evaluator.evaluate(&node);

        let page = Page {
            source_path: path.to_owned(),
            slug: slug.to_owned(),
            body: output,
            theme_config: evaluator.theme_config.borrow().clone(),
        };

        evaluator.reset();
        Ok(page)
    }

    fn link_file(&self, page: &Page, renderer: &theme::Renderer) -> Result<(), LinkError> {
        debug!("Linking {}", &page.slug);

        // Find the template that matches this path
        let template_name = self.templates
            .iter()
            .find(|&&(ref pat, _)| pat.matches_path(&page.source_path))
            .map(|&(_, ref name)| name.as_ref())
            .unwrap_or("default");

        let rendered = renderer.render(template_name, &self.theme_constants, page)?;

        let mut output_path = self.output.join(&page.slug);
        output_path.set_extension("html");
        let output_dir = output_path.parent().expect("Couldn't get output directory");

        fs::create_dir_all(output_dir)?;
        let mut file = File::create(&output_path)?;
        file.write_all(rendered.as_bytes())?;

        Ok(())
    }

    fn build_project(&mut self) {
        let mut pending_pages = vec![];
        let mut titles = HashMap::new();

        for entry in walkdir::WalkDir::new(&self.content_dir) {
            let entry = entry.expect("Failed to walk dir");
            if !entry.file_type().is_file() {
                continue;
            }

            let path = entry.path();
            let slug = path.strip_prefix(&self.content_dir)
                .expect("Failed to get output path");
            let slug = slug.file_stem().unwrap().to_string_lossy();
            self.evaluator.set_slug(&slug);
            match self.build_file(&self.evaluator, &slug, path) {
                Ok(page) => {
                    titles.insert(page.slug.to_owned(), page.title());
                    pending_pages.push(page);
                }
                Err(_) => {
                    error!("Failed to build {}", path.to_string_lossy());
                }
            }
        }

        let mut toctree = mem::replace(&mut self.evaluator.toctree, RefCell::new(TocTree::new()))
            .into_inner();
        toctree.finish(titles);

        let renderer = theme::Renderer::new(&self.theme, toctree)
            .expect("Failed to construct renderer");
        for page in &pending_pages {
            self.link_file(page, &renderer)
                .expect("Failed to link page");
        }
    }
}

fn main() {
    let mut config = Project::read_toml(Path::new("config.toml"))
        .expect("Failed to open config.toml");

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("The Rocket documentation build system.");
        ap.refer(&mut config.verbose)
            .add_option(&["-v", "--verbose"], StoreTrue, "Be verbose");
        ap.parse_args_or_exit();
    }

    let loglevel = if config.verbose {
        log::LogLevel::Debug
    } else {
        log::LogLevel::Info
    };

    simple_logger::init_with_level(loglevel).expect("Failed to initialize logger");

    let start_time = time::precise_time_ns();
    config.build_project();

    info!("Took {} seconds",
          (time::precise_time_ns() - start_time) as f64 / (1_000_000_000 as f64));
}
<commit_msg>Fix slug generation for files in subdirectories<commit_after>extern crate argparse;
extern crate comrak;
extern crate glob;
extern crate handlebars;
extern crate lazycell;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate simple_logger;
extern crate syntect;
extern crate regex;
extern crate time;
extern crate toml;
extern crate typed_arena;
extern crate walkdir;

mod directives;
mod evaluator;
mod highlighter;
mod lex;
mod markdown;
mod page;
mod parse;
mod theme;
mod toctree;

use std::cell::RefCell;
use std::collections::HashMap;
use std::convert::From;
use std::fs::{self, File};
use std::io::{self, Read, Write};
use std::mem;
use std::path::{Path, PathBuf};
use argparse::{ArgumentParser, StoreTrue};
use evaluator::Evaluator;
use page::Page;
use toctree::TocTree;

#[derive(Debug)]
enum LinkError {
    TemplateError(handlebars::RenderError),
    IOError(io::Error),
}

impl From<handlebars::RenderError> for LinkError {
    fn from(orig: handlebars::RenderError) -> Self {
        LinkError::TemplateError(orig)
    }
}

impl From<io::Error> for LinkError {
    fn from(orig: io::Error) -> Self {
        LinkError::IOError(orig)
    }
}

#[derive(Deserialize)]
struct RawConfig {
    syntax_theme: Option<String>,
    theme: Option<PathBuf>,
    content_dir: Option<PathBuf>,
    output: Option<PathBuf>,
    templates: HashMap<String, String>,
    theme_constants: Option<serde_json::map::Map<String, serde_json::Value>>,
}

struct Project {
    verbose: bool,
    theme: theme::Theme,
    content_dir: PathBuf,
    output: PathBuf,
    templates: Vec<(glob::Pattern, String)>,
    theme_constants: serde_json::map::Map<String, serde_json::Value>,
    evaluator: Evaluator,
}

impl Project {
    fn read_toml(path: &Path) -> Result<Project, ()> {
        let mut file = File::open(path).or(Err(()))?;
        let mut data = String::new();
        file.read_to_string(&mut data).or(Err(()))?;
        let config: RawConfig = toml::from_str(&data).or(Err(()))?;

        let theme_path = config.theme.ok_or(())?;
        let theme = theme::Theme::load(&theme_path)?;

        let path_patterns: Result<Vec<_>, ()> = config
            .templates
            .iter()
            .map(|(k, v)| {
                     let pattern = match glob::Pattern::new(k) {
                         Ok(p) => p,
                         Err(_) => return Err(()),
                     };
                     Ok((pattern, v.to_owned()))
                 })
            .collect();

        let path_patterns = path_patterns.or(Err(()))?;

        let syntax_theme = config
            .syntax_theme
            .unwrap_or_else(|| highlighter::DEFAULT_SYNTAX_THEME.to_owned());
        let mut evaluator = Evaluator::new_with_options(&syntax_theme);
        evaluator.register("md", Box::new(directives::Markdown::new()));
        evaluator.register("table", Box::new(directives::Dummy::new()));
        evaluator.register("version", Box::new(directives::Version::new("3.4.0")));
        evaluator.register("note",
                           Box::new(directives::Admonition::new("Note", "note")));
        evaluator.register("warning",
                           Box::new(directives::Admonition::new("Warning", "warning")));
        evaluator.register("manual",
                           Box::new(directives::LinkTemplate::new("https://docs.mongodb.com/manual")));
        evaluator.register("definition-list",
                           Box::new(directives::DefinitionList::new()));
        evaluator.register("concat", Box::new(directives::Concat::new()));
        evaluator.register("include", Box::new(directives::Include::new()));
        evaluator.register("import", Box::new(directives::Import::new()));
        evaluator.register("null", Box::new(directives::Dummy::new()));
        evaluator.register("let", Box::new(directives::Let::new()));
        evaluator.register("define", Box::new(directives::Define::new()));
        evaluator.register("get", Box::new(directives::Get::new()));
        evaluator.register("theme-config", Box::new(directives::ThemeConfig::new()));
        evaluator.register("toctree", Box::new(directives::TocTree::new()));

        Ok(Project {
               verbose: false,
               theme: theme,
               content_dir: config
                   .content_dir
                   .unwrap_or_else(|| PathBuf::from("content")),
               output: config.output.unwrap_or_else(|| PathBuf::from("build")),
               templates: path_patterns,
               theme_constants: config
                   .theme_constants
                   .unwrap_or_else(serde_json::map::Map::new),
               evaluator: evaluator,
           })
    }

    fn build_file(&self, evaluator: &Evaluator, slug: &str, path: &Path) -> Result<Page, ()> {
        debug!("Compiling {}", slug);

        let node = match evaluator.parser.borrow_mut().parse(path) {
            Ok(n) => n,
            Err(_) => {
                error!("Failed to parse {}", path.to_string_lossy());
                return Err(());
            }
        };

        let output = evaluator.evaluate(&node);

        let page = Page {
            source_path: path.to_owned(),
            slug: slug.to_owned(),
            body: output,
            theme_config: evaluator.theme_config.borrow().clone(),
        };

        evaluator.reset();
        Ok(page)
    }

    fn link_file(&self, page: &Page, renderer: &theme::Renderer) -> Result<(), LinkError> {
        debug!("Linking {}", &page.slug);

        // Find the template that matches this path
        let template_name = self.templates
            .iter()
            .find(|&&(ref pat, _)| pat.matches_path(&page.source_path))
            .map(|&(_, ref name)| name.as_ref())
            .unwrap_or("default");

        let rendered = renderer.render(template_name, &self.theme_constants, page)?;

        let mut output_path = self.output.join(&page.slug);
        output_path.set_extension("html");
        let output_dir = output_path.parent().expect("Couldn't get output directory");

        fs::create_dir_all(output_dir)?;
        let mut file = File::create(&output_path)?;
        file.write_all(rendered.as_bytes())?;

        Ok(())
    }

    fn build_project(&mut self) {
        let mut pending_pages = vec![];
        let mut titles = HashMap::new();

        for entry in walkdir::WalkDir::new(&self.content_dir) {
            let entry = entry.expect("Failed to walk dir");
            if !entry.file_type().is_file() {
                continue;
            }

            let path = entry.path();
            let slug = path.strip_prefix(&self.content_dir)
                .expect("Failed to get output path");
            let dir = slug.parent().unwrap();
            let slug = dir.join(slug.file_stem().unwrap());
            let slug_str = slug.to_string_lossy();

            self.evaluator.set_slug(&slug_str);
            match self.build_file(&self.evaluator, &slug_str, path) {
                Ok(page) => {
                    titles.insert(page.slug.to_owned(), page.title());
                    pending_pages.push(page);
                }
                Err(_) => {
                    error!("Failed to build {}", path.to_string_lossy());
                }
            }
        }

        let mut toctree = mem::replace(&mut self.evaluator.toctree, RefCell::new(TocTree::new()))
            .into_inner();
        toctree.finish(titles);

        let renderer = theme::Renderer::new(&self.theme, toctree)
            .expect("Failed to construct renderer");
        for page in &pending_pages {
            self.link_file(page, &renderer)
                .expect("Failed to link page");
        }
    }
}

fn main() {
    let mut config = Project::read_toml(Path::new("config.toml"))
        .expect("Failed to open config.toml");

    {
        let mut ap = ArgumentParser::new();
        ap.set_description("The Rocket documentation build system.");
        ap.refer(&mut config.verbose)
            .add_option(&["-v", "--verbose"], StoreTrue, "Be verbose");
        ap.parse_args_or_exit();
    }

    let loglevel = if config.verbose {
        log::LogLevel::Debug
    } else {
        log::LogLevel::Info
    };

    simple_logger::init_with_level(loglevel).expect("Failed to initialize logger");

    let start_time = time::precise_time_ns();
    config.build_project();

    info!("Took {} seconds",
          (time::precise_time_ns() - start_time) as f64 / (1_000_000_000 as f64));
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(oak)]

extern crate oak_runtime;
use oak_runtime::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

grammar! awesome {
    #![show_api]

    program
        = (expr / decl / stmt)*

    decl
        = class_decl > to_class_decl
        / method_decl > to_method_decl

    class_decl
        = kw_class spacing ident class_body

    class_body
        = lbracket spacing method_decl* rbracket

    method_decl
        = kw_def spacing ident lparen params_list? rparen block

    block
        = lbracket spacing (stmt / expr)* rbracket

    stmt
        = if_stmt > to_if_stmt
        / while_stmt > to_while_stmt

    if_stmt
        = kw_if expr block

    while_stmt
        = kw_while expr block

    assign_expr
        = ident bind_op expr

    expr
        = spacing cond_expr (cond_expr_op cond_expr)* > fold_left

    cond_expr
        = add_expr (add_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (mult_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr

    primary_expr
        = call > call_expr
        / string > string_expr
        / number > number_expr
        / assign_expr > to_assign_expr
        / ident > variable_expr
        / lparen expr rparen

    call
        = (ident ".")? ident lparen arg_list? rparen

    arg_list
        = (expr ("," spacing expr)*)

    params_list
        = (ident ("," spacing ident)*)

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    ident = !digit !keyword ident_char+ spacing > to_string
    ident_char = ["a-zA-Z0-9_"]
    sym_char = ["!@#$%^&*()-=_+[]\\{}|;:,./<>? \n\r\t"]

    digit = ["0-9"]
    number = digit+ spacing > to_number
    string = (dbl_quot_string / sng_quot_string) spacing
    dbl_quot_string = dbl_quot (ident_char / digit / sym_char)* dbl_quot
    sng_quot_string = sng_quot (ident_char / digit / sym_char)* sng_quot
    spacing = [" \n\r\t"]* -> ()

    kw_def = "def"
    kw_class = "class"
    kw_true = "true"
    kw_false = "false"
    kw_nil = "nil"
    kw_if = "if"
    kw_while = "while"
    kw_tail = !ident_char spacing

    keyword
        = kw_def
        / kw_if
        / kw_class
        / kw_true
        / kw_false
        / kw_nil
        / kw_tail

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" spacing
    rbracket = "}" spacing
    dbl_quot = "\""
    sng_quot = "'"

    terminator = (";" / "\n") spacing

    use std::str::FromStr;
    use self::Expression::*;
    use self::BinOp::*;

    pub type PExpr = Box<Expression>;

    #[derive(Debug)]
    pub enum Expression {
        Variable(String),
        NumberLiteral(u32),
        StringLiteral(String),
        BinaryExpr(BinOp, PExpr, PExpr),
        Call(Option<String>, String, Option<(PExpr, Vec<PExpr>)>),
        AssingExpr(String, PExpr),
        MethodDecl(String, Option<(String, Vec<String>)>, Vec<PExpr>),
        ClassDecl(String, Vec<(String, Option<(String, Vec<String>)>, Vec<PExpr>)>),
        IfStatement(PExpr, Vec<PExpr>),
        WhileStatement(PExpr, Vec<PExpr>),
        Block(Vec<PExpr>)
    }

    #[derive(Debug)]
    pub enum BinOp {
        Add, Sub, Mul, Div, Lt, Lte, Gt, Gte, Ne, Eq, And, Or
    }

    fn to_number(raw_text: Vec<char>) -> u32 {
        u32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn number_expr(value: u32) -> PExpr {
        Box::new(NumberLiteral(value))
    }

    fn string_expr(raw_text: Vec<char>) -> PExpr {
        Box::new(StringLiteral(to_string(raw_text)))
    }

    fn variable_expr(ident: String) -> PExpr {
        Box::new(Variable(ident))
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn fold_left(head: PExpr, rest: Vec<(BinOp, PExpr)>) -> PExpr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Box::new(BinaryExpr(op, accu, expr)))
    }

    fn fold_right(front: Vec<(PExpr, BinOp)>, last: PExpr) -> PExpr {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| Box::new(BinaryExpr(op, expr, accu)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn call_expr(receiver: Option<String>, method: String, args: Option<(PExpr, Vec<PExpr>)>) -> PExpr {
        Box::new(Call(receiver, method, args))
    }

    fn to_assign_expr(variable: String, exp: PExpr) -> PExpr {
        Box::new(AssingExpr(variable, exp))
    }

    fn to_class_decl(name: String, methods: Vec<(String, Option<(String, Vec<String>)>, Vec<PExpr>)>) -> PExpr {
        Box::new(ClassDecl(name, methods))
    }

    fn to_method_decl(name: String, params: Option<(String, Vec<String>)>, body: Vec<PExpr>) -> PExpr {
        Box::new(MethodDecl(name, params, body))
    }

    fn to_if_stmt(condition: PExpr, block: Vec<PExpr>) -> PExpr {
        Box::new(IfStatement(condition, block))
    }

    fn to_while_stmt(condition: PExpr,  block: Vec<PExpr>) -> PExpr {
      Box::new(WhileStatement(condition, block))
    }
}

fn analyse_state(state: ParseState<StrStream, awesome::PExpr>) {
    match state.into_result() {
        Ok((success, error)) => {
            if success.partial_read() {
                println!("Partial match: {:?} because: {}", success.data, error);
            } else {
                println!("Full match: {:?}", success.data);
            }
        }
        Err(error) => {
            println!("Error: {}", error);
        }
    }
}

fn main() {
    let f = File::open("./src/example.awm").ok().expect("failed to open file");
    let mut reader = BufReader::new(f);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    println!("{:?}", awesome::parse_program(contents.stream()));
}
<commit_msg>Changed precendence of assigments.<commit_after>#![feature(plugin)]
#![plugin(oak)]

extern crate oak_runtime;
use oak_runtime::*;

use std::io::prelude::*;
use std::fs::File;
use std::io::BufReader;

grammar! awesome {
    #![show_api]

    program
        = (expr / decl / stmt)*

    decl
        = class_decl > to_class_decl
        / method_decl > to_method_decl

    class_decl
        = kw_class spacing ident class_body

    class_body
        = lbracket spacing method_decl* rbracket

    method_decl
        = kw_def spacing ident lparen params_list? rparen block

    block
        = lbracket spacing (stmt / expr)* rbracket

    stmt
        = if_stmt > to_if_stmt
        / while_stmt > to_while_stmt

    if_stmt
        = kw_if expr block

    while_stmt
        = kw_while expr block

    assign_expr
        = ident bind_op expr

    expr
        = spacing cond_expr (cond_expr_op cond_expr)* > fold_left

    cond_expr
        = add_expr (add_expr_op add_expr)* > fold_left

    add_expr
        = mult_expr (mult_expr_op mult_expr)* > fold_left

    mult_expr
        = primary_expr

    primary_expr
        = assign_expr > to_assign_expr
        / call > call_expr
        / string > string_expr
        / number > number_expr
        / ident > variable_expr
        / lparen expr rparen

    call
        = (ident ".")? ident lparen arg_list? rparen

    arg_list
        = (expr ("," spacing expr)*)

    params_list
        = (ident ("," spacing ident)*)

    add_expr_op
        = add_op > add_bin_op
        / sub_op > sub_bin_op

    mult_expr_op
        = mul_op > mul_bin_op
        / div_op > div_bin_op

    cond_expr_op
        = lt_op > lt_bin_op /
        lte_op > lte_bin_op /
        gt_op > gt_bin_op /
        gte_op > gte_bin_op /
        ne_op > ne_bin_op /
        eq_op > eq_bin_op /
        andand_op > and_bin_op /
        oror_op > or_bin_op

    ident = !digit !keyword ident_char+ spacing > to_string
    ident_char = ["a-zA-Z0-9_"]
    sym_char = ["!@#$%^&*()-=_+[]\\{}|;:,./<>? \n\r\t"]

    digit = ["0-9"]
    number = digit+ spacing > to_number
    string = (dbl_quot_string / sng_quot_string) spacing
    dbl_quot_string = dbl_quot (ident_char / digit / sym_char)* dbl_quot
    sng_quot_string = sng_quot (ident_char / digit / sym_char)* sng_quot
    spacing = [" \n\r\t"]* -> ()

    kw_def = "def"
    kw_class = "class"
    kw_true = "true"
    kw_false = "false"
    kw_nil = "nil"
    kw_if = "if"
    kw_while = "while"
    kw_tail = !ident_char spacing

    keyword
        = kw_def
        / kw_if
        / kw_class
        / kw_true
        / kw_false
        / kw_nil
        / kw_tail

    bind_op = "=" spacing
    add_op = "+" spacing
    sub_op = "-" spacing
    mul_op = "*" spacing
    div_op = "/" spacing
    lt_op = "<" spacing
    lte_op = "<=" spacing
    gt_op = ">" spacing
    gte_op = ">=" spacing
    ne_op = "!=" spacing
    eq_op = "==" spacing
    andand_op  = "&&" spacing
    oror_op = "||" spacing

    lparen = "(" spacing
    rparen = ")" spacing
    lbracket = "{" spacing
    rbracket = "}" spacing
    dbl_quot = "\""
    sng_quot = "'"

    terminator = (";" / "\n") spacing

    use std::str::FromStr;
    use self::Expression::*;
    use self::BinOp::*;

    pub type PExpr = Box<Expression>;

    #[derive(Debug)]
    pub enum Expression {
        Variable(String),
        NumberLiteral(u32),
        StringLiteral(String),
        BinaryExpr(BinOp, PExpr, PExpr),
        Call(Option<String>, String, Option<(PExpr, Vec<PExpr>)>),
        AssingExpr(String, PExpr),
        MethodDecl(String, Option<(String, Vec<String>)>, Vec<PExpr>),
        ClassDecl(String, Vec<(String, Option<(String, Vec<String>)>, Vec<PExpr>)>),
        IfStatement(PExpr, Vec<PExpr>),
        WhileStatement(PExpr, Vec<PExpr>),
        Block(Vec<PExpr>)
    }

    #[derive(Debug)]
    pub enum BinOp {
        Add, Sub, Mul, Div, Lt, Lte, Gt, Gte, Ne, Eq, And, Or
    }

    fn to_number(raw_text: Vec<char>) -> u32 {
        u32::from_str(&*to_string(raw_text)).unwrap()
    }

    fn number_expr(value: u32) -> PExpr {
        Box::new(NumberLiteral(value))
    }

    fn string_expr(raw_text: Vec<char>) -> PExpr {
        Box::new(StringLiteral(to_string(raw_text)))
    }

    fn variable_expr(ident: String) -> PExpr {
        Box::new(Variable(ident))
    }

    fn to_string(raw_text: Vec<char>) -> String {
        raw_text.into_iter().collect()
    }

    fn fold_left(head: PExpr, rest: Vec<(BinOp, PExpr)>) -> PExpr {
        rest.into_iter().fold(head,
          |accu, (op, expr)| Box::new(BinaryExpr(op, accu, expr)))
    }

    fn fold_right(front: Vec<(PExpr, BinOp)>, last: PExpr) -> PExpr {
        front.into_iter().rev().fold(last,
          |accu, (expr, op)| Box::new(BinaryExpr(op, expr, accu)))
    }

    fn add_bin_op() -> BinOp { Add }
    fn sub_bin_op() -> BinOp { Sub }
    fn mul_bin_op() -> BinOp { Mul }
    fn div_bin_op() -> BinOp { Div }
    fn lt_bin_op() -> BinOp { Lt }
    fn lte_bin_op() -> BinOp { Lte }
    fn gt_bin_op() -> BinOp { Gt }
    fn gte_bin_op() -> BinOp { Gte }
    fn ne_bin_op() -> BinOp { Ne }
    fn eq_bin_op() -> BinOp { Eq }
    fn and_bin_op() -> BinOp { And }
    fn or_bin_op() -> BinOp { Or }

    fn call_expr(receiver: Option<String>, method: String, args: Option<(PExpr, Vec<PExpr>)>) -> PExpr {
        Box::new(Call(receiver, method, args))
    }

    fn to_assign_expr(variable: String, exp: PExpr) -> PExpr {
        Box::new(AssingExpr(variable, exp))
    }

    fn to_class_decl(name: String, methods: Vec<(String, Option<(String, Vec<String>)>, Vec<PExpr>)>) -> PExpr {
        Box::new(ClassDecl(name, methods))
    }

    fn to_method_decl(name: String, params: Option<(String, Vec<String>)>, body: Vec<PExpr>) -> PExpr {
        Box::new(MethodDecl(name, params, body))
    }

    fn to_if_stmt(condition: PExpr, block: Vec<PExpr>) -> PExpr {
        Box::new(IfStatement(condition, block))
    }

    fn to_while_stmt(condition: PExpr,  block: Vec<PExpr>) -> PExpr {
      Box::new(WhileStatement(condition, block))
    }
}

fn analyse_state(state: ParseState<StrStream, awesome::PExpr>) {
    match state.into_result() {
        Ok((success, error)) => {
            if success.partial_read() {
                println!("Partial match: {:?} because: {}", success.data, error);
            } else {
                println!("Full match: {:?}", success.data);
            }
        }
        Err(error) => {
            println!("Error: {}", error);
        }
    }
}

fn main() {
    let f = File::open("./src/example.awm").ok().expect("failed to open file");
    let mut reader = BufReader::new(f);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    println!("{:?}", awesome::parse_program(contents.stream()));
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate wayland_client;

extern crate tempfile;

extern crate byteorder;
extern crate image;

use std::env;
use std::process::exit;
use image::open;
use std::mem::transmute;
use std::os::unix::io::AsRawFd;
use std::io::Write;

use wayland_client::wayland::get_display;
use wayland_client::wayland::compositor::{WlCompositor, WlSurface};
use wayland_client::wayland::shell::WlShell;
use wayland_client::wayland::shm::{WlBuffer, WlShm, WlShmFormat};
use wayland_client::wayland::seat::{WlSeat, WlPointerEvent};
use wayland_client::cursor::load_theme;
use wayland_client::{EventIterator, Proxy};

use byteorder::{NativeEndian, WriteBytesExt};

wayland_env!(WaylandEnv,
             compositor: WlCompositor,
             shell: WlShell,
             shm: WlShm,
             seat: WlSeat
);

type BufferResult = Result<WlBuffer, ()>;

/// Hack to deal with edge case between the two cursor buffer types...
enum CursorBuffer {
    /// The buffer has been leaked into memory.
    /// This should eventually be fixed, but since it's just the cursor
    /// it's not a big issue.
    Null,
    /// The buffer for the cursor, this can be destroyed so it should last
    /// as long as the program (or until you replace it with another).
    Buf(WlBuffer)
}

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
/// Holds the bytes to represent a colored background.
/// To be written into a wayland surface.
pub struct Color(pub [u8; 4]);

impl Color {
    /// Generate a new color out of a u32.
    /// E.G: 0xFFFFFF
    pub fn from_u32(color: u32) -> Self {
        unsafe { Color(transmute(color)) }
    }

    pub fn as_u32(&self) -> u32 {
        unsafe { transmute(self.0)}
    }
}

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() < 2 {
        println!("Please supply either a file path or a color (written in hex)");
        println!("Please also supply a path to a cursor image");
        exit(1);
    }
    let input = &args[1];
    let cursor_path = args.get(2);

    let (display, iter) = get_display()
        .expect("Unable to connect to a wayland compositor");
    let (env, evt_iter) = WaylandEnv::init(display, iter);
    let compositor = env.compositor.as_ref().map(|o| &o.0).unwrap();
    let shell = env.shell.as_ref().map(|o| &o.0).unwrap();
    let mut background_surface = compositor.create_surface();
    let shell_surface = shell.get_shell_surface(&background_surface);
    shell_surface.set_class("Background".into());
    // TODO Actually give it the path or something idk
    shell_surface.set_title(input.clone());

    // We need to hold on to this buffer, this holds the background image!
    let _background_buffer = if let Ok(color) = input.parse::<u32>() {
        let color = Color::from_u32(color);
        generate_solid_background(color, &mut background_surface, &env)
    } else {
        generate_image_background(input.as_str(), &mut background_surface, &env)
    }.expect("could not generate image");

    background_surface.commit();
    background_surface.set_buffer_scale(1);
    let mut cursor_surface = compositor.create_surface();
    let _cursor_buffer = self::cursor_surface(cursor_path, &mut cursor_surface, &env);
    main_background_loop(background_surface, cursor_surface, evt_iter, &env);
}

fn rgba_conversion(num: u8, third_num: u32) -> u8 {
    let big_num = num as u32;
    ((big_num * third_num) / 255) as u8
}

/// Given a solid color, writes bytes associated with that color to
/// a special Wayland surface which is then rendered as a background for Way Cooler.
fn generate_solid_background(color: Color, background_surface: &mut WlSurface,
                                 env: &WaylandEnv) -> BufferResult {
    // Get shortcuts to the globals.
    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    // Create the surface we are going to write into
    let mut tmp = tempfile::tempfile().ok().expect("Unable to create a tempfile.");

    // Calculate how big the buffer needs to be from the output resolution
    // TODO Get the output size from way cooler somehow...
    //let resolution = output.get_resolution()
    //    .expect("Couldn't get output resolution");
    //let (width, height) = (resolution.w as i32, resolution.h as i32);
    let width = 16; let height = 9;
    let size = (width * height) as i32;

    // Write in the color coding to the surface
    for _ in 0..size {
        unsafe {
            tmp.write_u32::<NativeEndian>(transmute(color.0))
                .expect("Could not write to file")
        }
    }
    tmp.flush()
        .expect("Could not flush buffer");

    // Create the buffer that is mem-mapped to the temp file descriptor
    let pool = shm.create_pool(tmp.as_raw_fd(), size);
    let background_buffer = pool.create_buffer(0, width, height, width, WlShmFormat::Argb8888);
    // Tell Way Cooler not to set put this in the tree, treat as background

    // Attach the buffer to the surface
    background_surface.attach(Some(&background_buffer), 0, 0);
    Ok(background_buffer)
}

/// Given the data from an image, writes it to a special Wayland surface
/// which is then rendered as a background for Way Cooler.
fn generate_image_background(path: &str, background_surface: &mut WlSurface,
                                 env: &WaylandEnv) -> BufferResult {
    // TODO support more formats, split into separate function
    let image = open(path)
        .unwrap_or_else(|_| {
            println!("Could not open \"{:?}\"", path);
            panic!("Could not open image file");
        });
    let mut image = image.to_rgba();
    let width = image.width();
    let height = image.height();
    let stride = width * 4;
    let size = stride * height;
    // TODO Split this into its own function
    {
        let pixels = image.enumerate_pixels_mut();
        for (_x, _y, pixel) in pixels {
            let alpha = pixel[3] as u32;
            pixel[0] = rgba_conversion(pixel[0], alpha);
            pixel[1] = rgba_conversion(pixel[1], alpha);
            pixel[2] = rgba_conversion(pixel[2], alpha);

            let tmp = pixel[2];
            pixel[2] = pixel[0];
            pixel[0] = tmp;
        }
    }
    let vec = image.into_vec();
    let mut tmp = tempfile::NamedTempFile::new().expect("Unable to create a tempfile.");
    tmp.set_len(size as u64).expect("Could not truncate length of file");
    tmp.write_all(&*vec).unwrap();

    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    // Create the surface we are going to write into

    let pool = shm.create_pool(tmp.as_raw_fd(), size as i32);
    let background_buffer = pool.create_buffer(0, width as i32, height as i32, stride as i32, WlShmFormat::Argb8888);

    // Attach the buffer to the surface
    background_surface.attach(Some(&background_buffer), 0, 0);
    background_surface.damage(0, 0, width as i32, height as i32);
    Ok(background_buffer)
}

fn cursor_surface(cursor_path: Option<&String>, cursor_surface: &mut WlSurface, env: &WaylandEnv)
                  -> Result<CursorBuffer, ()> {
    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    let cursor_theme = load_theme(None, 16, shm);
    /* If the theme has a predefined cursor, just use that */
    let cursor_buffer: WlBuffer;
    match cursor_path {
        None => {
            if let Some(cursor) = cursor_theme.get_cursor("default") {
                let cursor_frame_buffer = &*cursor.frame_buffer(0).expect("Couldn't get frame_buffer");
                cursor_surface.attach(Some(cursor_frame_buffer), 0, 0);
                ::std::mem::forget(cursor_frame_buffer);
                return Ok(CursorBuffer::Null)
            } else {
                println!("Could not find system-wide cursor, please supply one on the command line");
                ::std::process::exit(1);
            }
        },
        Some(cursor_path) => {
            let image = open(cursor_path)
                .unwrap_or_else(|_| {
                    println!("Could not open \"{:?}\"", cursor_path);
                    panic!("Could not open image file");
                });
            let mut image = image.to_rgba();
            let width = image.width();
            let height = image.height();
            let stride = width * 4;
            let size = stride * height;
            {
                let pixels = image.enumerate_pixels_mut();
                for (_x, _y, pixel) in pixels {
                    let alpha = pixel[3] as u32;
                    pixel[0] = rgba_conversion(pixel[0], alpha);
                    pixel[1] = rgba_conversion(pixel[1], alpha);
                    pixel[2] = rgba_conversion(pixel[2], alpha);

                    let tmp = pixel[2];
                    pixel[2] = pixel[0];
                    pixel[0] = tmp;
                }
            }
            let vec = image.into_vec();
            let mut tmp = tempfile::NamedTempFile::new().expect("Unable to create a tempfile.");
            tmp.set_len(size as u64).expect("Could not truncate length of file");
            tmp.write_all(&*vec).unwrap();
            let pool = shm.create_pool(tmp.as_raw_fd(), size as i32);
            cursor_buffer = pool.create_buffer(0, width as i32, height as i32, stride as i32, WlShmFormat::Argb8888);
            cursor_surface.attach(Some(&cursor_buffer), 0, 0);
        }
    }
    Ok(CursorBuffer::Buf(cursor_buffer))
}

/// Main loop for rendering backgrounds.
/// Need to keep the surface alive, and update it if the
/// user wants to change the background.
#[allow(unused_variables)]
fn main_background_loop(background_surface: WlSurface, cursor_surface: WlSurface, mut event_iter: EventIterator, env: &WaylandEnv) {
    use wayland_client::wayland::WaylandProtocolEvent;
    use wayland_client::Event;
    let seat = env.seat.as_ref().map(|o| &o.0).unwrap();
    let mut pointer = seat.get_pointer();

    pointer.set_event_iterator(&event_iter);
    pointer.set_cursor(0, Some(&cursor_surface), 0, 0);
    background_surface.commit();
    event_iter.sync_roundtrip().unwrap();
    loop {
        for event in &mut event_iter {
            match event {
                Event::Wayland(wayland_event) => {
                    match wayland_event {
                        WaylandProtocolEvent::WlPointer(id, pointer_event) => {
                            match pointer_event {
                                WlPointerEvent::Enter(serial, background_surface, surface_x, surface_y) => {
                                    pointer.set_cursor(0, Some(&cursor_surface), 0, 0);
                                },
                                _ => {
                                }
                            }
                        },
                        _ => {/* unhandled events */}
                    }
                }
                _ => { /* unhandled events */ }
            }
        }
        event_iter.dispatch().expect("Connection with the compositor was lost.");
    }
}

#[test]
fn test_rgba_conversion() {
    assert_eq!(rgba_conversion(10, 254), 9);
    assert_eq!(rgba_conversion(2, 255), 2);
    assert_eq!(rgba_conversion(255, 500), 500);
}
<commit_msg>Compiled in cursor, no longer specified at runtime<commit_after>#[macro_use]
extern crate wayland_client;

extern crate tempfile;

extern crate byteorder;
extern crate image;

use std::env;
use std::process::exit;
use image::{load_from_memory, open};
use std::mem::transmute;
use std::os::unix::io::AsRawFd;
use std::io::Write;

use wayland_client::wayland::get_display;
use wayland_client::wayland::compositor::{WlCompositor, WlSurface};
use wayland_client::wayland::shell::WlShell;
use wayland_client::wayland::shm::{WlBuffer, WlShm, WlShmFormat};
use wayland_client::wayland::seat::{WlSeat, WlPointerEvent};
use wayland_client::{EventIterator, Proxy};

use byteorder::{NativeEndian, WriteBytesExt};

wayland_env!(WaylandEnv,
             compositor: WlCompositor,
             shell: WlShell,
             shm: WlShm,
             seat: WlSeat
);

const CURSOR: &'static [u8; 656] = include_bytes!("../assets/arrow.png");

type BufferResult = Result<WlBuffer, ()>;

#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
/// Holds the bytes to represent a colored background.
/// To be written into a wayland surface.
pub struct Color(pub [u8; 4]);

impl Color {
    /// Generate a new color out of a u32.
    /// E.G: 0xFFFFFF
    pub fn from_u32(color: u32) -> Self {
        unsafe { Color(transmute(color)) }
    }

    pub fn as_u32(&self) -> u32 {
        unsafe { transmute(self.0)}
    }
}

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() < 1 {
        println!("Please supply either a file path or a color (written in hex)");
        exit(1);
    }
    let input = &args[1];

    let (display, iter) = get_display()
        .expect("Unable to connect to a wayland compositor");
    let (env, evt_iter) = WaylandEnv::init(display, iter);
    let compositor = env.compositor.as_ref().map(|o| &o.0).unwrap();
    let shell = env.shell.as_ref().map(|o| &o.0).unwrap();
    let mut background_surface = compositor.create_surface();
    let shell_surface = shell.get_shell_surface(&background_surface);
    shell_surface.set_class("Background".into());
    // TODO Actually give it the path or something idk
    shell_surface.set_title(input.clone());

    // We need to hold on to this buffer, this holds the background image!
    let _background_buffer = if let Ok(color) = input.parse::<u32>() {
        let color = Color::from_u32(color);
        generate_solid_background(color, &mut background_surface, &env)
    } else {
        generate_image_background(input.as_str(), &mut background_surface, &env)
    }.expect("could not generate image");

    background_surface.commit();
    background_surface.set_buffer_scale(1);
    let mut cursor_surface = compositor.create_surface();
    let _cursor_buffer = self::cursor_surface(&mut cursor_surface, &env);
    main_background_loop(background_surface, cursor_surface, evt_iter, &env);
}

fn rgba_conversion(num: u8, third_num: u32) -> u8 {
    let big_num = num as u32;
    ((big_num * third_num) / 255) as u8
}

/// Given a solid color, writes bytes associated with that color to
/// a special Wayland surface which is then rendered as a background for Way Cooler.
fn generate_solid_background(color: Color, background_surface: &mut WlSurface,
                                 env: &WaylandEnv) -> BufferResult {
    // Get shortcuts to the globals.
    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    // Create the surface we are going to write into
    let mut tmp = tempfile::tempfile().ok().expect("Unable to create a tempfile.");

    // Calculate how big the buffer needs to be from the output resolution
    // TODO Get the output size from way cooler somehow...
    //let resolution = output.get_resolution()
    //    .expect("Couldn't get output resolution");
    //let (width, height) = (resolution.w as i32, resolution.h as i32);
    let width = 16; let height = 9;
    let size = (width * height) as i32;

    // Write in the color coding to the surface
    for _ in 0..size {
        unsafe {
            tmp.write_u32::<NativeEndian>(transmute(color.0))
                .expect("Could not write to file")
        }
    }
    tmp.flush()
        .expect("Could not flush buffer");

    // Create the buffer that is mem-mapped to the temp file descriptor
    let pool = shm.create_pool(tmp.as_raw_fd(), size);
    let background_buffer = pool.create_buffer(0, width, height, width, WlShmFormat::Argb8888);
    // Tell Way Cooler not to set put this in the tree, treat as background

    // Attach the buffer to the surface
    background_surface.attach(Some(&background_buffer), 0, 0);
    Ok(background_buffer)
}

/// Given the data from an image, writes it to a special Wayland surface
/// which is then rendered as a background for Way Cooler.
fn generate_image_background(path: &str, background_surface: &mut WlSurface,
                             env: &WaylandEnv) -> BufferResult {
    // TODO support more formats, split into separate function
    let image = open(path)
        .unwrap_or_else(|_| {
            println!("Could not open image file \"{:?}\"", path);
            ::std::process::exit(1);
        });
    /*let image = load_from_memory(CURSOR)
        .expect("Could not read cursor data, report to maintainer!");*/
    let mut image = image.to_rgba();
    let width = image.width();
    let height = image.height();
    let stride = width * 4;
    let size = stride * height;
    // TODO Split this into its own function
    {
        let pixels = image.enumerate_pixels_mut();
        for (_x, _y, pixel) in pixels {
            let alpha = pixel[3] as u32;
            pixel[0] = rgba_conversion(pixel[0], alpha);
            pixel[1] = rgba_conversion(pixel[1], alpha);
            pixel[2] = rgba_conversion(pixel[2], alpha);

            let tmp = pixel[2];
            pixel[2] = pixel[0];
            pixel[0] = tmp;
        }
    }
    let vec = image.into_vec();
    let mut tmp = tempfile::NamedTempFile::new().expect("Unable to create a tempfile.");
    tmp.set_len(size as u64).expect("Could not truncate length of file");
    tmp.write_all(&*vec).unwrap();

    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    // Create the surface we are going to write into

    let pool = shm.create_pool(tmp.as_raw_fd(), size as i32);
    let background_buffer = pool.create_buffer(0, width as i32, height as i32, stride as i32, WlShmFormat::Argb8888);

    // Attach the buffer to the surface
    background_surface.attach(Some(&background_buffer), 0, 0);
    background_surface.damage(0, 0, width as i32, height as i32);
    Ok(background_buffer)
}

fn cursor_surface(cursor_surface: &mut WlSurface, env: &WaylandEnv) -> BufferResult {
    let shm = env.shm.as_ref().map(|o| &o.0).unwrap();

    let image = load_from_memory(CURSOR)
        .expect("Could not read cursor data, report to maintainer!");
    let mut image = image.to_rgba();
    let width = image.width();
    let height = image.height();
    let stride = width * 4;
    let size = stride * height;
    {
        let pixels = image.enumerate_pixels_mut();
        for (_x, _y, pixel) in pixels {
            let alpha = pixel[3] as u32;
            pixel[0] = rgba_conversion(pixel[0], alpha);
            pixel[1] = rgba_conversion(pixel[1], alpha);
            pixel[2] = rgba_conversion(pixel[2], alpha);

            let tmp = pixel[2];
            pixel[2] = pixel[0];
            pixel[0] = tmp;
        }
    }
    let vec = image.into_vec();
    let mut tmp = tempfile::NamedTempFile::new().expect("Unable to create a tempfile.");
    tmp.set_len(size as u64).expect("Could not truncate length of file");
    tmp.write_all(&*vec).unwrap();
    let pool = shm.create_pool(tmp.as_raw_fd(), size as i32);
    let cursor_buffer = pool.create_buffer(0, width as i32, height as i32, stride as i32, WlShmFormat::Argb8888);
    cursor_surface.attach(Some(&cursor_buffer), 0, 0);
    Ok(cursor_buffer)
}

/// Main loop for rendering backgrounds.
/// Need to keep the surface alive, and update it if the
/// user wants to change the background.
#[allow(unused_variables)]
fn main_background_loop(background_surface: WlSurface, cursor_surface: WlSurface, mut event_iter: EventIterator, env: &WaylandEnv) {
    use wayland_client::wayland::WaylandProtocolEvent;
    use wayland_client::Event;
    let seat = env.seat.as_ref().map(|o| &o.0).unwrap();
    let mut pointer = seat.get_pointer();

    pointer.set_event_iterator(&event_iter);
    pointer.set_cursor(0, Some(&cursor_surface), 0, 0);
    background_surface.commit();
    event_iter.sync_roundtrip().unwrap();
    loop {
        for event in &mut event_iter {
            match event {
                Event::Wayland(wayland_event) => {
                    match wayland_event {
                        WaylandProtocolEvent::WlPointer(id, pointer_event) => {
                            match pointer_event {
                                WlPointerEvent::Enter(serial, background_surface, surface_x, surface_y) => {
                                    pointer.set_cursor(0, Some(&cursor_surface), 0, 0);
                                },
                                _ => {
                                }
                            }
                        },
                        _ => {/* unhandled events */}
                    }
                }
                _ => { /* unhandled events */ }
            }
        }
        event_iter.dispatch().expect("Connection with the compositor was lost.");
    }
}

#[test]
fn test_rgba_conversion() {
    assert_eq!(rgba_conversion(10, 254), 9);
    assert_eq!(rgba_conversion(2, 255), 2);
    assert_eq!(rgba_conversion(255, 500), 500);
}
<|endoftext|>


<commit_before>use std::env;
use std::error::Error;
use std::fs::File;
use std::path::Path;
use std::io::Read;
use std::process;

enum BfOpKind {
    InvalidOp,
    IncPtr,
    DecPtr,
    IncData,
    DecData,
    ReadStdin,
    WriteStdout,
    JumpIfDataZero,
    JumpIfDataNotZero,
}

#[allow(dead_code)]
fn bf_op_kind_name(kind: BfOpKind) -> char {
    match kind {
        BfOpKind::IncPtr => return '>',
        BfOpKind::DecPtr => return '<',
        BfOpKind::IncData => return '+',
        BfOpKind::DecData => return '-',
        BfOpKind::ReadStdin => return ',',
        BfOpKind::WriteStdout => return '.',
        BfOpKind::JumpIfDataZero => return '[',
        BfOpKind::JumpIfDataNotZero => return ']',
        BfOpKind::InvalidOp => return 'x',
    }
}

struct BfOp {
    kind: BfOpKind,
    argument: u64,
}

fn translate_code(code: &Vec<u8>) -> Vec<BfOp> {
    let mut ptr = 0;
    let code_size = code.len();
    let mut ops =  Vec::new();
    let mut open_bracket_stack = Vec::new();

    while ptr < code_size {
        let instruction = code[ptr];
        if instruction == '[' as u8 {
            open_bracket_stack.push(ops.len() as u64);
            ops.push(BfOp{ kind: BfOpKind::JumpIfDataZero,
                            argument: 0 });
            ptr += 1;
        } else if instruction == ']' as u8 {
            if open_bracket_stack.is_empty() {
                panic!("Unmatch closing ']': ptr={}", ptr);
            }
            let open_bracket_offset =
                    open_bracket_stack[open_bracket_stack.len()-1];
            open_bracket_stack.pop();

            ops[open_bracket_offset as usize].argument = ops.len() as u64;
            ops.push(BfOp{ kind:BfOpKind::JumpIfDataNotZero,
                            argument: open_bracket_offset });
            ptr += 1;
        } else {
            let start = ptr;
            ptr += 1;
            while ptr < code_size && code[ptr] == instruction {
                ptr += 1;
            }

            let num_repeats = ptr - start;

            let mut kind = BfOpKind::InvalidOp;
            match instruction as char {
                '>' => kind = BfOpKind::IncPtr,
                '<' => kind = BfOpKind::DecPtr,
                '+' => kind = BfOpKind::IncData,
                '-' => kind = BfOpKind::DecData,
                ',' => kind = BfOpKind::ReadStdin,
                '.' => kind = BfOpKind::WriteStdout,
                _ => {}
            }

            ops.push(BfOp{ kind: kind, argument: num_repeats as u64 });
        }
    }

    ops
}

fn input() -> u8 {
    let c = match std::io::stdin().bytes().next()
                .and_then(|result| result.ok()).map(|byte| byte as u8) {
        None => process::exit(0),
        Some(c) => c,
    };
    c
}

fn output(c: u8) {
    print!("{}", c as char);
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let path = Path::new(&args[1]);
    let display = path.display();

    let mut file = match File::open(&path) {
        Err(why) => panic!("Could not open {}: {}",
                           display, Error::description(&why)),
        Ok(file) => file,
    };

    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Err(why) => panic!("Could not read {}: {}",
                           display, Error::description(&why)),
        Ok(_) => {},
    }

    let mut code_ptr: usize = 0;
    let mut data_ptr: usize = 0;
    let code = s.into_bytes();
    let mut data = [0 as u8; 30000];
    let ops = translate_code(&code);

    while code_ptr < ops.len() {
        let op = &ops[code_ptr];
        let kind = &op.kind;

        match kind {
            &BfOpKind::IncPtr => data_ptr += op.argument as usize,
            &BfOpKind::DecPtr => data_ptr -= op.argument as usize,
            &BfOpKind::IncData => data[data_ptr] += op.argument as u8,
            &BfOpKind::DecData => data[data_ptr] -= op.argument as u8,
            &BfOpKind::ReadStdin => {
                for _ in 0..op.argument {
                    data[data_ptr] = input();
                }
            },
            &BfOpKind::WriteStdout => {
                for _ in 0..op.argument {
                    output(data[data_ptr]);
                }
            },
            &BfOpKind::JumpIfDataZero => {
                if data[data_ptr] == 0 {
                    code_ptr = op.argument as usize;
                }
            },
            &BfOpKind::JumpIfDataNotZero => {
                if data[data_ptr] != 0 {
                    code_ptr = op.argument as usize;
                }
            },
            _ => {},
        }
        code_ptr += 1;
    }
}
<commit_msg>Add optimize_loop<commit_after>use std::env;
use std::error::Error;
use std::fs::File;
use std::path::Path;
use std::io::Read;
use std::process;

#[derive(PartialEq)]
enum BfOpKind {
    InvalidOp,
    IncPtr,
    DecPtr,
    IncData,
    DecData,
    ReadStdin,
    WriteStdout,
    LoopSetToZero,
    LoopMovePtr,
    LoopMoveData,
    JumpIfDataZero,
    JumpIfDataNotZero,
}

#[allow(dead_code)]
fn bf_op_kind_name(kind: BfOpKind) -> char {
    match kind {
        BfOpKind::IncPtr => return '>',
        BfOpKind::DecPtr => return '<',
        BfOpKind::IncData => return '+',
        BfOpKind::DecData => return '-',
        BfOpKind::ReadStdin => return ',',
        BfOpKind::WriteStdout => return '.',
        BfOpKind::JumpIfDataZero => return '[',
        BfOpKind::JumpIfDataNotZero => return ']',
        BfOpKind::LoopSetToZero => return 's',
        BfOpKind::LoopMovePtr => return 'm',
        BfOpKind::LoopMoveData => return 'd',
        BfOpKind::InvalidOp => return 'x',
    }
}

struct BfOp {
    kind: BfOpKind,
    argument: i64,
}

fn optimize_loop(ops: &Vec<BfOp>, loop_start: i64) -> Vec<BfOp> {
    let mut new_ops = Vec::new();

    if ops.len() as i64 - loop_start == 2 {
        let repeated_op = &ops[loop_start as usize + 1];
        if repeated_op.kind == BfOpKind::IncData ||
            repeated_op.kind == BfOpKind::DecData {
            new_ops.push(BfOp {kind: BfOpKind::LoopSetToZero, argument: 0});
        } else if repeated_op.kind == BfOpKind::IncPtr ||
            repeated_op.kind == BfOpKind::DecPtr {
            if repeated_op.kind == BfOpKind::IncPtr {
                new_ops.push(
                            BfOp { kind: BfOpKind::LoopMovePtr,
                                argument: repeated_op.argument});
            } else {
                new_ops.push(
                            BfOp { kind: BfOpKind::LoopMovePtr,
                                argument: -repeated_op.argument});
            }
        } else if ops.len() as i64 - loop_start == 5 {
            if ops[loop_start as usize + 1].kind == BfOpKind::DecData &&
                ops[loop_start as usize + 3].kind == BfOpKind::IncData &&
                ops[loop_start as usize + 1].argument == 1 &&
                ops[loop_start as usize + 3].argument == 1 {

                if ops[loop_start as usize + 2].kind == BfOpKind::IncPtr &&
                    ops[loop_start as usize + 4].kind == BfOpKind::DecPtr &&
                    ops[loop_start as usize + 2].argument ==
                    ops[loop_start as usize + 4].argument {
                    new_ops.push(
                        BfOp { kind: BfOpKind::LoopMoveData,
                            argument: ops[loop_start as usize + 4].argument});
                } else if ops[loop_start as usize + 2].kind == BfOpKind::DecPtr &&
                    ops[loop_start as usize + 4].kind == BfOpKind::IncPtr &&
                    ops[loop_start as usize + 2].argument ==
                    ops[loop_start as usize + 4].argument {
                    new_ops.push(
                        BfOp { kind: BfOpKind::LoopMoveData,
                            argument: -ops[loop_start as usize + 2].argument});
                }
            }
        }
    }

    new_ops
}

fn translate_code(code: &Vec<u8>) -> Vec<BfOp> {
    let mut ptr = 0;
    let code_size = code.len();
    let mut ops = Vec::new();
    let mut open_bracket_stack = Vec::new();

    while ptr < code_size {
        let instruction = code[ptr];
        if instruction == '[' as u8 {
            open_bracket_stack.push(ops.len() as i64);
            ops.push(BfOp{ kind: BfOpKind::JumpIfDataZero,
                            argument: 0 });
            ptr += 1;
        } else if instruction == ']' as u8 {
            if open_bracket_stack.is_empty() {
                panic!("Unmatch closing ']': ptr={}", ptr);
            }
            let open_bracket_offset =
                    open_bracket_stack[open_bracket_stack.len()-1];
            open_bracket_stack.pop();

            let mut optimized_loop = optimize_loop(&ops, open_bracket_offset);

            if optimized_loop.is_empty() {
                ops[open_bracket_offset as usize].argument = ops.len() as i64;
                ops.push(BfOp{ kind: BfOpKind::JumpIfDataNotZero,
                                argument: open_bracket_offset});
            } else {
                let ops_len: usize  = ops.len() - 1;
                ops.drain(open_bracket_offset as usize ..ops_len);
                ops.append(&mut optimized_loop);
            }
            ptr += 1;
        } else {
            let start = ptr;
            ptr += 1;
            while ptr < code_size && code[ptr] == instruction {
                ptr += 1;
            }

            let num_repeats = ptr - start;

            let mut kind = BfOpKind::InvalidOp;
            match instruction as char {
                '>' => kind = BfOpKind::IncPtr,
                '<' => kind = BfOpKind::DecPtr,
                '+' => kind = BfOpKind::IncData,
                '-' => kind = BfOpKind::DecData,
                ',' => kind = BfOpKind::ReadStdin,
                '.' => kind = BfOpKind::WriteStdout,
                _ => {}
            }

            ops.push(BfOp{ kind: kind, argument: num_repeats as i64 });
        }
    }

    ops
}

fn input() -> u8 {
    let c = match std::io::stdin().bytes().next()
                .and_then(|result| result.ok()).map(|byte| byte as u8) {
        None => process::exit(0),
        Some(c) => c,
    };
    c
}

fn output(c: u8) {
    print!("{}", c as char);
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let path = Path::new(&args[1]);
    let display = path.display();

    let mut file = match File::open(&path) {
        Err(why) => panic!("Could not open {}: {}",
                           display, Error::description(&why)),
        Ok(file) => file,
    };

    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Err(why) => panic!("Could not read {}: {}",
                           display, Error::description(&why)),
        Ok(_) => {},
    }

    let mut code_ptr: usize = 0;
    let mut data_ptr: usize = 0;
    let code = s.into_bytes();
    let mut data = [0 as u8; 30000];
    let ops = translate_code(&code);

    while code_ptr < ops.len() {
        let op = &ops[code_ptr];
        let kind = &op.kind;

        match kind {
            &BfOpKind::IncPtr => data_ptr += op.argument as usize,
            &BfOpKind::DecPtr => data_ptr -= op.argument as usize,
            &BfOpKind::IncData => data[data_ptr] += op.argument as u8,
            &BfOpKind::DecData => data[data_ptr] -= op.argument as u8,
            &BfOpKind::ReadStdin => {
                for _ in 0..op.argument {
                    data[data_ptr] = input();
                }
            },
            &BfOpKind::WriteStdout => {
                for _ in 0..op.argument {
                    output(data[data_ptr]);
                }
            },
            &BfOpKind::LoopSetToZero => data[data_ptr] = 0,
            &BfOpKind::LoopMovePtr => {
                while data[data_ptr] != 0 {
                    data_ptr += op.argument as usize;
                }
            },
            &BfOpKind::LoopMoveData => {
                if data[data_ptr] != 0 {
                    let move_to_ptr = data_ptr + op.argument as usize;
                    data[move_to_ptr] += data[data_ptr];
                    data[data_ptr] = 0;
                }
            },
            &BfOpKind::JumpIfDataZero => {
                if data[data_ptr] == 0 {
                    code_ptr = op.argument as usize;
                }
            },
            &BfOpKind::JumpIfDataNotZero => {
                if data[data_ptr] != 0 {
                    code_ptr = op.argument as usize;
                }
            },
            _ => {},
        }
        code_ptr += 1;
    }
}
<|endoftext|>


<commit_before>#![allow(unused_variables)]
#[allow(dead_code)]

mod sysgraph;

use sysgraph::args::{Args};

fn main() {

    let args = Args::parse().unwrap();

    println!("args => {:?}", args);
}
<commit_msg>minor err handling<commit_after>#![allow(unused_variables)]
#[allow(dead_code)]

mod sysgraph;

use sysgraph::args::{Args};
use std::process;

fn main() {

    let args = Args::parse();

    if args.is_err() {
        eprintln!("error: {}", args.unwrap_err());
        process::exit(1);
    }

    println!("args => {:?}", args);
}
<|endoftext|>


<commit_before>use std::io::{self, Read};
use std::env;
use std::fmt;

struct Col {
    pub buffers: Vec<String>
}
impl Col {
    fn new() -> Col {
        Col { buffers: Vec::new() }
    }
    fn add_buf(&mut self) {
        self.buffers.push(String::new());
    }
    fn append(&mut self, chr: char) {
        let mut len = self.buffers.len();

        if len == 0 {
            self.add_buf();
            len = 1;
        }

        let ref mut buffer = self.buffers[len-1];
        buffer.push(chr);
    }
    fn append_str(&mut self, str: &str) {
        for chr in str.chars() {
            self.append(chr);
        }
    }
    fn out(&self) -> String {
        let mut out: String = String::new();

        out.push_str("
");
        for ref buf in self.buffers.iter() {
            out.push_str(format!("
{}
", buf).as_str());
        }
        out.push_str("
");

        out
    }
}

struct Row {
    pub cols: Vec<Col>
}
impl Row {
    fn add_col(&mut self, col: Col) {
        self.cols.push(col);
    }
    fn get_col(&mut self, index: u8) -> &mut Col {
        self.cols.get_mut(index as usize).unwrap()
    }
    fn col_count(&self) -> usize {
        self.cols.len()
    }
    fn new() -> Row {
        let mut row: Row = Row { cols: Vec::new() };
        row.add_col(Col::new());
        row
    }
    fn out(&self) -> String {
        let mut out: String = String::new();

        out.push_str("
");
        for ref col in self.cols.iter() {
            let formatted = format!("{}", col.out());
            out.push_str(formatted.as_str());
        }
        out.push_str("
");

        out
    }
}

struct Template {
    container_start: String,
    container_end: String,
    row_start: String,
    row_end: String,
    col_start: String,
    col_end: String,
    segment_start: String,
    segment_end: String,
    label: String,
    text: String,
    checkbox: String,
    radio: String,
    textarea: String,
    hr: String,
    button: String
}

/**
 * An empty line implies a new "row"
 * A line starting with a | implies a columnar form section
 * [value] is an input text field
 * {value} is an input textarea field
 * @ is a radio
 * * is a checkbox
 * --- is an hr
 *
 */
fn main() {
    // Read in standard input
    let mut buffer = String::new();
    io::stdin().read_to_string(&mut buffer)
        .expect("Error reading from stdin");

    // Split input by line
    let v: Vec<&str> = buffer.split("\n").collect();

    // Keep track of rows in output
    let mut rows: Vec<Row> = Vec::new();
    let mut row: Row = Row::new();

    // Check arg for template
    let template = match env::args().nth(1) {
        /*
        Some(file) => {
            Template {
                container_start: "",
                container_end: "",
                row_start: "
",
                row_end: "
",
                col_start: "",
                col_end: "",
                segment_start: "",
                segment_end: "
",
                label: "{[value}}",
                text: "<input type=\"text\" value=\"{{value}}\"/>",
                checkbox: "<input type=\"checkbox\"/>",
                radio: "<input type=\"radio\"/>",
                textarea: "<textarea>{{value}}</textarea>",
                hr: "
",
                button: "<button>{{value}}</button>"
            }

        },
        */
        _ => Template {
            container_start: "".to_string(),
            container_end: "".to_string(),
            row_start: "
".to_string(),
            row_end: "
".to_string(),
            col_start: "".to_string(),
            col_end: "".to_string(),
            segment_start: "".to_string(),
            segment_end: "
".to_string(),
            label: "{[value}}".to_string(),
            text: "<input type=\"text\" value=\"{{value}}\"/>".to_string(),
            checkbox: "<input type=\"checkbox\"/>".to_string(),
            radio: "<input type=\"radio\"/>".to_string(),
            textarea: "<textarea>{{value}}</textarea>".to_string(),
            hr: "
".to_string(),
            button: "<button>{{value}}</button>".to_string()
        }
    };

    // Iterate over lines in input
    for line in &v {
        // New row by way of empty line
        if line.chars().count() == 0 {
            rows.push(row);
            row = Row::new();
            continue;
        }

        let mut form_mode = false; // If user toggled form mode
        let mut col_index: u8 = 1; // Keeping tracking of column index
        let mut dashes: u8 = 0; // Keep track of dash count

        // Iterate over characters in string
        for (i, c) in line.chars().enumerate() {
            // Match c against known tokens
            match c {
                '-' => {
                    dashes += 1;
                    if dashes == 3 {
                        row.get_col(col_index-1)
                            .append_str("
");
                        break;
                    }
                },
                '|' => {
                    if i == 0 {
                        form_mode = true;
                        row.get_col(col_index-1).add_buf()
                    } else if form_mode {
                        // Check if we have enough columns in row
                        // if not add a new column
                        if (row.col_count() as u8) < col_index + 1 {
                            row.add_col(Col::new());
                        }

                        // Increment index
                        col_index += 1;

                        row.get_col(col_index-1).add_buf();
                    } else {
                        row.get_col(col_index-1).append(c);
                    }
                },
                '<' => row.get_col(col_index-1)
                        .append_str(""),
                '>' => row.get_col(col_index-1)
                        .append_str(""),
                '[' => row.get_col(col_index-1)
                        .append_str("<input type=\"text\" value=\""),
                ']' => row.get_col(col_index-1)
                        .append_str("\">"),
                '{' => row.get_col(col_index-1)
                        .append_str("<textarea>"),
                '}' => row.get_col(col_index-1)
                        .append_str("</textarea>"),
                '@' => row.get_col(col_index-1)
                        .append_str("<input type=\"radio\">"),
                '(' => row.get_col(col_index-1)
                        .append_str("<button class=\"btn\">"),
                ')' => row.get_col(col_index-1)
                        .append_str("</button>"),
                _ => row.get_col(col_index-1).append(c)
            }
        }
    }

    println!("
");
    for row in rows {
        println!("{}", row.out());
    }
    println!("
");
}
<commit_msg>Starting template<commit_after>use std::io::{self, Read};
use std::env;
use std::fmt;
use std::fs::File;

struct Col {
    pub buffers: Vec<String>
}
impl Col {
    fn new() -> Col {
        Col { buffers: Vec::new() }
    }
    fn add_buf(&mut self) {
        self.buffers.push(String::new());
    }
    fn append(&mut self, chr: char) {
        let mut len = self.buffers.len();

        if len == 0 {
            self.add_buf();
            len = 1;
        }

        let ref mut buffer = self.buffers[len-1];
        buffer.push(chr);
    }
    fn append_str(&mut self, str: &str) {
        for chr in str.chars() {
            self.append(chr);
        }
    }
    fn out(&self, template: &Template) -> String {
        let mut out: String = String::new();

        out.push_str(template.col_start.as_str());
        for ref buf in self.buffers.iter() {
            out.push_str(format!("{}{}{}",
                    template.segment_start.as_str(),
                    buf,
                    template.segment_end.as_str()
                ).as_str());
        }
        out.push_str(template.col_end.as_str());

        out
    }
}

struct Row {
    pub cols: Vec<Col>
}
impl Row {
    fn add_col(&mut self, col: Col) {
        self.cols.push(col);
    }
    fn get_col(&mut self, index: u8) -> &mut Col {
        self.cols.get_mut(index as usize).unwrap()
    }
    fn col_count(&self) -> usize {
        self.cols.len()
    }
    fn new() -> Row {
        let mut row: Row = Row { cols: Vec::new() };
        row.add_col(Col::new());
        row
    }
    fn out(&self, template: &Template) -> String {
        let mut out: String = String::new();

        out.push_str(template.row_start.as_str());
        for ref col in self.cols.iter() {
            let formatted = format!("{}", col.out(template));
            out.push_str(formatted.as_str());
        }
        out.push_str(template.row_end.as_str());

        out
    }
}

struct Template {
    container_start: String,
    container_end: String,
    row_start: String,
    row_end: String,
    col_start: String,
    col_end: String,
    segment_start: String,
    segment_end: String,
    label: String,
    text: String,
    checkbox: String,
    radio: String,
    textarea: String,
    hr: String,
    button: String
}

/**
 * An empty line implies a new "row"
 * A line starting with a | implies a columnar form section
 * [value] is an input text field
 * {value} is an input textarea field
 * @ is a radio
 * * is a checkbox
 * --- is an hr
 *
 */
fn main() {
    // Read in standard input
    let mut buffer = String::new();
    io::stdin().read_to_string(&mut buffer)
        .expect("Error reading from stdin");

    // Split input by line
    let v: Vec<&str> = buffer.split("\n").collect();

    // Keep track of rows in output
    let mut rows: Vec<Row> = Vec::new();
    let mut row: Row = Row::new();

    // Check arg for template
    let template = match env::args().nth(1) {
        Some(file) => {
            let dir = env::current_dir().unwrap();
            let template_file = format!("{}/{}", dir.display(), file);

            let mut in_file = match File::open(&template_file) {
                Err(why) => panic!("Unable to open template file"),
                Ok(file) => file,
            };

            let mut content = String::new();
            in_file.read_to_string(&mut content)
                .expect("Unable to process template file");

            let sp: Vec<&str> = content.split("\n").collect();

            Template {
                container_start: sp[0].to_string().trim().to_string(),
                container_end: sp[14].to_string().trim().to_string(),
                row_start: sp[1].to_string().trim().to_string(),
                row_end: sp[13].to_string().trim().to_string(),
                col_start: sp[2].to_string().trim().to_string(),
                col_end: sp[12].to_string().trim().to_string(),
                segment_start: sp[3].to_string().trim().to_string(),
                segment_end: sp[11].to_string().trim().to_string(),
                label: sp[4].to_string().trim().to_string(),
                text: sp[5].to_string().trim().to_string(),
                checkbox: sp[6].to_string().trim().to_string(),
                radio: sp[7].to_string().trim().to_string(),
                textarea: sp[8].to_string().trim().to_string(),
                hr: sp[9].to_string().trim().to_string(),
                button: sp[10].to_string().trim().to_string()
            }

        },
        _ => Template {
            container_start: "".to_string(),
            container_end: "".to_string(),
            row_start: "
".to_string(),
            row_end: "
".to_string(),
            col_start: "".to_string(),
            col_end: "".to_string(),
            segment_start: "".to_string(),
            segment_end: "
".to_string(),
            label: "{[value}}".to_string(),
            text: "<input type=\"text\" value=\"{{value}}\"/>".to_string(),
            checkbox: "<input type=\"checkbox\"/>".to_string(),
            radio: "<input type=\"radio\"/>".to_string(),
            textarea: "<textarea>{{value}}</textarea>".to_string(),
            hr: "
".to_string(),
            button: "<button>{{value}}</button>".to_string()
        }
    };

    // Iterate over lines in input
    for line in &v {
        // New row by way of empty line
        if line.chars().count() == 0 {
            rows.push(row);
            row = Row::new();
            continue;
        }

        let mut form_mode = false; // If user toggled form mode
        let mut col_index: u8 = 1; // Keeping tracking of column index
        let mut dashes: u8 = 0; // Keep track of dash count

        // Iterate over characters in string
        for (i, c) in line.chars().enumerate() {
            // Match c against known tokens
            match c {
                '-' => {
                    dashes += 1;
                    if dashes == 3 {
                        row.get_col(col_index-1)
                            .append_str("
");
                        break;
                    }
                },
                '|' => {
                    if i == 0 {
                        form_mode = true;
                        row.get_col(col_index-1).add_buf()
                    } else if form_mode {
                        // Check if we have enough columns in row
                        // if not add a new column
                        if (row.col_count() as u8) < col_index + 1 {
                            row.add_col(Col::new());
                        }

                        // Increment index
                        col_index += 1;

                        row.get_col(col_index-1).add_buf();
                    } else {
                        row.get_col(col_index-1).append(c);
                    }
                },
                '<' => row.get_col(col_index-1)
                        .append_str(""),
                '>' => row.get_col(col_index-1)
                        .append_str(""),
                '[' => row.get_col(col_index-1)
                        .append_str("<input type=\"text\" value=\""),
                ']' => row.get_col(col_index-1)
                        .append_str("\">"),
                '{' => row.get_col(col_index-1)
                        .append_str("<textarea>"),
                '}' => row.get_col(col_index-1)
                        .append_str("</textarea>"),
                '@' => row.get_col(col_index-1)
                        .append_str("<input type=\"radio\">"),
                '(' => row.get_col(col_index-1)
                        .append_str("<button class=\"btn\">"),
                ')' => row.get_col(col_index-1)
                        .append_str("</button>"),
                _ => row.get_col(col_index-1).append(c)
            }
        }
    }

    println!("{}", template.container_start);
    for row in rows {
        println!("{}", row.out(&template));
    }
    println!("{}", template.container_end);
}
<|endoftext|>


<commit_before>#![feature(env)]
#![feature(core)]
#![feature(io)]
#![feature(os)]

use std::env;
use std::old_io;

fn main() {
    let upload_url = "http://uguu.se/api.php?d=upload";
    let shitty_args = env::args();
    let mut args = Vec::new();
    let counter: usize = 0;

    // I want to be able to index arguments so I push them to a vector.
    for x in shitty_args {
        match x.into_string() {
            Ok(r)   => args.push(r),
            Err(e)  => panic!("Something went wrong. It has something to do with command-line arguments. Error: {:?}", e),
        }
    }

    // Efficiency?
    let args_len: usize = args.len();

    if args_len < 2 {
        panic!("\n\nYou fucked up. Not enough arguments were supplied.
If you want to know how to use this program, use the --help flag (./uguupload --help)\n\n");
    }

    if args[1] == "--help" {
        println!("Uguupload - A program for uploading files to http://uguu.se

Usage: ./uguupload [options] [FILE]

[FILENAME] is the name you want for the file.
[FILE] is the path to the file you want to upload.

Uploading several files at once is possible. See Example 2 below.

OPTIONS
    -f, --filenames
        Allows you to specify filenames for files.
        See Example 3.

EXAMPLES
    Example 1:
        ./uguupload foo.txt
        This will return http://a.uguu.se/sdfyse_[FILE]

    Example 2:
        ./uguupload foo.txt bar.txt foobar.txt
        This will return three (3) files

    Example 3:
        ./uguupload -f foo.txt foo.txt bar.txt foo.txt foobar.txt foo.txt

        The first argument, foo.txt is the filename and the second argument, foo.txt, is the file and so on.
        bar.txt is the filename and foo.txt is the file. Same for foobar.txt and foo.txt

        Syntax in other words:
        ./uguupload -f [FILENAME] [FILE]");

        return;
    } else if args[1] == "-f" || args[1] == "--filenames" {
        upload_files_filenames(upload_url, args, args_len, counter);
    } else {
        upload_files(upload_url, args, args_len, counter);
    }
}

// Upload files where the name of the file is the filename.
fn upload_files(upload_url: &str, args: Vec<String>, args_len: usize, counter: usize) {
    for x in range(1, args_len) {
        // Checking stuff so we don't go out of the index.
        if x + counter < args_len {
            let filename = format!("name={}", args[x + counter]);
            let file = format!("file=@{}", args[x + counter]);

            let mut curl = old_io::Command::new("curl");
                curl.args(&["-F", filename.as_slice()]);
                curl.args(&["-F", file.as_slice()]);
                curl.arg(upload_url);

            match curl.output() {
                Ok(r)   => {
                    if String::from_utf8_lossy(r.output.as_slice()) == "" {
                        println!("Failed to upload: {}", args[x + counter]);
                    } else {
                        println!("\nSuccessfully uploaded {}\n{}", args[x + counter], String::from_utf8_lossy(r.output.as_slice()));
                    }
                },
                Err(e)  => panic!("Failed to upload: {}", e),
            }
        }
    }
}

//Upload files with user-specified filenames
fn upload_files_filenames(upload_url: &str, args: Vec<String>, args_len: usize, mut counter: usize) {
    // The index starts at two (2) because of the flag
    for x in range(2, args_len) {
        // Checking stuff so we don't go out of the index.
        if x + 1 + counter < args_len {
            let filename = format!("name={}", args[x + counter]);
            let file = format!("file=@{}", args[x + 1 + counter]);

            let mut curl = old_io::Command::new("curl");
                curl.args(&["-F", filename.as_slice()]);
                curl.args(&["-F", file.as_slice()]);
                curl.arg(upload_url);

            match curl.output() {
                Ok(r)   => {
                    if String::from_utf8_lossy(r.output.as_slice()) == "" {
                        println!("Failed to upload {}:{} (filename:file)", args[x + counter], args[x + 1 + counter]);
                    } else {
                        println!("\nSuccessfully uploaded {}:{} (filename:file)\n{}", args[x + counter], args[x + 1 + counter], String::from_utf8_lossy(r.output.as_slice()));
                    }
                },
                Err(e)  => panic!("Failed to upload: {}", e),
            }
        }

        counter += 1;
    }
}
<commit_msg>Added support for random names. the flag is -r<commit_after>#![feature(env)]
#![feature(core)]
#![feature(io)]
#![feature(os)]

use std::env;
use std::old_io;

fn main() {
    let upload_url = "http://uguu.se/api.php?d=upload";
    let shitty_args = env::args();
    let mut args = Vec::new();
    let counter: usize = 0;

    // I want to be able to index arguments so I push them to a vector.
    for x in shitty_args {
        match x.into_string() {
            Ok(r)   => args.push(r),
            Err(e)  => panic!("Something went wrong. It has something to do with command-line arguments. Error: {:?}", e),
        }
    }

    // Efficiency?
    let args_len: usize = args.len();

    if args_len < 2 {
        panic!("\n\nYou fucked up. Not enough arguments were supplied.
If you want to know how to use this program, use the --help flag (./uguupload --help)\n\n");
    }

    if args[1] == "--help" {
        println!("Usage: ./uguupload [options] [FILE]

[FILENAME] is the name you want for the file.
[FILE] is the path to the file you want to upload.

Uploading several files at once is possible. See Example 2 below.

OPTIONS
    -f, --filenames
        Allows you to specify filenames for files.
        See Example 3.

EXAMPLES
    Example 1:
        ./uguupload foo.txt
        This will return http://a.uguu.se/sdfyse_[FILE]

    Example 2:
        ./uguupload foo.txt bar.txt foobar.txt
        This will return three (3) files

    Example 3:
        ./uguupload -f foo.txt foo.txt bar.txt foo.txt foobar.txt foo.txt

        The first argument, foo.txt is the filename and the second argument, foo.txt, is the file and so on.
        bar.txt is the filename and foo.txt is the file. Same for foobar.txt and foo.txt

        Syntax in other words:
        ./uguupload -f [FILENAME] [FILE]");

        return;
    } else if args[1] == "-f" || args[1] == "--filename" {
        upload_files_filenames(upload_url, args, args_len, counter);
    } else if args[1] == "-r" || args[1] == "--random" {
        upload_files_random_filenames(upload_url, args, args_len, counter);
    } else {
        upload_files(upload_url, args, args_len, counter);
    }
}

// Upload files where the name of the file is the filename.
fn upload_files(upload_url: &str, args: Vec<String>, args_len: usize, counter: usize) {
    for x in range(1, args_len) {
        // Checking stuff so we don't go out of the index.
        if x + counter < args_len {
            let filename = format!("name={}", args[x + counter]);
            let file = format!("file=@{}", args[x + counter]);

            let mut curl = old_io::Command::new("curl");
                curl.args(&["-F", filename.as_slice()]);
                curl.args(&["-F", file.as_slice()]);
                curl.arg(upload_url);

            match curl.output() {
                Ok(r)   => {
                    if String::from_utf8_lossy(r.output.as_slice()) == "" {
                        println!("Failed to upload: {}", args[x + counter]);
                    } else {
                        println!("\nSuccessfully uploaded {}\n{}", args[x + counter], String::from_utf8_lossy(r.output.as_slice()));
                    }
                },
                Err(e)  => panic!("Failed to upload: {}", e),
            }
        }
    }
}

//Upload files with user-specified filenames
fn upload_files_filenames(upload_url: &str, args: Vec<String>, args_len: usize, mut counter: usize) {
    // The index starts at two (2) because of the flag
    for x in range(2, args_len) {
        // Checking stuff so we don't go out of the index.
        if x + 1 + counter < args_len {
            let filename = format!("name={}", args[x + counter]);
            let file = format!("file=@{}", args[x + 1 + counter]);

            let mut curl = old_io::Command::new("curl");
                curl.args(&["-F", filename.as_slice()]);
                curl.args(&["-F", file.as_slice()]);
                curl.arg(upload_url);

            match curl.output() {
                Ok(r)   => {
                    if String::from_utf8_lossy(r.output.as_slice()) == "" {
                        println!("Failed to upload {}:{} (filename:file)", args[x + counter], args[x + 1 + counter]);
                    } else {
                        println!("\nSuccessfully uploaded {}:{} (filename:file)\n{}", args[x + counter], args[x + 1 + counter], String::from_utf8_lossy(r.output.as_slice()));
                    }
                },
                Err(e)  => panic!("Failed to upload: {}", e),
            }
        }

        counter += 1;
    }
}

fn upload_files_random_filenames(upload_url: &str, args: Vec<String>, args_len: usize, counter: usize) {
    for x in range(2, args_len) {
        // Checking stuff so we don't go out of the index.
        if x + counter < args_len {
            let filename = format!("name={}", args[x + counter]);
            let file = format!("file=@{}", args[x + counter]);

            let mut curl = old_io::Command::new("curl");
                curl.args(&["-F", filename.as_slice()]);
                curl.args(&["-F", file.as_slice()]);
                curl.args(&["-F", "randomname=true"]);
                curl.arg(upload_url);

            match curl.output() {
                Ok(r)   => {
                    if String::from_utf8_lossy(r.output.as_slice()) == "" {
                        println!("Failed to upload: {}", args[x + counter]);
                    } else {
                        println!("\nSuccessfully uploaded {}\n{}", args[x + counter], String::from_utf8_lossy(r.output.as_slice()));
                    }
                },
                Err(e)  => panic!("Failed to upload: {}", e),
            }
        }
    }
}
<|endoftext|>


<commit_before>mod operation;
mod tokenize;
mod log_entry;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate chrono;
extern crate clap;

use log_entry::log_entry::LogEntry;
use operation::operation::OperationSource;
use clap::{Arg, App};
use std::io::prelude::*;
use std::path::Path;
use std::fs::File;
use std::io::BufReader;
use std::collections::HashMap;
use chrono::{DateTime, UTC};

#[derive(Debug, Serialize, Deserialize)]
struct OutputEntry {
    unique_id : String,
    timestamp : DateTime<UTC>,
    episode_number: u16,
    complete_download: bool
}

impl OutputEntry {
    fn from(e : &LogEntry) -> OutputEntry {
        OutputEntry {
            unique_id: match e.request_id {
                Some(ref x) => x.clone(),
                None => "".to_string()
            },
            timestamp: e.timestamp.clone(),
            episode_number: 0,
            complete_download: e.was_complete_download()
        }
    }
}

fn main() {
    let matches = App::new("Podlog")
        .version("0.1")
        .arg(Arg::with_name("FILENAME")
            .required(true)
            .index(1))
        .get_matches();

    let filename = matches.value_of("FILENAME").unwrap();
    let mut results : HashMap<String, Vec<OutputEntry> > = HashMap::new();
    foo(filename, &mut results);
}

fn foo(filename : &str, results : &mut HashMap<String, Vec<OutputEntry> >) -> () {
    let path = Path::new(filename);
    let file = BufReader::new(File::open(&path).unwrap());
    let lines = file.lines().filter_map(|result| result.ok()); // Filter out bad rows
    let entries = lines.map(|x| LogEntry::from_str(&x))
                       .filter(|x| x.operation.source == OperationSource::WEBSITE)
                       .filter(|ref x| x.is_audio_file());

    for entry in entries {
        let path = entry.path.clone().unwrap();
        if !results.contains_key(&path) {
            results.insert(path, Vec::new());
        } else {
            let mut x = results.get_mut(&path);
            if x.is_some() {
                x.as_mut().unwrap().push(OutputEntry::from(&entry));
            }
        }
    }
    let storage = serde_json::to_string_pretty(&results).unwrap();
    println!("{}", storage);
}

// Output Format:
// UniqueID, DateTime, Episode, Was Complete Download
<commit_msg>Move results printing out of the main body<commit_after>mod operation;
mod tokenize;
mod log_entry;

#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate chrono;
extern crate clap;

use log_entry::log_entry::LogEntry;
use operation::operation::OperationSource;
use clap::{Arg, App};
use std::io::prelude::*;
use std::path::Path;
use std::fs::File;
use std::io::BufReader;
use std::collections::HashMap;
use chrono::{DateTime, UTC};

#[derive(Debug, Serialize, Deserialize)]
struct OutputEntry {
    unique_id : String,
    timestamp : DateTime<UTC>,
    episode_number: u16,
    complete_download: bool
}

impl OutputEntry {
    fn from(e : &LogEntry) -> OutputEntry {
        OutputEntry {
            unique_id: match e.request_id {
                Some(ref x) => x.clone(),
                None => "".to_string()
            },
            timestamp: e.timestamp.clone(),
            episode_number: 0,
            complete_download: e.was_complete_download()
        }
    }
}

fn main() {
    let matches = App::new("Podlog")
        .version("0.1")
        .arg(Arg::with_name("FILENAME")
            .required(true)
            .index(1))
        .get_matches();

    let filename = matches.value_of("FILENAME").unwrap();
    let mut results : HashMap<String, Vec<OutputEntry> > = HashMap::new();
    foo(filename, &mut results);
    let storage = serde_json::to_string_pretty(&results).unwrap();
    println!("{}", storage);
}

fn foo(filename : &str, results : &mut HashMap<String, Vec<OutputEntry> >) -> () {
    let path = Path::new(filename);
    let file = BufReader::new(File::open(&path).unwrap());
    let lines = file.lines().filter_map(|result| result.ok()); // Filter out bad rows
    let entries = lines.map(|x| LogEntry::from_str(&x))
                       .filter(|x| x.operation.source == OperationSource::WEBSITE)
                       .filter(|ref x| x.is_audio_file());

    for entry in entries {
        let path = entry.path.clone().unwrap();
        if !results.contains_key(&path) {
            results.insert(path, Vec::new());
        } else {
            let mut x = results.get_mut(&path);
            if x.is_some() {
                x.as_mut().unwrap().push(OutputEntry::from(&entry));
            }
        }
    }
}

// Output Format:
// UniqueID, DateTime, Episode, Was Complete Download
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>add CHIP8 struct<commit_after>fn main() {
    let chip = CHIP8::new();
    println!("{:?}", chip);
}

const RAM_SIZE: usize = 4096;
const GPR_COUNT: usize = 16;

#[derive(Debug)]
struct CHIP8 {
    ram: Vec<u8>,

    // Current opcode
    opcode: u16,

    // General Purpose Registers
    v: Vec<u8>,

    // Index Register
    i: u16,

    // Program Counter
    pc: u16,
}

impl CHIP8 {
    pub fn new() -> CHIP8 {
        let ram = vec![0; RAM_SIZE];

        CHIP8 {
            ram: ram,
            opcode: 0,
            v: vec![0; GPR_COUNT],
            i: 0,
            pc: 0,
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate bmp;
extern crate num;

use num::complex::*;
use bmp::{Image, Pixel};

const SIZE: u32 = 512;
const ESCAPE_LIMIT: f64 = 1000000.0;
const ITER_LIMIT: u32 = 200;
const WIDTH: f64 = 3.0;
const HEIGHT: f64 = 3.0;
const C_VAL: Complex64 = Complex{re: 0.25, im: 0.5};

// Mendelbrot transform
fn fractal_func(c: Complex64) -> Box<Fn(Complex64) -> Complex64>
{
    return Box::new(move |z: Complex64| z.powf(2.0) + c);
}

fn run_until_escape(z: Complex64, escape_limit: f64, iter_limit: u32,
                    gen_fn: Box<Fn(Complex64) -> Complex64>) -> u32
{
    let mut temp = z;
    let mut n: u32 = 0;
    while temp.norm_sqr() < escape_limit && n < iter_limit {
        n += 1;
        temp = (*gen_fn)(temp);
    }

    return n;
}

fn main() {
    let mut img = Image::new(SIZE, SIZE);
    /*
    // Fixed size Array, using vectors instead
    let mut pixels: [[u32; (SIZE as usize)]; (SIZE as usize)] =
        [[0; (SIZE as usize)]; (SIZE as usize)];
    */
    let mut pixels = vec![vec![0; (SIZE as usize)]; (SIZE as usize)];

    for (x,y) in img.coordinates()
    {
        let float_x: f64 = WIDTH*((x as f64)/(SIZE as f64) - 0.5);
        let float_y: f64 = HEIGHT*((y as f64)/(SIZE as f64) - 0.5);
        let iterations = run_until_escape(Complex{re:float_x, im:float_y},
            ESCAPE_LIMIT, ITER_LIMIT,
            fractal_func(C_VAL));
        pixels[x as usize][y as usize] = iterations;
    }

    let mut max = 0;
    for x in 0..SIZE {
        for y in 0..SIZE {
            let current = pixels[x as usize][y as usize];
            if current < ITER_LIMIT && current > max {
               max = current;
            }
        }
    }
    println!("{}", max);

    for x in 0..SIZE {
        for y in 0..SIZE {
            let current = pixels[x as usize][y as usize];
            if current < ITER_LIMIT {
                pixels[x as usize][y as usize] *= 256;
                pixels[x as usize][y as usize] /= max;
            }
            else {
                pixels[x as usize][y as usize] = 256;
            }
        }
    }

    for (x,y) in img.coordinates()
    {
        let val = pixels[x as usize][y as usize];
        img.set_pixel(x, y, px!(val, val, val));
    }
    let _ = img.save("test.bmp");
}
<commit_msg>Changed to linear indexing and added a more compact max pixel calculation<commit_after>#[macro_use]
extern crate bmp;
extern crate num;

use num::complex::*;
use bmp::{Image, Pixel};

const SIZE: u32 = 512;
const ESCAPE_LIMIT: f64 = 1000000.0;
const ITER_LIMIT: u32 = 200;
const WIDTH: f64 = 3.0;
const HEIGHT: f64 = 3.0;
const C_VAL: Complex64 = Complex{re: 0.25, im: 0.5};

// Mendelbrot transform
fn fractal_func(c: Complex64) -> Box<Fn(Complex64) -> Complex64>
{
    return Box::new(move |z: Complex64| z.powf(2.0) + c);
}

fn run_until_escape(z: Complex64, escape_limit: f64, iter_limit: u32,
                    gen_fn: Box<Fn(Complex64) -> Complex64>) -> u32
{
    let mut temp = z;
    let mut n: u32 = 0;
    while temp.norm_sqr() < escape_limit && n < iter_limit {
        n += 1;
        temp = (*gen_fn)(temp);
    }

    return n;
}

fn main() {
    let mut pixels = vec![0; (SIZE*SIZE) as usize];

    let coordinates: Vec<(u32, u32)> = (0..SIZE).flat_map(move |x| (0..SIZE).map(move |y| (x,y))).collect();
    for &(x, y) in &coordinates {
        let float_x: f64 = WIDTH*((x as f64)/(SIZE as f64) - 0.5);
        let float_y: f64 = HEIGHT*((y as f64)/(SIZE as f64) - 0.5);
        let iterations = run_until_escape(Complex{re:float_x, im:float_y},
                                          ESCAPE_LIMIT, ITER_LIMIT,
                                          fractal_func(C_VAL));
        pixels[(SIZE*x + y) as usize] = iterations;
    }

    let max = pixels.iter().cloned().filter(|&x| x < ITER_LIMIT).max().unwrap();
    println!("max pixel: {}", max);

    for &(x, y) in &coordinates {
            let current = pixels[(SIZE*x + y) as usize];
            if current < ITER_LIMIT {
                pixels[(SIZE*x + y) as usize] *= 256;
                pixels[(SIZE*x + y) as usize] /= max;
            }
            else {
                pixels[(SIZE*x + y) as usize] = 256;
            }
    }

    let mut img = Image::new(SIZE, SIZE);
    for (x,y) in img.coordinates()
    {
        let val = pixels[(SIZE*x + y) as usize];
        img.set_pixel(x, y, px!(val, val, val));
    }

    let _ = img.save("test.bmp");
}
<|endoftext|>