<commit_before>// MIT License
//
// Copyright (c) 2016 Alexander Thaller <alexander@thaller.ws>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
extern crate chrono;
extern crate githelper;
extern crate lablog_lib;
extern crate loggerv;
extern crate regex;
extern crate tempdir;
extern crate xdg;

#[macro_use]
extern crate clap;

#[macro_use]
extern crate log;

use chrono::*;
use clap::App;
use clap::ArgMatches as Args;
use lablog_lib::file_to_string;
use lablog_lib::filter_notes_by_timestamp;
use lablog_lib::format_projects_notes;
use lablog_lib::get_projects;
use lablog_lib::get_projects_notes;
use lablog_lib::get_timeline_for_notes;
use lablog_lib::git_commit_note;
use lablog_lib::Note;
use lablog_lib::ProjectsNotes;
use lablog_lib::try_multiple_time_parser;
use lablog_lib::write_note;
use log::LogLevel;
use regex::Regex;
use std::collections::BTreeMap as DataMap;
use std::collections::BTreeSet as DataSet;
use std::env;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use tempdir::TempDir;
use xdg::BaseDirectories;

#[derive(Debug)]
struct Options {
    datadir: PathBuf,
}

fn main() {
    let yaml = load_yaml!("cli.yml");
    let app = App::from_yaml(yaml)
        .version(crate_version!())
        .get_matches();

    let matches = match app.subcommand.clone() {
        Some(subcommand) => subcommand.matches,
        None => app.clone(),
    };

    let loglevel: LogLevel = app.value_of("loglevel").unwrap().parse().unwrap();
    loggerv::init_with_level(loglevel).unwrap();

    let options = get_options(&app);

    trace!("app: {:#?}", app);
    trace!("matches: {:#?}", matches);
    trace!("options: {:#?}", options);

    run(app, options)
}

fn run(args: Args, options: Options) {
    match args.subcommand.clone() {
        Some(command) => {
            match command.name.as_str() {
                "dates" => run_dates(command.matches, options),
                "note" => run_note(command.matches, options),
                "notes" => run_notes(command.matches, options),
                "timestamps" => run_timestamps(command.matches, options),
                "projects" => run_projects(command.matches, options),
                "repo" => run_repo(command.matches, options),
                "search" => run_search(command.matches, options),
                "timeline" => run_timeline(command.matches, options),
                _ => {
                    error!("do not know what to do with this command: {}",
                           command.name.as_str())
                }
            }
        }
        None => run_projects(args, options),
    }
}

fn run_dates(args: Args, options: Options) {
    let notes = get_filtered_notes(&args, &options);

    let mut dates = DataMap::default();
    for notes in notes.values() {
        for note in notes {
            *dates.entry(note.time_stamp.date()).or_insert(0) += 1;
        }
    }

    for (date, count) in dates {
        println!("{} {}", date, count)
    }
}

fn run_note(args: Args, options: Options) {
    trace!("run_note args: {:#?}", args);
    let project = args.value_of("project");

    let text = if args.is_present("editor") {
        string_from_editor()
    } else {
        match args.value_of("file") {
            Some(file_path) => {
                let file_text = file_to_string(Path::new(file_path)).unwrap();
                trace!("text from file: {}", file_text);
                file_text
            }
            None => {
                match args.value_of("text") {
                    Some(text) => String::from(text),
                    None => String::from(""),
                }
            }
        }
    };

    debug!("project: {:#?}", project);
    debug!("text: {}", text);

    let timestamp: DateTime<UTC> = match args.value_of("timestamp") {
        None => UTC::now().into(),
        Some(ts) => ts.parse().unwrap(),
    };

    let note = Note {
        time_stamp: timestamp,
        value: text.into(),
    };

    if write_note(&options.datadir, project, &note).is_some() {
        git_commit_note(&options.datadir, project, &note)
    }
}

fn run_notes(args: Args, options: Options) {
    let notes = get_filtered_notes(&args, &options);
    println!("{}", format_projects_notes(notes));
}

fn run_timestamps(args: Args, options: Options) {
    let notes = get_filtered_notes(&args, &options);

    for (project, notes) in notes {
        println!("{}", project);

        for (i, note) in notes.iter().enumerate() {
            println!("{}\t{}", i, note.time_stamp)
        }

        println!("");
    }
}

fn run_projects(args: Args, options: Options) {
    let projects = get_projects(&options.datadir, args.value_of("project"));
    trace!("projects: {:#?}", projects);

    for project in projects {
        println!("{}", project)
    }
}

fn run_repo(args: Args, options: Options) {
    if let Some(command) = args.subcommand.clone() {
        match command.name.as_str() {
            "init" => run_repo_init(&args, options),
            "pull" => run_repo_pull(options),
            "push" => run_repo_push(options),
            "sync" => run_repo_sync(options),
            _ => {
                error!("do not know what to do with this command: {}",
                       command.name.as_str())
            }
        }
    }
}

fn run_repo_pull(options: Options) {
    info!("pulling from remote repository");
    githelper::pull(options.datadir.as_path()).expect("can not pull from repo");
}

fn run_repo_push(options: Options) {
    info!("pushing to remote repository");
    githelper::push(options.datadir.as_path()).expect("can not push to repo");
}

fn run_repo_sync(options: Options) {
    info!("syncing with remote repository");
    githelper::sync(options.datadir.as_path()).expect("can not sync with repo");
}

fn run_repo_init(args: &Args, options: Options) {
    let datadir = options.datadir;

    match args.value_of("remote") {
        Some(remote) => {
            match githelper::clone(datadir.as_path(), remote) {
                Err(err) => error!("can not clone git repository from remote: {}", err),
                Ok(info) => info!("repo was cloned: {}", info),
            }
        }
        None => {
            match githelper::status(datadir.as_path()) {
                Ok(status) => error!("repository is already initialized: {}", status),
                Err(_) => {
                    githelper::init(datadir.as_path()).expect("can not initialize git repo");
                    githelper::commit(datadir.as_path(), "initial commit")
                        .expect("can not add initial commit to git repo");
                }
            };
        }
    }
}

fn run_search(args: Args, options: Options) {
    let text = args.value_of("text").unwrap();
    let notes = get_filtered_notes(&args, &options);

    let re = Regex::new(text).unwrap();

    let mut searched = DataMap::default();
    for (project, notes) in notes {
        for note in notes {
            for line in note.value.lines() {
                if re.is_match(line) {
                    debug!("match on line: {}", line);

                    let find = re.find(line).unwrap();

                    debug!("find: {:#?}", find);

                    let replaced = String::from(line);
                    // Disabled until
                    // https://doc.rust-lang.org/std/string/struct.String.html#method.insert_str is
                    // in stable
                    // let mut replaced = String::from(line);
                    // replaced.insert_str(find.1, "\x1B[0m\x1B[0m");
                    // replaced.insert_str(find.0, "\x1B[1m\x1B[31m");

                    debug!("replaced: {}", replaced);

                    searched.entry(project.clone())
                        .or_insert_with(DataSet::default)
                        .insert(replaced);
                }
            }
        }
    }

    let mut out = String::new();

    for (project, notes) in searched {
        out.push_str(format!("== {}\n", project).as_str());
        for note in notes {
            out.push_str(note.as_str());
            out.push_str("\n");
        }

        out.push_str("\n\n");
    }

    println!("{}", out);
}

fn run_timeline(args: Args, options: Options) {
    let notes = get_filtered_notes(&args, &options);
    println!("{}", get_timeline_for_notes(notes));
}

fn string_from_editor() -> String {
    let tmpdir = TempDir::new("lablog_tmp").unwrap();
    let tmppath = tmpdir.path().join("note.asciidoc");
    let editor = match env::var("VISUAL") {
        Ok(val) => val,
        Err(_) => {
            match env::var("EDITOR") {
                Ok(val) => val,
                Err(_) => panic!("Neither $VISUAL nor $EDITOR is set."),
            }
        }
    };

    let mut editor_command = Command::new(editor);
    editor_command.arg(tmppath.display().to_string());

    let editor_proc = editor_command.spawn();
    if editor_proc.expect("Couldn't launch editor").wait().is_ok() {
        file_to_string(&tmppath).unwrap()
    } else {
        panic!("The editor broke")
    }
}

fn get_options(args: &Args) -> Options {
    let datadir = match args.value_of("datadir").unwrap() {
        "$XDG_DATA_HOME/lablog" => {
            let xdg = BaseDirectories::new().unwrap();
            xdg.create_data_directory("lablog").unwrap()
        }
        _ => PathBuf::from(args.value_of("datadir").unwrap()),
    };

    let options = Options { datadir: datadir };

    debug!("options: {:?}", options);
    options
}

fn get_filtered_notes(args: &Args, options: &Options) -> ProjectsNotes {
    let projects = get_projects(&options.datadir, args.value_of("project"));
    let project_notes = get_projects_notes(&options.datadir, projects);

    let after_notes = match args.value_of("filter_after") {
        Some(filter) => {
            debug!("filter notes after {}", filter);
            let timestamp = try_multiple_time_parser(filter)
                .expect("can not parse timestamp from after parameter");
            debug!("filter notes after timestamp: {:#?}", timestamp);

            filter_notes_by_timestamp(project_notes, timestamp, true)
        }
        None => project_notes,
    };

    match args.value_of("filter_before") {
        Some(filter) => {
            debug!("filter notes before timestamp {}", filter);
            let timestamp = try_multiple_time_parser(filter)
                .expect("can not parse timestamp from parameter");
            debug!("filter notes before timestamp parsed: {:#?}", timestamp);

            filter_notes_by_timestamp(after_notes, timestamp, false)
        }
        None => after_notes,
    }
}
<commit_msg>Fixed coloring of the search.<commit_after>// MIT License
//
// Copyright (c) 2016 Alexander Thaller <alexander@thaller.ws>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#![feature(insert_str)]

extern crate chrono;
extern crate githelper;
extern crate lablog_lib;
extern crate loggerv;
extern crate regex;
extern crate tempdir;
extern crate xdg;

#[macro_use]
extern crate clap;

#[macro_use]
extern crate log;

use chrono::*;
use clap::App;
use clap::ArgMatches as Args;
use lablog_lib::file_to_string;
use lablog_lib::filter_notes_by_timestamp;
use lablog_lib::format_projects_notes;
use lablog_lib::get_projects;
use lablog_lib::get_projects_notes;
use lablog_lib::get_timeline_for_notes;
use lablog_lib::git_commit_note;
use lablog_lib::Note;
use lablog_lib::ProjectsNotes;
use lablog_lib::try_multiple_time_parser;
use lablog_lib::write_note;
use log::LogLevel;
use regex::Regex;
use std::collections::BTreeMap as DataMap;
use std::collections::BTreeSet as DataSet;
use std::env;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use tempdir::TempDir;
use xdg::BaseDirectories;

#[derive(Debug)]
struct Options {
    datadir: PathBuf,
}

fn main() {
    let yaml = load_yaml!("cli.yml");
    let app = App::from_yaml(yaml)
        .version(crate_version!())
        .get_matches();

    let matches = match app.subcommand.clone() {
        Some(subcommand) => subcommand.matches,
        None => app.clone(),
    };

    let loglevel: LogLevel = app.value_of("loglevel").unwrap().parse().unwrap();
    loggerv::init_with_level(loglevel).unwrap();

    let options = get_options(&app);

    trace!("app: {:#?}", app);
    trace!("matches: {:#?}", matches);
    trace!("options: {:#?}", options);

    run(app, options)
}

fn run(args: Args, options: Options) {
    match args.subcommand.clone() {
        Some(command) => {
            match command.name.as_str() {
                "dates" => run_dates(command.matches, options),
                "note" => run_note(command.matches, options),
                "notes" => run_notes(command.matches, options),
                "timestamps" => run_timestamps(command.matches, options),
                "projects" => run_projects(command.matches, options),
                "repo" => run_repo(command.matches, options),
                "search" => run_search(command.matches, options),
                "timeline" => run_timeline(command.matches, options),
                _ => {
                    error!("do not know what to do with this command: {}",
                           command.name.as_str())
                }
            }
        }
        None => run_projects(args, options),
    }
}

fn run_dates(args: Args, options: Options) {
    let notes = get_filtered_notes(&args, &options);

    let mut dates = DataMap::default();
    for notes in notes.values() {
        for note in notes {
            *dates.entry(note.time_stamp.date()).or_insert(0) += 1;
        }
    }

    for (date, count) in dates {
        println!("{} {}", date, count)
    }
}

fn run_note(args: Args, options: Options) {
    trace!("run_note args: {:#?}", args);
    let project = args.value_of("project");

    let text = if args.is_present("editor") {
        string_from_editor()
    } else {
        match args.value_of("file") {
            Some(file_path) => {
                let file_text = file_to_string(Path::new(file_path)).unwrap();
                trace!("text from file: {}", file_text);
                file_text
            }
            None => {
                match args.value_of("text") {
                    Some(text) => String::from(text),
                    None => String::from(""),
                }
            }
        }
    };

    debug!("project: {:#?}", project);
    debug!("text: {}", text);

    let timestamp: DateTime<UTC> = match args.value_of("timestamp") {
        None => UTC::now().into(),
        Some(ts) => ts.parse().unwrap(),
    };

    let note = Note {
        time_stamp: timestamp,
        value: text.into(),
    };

    if write_note(&options.datadir, project, &note).is_some() {
        git_commit_note(&options.datadir, project, &note)
    }
}

fn run_notes(args: Args, options: Options) {
    let notes = get_filtered_notes(&args, &options);
    println!("{}", format_projects_notes(notes));
}

fn run_timestamps(args: Args, options: Options) {
    let notes = get_filtered_notes(&args, &options);

    for (project, notes) in notes {
        println!("{}", project);

        for (i, note) in notes.iter().enumerate() {
            println!("{}\t{}", i, note.time_stamp)
        }

        println!("");
    }
}

fn run_projects(args: Args, options: Options) {
    let projects = get_projects(&options.datadir, args.value_of("project"));
    trace!("projects: {:#?}", projects);

    for project in projects {
        println!("{}", project)
    }
}

fn run_repo(args: Args, options: Options) {
    if let Some(command) = args.subcommand.clone() {
        match command.name.as_str() {
            "init" => run_repo_init(&args, options),
            "pull" => run_repo_pull(options),
            "push" => run_repo_push(options),
            "sync" => run_repo_sync(options),
            _ => {
                error!("do not know what to do with this command: {}",
                       command.name.as_str())
            }
        }
    }
}

fn run_repo_pull(options: Options) {
    info!("pulling from remote repository");
    githelper::pull(options.datadir.as_path()).expect("can not pull from repo");
}

fn run_repo_push(options: Options) {
    info!("pushing to remote repository");
    githelper::push(options.datadir.as_path()).expect("can not push to repo");
}

fn run_repo_sync(options: Options) {
    info!("syncing with remote repository");
    githelper::sync(options.datadir.as_path()).expect("can not sync with repo");
}

fn run_repo_init(args: &Args, options: Options) {
    let datadir = options.datadir;

    match args.value_of("remote") {
        Some(remote) => {
            match githelper::clone(datadir.as_path(), remote) {
                Err(err) => error!("can not clone git repository from remote: {}", err),
                Ok(info) => info!("repo was cloned: {}", info),
            }
        }
        None => {
            match githelper::status(datadir.as_path()) {
                Ok(status) => error!("repository is already initialized: {}", status),
                Err(_) => {
                    githelper::init(datadir.as_path()).expect("can not initialize git repo");
                    githelper::commit(datadir.as_path(), "initial commit")
                        .expect("can not add initial commit to git repo");
                }
            };
        }
    }
}

fn run_search(args: Args, options: Options) {
    let text = args.value_of("text").unwrap();
    let notes = get_filtered_notes(&args, &options);

    let re = Regex::new(text).unwrap();

    let mut searched = DataMap::default();
    for (project, notes) in notes {
        for note in notes {
            for line in note.value.lines() {
                if re.is_match(line) {
                    debug!("match on line: {}", line);

                    let find = re.find(line).unwrap();

                    debug!("find: {:#?}", find);

                    let mut replaced = String::from(line);
                    replaced.insert_str(find.1, "\x1B[0m\x1B[0m");
                    replaced.insert_str(find.0, "\x1B[1m\x1B[31m");

                    debug!("replaced: {}", replaced);

                    searched.entry(project.clone())
                        .or_insert_with(DataSet::default)
                        .insert(replaced);
                }
            }
        }
    }

    let mut out = String::new();

    for (project, notes) in searched {
        out.push_str(format!("== {}\n", project).as_str());
        for note in notes {
            out.push_str(note.as_str());
            out.push_str("\n");
        }

        out.push_str("\n\n");
    }

    println!("{}", out);
}

fn run_timeline(args: Args, options: Options) {
    let notes = get_filtered_notes(&args, &options);
    println!("{}", get_timeline_for_notes(notes));
}

fn string_from_editor() -> String {
    let tmpdir = TempDir::new("lablog_tmp").unwrap();
    let tmppath = tmpdir.path().join("note.asciidoc");
    let editor = match env::var("VISUAL") {
        Ok(val) => val,
        Err(_) => {
            match env::var("EDITOR") {
                Ok(val) => val,
                Err(_) => panic!("Neither $VISUAL nor $EDITOR is set."),
            }
        }
    };

    let mut editor_command = Command::new(editor);
    editor_command.arg(tmppath.display().to_string());

    let editor_proc = editor_command.spawn();
    if editor_proc.expect("Couldn't launch editor").wait().is_ok() {
        file_to_string(&tmppath).unwrap()
    } else {
        panic!("The editor broke")
    }
}

fn get_options(args: &Args) -> Options {
    let datadir = match args.value_of("datadir").unwrap() {
        "$XDG_DATA_HOME/lablog" => {
            let xdg = BaseDirectories::new().unwrap();
            xdg.create_data_directory("lablog").unwrap()
        }
        _ => PathBuf::from(args.value_of("datadir").unwrap()),
    };

    let options = Options { datadir: datadir };

    debug!("options: {:?}", options);
    options
}

fn get_filtered_notes(args: &Args, options: &Options) -> ProjectsNotes {
    let projects = get_projects(&options.datadir, args.value_of("project"));
    let project_notes = get_projects_notes(&options.datadir, projects);

    let after_notes = match args.value_of("filter_after") {
        Some(filter) => {
            debug!("filter notes after {}", filter);
            let timestamp = try_multiple_time_parser(filter)
                .expect("can not parse timestamp from after parameter");
            debug!("filter notes after timestamp: {:#?}", timestamp);

            filter_notes_by_timestamp(project_notes, timestamp, true)
        }
        None => project_notes,
    };

    match args.value_of("filter_before") {
        Some(filter) => {
            debug!("filter notes before timestamp {}", filter);
            let timestamp = try_multiple_time_parser(filter)
                .expect("can not parse timestamp from parameter");
            debug!("filter notes before timestamp parsed: {:#?}", timestamp);

            filter_notes_by_timestamp(after_notes, timestamp, false)
        }
        None => after_notes,
    }
}
<|endoftext|>


<commit_before>//! Super fast HTML template engine.

use std::fmt;
use std::fmt::Writer as FmtWriter;

pub type FmtResult<T> = Result<T, fmt::Error>;

/// Utilities for escaping HTML5 markup.
///
/// These follow the *HTML fragment serialization algorithm*, as
/// specified by the [HTML 5.1 Working Draft][1].
///
/// [1]: http://www.w3.org/TR/html51/syntax.html#escapingString
pub mod escape {
    use std::fmt::Writer as FmtWriter;

    use super::render;
    use super::rt;

    /// Escape a double-quoted attribute value, as per HTML5 rules.
    pub fn attribute(s: &str) -> String {
        render(|w| rt::escape_attribute(w, |w| w.write_str(s)))
    }

    /// Escape non-attribute text content, as per HTML5 rules.
    pub fn non_attribute(s: &str) -> String {
        render(|w| rt::escape_non_attribute(w, |w| w.write_str(s)))
    }
}

/// Internal functions used by the `maud_macros` package. You should
/// never need to call these directly.
#[experimental = "These functions should not be called directly.
Use the macros in `maud_macros` instead."]
pub mod rt {
    use std::fmt::Writer as FmtWriter;
    use super::FmtResult;

    struct AttrEscaper<'a, 'b: 'a> {
        inner: &'a mut (FmtWriter + 'b),
    }

    impl<'a, 'b> FmtWriter for AttrEscaper<'a, 'b> {
        fn write_str(&mut self, s: &str) -> FmtResult<()> {
            for c in s.chars() {
                try!(match c {
                    '&' => self.inner.write_str("&"),
                    '\u{A0}' => self.inner.write_str(" "),
                    '"' => self.inner.write_str("""),
                    _ => write!(self.inner, "{}", c),
                });
            }
            Ok(())
        }
    }

    struct NonAttrEscaper<'a, 'b: 'a> {
        inner: &'a mut (FmtWriter + 'b),
    }

    impl<'a, 'b> FmtWriter for NonAttrEscaper<'a, 'b> {
        fn write_str(&mut self, s: &str) -> FmtResult<()> {
            for c in s.chars() {
                try!(match c {
                    '&' => self.inner.write_str("&"),
                    '\u{A0}' => self.inner.write_str(" "),
                    '<' => self.inner.write_str("<"),
                    '>' => self.inner.write_str(">"),
                    _ => write!(self.inner, "{}", c),
                });
            }
            Ok(())
        }
    }

    #[inline]
    pub fn escape_attribute<F>(w: &mut FmtWriter, f: F) -> FmtResult<()> where
        F: FnOnce(&mut FmtWriter) -> FmtResult<()>
    {
        f(&mut AttrEscaper { inner: w })
    }

    #[inline]
    pub fn escape_non_attribute<F>(w: &mut FmtWriter, f: F) -> FmtResult<()> where
        F: FnOnce(&mut FmtWriter) -> FmtResult<()>
    {
        f(&mut NonAttrEscaper { inner: w })
    }
}

/// Render a template into a `String`.
pub fn render<F>(template: F) -> String where
    F: FnOnce(&mut FmtWriter) -> FmtResult<()>
{
    let mut buf = String::new();
    template(&mut buf).unwrap();
    buf
}
<commit_msg>Mute unstable warnings<commit_after>//! Super fast HTML template engine.

#![allow(unstable)]

use std::fmt;
use std::fmt::Writer as FmtWriter;

pub type FmtResult<T> = Result<T, fmt::Error>;

/// Utilities for escaping HTML5 markup.
///
/// These follow the *HTML fragment serialization algorithm*, as
/// specified by the [HTML 5.1 Working Draft][1].
///
/// [1]: http://www.w3.org/TR/html51/syntax.html#escapingString
pub mod escape {
    use std::fmt::Writer as FmtWriter;

    use super::render;
    use super::rt;

    /// Escape a double-quoted attribute value, as per HTML5 rules.
    pub fn attribute(s: &str) -> String {
        render(|w| rt::escape_attribute(w, |w| w.write_str(s)))
    }

    /// Escape non-attribute text content, as per HTML5 rules.
    pub fn non_attribute(s: &str) -> String {
        render(|w| rt::escape_non_attribute(w, |w| w.write_str(s)))
    }
}

/// Internal functions used by the `maud_macros` package. You should
/// never need to call these directly.
#[experimental = "These functions should not be called directly.
Use the macros in `maud_macros` instead."]
pub mod rt {
    use std::fmt::Writer as FmtWriter;
    use super::FmtResult;

    struct AttrEscaper<'a, 'b: 'a> {
        inner: &'a mut (FmtWriter + 'b),
    }

    impl<'a, 'b> FmtWriter for AttrEscaper<'a, 'b> {
        fn write_str(&mut self, s: &str) -> FmtResult<()> {
            for c in s.chars() {
                try!(match c {
                    '&' => self.inner.write_str("&"),
                    '\u{A0}' => self.inner.write_str(" "),
                    '"' => self.inner.write_str("""),
                    _ => write!(self.inner, "{}", c),
                });
            }
            Ok(())
        }
    }

    struct NonAttrEscaper<'a, 'b: 'a> {
        inner: &'a mut (FmtWriter + 'b),
    }

    impl<'a, 'b> FmtWriter for NonAttrEscaper<'a, 'b> {
        fn write_str(&mut self, s: &str) -> FmtResult<()> {
            for c in s.chars() {
                try!(match c {
                    '&' => self.inner.write_str("&"),
                    '\u{A0}' => self.inner.write_str(" "),
                    '<' => self.inner.write_str("<"),
                    '>' => self.inner.write_str(">"),
                    _ => write!(self.inner, "{}", c),
                });
            }
            Ok(())
        }
    }

    #[inline]
    pub fn escape_attribute<F>(w: &mut FmtWriter, f: F) -> FmtResult<()> where
        F: FnOnce(&mut FmtWriter) -> FmtResult<()>
    {
        f(&mut AttrEscaper { inner: w })
    }

    #[inline]
    pub fn escape_non_attribute<F>(w: &mut FmtWriter, f: F) -> FmtResult<()> where
        F: FnOnce(&mut FmtWriter) -> FmtResult<()>
    {
        f(&mut NonAttrEscaper { inner: w })
    }
}

/// Render a template into a `String`.
pub fn render<F>(template: F) -> String where
    F: FnOnce(&mut FmtWriter) -> FmtResult<()>
{
    let mut buf = String::new();
    template(&mut buf).unwrap();
    buf
}
<|endoftext|>


<commit_before>
#[allow(unused_assignments)]

pub fn add (a: i8, b: i8) -> i8 {
    let mut i: i8 = 0;
    let mut c: i8 = 0;
    i = a ^ b;
    c = (a & b) << 1;

    if c & i != 0i8 {
        return add(i, c);
    }
    return i | c;
}

pub fn subtract (a: i8, b: i8) -> i8 {
    let not_b_plus_1 = add(!b, 1i8);
    return add(a, not_b_plus_1);
}

// return a > b
pub fn gt(a: i8, b: i8) -> bool {
    let a = a ^ 0b1000_0000;
    let b = b ^ 0b1000_0000;

    let mut ltb = (!a & b) as u8;
    let mut gtb = (a & !b) as u8;

    ltb = ltb | (ltb >> 1);
    ltb = ltb | (ltb >> 2);
    ltb = ltb | (ltb >> 4);

    return (gtb & !ltb) != 0;
}

pub fn lt(a: i8, b: i8) -> bool {
    return a != b && !gt(a, b);
}
<commit_msg>clean up warnings<commit_after>
#[allow(unused_assignments)]

pub fn add (a: i8, b: i8) -> i8 {
    let mut i: i8 = 0;
    let mut c: i8 = 0;
    i = a ^ b;
    c = (a & b) << 1;

    if c & i != 0i8 {
        return add(i, c);
    }
    return i | c;
}

pub fn subtract (a: i8, b: i8) -> i8 {
    let not_b_plus_1 = add(!b, 1i8);
    return add(a, not_b_plus_1);
}

// return a > b
#[allow(overflowing_literals)]
pub fn gt(a: i8, b: i8) -> bool {
    let a = a ^ 0b1000_0000;
    let b = b ^ 0b1000_0000;

    let mut ltb = (!a & b) as u8;
    let gtb = (a & !b) as u8;

    ltb = ltb | (ltb >> 1);
    ltb = ltb | (ltb >> 2);
    ltb = ltb | (ltb >> 4);

    return (gtb & !ltb) != 0;
}

pub fn lt(a: i8, b: i8) -> bool {
    return a != b && !gt(a, b);
}
<|endoftext|>


<commit_before>use sdl2;
use sdl2::audio::{AudioCallback,AudioDevice,AudioSpecDesired};
use sdl2::event::Event;
use sdl2::pixels::Color::RGB;
use sdl2::rect::Rect;
use sdl2::render::Renderer;
use sdl2::keyboard::Scancode;
use sdl2::Sdl;
use super::{GFX_H,GFX_W,Mode,wav};

const SCALE: usize = 8;

pub struct BeepCallback;

impl BeepCallback {
    fn new() -> Self {
        BeepCallback
    }
}

impl AudioCallback for BeepCallback {
    type Channel = u8;

    fn callback(&mut self, out: &mut [u8]) {
        assert!(out.len() == wav::PLAYBACK_BUFFER.len());
        for i in 0..wav::PLAYBACK_BUFFER.len() {
            out[i] = wav::PLAYBACK_BUFFER[i];
        }
    }

}

pub struct Ui {
    sdl_ctx: Sdl,
    renderer: Renderer<'static>,
    audio: AudioDevice<BeepCallback>,
}

impl Ui {

    pub fn new() -> Self {
        let sdl_ctx = sdl2::init().unwrap();
        let video_subsystem = sdl_ctx.video().unwrap();
        let window = video_subsystem.window("chip8",
                                     (GFX_W * SCALE) as u32,
                                     (GFX_H * SCALE) as u32)
                                    .position_centered()
                                    .build()
                                    .unwrap();

        let renderer = window.renderer().build().unwrap();

        let audio_subsystem = sdl_ctx.audio().unwrap();
        let audio_spec = AudioSpecDesired {
            freq: Some(wav::SAMPLE_RATE_HZ as i32),
            channels: Some(wav::CHANNELS as u8),
            samples: Some(wav::SAMPLES as u16)
        };

        let audio = audio_subsystem.open_playback(None, audio_spec, |_| {
            BeepCallback::new()
        }).unwrap();

        Ui { sdl_ctx: sdl_ctx, renderer: renderer, audio: audio }
    }

    pub fn beep(&self, on: bool) {
        match on {
            true => self.audio.resume(),
            false => self.audio.pause()
        }
    }

    pub fn refresh_gfx(&mut self, mode: Mode, gfx: &[[bool; GFX_H]; GFX_W]) {
        let bg = RGB(0x1c, 0x28, 0x41);
        let fg = RGB(0xff, 0xff, 0xff);
        let scale_factor = match (mode) {
            Mode::CHIP8 => SCALE * 2,
            Mode::SCHIP8 => SCALE
        };
        for x in 0..GFX_W {
            for y in 0..GFX_H {
                let pix_on = gfx[x][y];
                let color = if pix_on {fg} else {bg};
                let rx = (x * scale_factor) as i32;
                let ry = (y * scale_factor) as i32;
                let rw = scale_factor as u32;
                let rh = scale_factor as u32;
                let rect = Rect::new(rx, ry, rw, rh).unwrap().unwrap();
                self.renderer.set_draw_color(color);
                self.renderer.fill_rect(rect);
            }
        }
        self.renderer.present();
    }

    pub fn poll_event(&self) -> Option<Event> {
        let mut event_pump = self.sdl_ctx.event_pump().unwrap();
        return event_pump.poll_event();
    }

    pub fn get_updated_keys(&self) -> [bool; 16] {
        let event_pump = self.sdl_ctx.event_pump().unwrap();
        let keyboard_state = event_pump.keyboard_state();
        let mut keys = [false; 16];
        keys[0x0] = keyboard_state.is_scancode_pressed(Scancode::X);
        keys[0x1] = keyboard_state.is_scancode_pressed(Scancode::Num1);
        keys[0x2] = keyboard_state.is_scancode_pressed(Scancode::Num2);
        keys[0x3] = keyboard_state.is_scancode_pressed(Scancode::Num3);
        keys[0x4] = keyboard_state.is_scancode_pressed(Scancode::Q);
        keys[0x5] = keyboard_state.is_scancode_pressed(Scancode::W);
        keys[0x6] = keyboard_state.is_scancode_pressed(Scancode::E);
        keys[0x7] = keyboard_state.is_scancode_pressed(Scancode::A);
        keys[0x8] = keyboard_state.is_scancode_pressed(Scancode::S);
        keys[0x9] = keyboard_state.is_scancode_pressed(Scancode::D);
        keys[0xA] = keyboard_state.is_scancode_pressed(Scancode::Z);
        keys[0xB] = keyboard_state.is_scancode_pressed(Scancode::C);
        keys[0xC] = keyboard_state.is_scancode_pressed(Scancode::Num4);
        keys[0xD] = keyboard_state.is_scancode_pressed(Scancode::R);
        keys[0xE] = keyboard_state.is_scancode_pressed(Scancode::F);
        keys[0xF] = keyboard_state.is_scancode_pressed(Scancode::V);
        keys
    }

}
<commit_msg>Commented projection of subscreen onto drawing canvas.<commit_after>use sdl2;
use sdl2::audio::{AudioCallback,AudioDevice,AudioSpecDesired};
use sdl2::event::Event;
use sdl2::pixels::Color::RGB;
use sdl2::rect::Rect;
use sdl2::render::Renderer;
use sdl2::keyboard::Scancode;
use sdl2::Sdl;
use super::{GFX_H,GFX_W,Mode,wav};

const SCALE: usize = 8;

pub struct BeepCallback;

impl BeepCallback {
    fn new() -> Self {
        BeepCallback
    }
}

impl AudioCallback for BeepCallback {
    type Channel = u8;

    fn callback(&mut self, out: &mut [u8]) {
        assert!(out.len() == wav::PLAYBACK_BUFFER.len());
        for i in 0..wav::PLAYBACK_BUFFER.len() {
            out[i] = wav::PLAYBACK_BUFFER[i];
        }
    }

}

pub struct Ui {
    sdl_ctx: Sdl,
    renderer: Renderer<'static>,
    audio: AudioDevice<BeepCallback>,
}

impl Ui {

    pub fn new() -> Self {
        let sdl_ctx = sdl2::init().unwrap();
        let video_subsystem = sdl_ctx.video().unwrap();
        let window = video_subsystem.window("chip8",
                                     (GFX_W * SCALE) as u32,
                                     (GFX_H * SCALE) as u32)
                                    .position_centered()
                                    .build()
                                    .unwrap();

        let renderer = window.renderer().build().unwrap();

        let audio_subsystem = sdl_ctx.audio().unwrap();
        let audio_spec = AudioSpecDesired {
            freq: Some(wav::SAMPLE_RATE_HZ as i32),
            channels: Some(wav::CHANNELS as u8),
            samples: Some(wav::SAMPLES as u16)
        };

        let audio = audio_subsystem.open_playback(None, audio_spec, |_| {
            BeepCallback::new()
        }).unwrap();

        Ui { sdl_ctx: sdl_ctx, renderer: renderer, audio: audio }
    }

    pub fn beep(&self, on: bool) {
        match on {
            true => self.audio.resume(),
            false => self.audio.pause()
        }
    }

    pub fn refresh_gfx(&mut self, mode: Mode, gfx: &[[bool; GFX_H]; GFX_W]) {
        let bg = RGB(0x1c, 0x28, 0x41);
        let fg = RGB(0xff, 0xff, 0xff);
        let projection_factor = match (mode) {
            //
            // For plain CHIP8 mode, the 64x32 gfx subscreen will be projected
            // to fit the entire viewable area. The excess between 64x32 and
            // 128x64 will be projected offscreen.
            // +-----------------------+-----------------------+
            // |                       |                       |
            // |         64x32         |                       |
            // |                       |                       |
            // +-----------------------+    drawn offscreen    |
            // |                                               |
            // |                                               |
            // |                                               |
            // +-----------------------------------------------+ (128x64)
            Mode::CHIP8 => SCALE * 2,
            Mode::SCHIP8 => SCALE
        };
        for x in 0..GFX_W {
            for y in 0..GFX_H {
                let pix_on = gfx[x][y];
                let color = if pix_on {fg} else {bg};
                let rx = (x * projection_factor) as i32;
                let ry = (y * projection_factor) as i32;
                let rw = projection_factor as u32;
                let rh = projection_factor as u32;
                let rect = Rect::new(rx, ry, rw, rh).unwrap().unwrap();
                self.renderer.set_draw_color(color);
                self.renderer.fill_rect(rect);
            }
        }
        self.renderer.present();
    }

    pub fn poll_event(&self) -> Option<Event> {
        let mut event_pump = self.sdl_ctx.event_pump().unwrap();
        return event_pump.poll_event();
    }

    pub fn get_updated_keys(&self) -> [bool; 16] {
        let event_pump = self.sdl_ctx.event_pump().unwrap();
        let keyboard_state = event_pump.keyboard_state();
        let mut keys = [false; 16];
        keys[0x0] = keyboard_state.is_scancode_pressed(Scancode::X);
        keys[0x1] = keyboard_state.is_scancode_pressed(Scancode::Num1);
        keys[0x2] = keyboard_state.is_scancode_pressed(Scancode::Num2);
        keys[0x3] = keyboard_state.is_scancode_pressed(Scancode::Num3);
        keys[0x4] = keyboard_state.is_scancode_pressed(Scancode::Q);
        keys[0x5] = keyboard_state.is_scancode_pressed(Scancode::W);
        keys[0x6] = keyboard_state.is_scancode_pressed(Scancode::E);
        keys[0x7] = keyboard_state.is_scancode_pressed(Scancode::A);
        keys[0x8] = keyboard_state.is_scancode_pressed(Scancode::S);
        keys[0x9] = keyboard_state.is_scancode_pressed(Scancode::D);
        keys[0xA] = keyboard_state.is_scancode_pressed(Scancode::Z);
        keys[0xB] = keyboard_state.is_scancode_pressed(Scancode::C);
        keys[0xC] = keyboard_state.is_scancode_pressed(Scancode::Num4);
        keys[0xD] = keyboard_state.is_scancode_pressed(Scancode::R);
        keys[0xE] = keyboard_state.is_scancode_pressed(Scancode::F);
        keys[0xF] = keyboard_state.is_scancode_pressed(Scancode::V);
        keys
    }

}
<|endoftext|>


<commit_before>use std::fmt as StdFmt;

use comment::Comment;

#[derive(Debug, Eq, PartialEq)]
pub enum Language {
    C,
    Header,
    Hpp,
    Cpp,
    Css,
    Html,
    Java,
    JavaScript,
    Perl,
    Php,
    Python,
    Ruby,
    Rust,
    Xml,
    Toml,
    Go,
}

impl Language {
    pub fn from_ext(ext: &str) -> Option<Language> {
        match ext {
            "cpp" | "cp" | "cc" | "cxx" | "c++" | "C" => Some(Language::Cpp),
            "hpp" | "h++" => Some(Language::Hpp),
            "c" => Some(Language::C),
            "h" => Some(Language::Header),
            "css" => Some(Language::Css),
            "java" => Some(Language::Java),
            "js" => Some(Language::JavaScript),
            "rs" => Some(Language::Rust),
            "xml" => Some(Language::Xml),
            "html" | "htm" => Some(Language::Html),
            "py" => Some(Language::Python),
            "rb" => Some(Language::Ruby),
            "php" => Some(Language::Php),
            "toml" => Some(Language::Toml),
            "pl" => Some(Language::Perl),
            "go" => Some(Language::Go),
            _ => None,
        }
    }

    pub fn name(&self) -> &str {
        match *self {
            Language::Cpp => "C++",
            Language::Hpp => "C++ Header",
            Language::C => "C",
            Language::Header => "C Header",
            Language::Css => "CSS",
            Language::Java => "Java",
            Language::JavaScript => "JavaScript",
            Language::Rust => "Rust",
            Language::Xml => "XML",
            Language::Html => "HTML",
            Language::Python => "Python",
            Language::Ruby => "Ruby",
            Language::Php => "PHP",
            Language::Toml => "TOML",
            Language::Perl => "Perl",
            Language::Go => "Go",
        }
    }

    pub fn is_unsafe(&self) -> bool {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Rust => true,
            _ => false,
        }
    }

    pub fn unsafe_keyword(&self) -> Option<&str> {
        match *self {
            Language::Rust => Some("unsafe"),
            _ => None,
        }
    }
}

impl StdFmt::Display for Language {
    fn fmt(&self, f: &mut StdFmt::Formatter) -> StdFmt::Result {
        write!(f, "{}", self.name())
    }
}

impl Comment for Language {
	type Rep = &'static str;

    fn single(&self) -> Option<Vec<<Self as Comment>::Rep>> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::JavaScript |
            Language::Rust |
            Language::Go => Some(vec!["//"]),
            Language::Php => Some(vec!["//", "#"]),
            Language::Xml |
            Language::Html => Some(vec!["<!--"]),
            Language::Ruby |
            Language::Python |
            Language::Toml |
            Language::Perl => Some(vec!["#"]),

        }
    }

    fn multi_start(&self) -> Option<<Self as Comment>::Rep> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::JavaScript |
            Language::Go |
            Language::Rust |
            Language::Php => Some("/*"),
            Language::Xml |
            Language::Html => Some("<!--"),
            Language::Ruby => Some("=begin"),
            Language::Python => Some("'''"),
            Language::Toml |
            Language::Perl => None,
        }
    }

    fn multi_end(&self) -> Option<<Self as Comment>::Rep> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::Go |
            Language::JavaScript |
            Language::Rust |
            Language::Php => Some("*/"),
            Language::Xml |
            Language::Html => Some("-->"),
            Language::Ruby => Some("=end"),
            Language::Python => Some("'''"),
            Language::Toml |
            Language::Perl => None,
        }
    }
}
<commit_msg>feat(languages): Add ASM, Shell, D and Nim<commit_after>use std::fmt as StdFmt;

use comment::Comment;

#[derive(Debug, Eq, PartialEq)]
pub enum Language {
    C,
    Header,
    Hpp,
    Cpp,
    Css,
    Html,
    Java,
    JavaScript,
    Perl,
    Php,
    Python,
    Ruby,
    Rust,
    Xml,
    Toml,
    Go,
    Assembly,
    Shell,
    D,
    Nim,
}

impl Language {
    pub fn from_ext(ext: &str) -> Option<Language> {
        match ext {
            "cpp" | "cp" | "cc" | "cxx" | "c++" | "C" => Some(Language::Cpp),
            "hpp" | "h++" => Some(Language::Hpp),
            "c" => Some(Language::C),
            "h" => Some(Language::Header),
            "css" => Some(Language::Css),
            "java" => Some(Language::Java),
            "js" => Some(Language::JavaScript),
            "rs" => Some(Language::Rust),
            "xml" => Some(Language::Xml),
            "html" | "htm" => Some(Language::Html),
            "py" => Some(Language::Python),
            "rb" => Some(Language::Ruby),
            "php" => Some(Language::Php),
            "toml" => Some(Language::Toml),
            "pl" => Some(Language::Perl),
            "go" => Some(Language::Go),
            "agc" | "asm" | "a51" | "inc" | "nasm" | "s" | "ms" => Some(Language::Assembly),
            "ps1" | "psd1" | "psm1" | "sh" | "bash" | "bats" | "cgi" | "command" | "fcgi" |
            "ksh" | "sh.in" | "tmux" | "tool" | "zsh" | "tcsh" | "csh" | "fish" => {
                Some(Language::Shell)
            }
            "d" | "di" => Some(Language::D),
            "nim" | "nimrod" => Some(Language::Nim),
            _ => None,
        }
    }

    pub fn name(&self) -> &str {
        match *self {
            Language::Cpp => "C++",
            Language::Hpp => "C++ Header",
            Language::C => "C",
            Language::Header => "C Header",
            Language::Css => "CSS",
            Language::Java => "Java",
            Language::JavaScript => "JavaScript",
            Language::Rust => "Rust",
            Language::Xml => "XML",
            Language::Html => "HTML",
            Language::Python => "Python",
            Language::Ruby => "Ruby",
            Language::Php => "PHP",
            Language::Toml => "TOML",
            Language::Perl => "Perl",
            Language::Go => "Go",
            Language::Assembly => "Assembly",
            Language::Shell => "Shell",
            Language::D => "D",
            Language::Nim => "Nim",
        }
    }

    pub fn is_unsafe(&self) -> bool {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Rust |
            Language::Assembly |
            Language::Nim => true,
            _ => false,
        }
    }

    pub fn unsafe_keyword(&self) -> Option<&str> {
        match *self {
            Language::Rust => Some("unsafe"),
            _ => None,
        }
    }
}

impl StdFmt::Display for Language {
    fn fmt(&self, f: &mut StdFmt::Formatter) -> StdFmt::Result {
        write!(f, "{}", self.name())
    }
}

impl Comment for Language {
    type Rep = &'static str;

    fn single(&self) -> Option<Vec<<Self as Comment>::Rep>> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::JavaScript |
            Language::Rust |
            Language::Go |
            Language::D => Some(vec!["//"]),
            Language::Php => Some(vec!["//", "#"]),
            Language::Xml |
            Language::Html => Some(vec!["<!--"]),
            Language::Ruby |
            Language::Python |
            Language::Toml |
            Language::Perl |
            Language::Assembly |
            Language::Shell |
            Language::Nim => Some(vec!["#"]),
        }
    }

    fn multi_start(&self) -> Option<<Self as Comment>::Rep> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::JavaScript |
            Language::Go |
            Language::Rust |
            Language::Php |
            Language::D => Some("/*"),
            Language::Xml |
            Language::Html => Some("<!--"),
            Language::Ruby => Some("=begin"),
            Language::Python => Some("'''"),
            Language::Nim => Some("#["),
            Language::Toml |
            Language::Perl |
            Language::Assembly |
            Language::Shell => None,
        }
    }

    fn multi_end(&self) -> Option<<Self as Comment>::Rep> {
        match *self {
            Language::C |
            Language::Cpp |
            Language::Hpp |
            Language::Header |
            Language::Css |
            Language::Java |
            Language::Go |
            Language::JavaScript |
            Language::Rust |
            Language::Php |
            Language::D => Some("*/"),
            Language::Xml |
            Language::Html => Some("-->"),
            Language::Ruby => Some("=end"),
            Language::Python => Some("'''"),
            Language::Nim => Some("]#"),
            Language::Toml |
            Language::Perl |
            Language::Assembly |
            Language::Shell => None,
        }
    }
}
<|endoftext|>


<commit_before>use super::imports::*;
use core::{Object, RpVersionedPackage, Version};
use semck;
use std::fmt;

/// Candidate to publish.
struct Match(Version, Box<Object>, RpPackage);

/// Formatting of candidate.
struct DisplayMatch<'a>(&'a Match);

impl<'a> fmt::Display for DisplayMatch<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let inner = &self.0;
        write!(f, "{}@{}", inner.1, inner.0)
    }
}

pub fn options<'a, 'b>() -> App<'a, 'b> {
    let out = SubCommand::with_name("publish").about("Publish specifications");

    let out = out.arg(Arg::with_name("force").long("force").help(
        "Force a publish, \
         even if it already \
         exists",
    ));

    let out = out.arg(Arg::with_name("pretend").long("pretend").help(
        "Pretend to \
         publish",
    ));

    let out = out.arg(Arg::with_name("no-semck").long("no-semck").help(
        "Disable Semantic \
         Checks",
    ));

    let out = out.arg(Arg::with_name("package").multiple(true));

    out
}

pub fn entry(matches: &ArgMatches) -> Result<()> {
    let manifest = setup_manifest(matches)?;
    let mut env = setup_env(&manifest)?;
    let mut repository = setup_repository(&manifest.repository)?;

    let mut resolver = setup_path_resolver(&manifest)?.ok_or_else(|| {
        "could not setup path resolver"
    })?;

    let packages: Vec<RpRequiredPackage> = matches
        .values_of("package")
        .into_iter()
        .flat_map(|it| it)
        .map(|p| RpRequiredPackage::parse(p).map_err(Into::into))
        .collect::<Result<_>>()?;

    let mut results = Vec::new();

    for publish in manifest.publish {
        let package = RpRequiredPackage::new(publish.package.clone(), None);
        let resolved = resolver.resolve(&package)?;

        if resolved.is_empty() {
            return Err(
                format!("no matching packages found for: {}", package).into(),
            );
        }

        // packages.push(RpRequiredPackage());
        for (_, object) in resolved {
            results.push(Match(
                publish.version.clone(),
                object,
                publish.package.clone(),
            ));
        }
    }

    for package in packages.iter() {
        let resolved = resolver.resolve(package)?;

        if resolved.is_empty() {
            return Err(
                format!("no matching packages found for: {}", package).into(),
            );
        }

        for (version, object) in resolved {
            let version = version.ok_or_else(
                || format!("{}: package without a version", object),
            )?;

            results.push(Match(version, object, package.package.clone()));
        }
    }

    let mut it = results.into_iter();

    let first = it.next().ok_or_else(|| format!("no packages to publish"))?;

    if let Some(next) = it.next() {
        warn!("matched: {}", DisplayMatch(&first));
        warn!("    and: {}", DisplayMatch(&next));

        while let Some(next) = it.next() {
            warn!("    and: {}", DisplayMatch(&next));
        }

        return Err("more than one matching package found".into());
    }

    let Match(version, object, package) = first;

    let force = matches.is_present("force");
    let pretend = matches.is_present("pretend");
    let no_semck = matches.is_present("no-semck");

    if !no_semck {
        // perform semck verification
        if let Some(d) = repository
            .all(&package)?
            .into_iter()
            .filter(|d| d.version.major == version.major)
            .last()
        {
            if d.version == version && !force {
                return Err(format!("Version {} already published", version).into());
            }

            info!("Checking semantics of {} -> {}", d.version, version);

            let previous = repository.get_object(&d)?.ok_or_else(|| {
                format!("No object found for deployment: {:?}", d)
            })?;

            let package_from = RpVersionedPackage::new(package.clone(), Some(d.version.clone()));
            let file_from = env.load_object(previous.clone(), &package_from)?;

            let package_to = RpVersionedPackage::new(package.clone(), Some(version.clone()));
            let file_to = env.load_object(object.clone(), &package_to)?;

            let violations = semck::check((&d.version, &file_from), (&version, &file_to))?;

            if !violations.is_empty() {
                let mut errors: Vec<Error> = Vec::new();

                for (i, v) in violations.into_iter().enumerate() {
                    errors.push(ErrorKind::SemckViolation(i, v).into());
                }

                errors.push("Hint: Use `--no-semck` to disable semantic checking".into());
                return Err(ErrorKind::Errors(errors).into());
            }
        }
    }

    if pretend {
        info!(
            "(pretend) publishing: {}@{} (from {})",
            package,
            version,
            object
        );
    } else {
        info!("publishing: {}@{} (from {})", package, version, object);
        repository.publish(&object, &package, &version, force)?;
    }

    Ok(())
}
<commit_msg>[publish] only check for multiple selected packages on arguments<commit_after>use super::imports::*;
use core::{Object, RpVersionedPackage, Version};
use semck;
use std::fmt;

/// Candidate to publish.
struct Match(Version, Box<Object>, RpPackage);

/// Formatting of candidate.
struct DisplayMatch<'a>(&'a (Option<Version>, Box<Object>));

impl<'a> fmt::Display for DisplayMatch<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let inner = &self.0;

        if let Some(ref version) = inner.0 {
            write!(f, "{}@{}", inner.1, version)
        } else {
            write!(f, "{}@*", inner.1)
        }
    }
}

pub fn options<'a, 'b>() -> App<'a, 'b> {
    let out = SubCommand::with_name("publish").about("Publish specifications");

    let out = out.arg(Arg::with_name("force").long("force").help(
        "Force a publish, \
         even if it already \
         exists",
    ));

    let out = out.arg(Arg::with_name("pretend").long("pretend").help(
        "Pretend to \
         publish",
    ));

    let out = out.arg(Arg::with_name("no-semck").long("no-semck").help(
        "Disable Semantic \
         Checks",
    ));

    let out = out.arg(Arg::with_name("package").multiple(true));

    out
}

pub fn entry(matches: &ArgMatches) -> Result<()> {
    let manifest = setup_manifest(matches)?;
    let mut env = setup_env(&manifest)?;

    let mut manifest_resolver = setup_path_resolver(&manifest)?.ok_or_else(|| {
        "could not setup manifest resolver"
    })?;

    let packages: Vec<RpRequiredPackage> = matches
        .values_of("package")
        .into_iter()
        .flat_map(|it| it)
        .map(|p| RpRequiredPackage::parse(p).map_err(Into::into))
        .collect::<Result<_>>()?;

    let mut results = Vec::new();

    for publish in manifest.publish {
        let package = RpRequiredPackage::new(publish.package.clone(), None);
        let resolved = manifest_resolver.resolve(&package)?;

        if resolved.is_empty() {
            return Err(
                format!("no matching packages found for: {}", package).into(),
            );
        }

        // packages.push(RpRequiredPackage());
        for (_, object) in resolved {
            results.push(Match(
                publish.version.clone(),
                object,
                publish.package.clone(),
            ));
        }
    }

    for package in packages.iter() {
        let resolved = manifest_resolver.resolve(package)?;

        if resolved.is_empty() {
            return Err(
                format!("no matching packages found for: {}", package).into(),
            );
        }

        let mut it = resolved.into_iter();

        let first = it.next().ok_or_else(|| format!("no packages to publish"))?;

        if let Some(next) = it.next() {
            warn!("matched: {}", DisplayMatch(&first));
            warn!("    and: {}", DisplayMatch(&next));

            while let Some(next) = it.next() {
                warn!("    and: {}", DisplayMatch(&next));
            }

            return Err("more than one matching package found".into());
        }

        let (version, object) = first;

        let version = version.ok_or_else(
            || format!("{}: package without a version", object),
        )?;

        results.push(Match(version, object, package.package.clone()));
    }

    let force = matches.is_present("force");
    let pretend = matches.is_present("pretend");
    let no_semck = matches.is_present("no-semck");

    let mut repository = setup_repository(&manifest.repository)?;

    let mut it = results.into_iter();

    while let Some(Match(version, object, package)) = it.next() {
        if !no_semck {
            // perform semck verification
            if let Some(d) = repository
                .all(&package)?
                .into_iter()
                .filter(|d| d.version.major == version.major)
                .last()
            {
                if d.version == version && !force {
                    return Err(format!("Version {} already published", version).into());
                }

                info!("Checking semantics of {} -> {}", d.version, version);

                let previous = repository.get_object(&d)?.ok_or_else(|| {
                    format!("No object found for deployment: {:?}", d)
                })?;

                let package_from =
                    RpVersionedPackage::new(package.clone(), Some(d.version.clone()));
                let file_from = env.load_object(previous.clone(), &package_from)?;

                let package_to = RpVersionedPackage::new(package.clone(), Some(version.clone()));
                let file_to = env.load_object(object.clone(), &package_to)?;

                let violations = semck::check((&d.version, &file_from), (&version, &file_to))?;

                if !violations.is_empty() {
                    let mut errors: Vec<Error> = Vec::new();

                    for (i, v) in violations.into_iter().enumerate() {
                        errors.push(ErrorKind::SemckViolation(i, v).into());
                    }

                    errors.push("Hint: Use `--no-semck` to disable semantic checking".into());
                    return Err(ErrorKind::Errors(errors).into());
                }
            }
        }

        if pretend {
            info!(
                "(pretend) publishing: {}@{} (from {})",
                package,
                version,
                object
            );
        } else {
            info!("publishing: {}@{} (from {})", package, version, object);
            repository.publish(&object, &package, &version, force)?;
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>//! Handle process life-time and message passing for proc-macro client

use crossbeam_channel::{bounded, Receiver, Sender};
use ra_tt::Subtree;

use crate::msg::{ErrorCode, Message, Request, Response, ResponseError};
use crate::rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind};

use io::{BufRead, BufReader};
use std::{
    convert::{TryFrom, TryInto},
    ffi::{OsStr, OsString},
    io::{self, Write},
    path::{Path, PathBuf},
    process::{Child, Command, Stdio},
    sync::{Arc, Weak},
};

#[derive(Debug, Default)]
pub(crate) struct ProcMacroProcessSrv {
    inner: Option<Weak<Sender<Task>>>,
}

#[derive(Debug)]
pub(crate) struct ProcMacroProcessThread {
    // XXX: drop order is significant
    sender: Arc<Sender<Task>>,
    handle: jod_thread::JoinHandle<()>,
}

struct Task {
    req: Request,
    result_tx: Sender<Option<Response>>,
}

struct Process {
    path: PathBuf,
    args: Vec<OsString>,
    child: Child,
}

impl Drop for Process {
    fn drop(&mut self) {
        let _ = self.child.kill();
    }
}

impl Process {
    fn run(
        path: PathBuf,
        args: impl IntoIterator<Item = impl AsRef<OsStr>>,
    ) -> io::Result<Process> {
        let args = args.into_iter().map(|s| s.as_ref().into()).collect();

        let child = Command::new(&path)
            .args(&args)
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::null())
            .spawn()?;

        Ok(Process { path, args, child })
    }

    fn restart(&mut self) -> io::Result<()> {
        let _ = self.child.kill();
        self.child = Command::new(&self.path)
            .args(&self.args)
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::null())
            .spawn()?;
        Ok(())
    }

    fn stdio(&mut self) -> Option<(impl Write, impl BufRead)> {
        let stdin = self.child.stdin.take()?;
        let stdout = self.child.stdout.take()?;
        let read = BufReader::new(stdout);

        Some((stdin, read))
    }
}

impl ProcMacroProcessSrv {
    pub fn run(
        process_path: PathBuf,
        args: impl IntoIterator<Item = impl AsRef<OsStr>>,
    ) -> io::Result<(ProcMacroProcessThread, ProcMacroProcessSrv)> {
        let process = Process::run(process_path, args)?;

        let (task_tx, task_rx) = bounded(0);
        let handle = jod_thread::spawn(move || {
            client_loop(task_rx, process);
        });

        let task_tx = Arc::new(task_tx);
        let srv = ProcMacroProcessSrv { inner: Some(Arc::downgrade(&task_tx)) };
        let thread = ProcMacroProcessThread { handle, sender: task_tx };

        Ok((thread, srv))
    }

    pub fn find_proc_macros(
        &self,
        dylib_path: &Path,
    ) -> Result<Vec<(String, ProcMacroKind)>, ra_tt::ExpansionError> {
        let task = ListMacrosTask { lib: dylib_path.to_path_buf() };

        let result: ListMacrosResult = self.send_task(Request::ListMacro(task))?;
        Ok(result.macros)
    }

    pub fn custom_derive(
        &self,
        dylib_path: &Path,
        subtree: &Subtree,
        derive_name: &str,
    ) -> Result<Subtree, ra_tt::ExpansionError> {
        let task = ExpansionTask {
            macro_body: subtree.clone(),
            macro_name: derive_name.to_string(),
            attributes: None,
            lib: dylib_path.to_path_buf(),
        };

        let result: ExpansionResult = self.send_task(Request::ExpansionMacro(task))?;
        Ok(result.expansion)
    }

    pub fn send_task<R>(&self, req: Request) -> Result<R, ra_tt::ExpansionError>
    where
        R: TryFrom<Response, Error = &'static str>,
    {
        let sender = match &self.inner {
            None => return Err(ra_tt::ExpansionError::Unknown("No sender is found.".to_string())),
            Some(it) => it,
        };

        let (result_tx, result_rx) = bounded(0);
        let sender = match sender.upgrade() {
            None => {
                return Err(ra_tt::ExpansionError::Unknown("Proc macro process is closed.".into()))
            }
            Some(it) => it,
        };
        sender.send(Task { req: req.into(), result_tx }).unwrap();
        let res = result_rx
            .recv()
            .map_err(|_| ra_tt::ExpansionError::Unknown("Proc macro thread is closed.".into()))?;

        match res {
            Some(Response::Error(err)) => {
                return Err(ra_tt::ExpansionError::ExpansionError(err.message));
            }
            Some(res) => Ok(res.try_into().map_err(|err| {
                ra_tt::ExpansionError::Unknown(format!(
                    "Fail to get response, reason : {:#?} ",
                    err
                ))
            })?),
            None => Err(ra_tt::ExpansionError::Unknown("Empty result".into())),
        }
    }
}

fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
    let (mut stdin, mut stdout) = match process.stdio() {
        None => return,
        Some(it) => it,
    };

    for task in task_rx {
        let Task { req, result_tx } = task;

        match send_request(&mut stdin, &mut stdout, req) {
            Ok(res) => result_tx.send(res).unwrap(),
            Err(_err) => {
                let res = Response::Error(ResponseError {
                    code: ErrorCode::ServerErrorEnd,
                    message: "Server closed".into(),
                });
                result_tx.send(res.into()).unwrap();
                // Restart the process
                if process.restart().is_err() {
                    break;
                }
                let stdio = match process.stdio() {
                    None => break,
                    Some(it) => it,
                };
                stdin = stdio.0;
                stdout = stdio.1;
            }
        }
    }
}

fn send_request(
    mut writer: &mut impl Write,
    mut reader: &mut impl BufRead,
    req: Request,
) -> io::Result<Option<Response>> {
    req.write(&mut writer)?;
    Ok(Response::read(&mut reader)?)
}
<commit_msg>Refactor a bit<commit_after>//! Handle process life-time and message passing for proc-macro client

use crossbeam_channel::{bounded, Receiver, Sender};
use ra_tt::Subtree;

use crate::msg::{ErrorCode, Message, Request, Response, ResponseError};
use crate::rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask, ProcMacroKind};

use io::{BufRead, BufReader};
use std::{
    convert::{TryFrom, TryInto},
    ffi::{OsStr, OsString},
    io::{self, Write},
    path::{Path, PathBuf},
    process::{Child, Command, Stdio},
    sync::{Arc, Weak},
};

#[derive(Debug, Default)]
pub(crate) struct ProcMacroProcessSrv {
    inner: Option<Weak<Sender<Task>>>,
}

#[derive(Debug)]
pub(crate) struct ProcMacroProcessThread {
    // XXX: drop order is significant
    sender: Arc<Sender<Task>>,
    handle: jod_thread::JoinHandle<()>,
}

impl ProcMacroProcessSrv {
    pub fn run(
        process_path: PathBuf,
        args: impl IntoIterator<Item = impl AsRef<OsStr>>,
    ) -> io::Result<(ProcMacroProcessThread, ProcMacroProcessSrv)> {
        let process = Process::run(process_path, args)?;

        let (task_tx, task_rx) = bounded(0);
        let handle = jod_thread::spawn(move || {
            client_loop(task_rx, process);
        });

        let task_tx = Arc::new(task_tx);
        let srv = ProcMacroProcessSrv { inner: Some(Arc::downgrade(&task_tx)) };
        let thread = ProcMacroProcessThread { handle, sender: task_tx };

        Ok((thread, srv))
    }

    pub fn find_proc_macros(
        &self,
        dylib_path: &Path,
    ) -> Result<Vec<(String, ProcMacroKind)>, ra_tt::ExpansionError> {
        let task = ListMacrosTask { lib: dylib_path.to_path_buf() };

        let result: ListMacrosResult = self.send_task(Request::ListMacro(task))?;
        Ok(result.macros)
    }

    pub fn custom_derive(
        &self,
        dylib_path: &Path,
        subtree: &Subtree,
        derive_name: &str,
    ) -> Result<Subtree, ra_tt::ExpansionError> {
        let task = ExpansionTask {
            macro_body: subtree.clone(),
            macro_name: derive_name.to_string(),
            attributes: None,
            lib: dylib_path.to_path_buf(),
        };

        let result: ExpansionResult = self.send_task(Request::ExpansionMacro(task))?;
        Ok(result.expansion)
    }

    pub fn send_task<R>(&self, req: Request) -> Result<R, ra_tt::ExpansionError>
    where
        R: TryFrom<Response, Error = &'static str>,
    {
        let sender = match &self.inner {
            None => return Err(ra_tt::ExpansionError::Unknown("No sender is found.".to_string())),
            Some(it) => it,
        };

        let (result_tx, result_rx) = bounded(0);
        let sender = match sender.upgrade() {
            None => {
                return Err(ra_tt::ExpansionError::Unknown("Proc macro process is closed.".into()))
            }
            Some(it) => it,
        };
        sender.send(Task { req: req.into(), result_tx }).unwrap();
        let res = result_rx
            .recv()
            .map_err(|_| ra_tt::ExpansionError::Unknown("Proc macro thread is closed.".into()))?;

        match res {
            Some(Response::Error(err)) => {
                return Err(ra_tt::ExpansionError::ExpansionError(err.message));
            }
            Some(res) => Ok(res.try_into().map_err(|err| {
                ra_tt::ExpansionError::Unknown(format!(
                    "Fail to get response, reason : {:#?} ",
                    err
                ))
            })?),
            None => Err(ra_tt::ExpansionError::Unknown("Empty result".into())),
        }
    }
}

fn client_loop(task_rx: Receiver<Task>, mut process: Process) {
    let (mut stdin, mut stdout) = match process.stdio() {
        None => return,
        Some(it) => it,
    };

    for task in task_rx {
        let Task { req, result_tx } = task;

        match send_request(&mut stdin, &mut stdout, req) {
            Ok(res) => result_tx.send(res).unwrap(),
            Err(_err) => {
                let res = Response::Error(ResponseError {
                    code: ErrorCode::ServerErrorEnd,
                    message: "Server closed".into(),
                });
                result_tx.send(res.into()).unwrap();
                // Restart the process
                if process.restart().is_err() {
                    break;
                }
                let stdio = match process.stdio() {
                    None => break,
                    Some(it) => it,
                };
                stdin = stdio.0;
                stdout = stdio.1;
            }
        }
    }
}

struct Task {
    req: Request,
    result_tx: Sender<Option<Response>>,
}

struct Process {
    path: PathBuf,
    args: Vec<OsString>,
    child: Child,
}

impl Drop for Process {
    fn drop(&mut self) {
        let _ = self.child.kill();
    }
}

impl Process {
    fn run(
        path: PathBuf,
        args: impl IntoIterator<Item = impl AsRef<OsStr>>,
    ) -> io::Result<Process> {
        let args = args.into_iter().map(|s| s.as_ref().into()).collect();
        let child = mk_child(&path, &args)?;
        Ok(Process { path, args, child })
    }

    fn restart(&mut self) -> io::Result<()> {
        let _ = self.child.kill();
        self.child = mk_child(&self.path, &self.args)?;
        Ok(())
    }

    fn stdio(&mut self) -> Option<(impl Write, impl BufRead)> {
        let stdin = self.child.stdin.take()?;
        let stdout = self.child.stdout.take()?;
        let read = BufReader::new(stdout);

        Some((stdin, read))
    }
}

fn mk_child(path: &Path, args: impl IntoIterator<Item = impl AsRef<OsStr>>) -> io::Result<Child> {
    Command::new(&path)
        .args(args)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::null())
        .spawn()
}

fn send_request(
    mut writer: &mut impl Write,
    mut reader: &mut impl BufRead,
    req: Request,
) -> io::Result<Option<Response>> {
    req.write(&mut writer)?;
    Ok(Response::read(&mut reader)?)
}
<|endoftext|>


<commit_before>use super::behaviors::{MouseBehavior, SelectionBehavior};
use crate::prelude::*;

widget!(
    /// The `ToggleButton` widget can be clicked by user and could switch between selected / not selected.
    /// It's used to perform an action.
    ///
    /// **CSS element:** `toggle-button`
    ToggleButton: MouseHandler,
    ChangedHandler {
        /// Sets or shares the background property.
        background: Brush,

        /// Sets or shares the border radius property.
        border_radius: f64,

        /// Sets or shares the border thickness property.
        border_width: Thickness,

        /// Sets or shares the border brush property.
        border_brush: Brush,

        /// Sets or shares the padding property.
        padding: Thickness,

        /// Sets or shares the foreground property.
        foreground: Brush,

        /// Sets or shares the text property.
        text: String16,

        /// Sets or share the font size property.
        font_size: f64,

        /// Sets or shares the font property.
        font: String,

        /// Sets or shares the icon property.
        icon: String,

        /// Sets or shares the icon brush property.
        icon_brush: Brush,

        /// Sets or share the icon font size property.
        icon_size: f64,

        /// Sets or shares the icon font property.
        icon_font: String,

        /// Sets or shares the pressed property.
        pressed: bool,

        /// Sets or shares the selected property.
        selected: bool
    }
);

impl Template for ToggleButton {
    fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
        self.name("ToggleButton")
            .element("toggle-button")
            .selected(false)
            .height(36.0)
            .min_width(64.0)
            .background(colors::LYNCH_COLOR)
            .border_radius(4.0)
            .border_width(0.0)
            .border_brush("transparent")
            .padding((16.0, 0.0, 16.0, 0.0))
            .foreground(colors::LINK_WATER_COLOR)
            .text("")
            .font_size(fonts::FONT_SIZE_12)
            .font("Roboto Regular")
            .icon("")
            .icon_font("Material Icons")
            .icon_size(fonts::ICON_FONT_SIZE_12)
            .icon_brush(colors::LINK_WATER_COLOR)
            .pressed(false)
            .child(
                MouseBehavior::create()
                    .pressed(id)
                    .enabled(id)
                    .target(id.0)
                    .child(
                        SelectionBehavior::create()
                            .selected(id)
                            .enabled(id)
                            .target(id.0)
                            .child(
                                Container::create()
                                    .background(id)
                                    .border_radius(id)
                                    .border_width(id)
                                    .border_brush(id)
                                    .padding(id)
                                    .child(
                                        Stack::create()
                                            .orientation("horizontal")
                                            .vertical_alignment("center")
                                            .horizontal_alignment("center")
                                            .child(
                                                FontIconBlock::create()
                                                    .margin((0.0, 0.0, 2.0, 0.0))
                                                    .icon(id)
                                                    .icon_brush(id)
                                                    .icon_size(id)
                                                    .icon_font(id)
                                                    .build(ctx),
                                            )
                                            .child(
                                                TextBlock::create()
                                                    .foreground(id)
                                                    .text(id)
                                                    .font_size(id)
                                                    .font(id)
                                                    .build(ctx),
                                            )
                                            .build(ctx),
                                    )
                                    .build(ctx),
                            )
                            .build(ctx),
                    )
                    .build(ctx),
            )
    }
}
<commit_msg>Update togglebutton layout.<commit_after>use super::behaviors::{MouseBehavior, SelectionBehavior};
use crate::prelude::*;

widget!(
    /// The `ToggleButton` widget can be clicked by user and could switch between selected / not selected.
    /// It's used to perform an action.
    ///
    /// **CSS element:** `toggle-button`
    ToggleButton: MouseHandler,
    ChangedHandler {
        /// Sets or shares the background property.
        background: Brush,

        /// Sets or shares the border radius property.
        border_radius: f64,

        /// Sets or shares the border thickness property.
        border_width: Thickness,

        /// Sets or shares the border brush property.
        border_brush: Brush,

        /// Sets or shares the padding property.
        padding: Thickness,

        /// Sets or shares the foreground property.
        foreground: Brush,

        /// Sets or shares the text property.
        text: String16,

        /// Sets or share the font size property.
        font_size: f64,

        /// Sets or shares the font property.
        font: String,

        /// Sets or shares the icon property.
        icon: String,

        /// Sets or shares the icon brush property.
        icon_brush: Brush,

        /// Sets or share the icon font size property.
        icon_size: f64,

        /// Sets or shares the icon font property.
        icon_font: String,

        /// Sets or shares the pressed property.
        pressed: bool,

        /// Sets or shares the selected property.
        selected: bool,

            /// Sets or shares the spacing between icon and text.
            spacing: f64
    }
);

impl Template for ToggleButton {
    fn template(self, id: Entity, ctx: &mut BuildContext) -> Self {
        self.name("ToggleButton")
            .element("toggle-button")
            .selected(false)
            .height(36.0)
            .min_width(64.0)
            .background(colors::LYNCH_COLOR)
            .border_radius(4.0)
            .border_width(0.0)
            .border_brush("transparent")
            .padding((16.0, 0.0, 16.0, 0.0))
            .foreground(colors::LINK_WATER_COLOR)
            .text("")
            .font_size(fonts::FONT_SIZE_12)
            .font("Roboto Regular")
            .icon("")
            .icon_font("Material Icons")
            .icon_size(fonts::ICON_FONT_SIZE_12)
            .icon_brush(colors::LINK_WATER_COLOR)
            .pressed(false)
            .spacing(8.0)
            .child(
                MouseBehavior::create()
                    .pressed(id)
                    .enabled(id)
                    .target(id.0)
                    .child(
                        SelectionBehavior::create()
                            .selected(id)
                            .enabled(id)
                            .target(id.0)
                            .child(
                                Container::create()
                                    .background(id)
                                    .border_radius(id)
                                    .border_width(id)
                                    .border_brush(id)
                                    .padding(id)
                                    .child(
                                        Stack::create()
                                            .orientation("horizontal")
                                            .spacing(id)
                                            .vertical_alignment("center")
                                            .horizontal_alignment("center")
                                            .child(
                                                FontIconBlock::create()
                                                .vertical_alignment("center")
                                                    .icon(id)
                                                    .icon_brush(id)
                                                    .icon_size(id)
                                                    .icon_font(id)
                                                    .build(ctx),
                                            )
                                            .child(
                                                TextBlock::create()
                                                .vertical_alignment("center")
                                                    .foreground(id)
                                                    .text(id)
                                                    .font_size(id)
                                                    .font(id)
                                                    .build(ctx),
                                            )
                                            .build(ctx),
                                    )
                                    .build(ctx),
                            )
                            .build(ctx),
                    )
                    .build(ctx),
            )
    }
}
<|endoftext|>


<commit_before><commit_msg>Add deleted comments in tests of module `impls_index`<commit_after><|endoftext|>


<commit_before>
extern crate libc;
mod mruby
{

    use libc::{c_char};

#[repr(C)]
    struct mrb_state;
#[repr(C)]
    struct mrb_value;
#[repr(C)]
    struct RClass;

#[link(name="m")]
#[link(name="mruby")]
    extern "C" {
        fn mrb_open() -> *mut mrb_state;
        fn mrb_load_string(state:*mut mrb_state,s:*const c_char) -> mrb_value;
        fn mrb_close(state:*mut mrb_state);
        fn mrb_class_get(state:*mut mrb_state,name:*const c_char) -> *mut RClass;
        fn mrb_define_class(state:*mut mrb_state,name:*const c_char,class:*mut RClass) -> *mut RClass;
    }

    pub struct Mrb{
        state:*mut mrb_state
    }

    pub struct Value {
        val :*mut mrb_value
    }

    pub struct Class {
        class :*mut RClass
    }

    pub fn open() -> Mrb {
        let s = unsafe { mrb_open() } ;
        Mrb{state:s}
    }

    impl Mrb {
        pub fn load_str(&self,s:&str) {
            let cs = s.to_c_str();
            unsafe {
                mrb_load_string(self.state,cs.as_ptr());
            }
        }

        pub fn close(&self) {
            unsafe {
                mrb_close(self.state);
            }
        }

        pub fn define_class(&self,name:&str,clz:&Class) -> Class {
            let cs = name.to_c_str();
            let c = unsafe { mrb_define_class(self.state,cs.as_ptr(),clz.class) } ;
            Class{class:c}
        }

        pub fn obj_class(&self) -> Class {
            let s = "Object";
            let c = unsafe { mrb_class_get(self.state,s.to_c_str().as_ptr()) } ;
            Class{class:c}
        }
    }

}

fn main() {
    let m = mruby::open();
    let exec = "[1,2,3].each do |i| puts i+1 end";
    m.load_str(exec);

    let o = &m.obj_class();
    let c = m.define_class("Hello",o);
    m.close();
}
<commit_msg>class add mrb ref<commit_after>
extern crate libc;
mod mruby
{

    use libc::{c_char};

#[repr(C)]
    struct mrb_state;
#[repr(C)]
    struct mrb_value;
#[repr(C)]
    struct RClass;

#[link(name="m")]
#[link(name="mruby")]
    extern "C" {
        fn mrb_open() -> *mut mrb_state;
        fn mrb_load_string(state:*mut mrb_state,s:*const c_char) -> mrb_value;
        fn mrb_close(state:*mut mrb_state);
        fn mrb_class_get(state:*mut mrb_state,name:*const c_char) -> *mut RClass;
        fn mrb_define_class(state:*mut mrb_state,name:*const c_char,class:*mut RClass) -> *mut RClass;
    }

    enum MvalType {
        TypeFalse ,
        TypeFree,
        TypeTrue,
        TypeFixnum,
        TypeSymbol,
        TypeUndef,
        TypeFloat,
        TypeCptr,
        TypeObject,
        TypeClass,
        TypeModule,
        TypeIClass,
        TypeSClass,
        TypeProc,
        TypeArray,
        TypeHash,
        TypeString,
        TypeRange,
        TypeException,
        TypeFile,
        TypeEnv,
        TypeData,
        TypeFiber,
        TypeMaxDefine
    }

    pub struct Mrb{
        state:*mut mrb_state
    }

    pub struct Value {
        val :*mut mrb_value
    }

    pub struct Class {
        mrb : &'r Mrb,
        class :*mut RClass
    }

    pub fn open() -> Mrb {
        let s = unsafe { mrb_open() } ;
        Mrb{state:s}
    }

    impl Mrb {
        pub fn load_str(&self,s:&str) {
            let cs = s.to_c_str();
            unsafe {
                mrb_load_string(self.state,cs.as_ptr());
            }
        }

        pub fn close(&self) {
            unsafe {
                mrb_close(self.state);
            }
        }

        pub fn define_class(&self,name:&str,clz:&Class) -> Class {
            let cs = name.to_c_str();
            let c = unsafe { mrb_define_class(self.state,cs.as_ptr(),clz.class) } ;
            Class{mrb:self,class:c}
        }

        pub fn obj_class(&self) -> Class {
            let s = "Object";
            let c = unsafe { mrb_class_get(self.state,s.to_c_str().as_ptr()) } ;
            Class{mrb:self,class:c}
        }
    }

}

fn main() {
    let m = mruby::open();
    let exec = "[1,2,3].each do |i| puts i+1 end";
    m.load_str(exec);

    let o = &m.obj_class();
    let c = m.define_class("Hello",o);
    m.close();
}

<|endoftext|>


<commit_before>use super::toolset::*;
use super::functional_tool::*;
use super::super::environment::*;

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct ListToolsResult {
    pub names: Vec<String>
}

impl ListToolsResult {
    ///
    /// Creates a new list tools result with a particular set of names
    ///
    pub fn with_names(names: Vec<&str>) -> ListToolsResult {
        ListToolsResult {
            names: names.iter().map(|s| String::from(*s)).collect()
        }
    }

    ///
    /// Creates a new list tools result with a particular set of names
    ///
    pub fn with_name_strings(names: Vec<String>) -> ListToolsResult {
        ListToolsResult {
            names: names
        }
    }
}

///
/// Toolset that adds a list-tools tool
///
pub struct ToolSetWithList<TToolSet: ToolSet> {
    source: TToolSet
}

///
/// Adds the list-tools tool to a toolset so we can obtain a list
///
pub fn add_list_to_toolset<TToolSet: ToolSet>(toolset: TToolSet) -> ToolSetWithList<TToolSet> {
    ToolSetWithList { source: toolset }
}

impl<TToolSet: ToolSet> ToolSet for ToolSetWithList<TToolSet> {
    ///
    /// Creates the tools in this toolset
    ///
    fn create_tools(self, environment: &Environment) -> Vec<Box<NamedTool>> {
        // Create the initial set of tools
        let mut result = self.source.create_tools(environment);

        // Get the names of the tools
        let mut names = vec![];
        for tool in result.iter() {
            names.push(String::from(tool.get_name()));
        }

        // Names will include list-tools, and should have no duplicates
        names.push(String::from(super::tool_name::LIST_TOOLS));
        names.sort();
        names.dedup();

        // Create the list-tools tool
        let list_tools = make_pure_tool(move |_: ()| { ListToolsResult { names: names.clone() } });

        result.push(Box::new((super::tool_name::LIST_TOOLS, list_tools)));

        result
    }
}

#[cfg(test)]
mod test {
    use serde_json::*;              // Rust says unused but the json! macro won't work without this
    use super::*;
    use super::super::empty_environment::*;
    use super::super::static_environment::*;
    use super::super::basic_toolset::*;
    use super::super::functional_tool::*;

    #[test]
    fn can_list_tools() {
        let toolset = BasicToolSet::from(vec![
            ("add-1", make_pure_tool(|x: i32| { x+1 })),
            ("add-2", make_pure_tool(|x: i32| { x+2 }))
        ]);
        let withlist    = add_list_to_toolset(toolset);
        let environment = StaticEnvironment::from_toolset(withlist, &EmptyEnvironment::new());

        let list_tool   = environment.get_typed_tool("list-tools").unwrap();
        let list_result = list_tool.invoke((), &environment);

        assert!(list_result == Ok(ListToolsResult::with_names(vec!["add-1", "add-2", "list-tools"])));
    }

    #[test]
    fn will_ignore_duplicates() {
        let toolset = BasicToolSet::from(vec![
            ("add-1", make_pure_tool(|x: i32| { x+1 })),
            ("add-1", make_pure_tool(|x: i32| { x+1 })),
            ("add-2", make_pure_tool(|x: i32| { x+2 }))
        ]);
        let withlist    = add_list_to_toolset(toolset);
        let environment = StaticEnvironment::from_toolset(withlist, &EmptyEnvironment::new());

        let list_tool   = environment.get_typed_tool("list-tools").unwrap();
        let list_result = list_tool.invoke((), &environment);

        assert!(list_result == Ok(ListToolsResult::with_names(vec!["add-1", "add-2", "list-tools"])));
    }
}
<commit_msg>Fix warning<commit_after>use super::toolset::*;
use super::functional_tool::*;
use super::super::environment::*;

#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct ListToolsResult {
    pub names: Vec<String>
}

impl ListToolsResult {
    ///
    /// Creates a new list tools result with a particular set of names
    ///
    pub fn with_names(names: Vec<&str>) -> ListToolsResult {
        ListToolsResult {
            names: names.iter().map(|s| String::from(*s)).collect()
        }
    }

    ///
    /// Creates a new list tools result with a particular set of names
    ///
    pub fn with_name_strings(names: Vec<String>) -> ListToolsResult {
        ListToolsResult {
            names: names
        }
    }
}

///
/// Toolset that adds a list-tools tool
///
pub struct ToolSetWithList<TToolSet: ToolSet> {
    source: TToolSet
}

///
/// Adds the list-tools tool to a toolset so we can obtain a list
///
pub fn add_list_to_toolset<TToolSet: ToolSet>(toolset: TToolSet) -> ToolSetWithList<TToolSet> {
    ToolSetWithList { source: toolset }
}

impl<TToolSet: ToolSet> ToolSet for ToolSetWithList<TToolSet> {
    ///
    /// Creates the tools in this toolset
    ///
    fn create_tools(self, environment: &Environment) -> Vec<Box<NamedTool>> {
        // Create the initial set of tools
        let mut result = self.source.create_tools(environment);

        // Get the names of the tools
        let mut names = vec![];
        for tool in result.iter() {
            names.push(String::from(tool.get_name()));
        }

        // Names will include list-tools, and should have no duplicates
        names.push(String::from(super::tool_name::LIST_TOOLS));
        names.sort();
        names.dedup();

        // Create the list-tools tool
        let list_tools = make_pure_tool(move |_: ()| { ListToolsResult { names: names.clone() } });

        result.push(Box::new((super::tool_name::LIST_TOOLS, list_tools)));

        result
    }
}

#[cfg(test)]
mod test {
    use serde_json::*;              // Rust says unused but the json! macro won't work without this
    use super::*;
    use super::super::empty_environment::*;
    use super::super::static_environment::*;
    use super::super::basic_toolset::*;

    #[test]
    fn can_list_tools() {
        let toolset = BasicToolSet::from(vec![
            ("add-1", make_pure_tool(|x: i32| { x+1 })),
            ("add-2", make_pure_tool(|x: i32| { x+2 }))
        ]);
        let withlist    = add_list_to_toolset(toolset);
        let environment = StaticEnvironment::from_toolset(withlist, &EmptyEnvironment::new());

        let list_tool   = environment.get_typed_tool("list-tools").unwrap();
        let list_result = list_tool.invoke((), &environment);

        assert!(list_result == Ok(ListToolsResult::with_names(vec!["add-1", "add-2", "list-tools"])));
    }

    #[test]
    fn will_ignore_duplicates() {
        let toolset = BasicToolSet::from(vec![
            ("add-1", make_pure_tool(|x: i32| { x+1 })),
            ("add-1", make_pure_tool(|x: i32| { x+1 })),
            ("add-2", make_pure_tool(|x: i32| { x+2 }))
        ]);
        let withlist    = add_list_to_toolset(toolset);
        let environment = StaticEnvironment::from_toolset(withlist, &EmptyEnvironment::new());

        let list_tool   = environment.get_typed_tool("list-tools").unwrap();
        let list_result = list_tool.invoke((), &environment);

        assert!(list_result == Ok(ListToolsResult::with_names(vec!["add-1", "add-2", "list-tools"])));
    }
}
<|endoftext|>