<commit_before>// Copyright 2017 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Very basic syntax detection.

use std::borrow::Borrow;
use std::collections::{BTreeMap, HashMap};
use std::path::Path;
use std::sync::Arc;

use crate::config::Table;

/// The canonical identifier for a particular `LanguageDefinition`.
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct LanguageId(Arc<String>);

/// Describes a `LanguageDefinition`. Although these are provided by plugins,
/// they are a fundamental concept in core, used to determine things like
/// plugin activations and active user config tables.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LanguageDefinition {
    pub name: LanguageId,
    pub extensions: Vec<String>,
    pub first_line_match: Option<String>,
    pub scope: String,
    #[serde(skip)]
    pub default_config: Option<Table>,
}

/// A repository of all loaded `LanguageDefinition`s.
#[derive(Debug, Default)]
pub struct Languages {
    // NOTE: BTreeMap is used for sorting the languages by name alphabetically
    named: BTreeMap<LanguageId, Arc<LanguageDefinition>>,
    extensions: HashMap<String, Arc<LanguageDefinition>>,
}

impl Languages {
    pub fn new(language_defs: &[LanguageDefinition]) -> Self {
        let mut named = BTreeMap::new();
        let mut extensions = HashMap::new();
        for lang in language_defs.iter() {
            let lang_arc = Arc::new(lang.clone());
            named.insert(lang.name.clone(), lang_arc.clone());
            for ext in &lang.extensions {
                extensions.insert(ext.clone(), lang_arc.clone());
            }
        }
        Languages { named, extensions }
    }

    pub fn language_for_path(&self, path: &Path) -> Option<Arc<LanguageDefinition>> {
        path.extension()
            .and_then(|ext| self.extensions.get(ext.to_str().unwrap_or_default()))
            .map(Arc::clone)
    }

    pub fn language_for_name<S>(&self, name: S) -> Option<Arc<LanguageDefinition>>
    where
        S: AsRef<str>,
    {
        self.named.get(name.as_ref()).map(Arc::clone)
    }

    /// Returns a Vec of any `LanguageDefinition`s which exist
    /// in `self` but not `other`.
    pub fn difference(&self, other: &Languages) -> Vec<Arc<LanguageDefinition>> {
        self.named
            .iter()
            .filter(|(k, _)| !other.named.contains_key(*k))
            .map(|(_, v)| v.clone())
            .collect()
    }

    pub fn iter(&self) -> impl Iterator<Item = &Arc<LanguageDefinition>> {
        self.named.values()
    }
}

impl AsRef<str> for LanguageId {
    fn as_ref(&self) -> &str {
        self.0.as_ref()
    }
}

// let's us use &str to query a HashMap with `LanguageId` keys
impl Borrow<str> for LanguageId {
    fn borrow(&self) -> &str {
        &self.0.as_ref()
    }
}

impl<'a> From<&'a str> for LanguageId {
    fn from(src: &'a str) -> LanguageId {
        LanguageId(Arc::new(src.into()))
    }
}

// for testing
#[cfg(test)]
impl LanguageDefinition {
    pub(crate) fn simple(name: &str, exts: &[&str], scope: &str, config: Option<Table>) -> Self {
        LanguageDefinition {
            name: name.into(),
            extensions: exts.iter().map(|s| (*s).into()).collect(),
            first_line_match: None,
            scope: scope.into(),
            default_config: config,
        }
    }
}
<commit_msg>Syntax detection fails for git commit messages<commit_after>// Copyright 2017 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Very basic syntax detection.

use std::borrow::Borrow;
use std::collections::{BTreeMap, HashMap};
use std::path::Path;
use std::sync::Arc;

use crate::config::Table;

/// The canonical identifier for a particular `LanguageDefinition`.
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct LanguageId(Arc<String>);

/// Describes a `LanguageDefinition`. Although these are provided by plugins,
/// they are a fundamental concept in core, used to determine things like
/// plugin activations and active user config tables.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LanguageDefinition {
    pub name: LanguageId,
    pub extensions: Vec<String>,
    pub first_line_match: Option<String>,
    pub scope: String,
    #[serde(skip)]
    pub default_config: Option<Table>,
}

/// A repository of all loaded `LanguageDefinition`s.
#[derive(Debug, Default)]
pub struct Languages {
    // NOTE: BTreeMap is used for sorting the languages by name alphabetically
    named: BTreeMap<LanguageId, Arc<LanguageDefinition>>,
    extensions: HashMap<String, Arc<LanguageDefinition>>,
}

impl Languages {
    pub fn new(language_defs: &[LanguageDefinition]) -> Self {
        let mut named = BTreeMap::new();
        let mut extensions = HashMap::new();
        for lang in language_defs.iter() {
            let lang_arc = Arc::new(lang.clone());
            named.insert(lang.name.clone(), lang_arc.clone());
            for ext in &lang.extensions {
                extensions.insert(ext.clone(), lang_arc.clone());
            }
        }
        Languages { named, extensions }
    }

    pub fn language_for_path(&self, path: &Path) -> Option<Arc<LanguageDefinition>> {
        match path.extension() {
            Some(_) => path
                .extension()
                .and_then(|ext| self.extensions.get(ext.to_str().unwrap_or_default()))
                .map(Arc::clone),
            None => path
                .file_name()
                .and_then(|name| self.extensions.get(name.to_str().unwrap_or_default()))
                .map(Arc::clone),
        }
    }

    pub fn language_for_name<S>(&self, name: S) -> Option<Arc<LanguageDefinition>>
    where
        S: AsRef<str>,
    {
        self.named.get(name.as_ref()).map(Arc::clone)
    }

    /// Returns a Vec of any `LanguageDefinition`s which exist
    /// in `self` but not `other`.
    pub fn difference(&self, other: &Languages) -> Vec<Arc<LanguageDefinition>> {
        self.named
            .iter()
            .filter(|(k, _)| !other.named.contains_key(*k))
            .map(|(_, v)| v.clone())
            .collect()
    }

    pub fn iter(&self) -> impl Iterator<Item = &Arc<LanguageDefinition>> {
        self.named.values()
    }
}

impl AsRef<str> for LanguageId {
    fn as_ref(&self) -> &str {
        self.0.as_ref()
    }
}

// let's us use &str to query a HashMap with `LanguageId` keys
impl Borrow<str> for LanguageId {
    fn borrow(&self) -> &str {
        &self.0.as_ref()
    }
}

impl<'a> From<&'a str> for LanguageId {
    fn from(src: &'a str) -> LanguageId {
        LanguageId(Arc::new(src.into()))
    }
}

// for testing
#[cfg(test)]
impl LanguageDefinition {
    pub(crate) fn simple(name: &str, exts: &[&str], scope: &str, config: Option<Table>) -> Self {
        LanguageDefinition {
            name: name.into(),
            extensions: exts.iter().map(|s| (*s).into()).collect(),
            first_line_match: None,
            scope: scope.into(),
            default_config: config,
        }
    }
}

// for testing
#[cfg(test)]
pub fn language_for_name() {}
<|endoftext|>


<commit_before>#[derive(Clone, Copy, PartialEq)]
#[repr(u8)]
enum Token {
    Mine = b'*',
    Empty = b' ',
}

impl Into<char> for Token {
    fn into(self) -> char {
        self as u8 as char
    }
}

impl Token {
    fn from(c: char) -> Result<Token, ()> {
        match c {
            '*' => Ok(Token::Mine),
            ' ' => Ok(Token::Empty),
            _ => Err(()),
        }
    }
}

struct Board {
    field: Vec<Vec<Token>>,
}

impl Board {
    fn new(minefield: &[&str]) -> Self {
        let mut field: Vec<Vec<Token>> = Vec::new();

        for row in minefield {
            let mut field_row: Vec<Token> = Vec::new();
            for char in row.chars() {
                let token = Token::from(char).unwrap();
                field_row.push(token);
            }
            field.push(field_row);
        }
        Board { field }
    }

    fn annotated(&self) -> Vec<String> {
        let mut annotated: Vec<String> = Vec::new();

        for (y, row) in self.field.iter().enumerate() {
            let mut annotated_row = String::new();
            for (x, token) in row.iter().enumerate() {
                match token {
                    Token::Mine => annotated_row.push(Token::Mine.into()),
                    Token::Empty => {
                        let neighbor_mines = self.num_neighbor_mines(y as u32, x as u32);
                        let annotated_location = if neighbor_mines == 0 {
                            " ".to_string()
                        } else {
                            neighbor_mines.to_string()
                        };
                        annotated_row.push_str(&annotated_location)
                    }
                }
            }
            annotated.push(annotated_row)
        }

        annotated
    }

    fn num_neighbor_mines(&self, y: u32, x: u32) -> usize {
        return self
            .get_neighbors(y, x)
            .iter()
            .filter(|neighbor| neighbor == &&&Token::Mine)
            .count();
    }

    fn get_neighbors(&self, y: u32, x: u32) -> Vec<&Token> {
        let mut neighbors = Vec::new();
        let y = y as i32;
        let x = x as i32;

        let delta_ys: Vec<i32> = (-1..=1).collect();
        for delta_y in delta_ys {
            let delta_xs: Vec<i32> = (-1..=1).collect();
            for delta_x in delta_xs {
                if delta_y == 0 && delta_x == 0 {
                    continue;
                }
                if y + delta_y < 0 || y + delta_y >= self.num_rows() as i32 {
                    continue;
                }
                if x + delta_x < 0 || x + delta_x >= self.num_cols() as i32 {
                    continue;
                }
                let neighbor = &self.field[(y + delta_y) as usize][(x + delta_x) as usize];
                neighbors.push(neighbor)
            }
        }

        neighbors
    }

    fn num_rows(&self) -> usize {
        return self.field.len();
    }

    fn num_cols(&self) -> usize {
        return self.field[0].len();
    }
}

pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let board = Board::new(minefield);
    return board.annotated();
}
<commit_msg>Functional Board::new()<commit_after>#[derive(Clone, Copy, PartialEq)]
#[repr(u8)]
enum Token {
    Mine = b'*',
    Empty = b' ',
}

impl Into<char> for Token {
    fn into(self) -> char {
        self as u8 as char
    }
}

impl Token {
    fn from(c: char) -> Result<Token, ()> {
        match c {
            '*' => Ok(Token::Mine),
            ' ' => Ok(Token::Empty),
            _ => Err(()),
        }
    }
}

struct Board {
    field: Vec<Vec<Token>>,
}

impl Board {
    fn new(minefield: &[&str]) -> Self {
        let field = minefield
            .iter()
            .map(|row| row.chars().map(|char| Token::from(char).unwrap()).collect())
            .collect();
        Board { field }
    }

    fn annotated(&self) -> Vec<String> {
        let mut annotated: Vec<String> = Vec::new();

        for (y, row) in self.field.iter().enumerate() {
            let mut annotated_row = String::new();
            for (x, token) in row.iter().enumerate() {
                match token {
                    Token::Mine => annotated_row.push(Token::Mine.into()),
                    Token::Empty => {
                        let neighbor_mines = self.num_neighbor_mines(y as u32, x as u32);
                        let annotated_location = if neighbor_mines == 0 {
                            " ".to_string()
                        } else {
                            neighbor_mines.to_string()
                        };
                        annotated_row.push_str(&annotated_location)
                    }
                }
            }
            annotated.push(annotated_row)
        }

        annotated
    }

    fn num_neighbor_mines(&self, y: u32, x: u32) -> usize {
        return self
            .get_neighbors(y, x)
            .iter()
            .filter(|neighbor| neighbor == &&&Token::Mine)
            .count();
    }

    fn get_neighbors(&self, y: u32, x: u32) -> Vec<&Token> {
        let mut neighbors = Vec::new();
        let y = y as i32;
        let x = x as i32;

        let delta_ys: Vec<i32> = (-1..=1).collect();
        for delta_y in delta_ys {
            let delta_xs: Vec<i32> = (-1..=1).collect();
            for delta_x in delta_xs {
                if delta_y == 0 && delta_x == 0 {
                    continue;
                }
                if y + delta_y < 0 || y + delta_y >= self.num_rows() as i32 {
                    continue;
                }
                if x + delta_x < 0 || x + delta_x >= self.num_cols() as i32 {
                    continue;
                }
                let neighbor = &self.field[(y + delta_y) as usize][(x + delta_x) as usize];
                neighbors.push(neighbor)
            }
        }

        neighbors
    }

    fn num_rows(&self) -> usize {
        return self.field.len();
    }

    fn num_cols(&self) -> usize {
        return self.field[0].len();
    }
}

pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let board = Board::new(minefield);
    return board.annotated();
}
<|endoftext|>


<commit_before>use std::collections::HashSet;

use choice::PatternElemChoice;
use meta::MetaAnalyzer;
use pattern::{CustomPatternElem, Pattern, PatternElem};
use stepper::Stepper;

/// Identifies patterns that describe a given sequence.
pub struct Analyzer {
    choices: Vec<PatternElemChoice>,
    meta: bool,
}

impl Analyzer {
    /// Creates a new Analyze from a slice of integers.
    pub fn from_slice(seq: &[i32]) -> Self {
        Self::with_custom_patterns(seq, false, Vec::new())
    }

    pub fn with_meta(seq: &[i32]) -> Self {
        Self::with_custom_patterns(seq, true, Vec::new())
    }

    /// Same as `from_slice`, but allows custom patterns to be specified.
    pub fn with_custom_patterns(seq: &[i32], meta: bool, pats: Vec<CustomPatternElem>) -> Self {
        Analyzer {
            meta: meta,
            choices: (0..seq.len() - 1).map(|i|
                         PatternElemChoice::from_i32_pair(seq[i], seq[i + 1], pats.clone())
                     ).collect()
        }
    }

    /// Attempts to find exactly one pattern of `n` operations that described the given sequence.
    pub fn find_any_pattern_of_length(&self, n: usize) -> Option<Pattern> {
        // TODO: Short-circuit finding one pattern instead of all of them
        self.find_patterns_of_length(n).pop()
    }

    /// Attempts to find exactly one pattern of maximum size `max` (in terms of number of
    /// operations) that describes the given sequence. It returns the smallest such pattern it can
    /// find .
    pub fn find_any_pattern(&self, max: usize) -> Option<Pattern> {
        for i in 1..max {
            let mut vec = self.find_patterns_of_length(i);

            // TODO: Short-circuit finding one pattern instead of all of them
            if !vec.is_empty() {
                return vec.pop();
            }
        }

        return None;
    }

    /// Finds all patterns with `n` operations that describe the given sequence.
    pub fn find_patterns_of_length(&self, range: usize) -> Vec<Pattern> {
        let mut pats = vec![Pattern::empty()];

        for i in 0..range {
            let choices: Vec<_> = step!(i => self.len(); range).map(|i| self.choices[i].clone()).collect();

            let meta_patterns = if self.meta {
                self.find_meta_patterns(i, range)
            } else {
                Vec::new()
            };

            let mut new = Vec::new();

            for pat in pats.iter_mut() {
                let mut new_pats = Self::intersection(&choices[..]);
                new_pats.extend(meta_patterns.clone());
                new.extend(pat.extend_each(new_pats.into_iter()).into_iter());
            }

            pats = new;

            // Makes results deterministic, which is helpful.
            pats.sort();
        }

        pats
    }

    /// Finds patterns of maximum size `max` (in terms of number of operations) that describe the
    /// given sequence. It will return all such patterns that are of minimal size (i.e. if a
    /// sequence can be described by a pattern of two operations, it will return all such patterns,
    /// but none of size three or greater).
    pub fn find_patterns(&self, max: usize) -> Vec<Pattern> {
        for i in 1..max {
            let vec = self.find_patterns_of_length(i);

            if !vec.is_empty() {
                return vec;
            }
        }

        return Vec::new();
    }

    #[inline]
    fn len(&self) -> usize {
        self.choices.len()
    }

    fn intersection(slice: &[PatternElemChoice]) -> HashSet<PatternElem> {
        let base = match slice.first() {
            Some(&PatternElemChoice(ref choices)) => choices.clone(),
            None => return HashSet::new()
        };

        slice.into_iter().fold(base, |set, choice| set.intersection(&choice.0).cloned().collect())
    }

    fn find_meta_patterns(&self, offset: usize, range: usize) -> Vec<PatternElem> {
        let choices: Vec<_> = step!(offset => self.len(); range).map(|i| self.choices[i].clone()).collect();
        let meta_analyzer = MetaAnalyzer::new(choices);

        meta_analyzer.find_patterns().into_iter().map(|pat| PatternElem::Meta(pat)).collect()
    }
}
<commit_msg>fix off-by-one error<commit_after>use std::collections::HashSet;

use choice::PatternElemChoice;
use meta::MetaAnalyzer;
use pattern::{CustomPatternElem, Pattern, PatternElem};
use stepper::Stepper;

/// Identifies patterns that describe a given sequence.
pub struct Analyzer {
    choices: Vec<PatternElemChoice>,
    meta: bool,
}

impl Analyzer {
    /// Creates a new Analyze from a slice of integers.
    pub fn from_slice(seq: &[i32]) -> Self {
        Self::with_custom_patterns(seq, false, Vec::new())
    }

    pub fn with_meta(seq: &[i32]) -> Self {
        Self::with_custom_patterns(seq, true, Vec::new())
    }

    /// Same as `from_slice`, but allows custom patterns to be specified.
    pub fn with_custom_patterns(seq: &[i32], meta: bool, pats: Vec<CustomPatternElem>) -> Self {
        Analyzer {
            meta: meta,
            choices: (0..seq.len() - 1).map(|i|
                         PatternElemChoice::from_i32_pair(seq[i], seq[i + 1], pats.clone())
                     ).collect()
        }
    }

    /// Attempts to find exactly one pattern of `n` operations that described the given sequence.
    pub fn find_any_pattern_of_length(&self, n: usize) -> Option<Pattern> {
        // TODO: Short-circuit finding one pattern instead of all of them
        self.find_patterns_of_length(n).pop()
    }

    /// Attempts to find exactly one pattern of maximum size `max` (in terms of number of
    /// operations) that describes the given sequence. It returns the smallest such pattern it can
    /// find .
    pub fn find_any_pattern(&self, max: usize) -> Option<Pattern> {
        for i in 1..max + 1 {
            let mut vec = self.find_patterns_of_length(i);

            // TODO: Short-circuit finding one pattern instead of all of them
            if !vec.is_empty() {
                return vec.pop();
            }
        }

        return None;
    }

    /// Finds all patterns with `n` operations that describe the given sequence.
    pub fn find_patterns_of_length(&self, range: usize) -> Vec<Pattern> {
        let mut pats = vec![Pattern::empty()];

        for i in 0..range {
            let choices: Vec<_> = step!(i => self.len(); range).map(|i| self.choices[i].clone()).collect();

            let meta_patterns = if self.meta {
                self.find_meta_patterns(i, range)
            } else {
                Vec::new()
            };

            let mut new = Vec::new();

            for pat in pats.iter_mut() {
                let mut new_pats = Self::intersection(&choices[..]);
                new_pats.extend(meta_patterns.clone());
                new.extend(pat.extend_each(new_pats.into_iter()).into_iter());
            }

            pats = new;

            // Makes results deterministic, which is helpful.
            pats.sort();
        }

        pats
    }

    /// Finds patterns of maximum size `max` (in terms of number of operations) that describe the
    /// given sequence. It will return all such patterns that are of minimal size (i.e. if a
    /// sequence can be described by a pattern of two operations, it will return all such patterns,
    /// but none of size three or greater).
    pub fn find_patterns(&self, max: usize) -> Vec<Pattern> {
        for i in 1..max + 1 {
            let vec = self.find_patterns_of_length(i);

            if !vec.is_empty() {
                return vec;
            }
        }

        return Vec::new();
    }

    #[inline]
    fn len(&self) -> usize {
        self.choices.len()
    }

    fn intersection(slice: &[PatternElemChoice]) -> HashSet<PatternElem> {
        let base = match slice.first() {
            Some(&PatternElemChoice(ref choices)) => choices.clone(),
            None => return HashSet::new()
        };

        slice.into_iter().fold(base, |set, choice| set.intersection(&choice.0).cloned().collect())
    }

    fn find_meta_patterns(&self, offset: usize, range: usize) -> Vec<PatternElem> {
        let choices: Vec<_> = step!(offset => self.len(); range).map(|i| self.choices[i].clone()).collect();
        let meta_analyzer = MetaAnalyzer::new(choices);

        meta_analyzer.find_patterns().into_iter().map(|pat| PatternElem::Meta(pat)).collect()
    }
}
<|endoftext|>


<commit_before>use clap::{Arg, ArgMatches, App};
use slog::Level;

use rt::Dim;

pub struct Config {
    pub output_file: String,
    pub log_level: Level,
    pub dim: Dim,
    pub integrator: SamplerIntegratorType,
    pub threads: u32,
}

arg_enum! {
  #[derive(Debug)]
  pub enum SamplerIntegratorType {
      Whitted,
      DirectLighting,
      PathTracing,
      Ao,
      Normal
  }
}

pub fn parse_args<'a>() -> ArgMatches<'a> {
    // TODO add block-size and ao-samples and whitted-max-ray? Or maybe not since eventually it
    // will be read from the scene file...
    App::new("rustracer")
        .version("0.1")
        .author("Antoine Büsch")
        .about("Toy raytracer in Rust based on PBRTv3")
        .arg(Arg::with_name("output")
                 .long("output")
                 .short("o")
                 .help("Output file name")
                 .default_value("image.png"))
        .arg(Arg::with_name("threads")
                 .long("threads")
                 .short("t")
                 .help("Number of worker threads")
                 .takes_value(true))
        .arg(Arg::with_name("dim")
                 .long("dim")
                 .short("d")
                 .help("Dimension of the output image")
                 .default_value("800x600"))
        .arg(Arg::with_name("integrator")
                 .long("integrator")
                 .short("i")
                 .help("SamplerIntegrator to use")
                 .possible_values(&SamplerIntegratorType::variants())
                 .default_value("Whitted"))
        .arg(Arg::with_name("spp").long("spp").help("Sample per pixels").default_value("4"))
        .arg(Arg::with_name("verbose").short("v").help("log debug information"))
        .arg(Arg::with_name("display").short("p").help("Display image as it is rendered"))
        .get_matches()
}
<commit_msg>Make DirectLighting the default integrator<commit_after>use clap::{Arg, ArgMatches, App};
use slog::Level;

use rt::Dim;

pub struct Config {
    pub output_file: String,
    pub log_level: Level,
    pub dim: Dim,
    pub integrator: SamplerIntegratorType,
    pub threads: u32,
}

arg_enum! {
  #[derive(Debug)]
  pub enum SamplerIntegratorType {
      Whitted,
      DirectLighting,
      PathTracing,
      Ao,
      Normal
  }
}

pub fn parse_args<'a>() -> ArgMatches<'a> {
    // TODO add block-size and ao-samples and whitted-max-ray? Or maybe not since eventually it
    // will be read from the scene file...
    App::new("rustracer")
        .version("0.1")
        .author("Antoine Büsch")
        .about("Toy raytracer in Rust based on PBRTv3")
        .arg(Arg::with_name("output")
                 .long("output")
                 .short("o")
                 .help("Output file name")
                 .default_value("image.png"))
        .arg(Arg::with_name("threads")
                 .long("threads")
                 .short("t")
                 .help("Number of worker threads")
                 .takes_value(true))
        .arg(Arg::with_name("dim")
                 .long("dim")
                 .short("d")
                 .help("Dimension of the output image")
                 .default_value("800x600"))
        .arg(Arg::with_name("integrator")
                 .long("integrator")
                 .short("i")
                 .help("SamplerIntegrator to use")
                 .possible_values(&SamplerIntegratorType::variants())
                 .default_value("DirectLighting"))
        .arg(Arg::with_name("spp").long("spp").help("Sample per pixels").default_value("4"))
        .arg(Arg::with_name("verbose").short("v").help("log debug information"))
        .arg(Arg::with_name("display").short("p").help("Display image as it is rendered"))
        .get_matches()
}
<|endoftext|>


<commit_before>#![crate_name = "rboy"]

#![feature(old_io, std_misc, core, env)]

#[macro_use]
extern crate log;

extern crate getopts;

extern crate sdl2;

extern crate rboy;

use rboy::device::Device;
use std::time::Duration;
use std::sync::{Arc,RwLock};
use std::sync::mpsc::{Sender,Receiver};
use std::sync::mpsc::TryRecvError::{Disconnected,Empty};
use std::old_io::timer;

static SCALE: usize = 2;
static EXITCODE_INCORRECTOPTIONS: i32 = 1;
static EXITCODE_CPULOADFAILS: i32 = 2;

#[cfg(not(test))]
fn set_exit_status(exitcode: i32)
{
    std::env::set_exit_status(exitcode);
}

fn main() {
    let mut opts = getopts::Options::new();
    opts.optflag("s", "serial", "Output serial to stdout");
    opts.optflag("c", "classic", "Force Classic mode");

    let args: Vec<_> = std::env::args().collect();

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { println!("{}", f); return }
    };

    let filename = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        let mut info_start = args[0].clone();
        info_start.push_str(" <filename>");
        println!("{}", opts.usage(info_start.as_slice()));
        set_exit_status(EXITCODE_INCORRECTOPTIONS);
        return;
    };

    let sdl_context = sdl2::init(sdl2::INIT_VIDEO).unwrap();
    let window = match sdl2::video::Window::new("RBoy - A gameboy in Rust",
                                                sdl2::video::WindowPos::PosUndefined,
                                                sdl2::video::WindowPos::PosUndefined,
                                                160*SCALE as i32,
                                                144*SCALE as i32,
                                                sdl2::video::WindowFlags::empty()) {
        Ok(window) => window,
        Err(err) => panic!("failed to open window: {}", err),
    };
    let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::RenderDriverIndex::Auto, sdl2::render::ACCELERATED) {
        Ok(screen) => screen,
        Err(err) => panic!("failed to open screen: {}", err),
    };

    let (sdl_tx, cpu_rx) = std::sync::mpsc::channel();
    let (cpu_tx, sdl_rx) = std::sync::mpsc::channel();
    let rawscreen = ::std::iter::repeat(0u8).take(160*144*3).collect();
    let arc = Arc::new(RwLock::new(rawscreen));
    let arc2 = arc.clone();

    let cpuloop_thread = std::thread::scoped(move|| cpuloop(&cpu_tx, &cpu_rx, arc2, filename.as_slice(), &matches));

    let mut timer = timer::Timer::new().unwrap();
    let periodic = timer.periodic(Duration::milliseconds(8));

    let mut event_queue = sdl_context.event_pump();
    'main : loop {
        let _ = periodic.recv();
        match sdl_rx.try_recv() {
            Err(Disconnected) => { break 'main },
            Ok(_) => recalculate_screen(&renderer, &arc),
            Err(Empty) => {},
        }
        for event in event_queue.poll_iter() {
            match event {
                sdl2::event::Event::Quit { .. } => break 'main,
                sdl2::event::Event::KeyDown { keycode: sdl2::keycode::KeyCode::Escape, .. }
                    => break 'main,
                sdl2::event::Event::KeyDown { keycode: sdl2::keycode::KeyCode::LShift, .. }
                    => { let _ = sdl_tx.send(GBEvent::SpeedUp); },
                sdl2::event::Event::KeyUp { keycode: sdl2::keycode::KeyCode::LShift, .. }
                    => { let _ = sdl_tx.send(GBEvent::SlowDown); },
                sdl2::event::Event::KeyDown { keycode: sdlkey, .. } => {
                    match sdl_to_keypad(sdlkey) {
                        Some(key) =>  { let _ = sdl_tx.send(GBEvent::KeyDown(key)); },
                        None => {},
                    }
                },
                sdl2::event::Event::KeyUp { keycode: sdlkey, .. } => {
                    match sdl_to_keypad(sdlkey) {
                        Some(key) => { let _ = sdl_tx.send(GBEvent::KeyUp(key)); },
                        None => {},
                    }
                },
                _ => {}
            }
        }
    }

    drop(sdl_tx); // Disconnect such that the cpuloop will exit
    let _ = cpuloop_thread.join();
}

fn sdl_to_keypad(key: sdl2::keycode::KeyCode) -> Option<rboy::KeypadKey> {
    match key {
        sdl2::keycode::KeyCode::Z => Some(rboy::KeypadKey::A),
        sdl2::keycode::KeyCode::X => Some(rboy::KeypadKey::B),
        sdl2::keycode::KeyCode::Up => Some(rboy::KeypadKey::Up),
        sdl2::keycode::KeyCode::Down => Some(rboy::KeypadKey::Down),
        sdl2::keycode::KeyCode::Left => Some(rboy::KeypadKey::Left),
        sdl2::keycode::KeyCode::Right => Some(rboy::KeypadKey::Right),
        sdl2::keycode::KeyCode::Space => Some(rboy::KeypadKey::Select),
        sdl2::keycode::KeyCode::Return => Some(rboy::KeypadKey::Start),
        _ => None,
    }
}

fn recalculate_screen(screen: &sdl2::render::Renderer, arc: &Arc<RwLock<Vec<u8>>>) {
    let mut drawer = screen.drawer();
    drawer.set_draw_color(sdl2::pixels::Color::RGB(0xFF, 0xFF, 0xFF));
    drawer.clear();

    let data =  arc.read().unwrap().clone();
    for y in range(0, 144) {
        for x in range(0, 160) {
            drawer.set_draw_color(sdl2::pixels::Color::RGB(data[y*160*3 + x*3 + 0],
                                                            data[y*160*3 + x*3 + 1],
                                                            data[y*160*3 + x*3 + 2]));
            drawer.draw_rect(sdl2::rect::Rect::new((x*SCALE) as i32, (y*SCALE) as i32, SCALE as i32, SCALE as i32));
        }
    }
    drawer.present();
}

enum GBEvent {
    KeyUp(rboy::KeypadKey),
    KeyDown(rboy::KeypadKey),
    SpeedUp,
    SlowDown,
}

fn cpuloop(cpu_tx: &Sender<u32>, cpu_rx: &Receiver<GBEvent>, arc: Arc<RwLock<Vec<u8>>>, filename: &str, matches: &getopts::Matches) {
    let opt_c = match matches.opt_present("classic") {
        true => Device::new(filename),
        false => Device::new_cgb(filename),
    };
    let mut c = match opt_c
    {
        Some(cpu) => { cpu },
        None => { error!("Could not get a valid gameboy"); set_exit_status(EXITCODE_CPULOADFAILS); return; },
    };
    c.set_stdout(matches.opt_present("serial"));

    let mut timer = timer::Timer::new().unwrap();
    let periodic = timer.periodic(Duration::milliseconds(8));
    let mut limit_speed = true;

    let waitticks = (4194.304f32 * 4.0) as u32;

    let mut ticks = 0;
    'cpuloop: loop {
        while ticks < waitticks {
            ticks += c.do_cycle();
            if c.check_and_reset_gpu_updated() {
                let mut data = arc.write().unwrap();
                let gpu_data = c.get_gpu_data();
                for i in range(0, data.len()) { data[i] = gpu_data[i]; }
                if cpu_tx.send(0).is_err() { break 'cpuloop };
            }
        }
        ticks -= waitticks;
        if limit_speed { let _ = periodic.recv(); }

        match cpu_rx.try_recv() {
            Ok(event) => match event {
                GBEvent::KeyUp(key) => c.keyup(key),
                GBEvent::KeyDown(key) => c.keydown(key),
                GBEvent::SpeedUp => limit_speed = false,
                GBEvent::SlowDown => limit_speed = true,
            },
            Err(Empty) => {},
            Err(Disconnected) => { break },
        };
    }
}
<commit_msg>Remove one more warning<commit_after>#![crate_name = "rboy"]

#![feature(old_io, std_misc, core, exit_status)]

#[macro_use]
extern crate log;

extern crate getopts;

extern crate sdl2;

extern crate rboy;

use rboy::device::Device;
use std::time::Duration;
use std::sync::{Arc,RwLock};
use std::sync::mpsc::{Sender,Receiver};
use std::sync::mpsc::TryRecvError::{Disconnected,Empty};
use std::old_io::timer;

static SCALE: usize = 2;
static EXITCODE_INCORRECTOPTIONS: i32 = 1;
static EXITCODE_CPULOADFAILS: i32 = 2;

#[cfg(not(test))]
fn set_exit_status(exitcode: i32)
{
    std::env::set_exit_status(exitcode);
}

fn main() {
    let mut opts = getopts::Options::new();
    opts.optflag("s", "serial", "Output serial to stdout");
    opts.optflag("c", "classic", "Force Classic mode");

    let args: Vec<_> = std::env::args().collect();

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { println!("{}", f); return }
    };

    let filename = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        let mut info_start = args[0].clone();
        info_start.push_str(" <filename>");
        println!("{}", opts.usage(info_start.as_slice()));
        set_exit_status(EXITCODE_INCORRECTOPTIONS);
        return;
    };

    let sdl_context = sdl2::init(sdl2::INIT_VIDEO).unwrap();
    let window = match sdl2::video::Window::new("RBoy - A gameboy in Rust",
                                                sdl2::video::WindowPos::PosUndefined,
                                                sdl2::video::WindowPos::PosUndefined,
                                                160*SCALE as i32,
                                                144*SCALE as i32,
                                                sdl2::video::WindowFlags::empty()) {
        Ok(window) => window,
        Err(err) => panic!("failed to open window: {}", err),
    };
    let renderer = match sdl2::render::Renderer::from_window(window, sdl2::render::RenderDriverIndex::Auto, sdl2::render::ACCELERATED) {
        Ok(screen) => screen,
        Err(err) => panic!("failed to open screen: {}", err),
    };

    let (sdl_tx, cpu_rx) = std::sync::mpsc::channel();
    let (cpu_tx, sdl_rx) = std::sync::mpsc::channel();
    let rawscreen = ::std::iter::repeat(0u8).take(160*144*3).collect();
    let arc = Arc::new(RwLock::new(rawscreen));
    let arc2 = arc.clone();

    let cpuloop_thread = std::thread::scoped(move|| cpuloop(&cpu_tx, &cpu_rx, arc2, filename.as_slice(), &matches));

    let mut timer = timer::Timer::new().unwrap();
    let periodic = timer.periodic(Duration::milliseconds(8));

    let mut event_queue = sdl_context.event_pump();
    'main : loop {
        let _ = periodic.recv();
        match sdl_rx.try_recv() {
            Err(Disconnected) => { break 'main },
            Ok(_) => recalculate_screen(&renderer, &arc),
            Err(Empty) => {},
        }
        for event in event_queue.poll_iter() {
            match event {
                sdl2::event::Event::Quit { .. } => break 'main,
                sdl2::event::Event::KeyDown { keycode: sdl2::keycode::KeyCode::Escape, .. }
                    => break 'main,
                sdl2::event::Event::KeyDown { keycode: sdl2::keycode::KeyCode::LShift, .. }
                    => { let _ = sdl_tx.send(GBEvent::SpeedUp); },
                sdl2::event::Event::KeyUp { keycode: sdl2::keycode::KeyCode::LShift, .. }
                    => { let _ = sdl_tx.send(GBEvent::SlowDown); },
                sdl2::event::Event::KeyDown { keycode: sdlkey, .. } => {
                    match sdl_to_keypad(sdlkey) {
                        Some(key) =>  { let _ = sdl_tx.send(GBEvent::KeyDown(key)); },
                        None => {},
                    }
                },
                sdl2::event::Event::KeyUp { keycode: sdlkey, .. } => {
                    match sdl_to_keypad(sdlkey) {
                        Some(key) => { let _ = sdl_tx.send(GBEvent::KeyUp(key)); },
                        None => {},
                    }
                },
                _ => {}
            }
        }
    }

    drop(sdl_tx); // Disconnect such that the cpuloop will exit
    let _ = cpuloop_thread.join();
}

fn sdl_to_keypad(key: sdl2::keycode::KeyCode) -> Option<rboy::KeypadKey> {
    match key {
        sdl2::keycode::KeyCode::Z => Some(rboy::KeypadKey::A),
        sdl2::keycode::KeyCode::X => Some(rboy::KeypadKey::B),
        sdl2::keycode::KeyCode::Up => Some(rboy::KeypadKey::Up),
        sdl2::keycode::KeyCode::Down => Some(rboy::KeypadKey::Down),
        sdl2::keycode::KeyCode::Left => Some(rboy::KeypadKey::Left),
        sdl2::keycode::KeyCode::Right => Some(rboy::KeypadKey::Right),
        sdl2::keycode::KeyCode::Space => Some(rboy::KeypadKey::Select),
        sdl2::keycode::KeyCode::Return => Some(rboy::KeypadKey::Start),
        _ => None,
    }
}

fn recalculate_screen(screen: &sdl2::render::Renderer, arc: &Arc<RwLock<Vec<u8>>>) {
    let mut drawer = screen.drawer();
    drawer.set_draw_color(sdl2::pixels::Color::RGB(0xFF, 0xFF, 0xFF));
    drawer.clear();

    let data =  arc.read().unwrap().clone();
    for y in range(0, 144) {
        for x in range(0, 160) {
            drawer.set_draw_color(sdl2::pixels::Color::RGB(data[y*160*3 + x*3 + 0],
                                                            data[y*160*3 + x*3 + 1],
                                                            data[y*160*3 + x*3 + 2]));
            drawer.draw_rect(sdl2::rect::Rect::new((x*SCALE) as i32, (y*SCALE) as i32, SCALE as i32, SCALE as i32));
        }
    }
    drawer.present();
}

enum GBEvent {
    KeyUp(rboy::KeypadKey),
    KeyDown(rboy::KeypadKey),
    SpeedUp,
    SlowDown,
}

fn cpuloop(cpu_tx: &Sender<u32>, cpu_rx: &Receiver<GBEvent>, arc: Arc<RwLock<Vec<u8>>>, filename: &str, matches: &getopts::Matches) {
    let opt_c = match matches.opt_present("classic") {
        true => Device::new(filename),
        false => Device::new_cgb(filename),
    };
    let mut c = match opt_c
    {
        Some(cpu) => { cpu },
        None => { error!("Could not get a valid gameboy"); set_exit_status(EXITCODE_CPULOADFAILS); return; },
    };
    c.set_stdout(matches.opt_present("serial"));

    let mut timer = timer::Timer::new().unwrap();
    let periodic = timer.periodic(Duration::milliseconds(8));
    let mut limit_speed = true;

    let waitticks = (4194.304f32 * 4.0) as u32;

    let mut ticks = 0;
    'cpuloop: loop {
        while ticks < waitticks {
            ticks += c.do_cycle();
            if c.check_and_reset_gpu_updated() {
                let mut data = arc.write().unwrap();
                let gpu_data = c.get_gpu_data();
                for i in range(0, data.len()) { data[i] = gpu_data[i]; }
                if cpu_tx.send(0).is_err() { break 'cpuloop };
            }
        }
        ticks -= waitticks;
        if limit_speed { let _ = periodic.recv(); }

        match cpu_rx.try_recv() {
            Ok(event) => match event {
                GBEvent::KeyUp(key) => c.keyup(key),
                GBEvent::KeyDown(key) => c.keydown(key),
                GBEvent::SpeedUp => limit_speed = false,
                GBEvent::SlowDown => limit_speed = true,
            },
            Err(Empty) => {},
            Err(Disconnected) => { break },
        };
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::fs::File;
use std::process::exit;
use std::io::{stdout, stderr, stdin, Error, Write, BufRead, BufReader};
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = r#"
NAME
    uniq - report or omit repeated lines

SYNOPSIS
    uniq [ -h | --help | -d | -u | -i ] [FILE]...

DESCRIPTION
    Filter adjacent matching lines of FILE(s) to standard output.

    With no FILE(s), read standard input.

OPTIONS
    -h
    --help
        display this help and exit
    -c
    --count
        precede each output line with a count of the number of times the line occurred in the input
    -i
    --ignore-case
        compare lines case-insensitively
    -d
    --repeated-lines
        only print duplicate lines, one for each group
    -u
    --unique-lines
        only print unique lines
"#; /* @MANEND */

fn lines_from_stdin() -> Result<Vec<String>, Error> {
    let stdin = stdin();
    let mut lines = Vec::new();

    let f = BufReader::new(stdin.lock());
    for line in f.lines() {
        lines.push(line?);
    }
    Ok(lines)
}

fn lines_from_files(paths: &Vec<&String>) -> Result<Vec<String>, Error> {
    let mut lines = Vec::new();

    for path in paths {
        let f = BufReader::new(File::open(path)?);
        for line in f.lines() {
            lines.push(line?);
        }
    }
    Ok(lines)
}

fn eq_strings(left: &str, right: &str, ignore_case: bool) -> bool {
    if ignore_case {
        left.to_lowercase() == right.to_lowercase()
    } else {
        left == right
    }
}

fn get_squashed_lines(lines: &[String], ignore_case: bool) -> Vec<(usize, &String)> {
    let mut squashed =  Vec::new();
    let llen = lines.len();

    let mut r: usize = 0;

    while r < llen {
        let mut rnext: usize = r + 1;
        let mut count: usize = 1;

        while rnext < llen && eq_strings(&lines[r], &lines[rnext], ignore_case) {
            count += 1;
            rnext += 1;
        }

        squashed.push((count, &lines[r]));
        r += count;
    }

    squashed
}

fn unique_lines(lines: Vec<(usize, &String)>) -> Vec<(usize, &String)> {
   lines.into_iter()
       .filter(|&(k,_)| k == 1)
       .collect::<Vec<_>>()
}

fn repeated_lines(lines: Vec<(usize, &String)>) -> Vec<(usize, &String)> {
   lines.into_iter()
       .filter(|&(k,_)| k > 1)
       .collect::<Vec<_>>()
}

fn main() {

    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(5)
        .add_flag(&["i", "ignore-case"])
        .add_flag(&["c", "count"])
        .add_flag(&["d", "repeated-lines"])
        .add_flag(&["u", "unique-lines"])
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    let lines = match parser.args.is_empty() {
        true => lines_from_stdin(),
        false => {
            let paths = parser.args.iter().collect::<Vec<_>>();
            lines_from_files(&paths)
        }
    };

    match lines {
        Ok(ref l) => {
            let mut squashed = get_squashed_lines(&l, parser.found("ignore-case"));

            if parser.found("unique-lines") {
                squashed = unique_lines(squashed);
            } else if parser.found("repeated-lines") {
                squashed = repeated_lines(squashed);
            }

            if parser.found("count") {
                for (c, v) in squashed {
                    println!("{} {}", c, v);
                }
            } else {
                for (_, v) in squashed {
                    println!("{}", v);
                }
            }
        }
        Err(e) => {
            let _ = write!(stderr, "{}", e);
        }
    }
}
<commit_msg>[WIP] String to Vec<u8> and buffered stdou<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::str;
use std::fs::File;
use std::process::exit;
use std::io::{stdout, stderr, stdin, Error, Write, BufRead, BufReader, BufWriter};
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = r#"
NAME
    uniq - report or omit repeated lines

SYNOPSIS
    uniq [ -h | --help | -d | -u | -i ] [FILE]...

DESCRIPTION
    Filter adjacent matching lines of FILE(s) to standard output.

    With no FILE(s), read standard input.

OPTIONS
    -h
    --help
        display this help and exit
    -c
    --count
        precede each output line with a count of the number of times the line occurred in the input
    -i
    --ignore-case
        compare lines case-insensitively
    -d
    --repeated-lines
        only print duplicate lines, one for each group
    -u
    --unique-lines
        only print unique lines
"#; /* @MANEND */

fn lines_from_stdin() -> Result<Vec<Vec<u8>>, Error> {
    let stdin = stdin();
    let mut lines = Vec::new();

    let f = BufReader::new(stdin.lock());
    for line in f.split(b'\n') {
        lines.push(line?);
    }
    Ok(lines)
}

fn lines_from_files(paths: &Vec<&String>) -> Result<Vec<Vec<u8>>, Error> {
    let mut lines = Vec::new();

    for path in paths {
        let f = BufReader::new(File::open(path)?);
        for line in f.split(b'\n') {
            lines.push(line?);
        }
    }
    Ok(lines)
}

fn to_lowercase(vector: &Vec<u8>) -> Vec<u8> {
    vector.iter().map(|c| 0x20 | c).collect::<Vec<_>>()
}

fn eq_strings(left: &Vec<u8>, right: &Vec<u8>, ignore_case: bool) -> bool {
    if ignore_case {
        to_lowercase(left) == to_lowercase(right)
    } else {
        left == right
    }
}

fn get_squashed_lines(lines: &Vec<Vec<u8>>, ignore_case: bool) -> Vec<(usize, &Vec<u8>)> {
    let mut squashed =  Vec::new();
    let llen = lines.len();

    let mut r: usize = 0;

    while r < llen {
        let mut rnext: usize = r + 1;
        let mut count: usize = 1;

        while rnext < llen && eq_strings(&lines[r], &lines[rnext], ignore_case) {
            count += 1;
            rnext += 1;
        }

        squashed.push((count, &lines[r]));
        r += count;
    }

    squashed
}

fn unique_lines(lines: Vec<(usize, &Vec<u8>)>) -> Vec<(usize, &Vec<u8>)> {
   lines.into_iter()
       .filter(|&(k,_)| k == 1)
       .collect::<Vec<_>>()
}

fn repeated_lines(lines: Vec<(usize, &Vec<u8>)>) -> Vec<(usize, &Vec<u8>)> {
   lines.into_iter()
       .filter(|&(k,_)| k > 1)
       .collect::<Vec<_>>()
}

fn main() {

    let stdout = stdout();
    let mut stdout = BufWriter::with_capacity(8192, stdout.lock());
    let mut stderr = stderr();
    let mut parser = ArgParser::new(5)
        .add_flag(&["i", "ignore-case"])
        .add_flag(&["c", "count"])
        .add_flag(&["d", "repeated-lines"])
        .add_flag(&["u", "unique-lines"])
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    let lines = match parser.args.is_empty() {
        true => lines_from_stdin(),
        false => {
            let paths = parser.args.iter().collect::<Vec<_>>();
            lines_from_files(&paths)
        }
    };

    match lines {
        Ok(ref l) => {
            let mut squashed = get_squashed_lines(&l, parser.found("ignore-case"));

            if parser.found("unique-lines") {
                squashed = unique_lines(squashed);
            } else if parser.found("repeated-lines") {
                squashed = repeated_lines(squashed);
            }

            if parser.found("count") {
                for (c, v) in squashed {
                    let line = str::from_utf8(&v[..]).expect("Unable to parse line");
                    stdout.write(&format!("{} {}\n", c, line).as_bytes()).unwrap();
                }
            } else {
                for (_, v) in squashed {
                    let line = str::from_utf8(&v[..]).expect("Unable to parse line");
                    stdout.write(&format!("{}\n", line).as_bytes()).unwrap();

                }
            }
        }
        Err(e) => {
            let _ = write!(stderr, "{}", e);
        }
    }
}
<|endoftext|>


<commit_before>use {Color, Timer, TimerPhase, TimingMethod, TimeSpan};
use super::timer;
use time_formatter::{timer as formatter, TimeFormatter, Short, Accuracy, DigitsFormat};
use time_formatter::none_wrapper::DashWrapper;
use comparison::{self, best_segments, none};
use std::cmp::max;
use serde_json::{to_writer, Result};
use std::io::Write;
use std::borrow::Cow;
use layout::editor::settings_description::{SettingsDescription, Field, Value};

#[derive(Default, Clone)]
pub struct Component {
    icon_id: usize,
    timer: timer::Component,
    settings: Settings,
}

#[derive(Clone, Serialize, Deserialize)]
pub struct Settings {
    pub comparison1: Option<String>,
    pub comparison2: Option<String>,
    pub hide_second_comparison: bool,
    pub timer: timer::Settings,
    pub segment_timer: timer::Settings,
    pub display_icon: bool,
    pub show_segment_name: bool,
}

#[derive(Serialize, Deserialize)]
pub struct State {
    pub timer: timer::State,
    pub segment_timer: Option<timer::State>,
    pub comparison1: Option<ComparisonState>,
    pub comparison2: Option<ComparisonState>,
    pub segment_name: Option<String>,
    pub icon_change: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct ComparisonState {
    pub name: String,
    pub time: String,
}

impl Default for Settings {
    fn default() -> Self {
        Settings {
            comparison1: None,
            comparison2: Some(String::from(best_segments::NAME)),
            hide_second_comparison: false,
            timer: Default::default(),
            segment_timer: Default::default(),
            display_icon: false,
            show_segment_name: false,
        }
    }
}

impl State {
    pub fn write_json<W>(&self, writer: W) -> Result<()>
    where
        W: Write,
    {
        to_writer(writer, self)
    }
}

impl Component {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn with_settings(settings: Settings) -> Self {
        let timer = timer::Component::with_settings(settings.timer.clone());
        Self {
            timer,
            settings,
            ..Default::default()
        }
    }

    pub fn settings(&self) -> &Settings {
        &self.settings
    }

    pub fn set_settings(&mut self, settings: Settings) {
        self.settings = settings;
        *self.timer.settings_mut() = self.settings.timer.clone();
    }

    pub fn name(&self) -> Cow<str> {
        "Detailed Timer".into()
    }

    pub fn state(&mut self, timer: &Timer) -> State {
        let current_phase = timer.current_phase();
        let timing_method = self.settings
            .timer
            .timing_method
            .unwrap_or_else(|| timer.current_timing_method());

        let last_split_index = if current_phase == TimerPhase::Ended {
            timer.run().len() - 1
        } else {
            max(0, timer.current_split_index()) as usize
        };

        let (comparison1, comparison2) = if current_phase != TimerPhase::NotRunning {
            let mut comparison1 = self.settings
                .comparison1
                .as_ref()
                .map(String::as_str)
                .unwrap_or_else(|| timer.current_comparison());

            let comparison2 = self.settings
                .comparison2
                .as_ref()
                .map(String::as_str)
                .unwrap_or_else(|| timer.current_comparison());

            let mut hide_comparison = self.settings.hide_second_comparison;

            if hide_comparison || !timer.run().comparisons().any(|c| c == comparison2) ||
                comparison2 == none::NAME
            {
                hide_comparison = true;
                if !timer.run().comparisons().any(|c| c == comparison1) ||
                    comparison1 == none::NAME
                {
                    comparison1 = timer.current_comparison();
                }
            } else if !timer.run().comparisons().any(|c| c == comparison1) ||
                       comparison1 == none::NAME
            {
                hide_comparison = true;
                comparison1 = comparison2;
            } else if comparison1 == comparison2 {
                hide_comparison = true;
            }

            let comparison1 = Some((
                comparison::shorten(comparison1),
                calculate_comparison_time(timer, timing_method, comparison1, last_split_index),
            ));

            let comparison2 = if !hide_comparison {
                Some((
                    comparison::shorten(comparison2),
                    calculate_comparison_time(timer, timing_method, comparison2, last_split_index),
                ))
            } else {
                None
            };

            (comparison1, comparison2)
        } else {
            Default::default()
        };

        let timer_state = self.timer.state(timer);
        let segment_time = calculate_segment_time(timer, timing_method, last_split_index);
        let segment_time_state = segment_time.map(|t| {
            timer::State {
                time: formatter::Time::with_digits_format(
                    self.settings.segment_timer.digits_format,
                ).format(t)
                    .to_string(),
                fraction: formatter::Fraction::with_accuracy(self.settings.segment_timer.accuracy)
                    .format(t)
                    .to_string(),
                color: Color::Default,
            }
        });

        let formatter = DashWrapper::new(Short::new());

        let comparison1 = comparison1.map(|(name, time)| {
            ComparisonState {
                name: name.to_string(),
                time: formatter.format(time).to_string(),
            }
        });

        let comparison2 = comparison2.map(|(name, time)| {
            ComparisonState {
                name: name.to_string(),
                time: formatter.format(time).to_string(),
            }
        });

        let icon_id = &mut self.icon_id;
        let icon_change = if self.settings.display_icon {
            timer
                .current_split()
                .and_then(|s| s.icon().check_for_change(icon_id).map(str::to_owned))
        } else if *icon_id != 0 {
            *icon_id = 0;
            Some(String::new())
        } else {
            None
        };

        let segment_name = if self.settings.show_segment_name {
            timer.current_split().map(|s| s.name().to_owned())
        } else {
            None
        };

        State {
            timer: timer_state,
            segment_timer: segment_time_state,
            comparison1,
            comparison2,
            segment_name,
            icon_change,
        }
    }

    pub fn remount(&mut self) {
        self.icon_id = 0;
    }

    pub fn settings_description(&self) -> SettingsDescription {
        SettingsDescription::with_fields(vec![
            Field::new(
                "Timing Method".into(),
                self.settings.timer.timing_method.into(),
            ),
            Field::new(
                "Comparison 1".into(),
                self.settings.comparison1.clone().into(),
            ),
            Field::new(
                "Comparison 2".into(),
                self.settings.comparison2.clone().into(),
            ),
            Field::new(
                "Hide Second Comparison".into(),
                self.settings.hide_second_comparison.into(),
            ),
            Field::new(
                "Timer Digits Format".into(),
                self.settings.timer.digits_format.into(),
            ),
            Field::new("Timer Accuracy".into(), self.settings.timer.accuracy.into()),
            Field::new(
                "Segment Timer Digits Format".into(),
                self.settings.segment_timer.digits_format.into(),
            ),
            Field::new(
                "Segment Timer Accuracy".into(),
                self.settings.segment_timer.accuracy.into(),
            ),
            Field::new(
                "Show Segment Name".into(),
                self.settings.show_segment_name.into(),
            ),
            Field::new("Display Icon".into(), self.settings.display_icon.into()),
        ])
    }

    pub fn set_value(&mut self, index: usize, value: Value) {
        match index {
            0 => self.settings.timer.timing_method = value.into(),
            1 => self.settings.comparison1 = value.into(),
            2 => self.settings.comparison2 = value.into(),
            3 => self.settings.hide_second_comparison = value.into(),
            4 => {
                let value: DigitsFormat = value.into();
                self.settings.timer.digits_format = value;
                self.timer.settings_mut().digits_format = value;
            }
            5 => {
                let value: Accuracy = value.into();
                self.settings.timer.accuracy = value;
                self.timer.settings_mut().accuracy = value;
            }
            6 => self.settings.segment_timer.digits_format = value.into(),
            7 => self.settings.segment_timer.accuracy = value.into(),
            8 => self.settings.show_segment_name = value.into(),
            9 => self.settings.display_icon = value.into(),
            _ => panic!("Unsupported Setting Index"),
        }
    }
}

fn calculate_comparison_time(
    timer: &Timer,
    timing_method: TimingMethod,
    comparison: &str,
    last_split_index: usize,
) -> Option<TimeSpan> {
    if comparison == best_segments::NAME {
        timer.run().segment(last_split_index).best_segment_time()[timing_method]
    } else if last_split_index == 0 {
        timer
            .run()
            .segment(0)
            .comparison_timing_method(comparison, timing_method)
    } else if timer.current_split_index() > 0 {
        TimeSpan::option_sub(
            timer
                .run()
                .segment(last_split_index)
                .comparison_timing_method(comparison, timing_method),
            timer
                .run()
                .segment(last_split_index - 1)
                .comparison_timing_method(comparison, timing_method),
        )
    } else {
        None
    }
}

fn calculate_segment_time(
    timer: &Timer,
    timing_method: TimingMethod,
    last_split_index: usize,
) -> Option<TimeSpan> {
    let last_split = if last_split_index > 0 {
        timer.run().segment(last_split_index - 1).split_time()[timing_method]
    } else {
        Some(TimeSpan::zero())
    };

    if timer.current_phase() == TimerPhase::NotRunning {
        Some(timer.run().offset())
    } else {
        TimeSpan::option_sub(timer.current_time()[timing_method], last_split)
    }
}
<commit_msg>Fix Detailed Timer's Segment Timer for Game Time<commit_after>use {Color, Timer, TimerPhase, TimingMethod, TimeSpan};
use super::timer;
use time_formatter::{timer as formatter, TimeFormatter, Short, Accuracy, DigitsFormat};
use time_formatter::none_wrapper::DashWrapper;
use comparison::{self, best_segments, none};
use std::cmp::max;
use serde_json::{to_writer, Result};
use std::io::Write;
use std::borrow::Cow;
use layout::editor::settings_description::{SettingsDescription, Field, Value};

#[derive(Default, Clone)]
pub struct Component {
    icon_id: usize,
    timer: timer::Component,
    settings: Settings,
}

#[derive(Clone, Serialize, Deserialize)]
pub struct Settings {
    pub comparison1: Option<String>,
    pub comparison2: Option<String>,
    pub hide_second_comparison: bool,
    pub timer: timer::Settings,
    pub segment_timer: timer::Settings,
    pub display_icon: bool,
    pub show_segment_name: bool,
}

#[derive(Serialize, Deserialize)]
pub struct State {
    pub timer: timer::State,
    pub segment_timer: Option<timer::State>,
    pub comparison1: Option<ComparisonState>,
    pub comparison2: Option<ComparisonState>,
    pub segment_name: Option<String>,
    pub icon_change: Option<String>,
}

#[derive(Serialize, Deserialize)]
pub struct ComparisonState {
    pub name: String,
    pub time: String,
}

impl Default for Settings {
    fn default() -> Self {
        Settings {
            comparison1: None,
            comparison2: Some(String::from(best_segments::NAME)),
            hide_second_comparison: false,
            timer: Default::default(),
            segment_timer: Default::default(),
            display_icon: false,
            show_segment_name: false,
        }
    }
}

impl State {
    pub fn write_json<W>(&self, writer: W) -> Result<()>
    where
        W: Write,
    {
        to_writer(writer, self)
    }
}

impl Component {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn with_settings(settings: Settings) -> Self {
        let timer = timer::Component::with_settings(settings.timer.clone());
        Self {
            timer,
            settings,
            ..Default::default()
        }
    }

    pub fn settings(&self) -> &Settings {
        &self.settings
    }

    pub fn set_settings(&mut self, settings: Settings) {
        self.settings = settings;
        *self.timer.settings_mut() = self.settings.timer.clone();
    }

    pub fn name(&self) -> Cow<str> {
        "Detailed Timer".into()
    }

    pub fn state(&mut self, timer: &Timer) -> State {
        let current_phase = timer.current_phase();
        let timing_method = self.settings
            .timer
            .timing_method
            .unwrap_or_else(|| timer.current_timing_method());

        let last_split_index = if current_phase == TimerPhase::Ended {
            timer.run().len() - 1
        } else {
            max(0, timer.current_split_index()) as usize
        };

        let (comparison1, comparison2) = if current_phase != TimerPhase::NotRunning {
            let mut comparison1 = self.settings
                .comparison1
                .as_ref()
                .map(String::as_str)
                .unwrap_or_else(|| timer.current_comparison());

            let comparison2 = self.settings
                .comparison2
                .as_ref()
                .map(String::as_str)
                .unwrap_or_else(|| timer.current_comparison());

            let mut hide_comparison = self.settings.hide_second_comparison;

            if hide_comparison || !timer.run().comparisons().any(|c| c == comparison2) ||
                comparison2 == none::NAME
            {
                hide_comparison = true;
                if !timer.run().comparisons().any(|c| c == comparison1) ||
                    comparison1 == none::NAME
                {
                    comparison1 = timer.current_comparison();
                }
            } else if !timer.run().comparisons().any(|c| c == comparison1) ||
                       comparison1 == none::NAME
            {
                hide_comparison = true;
                comparison1 = comparison2;
            } else if comparison1 == comparison2 {
                hide_comparison = true;
            }

            let comparison1 = Some((
                comparison::shorten(comparison1),
                calculate_comparison_time(timer, timing_method, comparison1, last_split_index),
            ));

            let comparison2 = if !hide_comparison {
                Some((
                    comparison::shorten(comparison2),
                    calculate_comparison_time(timer, timing_method, comparison2, last_split_index),
                ))
            } else {
                None
            };

            (comparison1, comparison2)
        } else {
            Default::default()
        };

        let timer_state = self.timer.state(timer);
        let mut segment_time = calculate_segment_time(timer, timing_method, last_split_index);

        if segment_time.is_none() && timing_method == TimingMethod::GameTime {
            segment_time = calculate_segment_time(timer, TimingMethod::RealTime, last_split_index);
        }

        let segment_time_state = segment_time.map(|t| {
            timer::State {
                time: formatter::Time::with_digits_format(
                    self.settings.segment_timer.digits_format,
                ).format(t)
                    .to_string(),
                fraction: formatter::Fraction::with_accuracy(self.settings.segment_timer.accuracy)
                    .format(t)
                    .to_string(),
                color: Color::Default,
            }
        });

        let formatter = DashWrapper::new(Short::new());

        let comparison1 = comparison1.map(|(name, time)| {
            ComparisonState {
                name: name.to_string(),
                time: formatter.format(time).to_string(),
            }
        });

        let comparison2 = comparison2.map(|(name, time)| {
            ComparisonState {
                name: name.to_string(),
                time: formatter.format(time).to_string(),
            }
        });

        let icon_id = &mut self.icon_id;
        let icon_change = if self.settings.display_icon {
            timer
                .current_split()
                .and_then(|s| s.icon().check_for_change(icon_id).map(str::to_owned))
        } else if *icon_id != 0 {
            *icon_id = 0;
            Some(String::new())
        } else {
            None
        };

        let segment_name = if self.settings.show_segment_name {
            timer.current_split().map(|s| s.name().to_owned())
        } else {
            None
        };

        State {
            timer: timer_state,
            segment_timer: segment_time_state,
            comparison1,
            comparison2,
            segment_name,
            icon_change,
        }
    }

    pub fn remount(&mut self) {
        self.icon_id = 0;
    }

    pub fn settings_description(&self) -> SettingsDescription {
        SettingsDescription::with_fields(vec![
            Field::new(
                "Timing Method".into(),
                self.settings.timer.timing_method.into(),
            ),
            Field::new(
                "Comparison 1".into(),
                self.settings.comparison1.clone().into(),
            ),
            Field::new(
                "Comparison 2".into(),
                self.settings.comparison2.clone().into(),
            ),
            Field::new(
                "Hide Second Comparison".into(),
                self.settings.hide_second_comparison.into(),
            ),
            Field::new(
                "Timer Digits Format".into(),
                self.settings.timer.digits_format.into(),
            ),
            Field::new("Timer Accuracy".into(), self.settings.timer.accuracy.into()),
            Field::new(
                "Segment Timer Digits Format".into(),
                self.settings.segment_timer.digits_format.into(),
            ),
            Field::new(
                "Segment Timer Accuracy".into(),
                self.settings.segment_timer.accuracy.into(),
            ),
            Field::new(
                "Show Segment Name".into(),
                self.settings.show_segment_name.into(),
            ),
            Field::new("Display Icon".into(), self.settings.display_icon.into()),
        ])
    }

    pub fn set_value(&mut self, index: usize, value: Value) {
        match index {
            0 => self.settings.timer.timing_method = value.into(),
            1 => self.settings.comparison1 = value.into(),
            2 => self.settings.comparison2 = value.into(),
            3 => self.settings.hide_second_comparison = value.into(),
            4 => {
                let value: DigitsFormat = value.into();
                self.settings.timer.digits_format = value;
                self.timer.settings_mut().digits_format = value;
            }
            5 => {
                let value: Accuracy = value.into();
                self.settings.timer.accuracy = value;
                self.timer.settings_mut().accuracy = value;
            }
            6 => self.settings.segment_timer.digits_format = value.into(),
            7 => self.settings.segment_timer.accuracy = value.into(),
            8 => self.settings.show_segment_name = value.into(),
            9 => self.settings.display_icon = value.into(),
            _ => panic!("Unsupported Setting Index"),
        }
    }
}

fn calculate_comparison_time(
    timer: &Timer,
    timing_method: TimingMethod,
    comparison: &str,
    last_split_index: usize,
) -> Option<TimeSpan> {
    if comparison == best_segments::NAME {
        timer.run().segment(last_split_index).best_segment_time()[timing_method]
    } else if last_split_index == 0 {
        timer
            .run()
            .segment(0)
            .comparison_timing_method(comparison, timing_method)
    } else if timer.current_split_index() > 0 {
        TimeSpan::option_sub(
            timer
                .run()
                .segment(last_split_index)
                .comparison_timing_method(comparison, timing_method),
            timer
                .run()
                .segment(last_split_index - 1)
                .comparison_timing_method(comparison, timing_method),
        )
    } else {
        None
    }
}

fn calculate_segment_time(
    timer: &Timer,
    timing_method: TimingMethod,
    last_split_index: usize,
) -> Option<TimeSpan> {
    let last_split = if last_split_index > 0 {
        timer.run().segment(last_split_index - 1).split_time()[timing_method]
    } else {
        Some(TimeSpan::zero())
    };

    if timer.current_phase() == TimerPhase::NotRunning {
        Some(timer.run().offset())
    } else {
        TimeSpan::option_sub(timer.current_time()[timing_method], last_split)
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_must_use)]

extern crate libc;

use self::libc::funcs::posix88::unistd::execvp;
use std::io::process::Command;
use std::thread::Thread;
use std::ptr::null;
use std::os;
use std::ffi::CString;
use std::io::fs::PathExtensions;
use std::io::{fs, File, Open, Write};
use config::Config;
use layout::LayoutMsg;
use xlib_window_system::XlibWindowSystem;
use workspaces::{Workspaces, MoveOp};
use xlib::Window;

pub enum Cmd {
  Exec(String),
  SwitchWorkspace(usize),
  SwitchScreen(usize),
  MoveToWorkspace(usize),
  MoveToScreen(usize),
  SendLayoutMsg(LayoutMsg),
  Reload,
  Exit,
  KillClient,
  FocusUp,
  FocusDown,
  FocusMaster,
  SwapUp,
  SwapDown,
  SwapMaster,
}

impl Cmd {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces<'a>, config: &Config) {
    match *self {
      Cmd::Exec(ref cmd) => {
        debug!("Cmd::Exec: {}", cmd);
        exec(cmd.clone());
      },
      Cmd::SwitchWorkspace(index) => {
        debug!("Cmd::SwitchWorkspace: {}", index);
        workspaces.switch_to(ws, config, index - 1);
      },
      Cmd::SwitchScreen(screen) => {
        debug!("Cmd::SwitchScreen: {}", screen);
        workspaces.switch_to_screen(ws, config, screen - 1);
      },
      Cmd::MoveToWorkspace(index) => {
        debug!("Cmd::MoveToWorkspace: {}", index);
        workspaces.move_window_to(ws, config, index - 1);
      },
      Cmd::MoveToScreen(screen) => {
        debug!("Cmd::MoveToScreen: {}", screen);
        workspaces.move_window_to_screen(ws, config, screen - 1);
      },
      Cmd::SendLayoutMsg(ref msg) => {
        debug!("Cmd::SendLayoutMsg::{}", msg);
        workspaces.current_mut().get_layout_mut().send_msg(msg.clone());
        workspaces.current().redraw(ws, config);
      },
      Cmd::Reload => {
        let path = os::self_exe_name().unwrap();
        let filename = String::from_str(path.filename_str().unwrap());
        let absolute = String::from_str(path.as_str().unwrap());
        let dir = String::from_str(path.dirname_str().unwrap());

        debug!("Cmd::Reload: compiling...");

        let mut cmd = Command::new(String::from_str("cargo"));
        cmd.cwd(&Path::new(dir)).arg("build").env("RUST_LOG", "none");

        match cmd.output() {
          Ok(output) => {
            if output.status.success() {
              debug!("Cmd::Reload: restarting... {}", absolute);

              unsafe {
                let mut slice : &mut [*const i8; 2] = &mut [
                  CString::from_slice(filename.as_bytes()).as_slice_with_nul().as_ptr(),
                  null()
                ];

                let path = Path::new(concat!(env!("HOME"), "/.xr3wm/.tmp"));
                if path.exists() {
                  fs::unlink(&path);
                }

                let mut file = File::open_mode(&path, Open, Write).unwrap();
                file.write_str(workspaces.serialize().as_slice());
                file.flush();

                execvp(CString::from_slice(absolute.as_bytes()).as_slice_with_nul().as_ptr(), slice.as_mut_ptr());
              }
            } else {
              panic!("failed to recompile: '{}'", output.status);
            }
          },
          _ => panic!("failed to start \"{}\"", cmd)
        }
      },
      Cmd::Exit => {
        debug!("Cmd::Exit");
        ws.close();
      },
      Cmd::KillClient => {
        debug!("Cmd::KillClient: {}", workspaces.current_mut().focused_window());
        ws.kill_window(workspaces.current_mut().focused_window());
      },
      Cmd::FocusUp => {
        debug!("Cmd::FocusUp: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Up);
      },
      Cmd::FocusDown => {
        debug!("Cmd::FocusDown: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Down);
      },
      Cmd::FocusMaster => {
        debug!("Cmd::FocusMaster: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Swap);
      },
      Cmd::SwapUp => {
        debug!("Cmd::SwapUp: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Up);
      },
      Cmd::SwapDown => {
        debug!("Cmd::SwapDown: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Down);
      },
      Cmd::SwapMaster => {
        debug!("Cmd::SwapMaster: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Swap);
      }
    }
  }
}

pub struct ManageHook {
  pub class_name: String,
  pub cmd: CmdManage
}

pub enum CmdManage {
  Move(usize),
  Float,
  Fullscreen,
  Ignore
}

impl CmdManage {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces<'a>, config: &Config, window: Window) {
    match *self {
      CmdManage::Move(index) => {
        if let Some(parent) = ws.transient_for(window) {
          if let Some(workspace) = workspaces.find_window(parent) {
            workspace.add_window(ws, config, window);
            workspace.focus_window(ws, config, window);
          }
        } else {
          debug!("CmdManage::Move: {}, {}", window, index);
          workspaces.get_mut(index - 1).add_window(ws, config, window);
          workspaces.get_mut(index - 1).focus_window(ws, config, window);
        }
      },
      CmdManage::Float => {
        debug!("CmdManage::Float");
        unimplemented!()
      },
      CmdManage::Fullscreen => {
        debug!("CmdManage::Fullscreen");
        unimplemented!()
      },
      CmdManage::Ignore => {
        debug!("CmdManage::Ignore");
        unimplemented!()
      }
    }
  }
}

pub enum LogInfo {
  Workspaces(Vec<String>, usize, Vec<bool>),
  Title(String),
  Layout(String)
}

pub struct LogHook<'a> {
  pub logs: Vec<CmdLogHook>,
  pub output: Box<Fn(Vec<LogInfo>) -> String + 'a>
}

impl<'a> LogHook<'a> {
  pub fn call<'b>(&mut self, ws: &XlibWindowSystem, workspaces: &Workspaces<'b>) {
    println!("{}", (self.output)(self.logs.iter().map(|x| x.call(ws, workspaces)).collect()));
  }
}

pub enum CmdLogHook {
  Workspaces,
  Title,
  Layout
}

impl CmdLogHook {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &Workspaces<'a>) -> LogInfo {
    match *self {
      CmdLogHook::Workspaces => {
        LogInfo::Workspaces(
          workspaces.all().iter().map(|x| x.get_tag()).collect(),
          workspaces.get_index(),
          workspaces.all().iter().map(|x| x.is_urgent()).collect())
      },
      CmdLogHook::Title => {
        LogInfo::Title(ws.get_window_title(workspaces.current().focused_window()))
      },
      CmdLogHook::Layout => {
        LogInfo::Layout(workspaces.current().get_layout().name())
      }
    }
  }
}

fn exec(cmd: String) {
  Thread::scoped(move || {
    let args : Vec<&str> = cmd.as_slice().split(' ').collect();

    if args.len() > 0 {
      let mut cmd = Command::new(args[0]);

      if args.len() > 1 {
        cmd.args(args.as_slice().slice_from(1));
      }

      match cmd.detached().output() {
        Ok(_) => (),
        _ => panic!("failed to start \"{}\"", cmd)
      }
    }
  }).detach();
}
<commit_msg>catching up to rust master<commit_after>#![allow(dead_code, unused_must_use)]

extern crate libc;

use self::libc::funcs::posix88::unistd::execvp;
use std::io::process::Command;
use std::thread::Thread;
use std::ptr::null;
use std::os;
use std::ffi::CString;
use std::io::fs::PathExtensions;
use std::io::{fs, File, Open, Write};
use config::Config;
use layout::LayoutMsg;
use xlib_window_system::XlibWindowSystem;
use workspaces::{Workspaces, MoveOp};
use xlib::Window;

pub enum Cmd {
  Exec(String),
  SwitchWorkspace(usize),
  SwitchScreen(usize),
  MoveToWorkspace(usize),
  MoveToScreen(usize),
  SendLayoutMsg(LayoutMsg),
  Reload,
  Exit,
  KillClient,
  FocusUp,
  FocusDown,
  FocusMaster,
  SwapUp,
  SwapDown,
  SwapMaster,
}

impl Cmd {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces<'a>, config: &Config) {
    match *self {
      Cmd::Exec(ref cmd) => {
        debug!("Cmd::Exec: {}", cmd);
        exec(cmd.clone());
      },
      Cmd::SwitchWorkspace(index) => {
        debug!("Cmd::SwitchWorkspace: {}", index);
        workspaces.switch_to(ws, config, index - 1);
      },
      Cmd::SwitchScreen(screen) => {
        debug!("Cmd::SwitchScreen: {}", screen);
        workspaces.switch_to_screen(ws, config, screen - 1);
      },
      Cmd::MoveToWorkspace(index) => {
        debug!("Cmd::MoveToWorkspace: {}", index);
        workspaces.move_window_to(ws, config, index - 1);
      },
      Cmd::MoveToScreen(screen) => {
        debug!("Cmd::MoveToScreen: {}", screen);
        workspaces.move_window_to_screen(ws, config, screen - 1);
      },
      Cmd::SendLayoutMsg(ref msg) => {
        debug!("Cmd::SendLayoutMsg::{}", msg);
        workspaces.current_mut().get_layout_mut().send_msg(msg.clone());
        workspaces.current().redraw(ws, config);
      },
      Cmd::Reload => {
        let path = os::self_exe_name().unwrap();
        let filename = String::from_str(path.filename_str().unwrap());
        let absolute = String::from_str(path.as_str().unwrap());
        let dir = String::from_str(path.dirname_str().unwrap());

        debug!("Cmd::Reload: compiling...");

        let mut cmd = Command::new(String::from_str("cargo"));
        cmd.cwd(&Path::new(dir)).arg("build").env("RUST_LOG", "none");

        match cmd.output() {
          Ok(output) => {
            if output.status.success() {
              debug!("Cmd::Reload: restarting... {}", absolute);

              unsafe {
                let mut slice : &mut [*const i8; 2] = &mut [
                  CString::from_slice(filename.as_bytes()).as_slice_with_nul().as_ptr(),
                  null()
                ];

                let path = Path::new(concat!(env!("HOME"), "/.xr3wm/.tmp"));
                if path.exists() {
                  fs::unlink(&path);
                }

                let mut file = File::open_mode(&path, Open, Write).unwrap();
                file.write_str(workspaces.serialize().as_slice());
                file.flush();

                execvp(CString::from_slice(absolute.as_bytes()).as_slice_with_nul().as_ptr(), slice.as_mut_ptr());
              }
            } else {
              panic!("failed to recompile: '{}'", output.status);
            }
          },
          _ => panic!("failed to start \"{:?}\"", cmd)
        }
      },
      Cmd::Exit => {
        debug!("Cmd::Exit");
        ws.close();
      },
      Cmd::KillClient => {
        debug!("Cmd::KillClient: {}", workspaces.current_mut().focused_window());
        ws.kill_window(workspaces.current_mut().focused_window());
      },
      Cmd::FocusUp => {
        debug!("Cmd::FocusUp: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Up);
      },
      Cmd::FocusDown => {
        debug!("Cmd::FocusDown: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Down);
      },
      Cmd::FocusMaster => {
        debug!("Cmd::FocusMaster: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Swap);
      },
      Cmd::SwapUp => {
        debug!("Cmd::SwapUp: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Up);
      },
      Cmd::SwapDown => {
        debug!("Cmd::SwapDown: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Down);
      },
      Cmd::SwapMaster => {
        debug!("Cmd::SwapMaster: {}", workspaces.current().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Swap);
      }
    }
  }
}

pub struct ManageHook {
  pub class_name: String,
  pub cmd: CmdManage
}

pub enum CmdManage {
  Move(usize),
  Float,
  Fullscreen,
  Ignore
}

impl CmdManage {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces<'a>, config: &Config, window: Window) {
    match *self {
      CmdManage::Move(index) => {
        if let Some(parent) = ws.transient_for(window) {
          if let Some(workspace) = workspaces.find_window(parent) {
            workspace.add_window(ws, config, window);
            workspace.focus_window(ws, config, window);
          }
        } else {
          debug!("CmdManage::Move: {}, {}", window, index);
          workspaces.get_mut(index - 1).add_window(ws, config, window);
          workspaces.get_mut(index - 1).focus_window(ws, config, window);
        }
      },
      CmdManage::Float => {
        debug!("CmdManage::Float");
        unimplemented!()
      },
      CmdManage::Fullscreen => {
        debug!("CmdManage::Fullscreen");
        unimplemented!()
      },
      CmdManage::Ignore => {
        debug!("CmdManage::Ignore");
        unimplemented!()
      }
    }
  }
}

pub enum LogInfo {
  Workspaces(Vec<String>, usize, Vec<bool>),
  Title(String),
  Layout(String)
}

pub struct LogHook<'a> {
  pub logs: Vec<CmdLogHook>,
  pub output: Box<Fn(Vec<LogInfo>) -> String + 'a>
}

impl<'a> LogHook<'a> {
  pub fn call<'b>(&mut self, ws: &XlibWindowSystem, workspaces: &Workspaces<'b>) {
    println!("{}", (self.output)(self.logs.iter().map(|x| x.call(ws, workspaces)).collect()));
  }
}

pub enum CmdLogHook {
  Workspaces,
  Title,
  Layout
}

impl CmdLogHook {
  pub fn call<'a>(&self, ws: &XlibWindowSystem, workspaces: &Workspaces<'a>) -> LogInfo {
    match *self {
      CmdLogHook::Workspaces => {
        LogInfo::Workspaces(
          workspaces.all().iter().map(|x| x.get_tag()).collect(),
          workspaces.get_index(),
          workspaces.all().iter().map(|x| x.is_urgent()).collect())
      },
      CmdLogHook::Title => {
        LogInfo::Title(ws.get_window_title(workspaces.current().focused_window()))
      },
      CmdLogHook::Layout => {
        LogInfo::Layout(workspaces.current().get_layout().name())
      }
    }
  }
}

fn exec(cmd: String) {
  Thread::scoped(move || {
    let args : Vec<&str> = cmd.as_slice().split(' ').collect();

    if args.len() > 0 {
      let mut cmd = Command::new(args[0]);

      if args.len() > 1 {
        cmd.args(args.as_slice().slice_from(1));
      }

      match cmd.detached().output() {
        Ok(_) => (),
        _ => panic!("failed to start \"{:?}\"", cmd)
      }
    }
  }).detach();
}
<|endoftext|>


<commit_before>
struct CalcObjects<'a> {
  first: &'a str,
  second: &'a str,
}

impl<'a> CalcObjects<'a> {
  fn max_length(&self) -> usize {
    if self.first.len() > self.second.len() {
      self.first.len()
    } else {
      self.second.len()
    }
  }
}

struct JaroWinkler<'a> {
  co: CalcObjects<'a>,
  matches1: Vec<char>,
  matches2: Vec<char>
}

impl<'b> JaroWinkler<'b> {
  fn new(this_obj: CalcObjects<'b>) -> JaroWinkler<'b> {
    let mut jw = JaroWinkler {
      co: this_obj,
      matches1: Vec::new(),
      matches2: Vec::new()
    };
    jw.matches1 = jw.get_common_chars(false);
    jw.matches2 = jw.get_common_chars(true);
    jw
  }

  fn get_common_chars(&self, ordering: bool) -> Vec<char> {
    let mut common_chars = Vec::new();
    let max_length = self.co.max_length();
    let match_buffer = ( max_length / 2 ) - 1;
    let mut f = self.co.first;
    let mut s = self.co.second;

    if ordering {
      f = self.co.second;
      s = self.co.first;
    }

    for (i, c) in f.chars().enumerate() {
      let s_index: usize = if i < match_buffer {
        0
      } else {
        i - match_buffer
      };

      let e_index: usize = if s.len() <= (i + match_buffer) {
        s.len()
      } else {
        i + match_buffer + 1
      };

      let word_slice = &s[s_index..e_index];
      if word_slice.contains(c) {
        common_chars.push(c);
      }
    }
    common_chars
  }

  fn calculate(&self) -> f32 {
    // Should it really return?
    if self.matches1.is_empty() || self.matches2.is_empty()
      || self.matches1.len() != self.matches2.len()
    {
      return 0.0;
    }

    let mut t = 0.0;
    for (a, b) in self.matches1.iter().zip(self.matches2.iter()) {
      if a != b {
        t += 0.5;
      }
    }

    let f1 = self.matches1.len() as f32 / self.co.first.len() as f32;
    let f2 = self.matches2.len() as f32 / self.co.second.len() as f32;
    let f3 = (self.matches1.len() as f32 - t) / self.matches1.len() as f32;
    (f1 + f2 + f3) / 3.0
  }
}

pub fn jaro_winkler_distance(str1: &str, str2: &str) -> f32 {
  let jw = JaroWinkler::new(CalcObjects { first: str1, second: str2 });
  jw.calculate()
}

/* pub fn levenshtein_distance(a: &str, b: &str) -> usize {
    // TODO: unimplemented
}*/
<commit_msg>Rewrite jaro-winkler to not be stateful<commit_after>use std::cmp;

fn max_length(str1: &str, str2: &str) -> usize {
    if str1.len() > str2.len() {
      str1.len()
    } else {
      str2.len()
    }
}

fn get_common_chars(str1: &str, str2: &str, ordering: bool) -> Vec<char> {
    let mut common_chars = Vec::new();
    let max_length = max_length(str1, str2);
    let match_buffer = ( max_length / 2 ) - 1;
    let mut f = str1;
    let mut s = str2;

    if ordering {
        f = str2;
        s = str1;
    }

    for (i, c) in f.chars().enumerate() {
        let s_index: usize = if i < match_buffer {
            0
        } else {
            i - match_buffer
        };

        let e_index: usize = if s.len() <= (i + match_buffer) {
            s.len()
        } else {
            i + match_buffer + 1
        };

        let word_slice = &s[s_index..e_index];
        if word_slice.contains(c) {
            common_chars.push(c);
        }
    }

    common_chars
}

pub fn jaro_winkler_distance(str1: &str, str2: &str) -> f32 {
    let matches1 = get_common_chars(str1, str2, false);
    let matches2 = get_common_chars(str1, str2, true);

    if matches1.is_empty() || matches2.is_empty()
      || matches1.len() != matches2.len()
    {
      return 0.0;
    }

    let mut t = 0.0;
    for (a, b) in matches1.iter().zip(matches2.iter()) {
      if a != b {
        t += 0.5;
      }
    }

    let f1 = matches1.len() as f32 / str1.len() as f32;
    let f2 = matches2.len() as f32 / str2.len() as f32;
    let f3 = (matches1.len() as f32 - t) / matches1.len() as f32;
    (f1 + f2 + f3) / 3.0
}

/* pub fn levenshtein_distance(a: &str, b: &str) -> usize {
    // TODO: unimplemented
}*/
<|endoftext|>