<commit_before>extern crate num;
extern crate portaudio;
extern crate rtlsdr;

use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::{Num, Zero};
use num::complex::Complex;
use std::env;
use std::f32::consts::PI;
use std::error::Error;
use pa::error::Error as PAError;
use std::thread;
use std::sync::mpsc::channel;

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8. I want the buffer sizes between the SDR
// and the audio sizes to match, but since we get two samples per read the
// buffer size needs to be double.
const SDR_BUF_SIZE: usize = 262144;

// The buffer size for the audio sink.
const AUDIO_BUF_SIZE: usize = 524288;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SDR_SAMPLE_RATE: u32 = 2400000;

// Here is the sample rate of the output waveform we'll try to use.
const AUDIO_SAMPLE_RATE: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

// We set the gain manually right now since it seems to be a better option
// than using the AGC (the SDR gets blazing hot with the AGC on).
const SDR_GAIN: i32 = 496;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args()
        .nth(1)
        .expect("Please specify the SDR index.")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args()
        .nth(2)
        .expect("Please specify a center frequency in MHz.")
        .parse::<f32>()?;
    let bandwidth: u32 = env::args()
        .nth(3)
        .expect("Please specify the bandwidth.")
        .parse::<u32>()?;

    // Set up the threading channels for communication between our two threads.
    let (dongle_tx, dongle_rx) = channel();
    let (demod_tx, demod_rx) = channel();

    // This thread only collects data off of the SDR as quickly as possible and
    // sends it out.
    thread::spawn(move || {
        // Initialize the SDR based on the user's input parameters.
        let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;
        let mut sdr =
            RTLSDR { rtlsdr: init_sdr(sdr_index, fm_freq, bandwidth).unwrap() };

        loop {
            let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
            let iq_vec = samps_to_cmplx(bytes).unwrap();
            dongle_tx.send(iq_vec).unwrap();
        }
    });

    // This thread does all of the signal processing required to demodulate
    // the signal and get it to a nice audio stream.
    thread::spawn(move || {
        // Decimating down to 100k samples seems to work the best. I don't
        // really quite get why that is, so I'll need to do more research.
        let dec_rate_filt = 6;
        let dec_rate_audio = 4;

        let taps_filt = windowed_sinc(
            bandwidth as f32,
            SDR_SAMPLE_RATE as f32,
            128,
            &hamming,
        );
        let taps_audio = windowed_sinc(
            bandwidth as f32 / dec_rate_filt as f32,
            SDR_SAMPLE_RATE as f32 / dec_rate_filt as f32,
            128,
            &hamming,
        );

        let mut prev = Complex::zero();
        loop {
            // First, low_pass and decimate the raw IQ signal.
            let mut iq_vec = dongle_rx.recv().unwrap();
            iq_vec = filter(&iq_vec, &taps_filt);
            iq_vec = decimate(iq_vec, dec_rate_filt);

            // Next, demodulate the signal and filter the signal again. The
            // second filter seems to help with the noise after demodulation.
            let res = demod_fm(iq_vec, prev);
            let mut demod_iq = filter_real(&res.0, &taps_audio);
            demod_iq = decimate(demod_iq, dec_rate_audio);
            prev = res.1;
            demod_tx.send(demod_iq).unwrap();
        }
    });

    // Initialize the PortAudio class. We use a blocking stream since we're
    // doing processing on the signal and can't keep up with non-blocking
    // timing requirements.
    let audio = try!(pa::PortAudio::new());
    let settings = try!(audio.default_output_stream_settings(
        CHANNELS,
        AUDIO_SAMPLE_RATE as f64,
        AUDIO_BUF_SIZE as u32,
    ));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    loop {
        let demod_iq = demod_rx.recv().unwrap();

        let out_frames = match stream.write_available() {
            Ok(available) => {
                match available {
                    pa::StreamAvailable::Frames(frames) => frames as u32,
                    pa::StreamAvailable::InputOverflowed => {
                        return Err(Box::new(PAError::InputOverflowed))
                    }
                    pa::StreamAvailable::OutputUnderflowed => {
                        return Err(Box::new(PAError::OutputUnderflowed))
                    }
                }
            }
            Err(e) => return Err(Box::new(e)),
        };

        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let write_frames = std::cmp::min(buffer_frames, out_frames);
        let n_write_samples = write_frames as usize * CHANNELS as usize;
        if write_frames == 0 {
            println!("We can't write any more frames!");
        }

        stream.write(
            write_frames,
            |output| for ix in 0..n_write_samples {
                output[ix] = demod_iq[ix];
            },
        )?;
    }
}

fn init_sdr(
    sdr_index: i32,
    fm_freq: u32,
    bandwidth: u32,
) -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SDR_SAMPLE_RATE));
    try!(sdr.set_tuner_bandwidth(bandwidth));
    try!(sdr.set_tuner_gain(SDR_GAIN));
    try!(sdr.set_agc_mode(false));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

fn decimate<T: Copy>(signal: Vec<T>, dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

fn samps_to_cmplx(bytes: Vec<u8>) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;

    }

    // Write the values to the complex value and normalize from [0, 255] to
    // [-1, 1].
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);
    for iq in bytes.chunks(2) {
        let iq_cmplx = Complex::new(
            (iq[0] as f32 - 127.0) / 127.0,
            (iq[1] as f32 - 127.0) / 127.0,
        );
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

fn demod_fm(
    iq: Vec<Complex<f32>>,
    prev: Complex<f32>,
) -> (Vec<f32>, Complex<f32>) {

    let mut p = prev.clone();
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());

    let gain = SDR_SAMPLE_RATE as f32 / (2.0 * PI * 75e3);

    for samp in iq.iter() {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

///
/// Filters a Complex vector.
///
fn filter<T: Copy + Num + Zero>(
    samples: &Vec<Complex<T>>,
    taps: &Vec<T>,
) -> Vec<Complex<T>> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<Complex<T>> =
        Vec::with_capacity(samples.len() - taps.len() + 1);

    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(Complex::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

///
/// Filter a real vector.
///
fn filter_real<T: Copy + Num + Zero>(
    samples: &Vec<T>,
    taps: &Vec<T>,
) -> Vec<T> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<T> =
        Vec::with_capacity(samples.len() - taps.len() + 1);
    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(T::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

///
/// Generates taps for a Hamming window.
///
fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

///
/// Generates filter taps for a sinc filter with a Hamming window.
///
fn windowed_sinc(
    cutoff_freq: f32,
    sample_rate: f32,
    ntaps: usize,
    window: &Fn(usize) -> Vec<f32>,
) -> Vec<f32> {
    // Convert the frequency to radians and make it a ratio of the sample rate.
    let wc: f32 = 2.0 * PI * cutoff_freq / sample_rate;

    let win_taps: Vec<f32> = window(ntaps);
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);

    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f: f32 = ix as f32;

        // The windowed sinc function is undefined at zero, so set it to
        // something sensible here.
        if ix == 0 {
            let hi = wc / PI * win_taps[(ix + m) as usize];
            taps.push(hi);
        } else {
            let hi = (ix_f * wc).sin() / (ix_f * PI) *
                win_taps[(ix + m) as usize];
            taps.push(hi);
        }
    }
    taps
}
<commit_msg>Samples are only written to the audio buffer once there's enough room for the entire buffer from the SDR<commit_after>extern crate num;
extern crate portaudio;
extern crate rtlsdr;

use portaudio as pa;
use rtlsdr::{RTLSDRDevice, RTLSDRError};
use num::{Num, Zero};
use num::complex::Complex;
use std::env;
use std::f32::consts::PI;
use std::error::Error;
use pa::error::Error as PAError;
use std::thread;
use std::sync::mpsc::channel;

// Make sure that the buffer size is radix-2, otherwise the read_sync function
// will fail with an error code of -8. I want the buffer sizes between the SDR
// and the audio sizes to match, but since we get two samples per read the
// buffer size needs to be double.
const SDR_BUF_SIZE: usize = 262144;

// The buffer size for the audio sink.
const AUDIO_BUF_SIZE: usize = 524288;

// Most other sample rates fail, but this one works for my particular device.
// I will investigate exactly what's happening here and generate a list of
// possible sample rates (if there are others besides this one).
const SDR_SAMPLE_RATE: u32 = 2400000;

// Here is the sample rate of the output waveform we'll try to use.
const AUDIO_SAMPLE_RATE: f32 = 48000.0;

// The number of channels being used for audio.
const CHANNELS: i32 = 2;

// We set the gain manually right now since it seems to be a better option
// than using the AGC (the SDR gets blazing hot with the AGC on).
const SDR_GAIN: i32 = 496;

fn main() {
    match run() {
        Ok(()) => (),
        Err(e) => println!("ERROR: {}", e),
    }
}

struct RTLSDR {
    rtlsdr: RTLSDRDevice,
}

unsafe impl Send for RTLSDR {}

fn run() -> Result<(), Box<Error>> {
    let sdr_index: i32 = env::args()
        .nth(1)
        .expect("Please specify the SDR index.")
        .parse::<i32>()?;
    let fm_freq_mhz: f32 = env::args()
        .nth(2)
        .expect("Please specify a center frequency in MHz.")
        .parse::<f32>()?;
    let bandwidth: u32 = env::args()
        .nth(3)
        .expect("Please specify the bandwidth.")
        .parse::<u32>()?;

    // Set up the threading channels for communication between our two threads.
    let (dongle_tx, dongle_rx) = channel();
    let (demod_tx, demod_rx) = channel();

    // This thread only collects data off of the SDR as quickly as possible and
    // sends it out.
    thread::spawn(move || {
        // Initialize the SDR based on the user's input parameters.
        let fm_freq: u32 = (fm_freq_mhz * 1e6) as u32;
        let mut sdr =
            RTLSDR { rtlsdr: init_sdr(sdr_index, fm_freq, bandwidth).unwrap() };

        loop {
            let bytes = sdr.rtlsdr.read_sync(SDR_BUF_SIZE).unwrap();
            let iq_vec = samps_to_cmplx(bytes).unwrap();
            dongle_tx.send(iq_vec).unwrap();
        }
    });

    // This thread does all of the signal processing required to demodulate
    // the signal and get it to a nice audio stream.
    thread::spawn(move || {
        // Decimating down to 100k samples seems to work the best. I don't
        // really quite get why that is, so I'll need to do more research.
        let dec_rate_filt = 6;
        let dec_rate_audio = 4;

        let taps_filt = windowed_sinc(
            bandwidth as f32,
            SDR_SAMPLE_RATE as f32,
            128,
            &hamming,
        );
        let taps_audio = windowed_sinc(
            bandwidth as f32 / dec_rate_filt as f32,
            SDR_SAMPLE_RATE as f32 / dec_rate_filt as f32,
            128,
            &hamming,
        );

        let mut prev = Complex::zero();
        loop {
            // First, low_pass and decimate the raw IQ signal.
            let mut iq_vec = dongle_rx.recv().unwrap();
            iq_vec = filter(&iq_vec, &taps_filt);
            iq_vec = decimate(iq_vec, dec_rate_filt);

            // Next, demodulate the signal and filter the signal again. The
            // second filter seems to help with the noise after demodulation.
            let res = demod_fm(iq_vec, prev);
            let mut demod_iq = filter_real(&res.0, &taps_audio);
            demod_iq = decimate(demod_iq, dec_rate_audio);
            prev = res.1;
            demod_tx.send(demod_iq).unwrap();
        }
    });

    // Initialize the PortAudio class. We use a blocking stream since we're
    // doing processing on the signal and can't keep up with non-blocking
    // timing requirements.
    let audio = try!(pa::PortAudio::new());
    let settings = try!(audio.default_output_stream_settings(
        CHANNELS,
        AUDIO_SAMPLE_RATE as f64,
        AUDIO_BUF_SIZE as u32,
    ));
    let mut stream = try!(audio.open_blocking_stream(settings));
    try!(stream.start());

    loop {
        let demod_iq = demod_rx.recv().unwrap();
        let buffer_frames = (demod_iq.len() / CHANNELS as usize) as u32;
        let mut out_frames = 0;

        while out_frames < buffer_frames {
            out_frames = match stream.write_available() {
                Ok(available) => {
                    match available {
                        pa::StreamAvailable::Frames(frames) => frames as u32,
                        pa::StreamAvailable::InputOverflowed => {
                            return Err(Box::new(PAError::InputOverflowed))
                        }
                        pa::StreamAvailable::OutputUnderflowed => {
                            return Err(Box::new(PAError::OutputUnderflowed))
                        }
                    }
                }
                Err(e) => return Err(Box::new(e)),
            };
        }

        let n_write_samples = buffer_frames as usize * CHANNELS as usize;

        stream.write(
            buffer_frames,
            |output| for ix in 0..n_write_samples {
                output[ix] = demod_iq[ix];
            },
        )?;
    }
}

fn init_sdr(
    sdr_index: i32,
    fm_freq: u32,
    bandwidth: u32,
) -> Result<RTLSDRDevice, RTLSDRError> {
    let mut sdr = try!(rtlsdr::open(sdr_index));
    try!(sdr.set_center_freq(fm_freq));
    try!(sdr.set_sample_rate(SDR_SAMPLE_RATE));
    try!(sdr.set_tuner_bandwidth(bandwidth));
    try!(sdr.set_tuner_gain(SDR_GAIN));
    try!(sdr.set_agc_mode(false));
    try!(sdr.reset_buffer());
    Ok(sdr)
}

fn decimate<T: Copy>(signal: Vec<T>, dec_rate: usize) -> Vec<T> {
    let mut ix = 0;
    let new_size = (signal.len() / dec_rate + 1) as usize;
    let mut signal_dec = Vec::<T>::with_capacity(new_size);
    while ix < signal.len() {
        signal_dec.push(signal[ix]);
        ix += dec_rate;
    }
    signal_dec
}

fn samps_to_cmplx(bytes: Vec<u8>) -> Option<Vec<Complex<f32>>> {
    // First, check that we've been given an even number of bytes. Not sure
    // what to do if we don't get I and Q.
    let bytes_len = bytes.len();
    if bytes_len % 2 != 0 {
        println!("Received an odd number of samples.");
        return None;

    }

    // Write the values to the complex value and normalize from [0, 255] to
    // [-1, 1].
    let mut iq_vec: Vec<Complex<f32>> = Vec::with_capacity(bytes_len / 2);
    for iq in bytes.chunks(2) {
        let iq_cmplx = Complex::new(
            (iq[0] as f32 - 127.0) / 127.0,
            (iq[1] as f32 - 127.0) / 127.0,
        );
        iq_vec.push(iq_cmplx);
    }
    Some(iq_vec)
}

fn demod_fm(
    iq: Vec<Complex<f32>>,
    prev: Complex<f32>,
) -> (Vec<f32>, Complex<f32>) {

    let mut p = prev.clone();
    let mut demod_queue: Vec<f32> = Vec::with_capacity(iq.len());

    let gain = SDR_SAMPLE_RATE as f32 / (2.0 * PI * 75e3);

    for samp in iq.iter() {
        let conj = p.conj() * samp;
        demod_queue.push(conj.arg() * gain);
        p = *samp;
    }
    (demod_queue, p)
}

///
/// Filters a Complex vector.
///
fn filter<T: Copy + Num + Zero>(
    samples: &Vec<Complex<T>>,
    taps: &Vec<T>,
) -> Vec<Complex<T>> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<Complex<T>> =
        Vec::with_capacity(samples.len() - taps.len() + 1);

    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(Complex::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

///
/// Filter a real vector.
///
fn filter_real<T: Copy + Num + Zero>(
    samples: &Vec<T>,
    taps: &Vec<T>,
) -> Vec<T> {
    // We'll lose taps.len() - 1 samples from the filtering.
    let mut filt_samps: Vec<T> =
        Vec::with_capacity(samples.len() - taps.len() + 1);
    for window in samples.windows(taps.len()) {
        let iter = window.iter().zip(taps.iter());
        let filt_samp = iter.fold(T::zero(), |acc, (x, y)| acc + *x * *y);
        filt_samps.push(filt_samp);
    }
    filt_samps
}

///
/// Generates taps for a Hamming window.
///
fn hamming(ntaps: usize) -> Vec<f32> {
    let m: f32 = ntaps as f32 - 1.0;
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);
    for ix in 0..ntaps {
        taps.push(0.54 - 0.46 * (2.0 * PI * ix as f32 / m).cos());
    }
    taps
}

///
/// Generates filter taps for a sinc filter with a Hamming window.
///
fn windowed_sinc(
    cutoff_freq: f32,
    sample_rate: f32,
    ntaps: usize,
    window: &Fn(usize) -> Vec<f32>,
) -> Vec<f32> {
    // Convert the frequency to radians and make it a ratio of the sample rate.
    let wc: f32 = 2.0 * PI * cutoff_freq / sample_rate;

    let win_taps: Vec<f32> = window(ntaps);
    let mut taps: Vec<f32> = Vec::with_capacity(ntaps);

    let ntaps_i: i32 = ntaps as i32;
    let m: i32 = (ntaps_i - 1) / 2;

    for ix in -m..m + 1 {
        let ix_f: f32 = ix as f32;

        // The windowed sinc function is undefined at zero, so set it to
        // something sensible here.
        if ix == 0 {
            let hi = wc / PI * win_taps[(ix + m) as usize];
            taps.push(hi);
        } else {
            let hi = (ix_f * wc).sin() / (ix_f * PI) *
                win_taps[(ix + m) as usize];
            taps.push(hi);
        }
    }
    taps
}
<|endoftext|>


<commit_before>//! Client for tldr-pages writting in Rust

#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unstable_features,
        unused_import_braces, unused_qualifications)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

extern crate hyper;
extern crate clap;
#[macro_use]
extern crate quick_error;

use std::io::{stderr, Read, Write};
use clap::{Arg, App};
use hyper::client::response::Response as HttpResponse;

#[cfg(target_os = "macos")]
const PLATFORM: &'static str = "osx";
#[cfg(not(target_os = "macos"))]
const PLATFORM: &'static str = "linux";

fn fetch_tldr(command: &str, platform: &str) -> Result<HttpResponse, Error> {
    let client = hyper::Client::new();
    let url = format!("http://raw.github.com/rprieto/tldr/master/pages/{platform}/{page}.md",
                      platform = platform,
                      page = command);

    let res = try!(client.get(&url)
                         .header(hyper::header::Connection::close())
                         .header(hyper::header::ContentType::plaintext())
                         .send()
                         .map_err(|err| Error::HttpRequest(command.to_owned(), err)));

    if res.status.is_success() {
        Ok(res)
    } else {
        Err(Error::HttpReponse(command.to_owned(), res.status))
    }
}

fn render_tldr<R: Read>(text: &mut R) -> Result<(), Error> {
    let mut buf = String::with_capacity(1024);
    try!(text.read_to_string(&mut buf));

    println!("{}", buf);
    Ok(())
}

quick_error! {
    #[derive(Debug)]
    enum Error {
        HttpRequest(command: String, err: hyper::Error) {
            from(err)
            cause(err)
            description("Error fetching page")
            display("Error fetching description for `{}`: {}", command, err)
        }
        HttpReponse(command: String, status: hyper::status::StatusCode) {
            description("Could not fetch description for command")
            display("Could not fetch description for command `{}`: {}", command, status)
        }
        Io(err: std::io::Error) {
            from()
            cause(err)
            description(err.description())
            display("Couldn't read stream")
        }
    }
}

fn main() {
    let matches = App::new("tldr")
                      .version(env!("CARGO_PKG_VERSION"))
                      .author("Pascal Hertleif <killercup@gmail.com>")
                      .about("Simplified and community-driven man pages")
                      .arg(Arg::with_name("command")
                               .help("Fetch the docs for command and render them to the \
                                      terminal.")
                               .required(true)
                               .index(1))
                      .get_matches();

    let command = matches.value_of("command").unwrap();

    fetch_tldr(command, "common")
        .or_else(|_| fetch_tldr(command, PLATFORM))
        .and_then(|mut res| render_tldr(&mut res))
        .unwrap_or_else(|err| {
            writeln!(stderr(), "{}", err).unwrap();
            std::process::exit(1);
        });
}
<commit_msg>feat(fetch): Stream HTTP Response to stdout<commit_after>//! Client for tldr-pages writting in Rust

#![deny(missing_docs,
        missing_debug_implementations, missing_copy_implementations,
        trivial_casts, trivial_numeric_casts,
        unsafe_code,
        unstable_features,
        unused_import_braces, unused_qualifications)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]

extern crate hyper;
extern crate clap;
#[macro_use]
extern crate quick_error;

use std::io::{stderr, stdout, Read, Write};
use clap::{Arg, App};
use hyper::client::response::Response as HttpResponse;

#[cfg(target_os = "macos")]
const PLATFORM: &'static str = "osx";
#[cfg(not(target_os = "macos"))]
const PLATFORM: &'static str = "linux";

fn fetch_tldr(command: &str, platform: &str) -> Result<HttpResponse, Error> {
    let client = hyper::Client::new();
    let url = format!("http://raw.github.com/rprieto/tldr/master/pages/{platform}/{page}.md",
                      platform = platform,
                      page = command);

    let res = try!(client.get(&url)
                         .header(hyper::header::Connection::close())
                         .header(hyper::header::ContentType::plaintext())
                         .send()
                         .map_err(|err| Error::HttpRequest(command.to_owned(), err)));

    if res.status.is_success() {
        Ok(res)
    } else {
        Err(Error::HttpReponse(command.to_owned(), res.status))
    }
}

fn render_tldr<R: Read>(text: &mut R) -> Result<(), Error> {
    pipe(text, &mut stdout())
}

fn pipe<R: Read, W: Write>(input: &mut R, output: &mut W) -> Result<(), Error> {
    let mut buffer = [0; 1024];

    loop {
        let written = try!(input.read(&mut buffer));
        if written == 0 { break; }
        try!(output.write_all(&buffer[0..written]));
        buffer = [0; 1024];
    }

    Ok(())
}

quick_error! {
    #[derive(Debug)]
    enum Error {
        HttpRequest(command: String, err: hyper::Error) {
            from(err)
            cause(err)
            description("Error fetching page")
            display("Error fetching description for `{}`: {}", command, err)
        }
        HttpReponse(command: String, status: hyper::status::StatusCode) {
            description("Could not fetch description for command")
            display("Could not fetch description for command `{}`: {}", command, status)
        }
        Io(err: std::io::Error) {
            from()
            cause(err)
            description(err.description())
            display("Couldn't read stream")
        }
    }
}

fn main() {
    let matches = App::new("tldr")
                      .version(env!("CARGO_PKG_VERSION"))
                      .author("Pascal Hertleif <killercup@gmail.com>")
                      .about("Simplified and community-driven man pages")
                      .arg(Arg::with_name("command")
                               .help("Fetch the docs for command and render them to the \
                                      terminal.")
                               .required(true)
                               .index(1))
                      .get_matches();

    let command = matches.value_of("command").unwrap();

    fetch_tldr(command, "common")
        .or_else(|_| fetch_tldr(command, PLATFORM))
        .and_then(|mut res| render_tldr(&mut res))
        .unwrap_or_else(|err| {
            writeln!(stderr(), "{}", err).unwrap();
            std::process::exit(1);
        });
}
<|endoftext|>


<commit_before>extern crate chrono;

use std::fmt;
use std::process::Command;
use std::str;
// use chrono::datetime::DateTime;
// use chrono::Local;
// use chrono::offset::TimeZone;
use chrono::*;

struct Branch {
    user: String,
    branch: String,
    date: DateTime<FixedOffset>,
}

impl fmt::Display for Branch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "user: {}\nbranch: {}\ndate: {}",
               self.user,
               self.branch,
               self.date)
    }
}

fn parse_repo(line: String) -> Option<Branch> {
    if !line.contains("refs/remotes/origin/HEAD") && !line.contains("refs/remotes/origin/master") {

        let mut user = String::new();
        let mut date = String::new();
        let mut branch = String::new();
        for (i, part) in line.split("^").enumerate() {
            match i {
                0 => user = part.to_string(),
                1 => branch = part.to_string(),
                2 => date = part.to_string(),
                _ => {}
            }
        }
        Some(Branch {
            user: user,
            branch: branch,
            date: DateTime::parse_from_rfc2822(&date).unwrap(),
        })
    } else {
        None
    }
}

fn main() {

    let v = get_git_data();

    for branch in v {
        println!("[branch]\n{}", branch);
    }
}

fn get_git_data() -> Vec<Branch> {
    let output = Command::new("git")
        .arg("for-each-ref")
        .arg("--sort=-committerdate")
        .arg("--format=%(authorname)^%(refname)^%(committerdate:rfc2822)")
        .arg("refs/remotes/origin/")
        .output()
        .expect("failed to execute process");
    let git_output = str::from_utf8(&output.stdout).unwrap();

    let mut v: Vec<Branch> = Vec::new();
    for line in git_output.lines() {
        parse_repo(line.to_string()).map(|x| v.push(x));
    }
    v
}
<commit_msg>problems<commit_after>extern crate chrono;

use std::fmt;
use std::process::Command;
use std::str;
use std::iter;
// use chrono::datetime::DateTime;
// use chrono::Local;
// use chrono::offset::TimeZone;
use chrono::*;

#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct Branch {
    user: String,
    date: DateTime<FixedOffset>,
    branch: String,
}

impl fmt::Display for Branch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "[{}] {} {}",
               self.date.format("%Y-%m-%d"),
               self.user,
               self.branch)
    }
}

impl fmt::Debug for Branch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "user: {}\nbranch: {}\ndate: {}",
               self.user,
               self.branch,
               self.date)
    }
}

fn parse_repo(line: String) -> Option<Branch> {
    if !line.contains("origin/HEAD") && !line.contains("origin/master") {
        let mut user = String::new();
        let mut date = String::new();
        let mut branch = String::new();
        for (i, part) in line.split("^").enumerate() {
            match i {
                0 => user = part.to_string(),
                1 => branch = part.to_string().replace("origin/", ""),
                2 => date = part.to_string(),
                _ => {}
            }
        }
        Some(Branch {
            user: user,
            branch: branch,
            date: DateTime::parse_from_rfc2822(&date).unwrap(),
        })
    } else {
        None
    }
}

fn main() {
    let mut v = get_git_data();
    v.sort();
    print_git_data(v);
}

fn print_git_data(v: Vec<Branch>) {
    let max = v.iter().fold(0, |max, branch| {
        let len = branch.user.len();
        if len > max {
            len
        } else {
            max
        }
    });
    println!("max: {}", max);
    for branch in v {
        let padding_count = max - branch.branch.len();
        let padding: String = iter::repeat(" ").take(padding_count).collect();
        print!("[{}]", branch.date.format("%Y-%m-%d"));
        print!("{}", branch.branch);
        println!("{}", padding);
    }
}

fn get_git_data() -> Vec<Branch> {
    let output = Command::new("git")
        .arg("for-each-ref")
        .arg("--format=%(authorname)^%(refname:short)^%(committerdate:rfc2822)")
        .arg("refs/remotes/origin/")
        .output()
        .expect("failed to execute process");
    let git_output = str::from_utf8(&output.stdout).unwrap();

    let mut v: Vec<Branch> = Vec::new();
    for line in git_output.lines() {
        parse_repo(line.to_string()).map(|x| v.push(x));
    }
    v
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;

#[derive(Debug, PartialEq, Clone)]
pub enum Token {
    Unknown(String), // Invalid test (basically non-ascii)
    Literal(String), // Numeric literal number
    Func(Function), // Pre-defined function (like cos() )
    Const(Constant), // Constant like pi or e
    Var(String), // str arbitrary single char variable name
    Op(Operator), // Any of the 4 operators (+-*/)
    Open, // Open parens '('
    Close, // Closing parens ')'
    Set(Vec<Token>), // [ (, tokens..., ) ]
}

#[derive(Debug, PartialEq, Clone)]
pub enum Function {
    Sqrt(Vec<Token>),
    Ln(Vec<Token>),
    Log(f64, Vec<Token>),
    Sin(Vec<Token>),
    Cos(Vec<Token>),
    Tan(Vec<Token>),
    Asin(Vec<Token>),
    Acos(Vec<Token>),
    Atan(Vec<Token>),
    Sinh(Vec<Token>),
    Cosh(Vec<Token>),
    Tanh(Vec<Token>),
    Asinh(Vec<Token>),
    Acosh(Vec<Token>),
    Atanh(Vec<Token>),
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Constant {
	Pi,
	E,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Operator {
    Add,
    Sub,
    Div,
    Mul,
    Pow,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Assoc {
    Left,
    Right,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Order {
    AddSub = 1,
    MulDiv = 2,
    IMul = 3, // Implicit multiplication
    Pow = 4,
    Paren = 5,
}

#[derive(Debug, PartialEq, Clone)]
struct Expression {
    tokens: Vec<Token>,
    constant: f64,
}

#[allow(dead_code)]
impl Expression {
	fn new(tokens: Vec<Token>, constant: f64) -> Self {
		Expression {tokens: tokens, constant: constant}
	}

	fn push(&mut self, token: Token) {
		self.tokens.push(token);
	}

	fn update_constant(&mut self, constant: &f64) {
		self.constant += *constant;
	}

	fn get_constant(&self) -> f64 {
		self.constant
	}

	fn get_tokens(&self) -> &[Token] {
		self.tokens.as_slice()
	}

	fn get_mut_tokens(&mut self) -> &mut [Token] {
		self.tokens.as_mut_slice()
	}

	fn replace_token(&mut self, index: usize, new_token: Token) {
		self.tokens.remove(index);
		self.tokens.insert(index, new_token);
	}

	fn replace_all_tokens(&mut self, new_token: Vec<Token>) {
		self.tokens = new_token
	}

	fn find_first(&self, token: &Token) -> Option<usize> {
		for i in 0..self.tokens.len() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn find_first_recursive(&self, token: &Token) -> Option<usize> {
		unimplemented!();
		for i in 0..self.tokens.len() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn find_last(&self, token: &Token) -> Option<usize> {
		for i in (0..self.tokens.len()).rev() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn split_at(&self, index: usize) -> (&[Token], &[Token]) {
		self.tokens.split_at(index)
	}

	fn len(&self) -> usize {
		self.tokens.len()
	}
}

fn main() {
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let mut input = String::new();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
    	input.clear();
    	print!(">>>> ");
    	stdout.flush().ok();
        stdin.read_line(&mut input).unwrap();
        input = strip_white_space(&input);
        input = input.to_lowercase();
        if input == "quit" {
        	print!("Exiting...");
        	break;
        }
        let expr = parse_input(&input).unwrap();
        println!("{:?}", &expr);
    }
}

fn strip_white_space(input: &String) -> String {
	input.split_whitespace().collect::<Vec<&str>>().join("")
}

fn parse_input(input: &String) -> Result<Expression, ()> {
	let mut expr: Expression = Expression::new(Vec::new(), 0.0);
	for c in input.chars() {
		match c {
			'-' => {
				expr.push(Token::Op(Operator::Sub));
			},
			'+' => {
				expr.push(Token::Op(Operator::Add));
			},
			'/' => {
				expr.push(Token::Op(Operator::Div));
			},
			'*' => {
				expr.push(Token::Op(Operator::Mul));
			},
			'^' => {
				expr.push(Token::Op(Operator::Pow));
			},
			'(' => {
				expr.push(Token::Open);
			},
			')' => {
				expr.push(Token::Close);
			},
			_ => continue,
		}
	}
	// Once we find an outermost (), split the rest of the expression after that off into a new vector
	//let mut expr_vecs: Vec<Vec<Token>> = Vec::new();
	while let Some(index) = expr.find_first(&Token::Open) { // If we find an index of an Open
		let end_set: usize = expr.find_last(&Token::Close).unwrap(); // Finds the last Close, need to find the one that actually matches the proper Open (if two Sets are on same depth)
		let mut lhs: Vec<Token> = Vec::new();
		{
			let (temp_lhs, temp_rhs) = expr.split_at(index); // [0, where set should be placed)
			lhs = temp_lhs.to_vec();
			let mut rhs = temp_rhs.to_vec(); // [where set should be placed, len)
			rhs.remove(0);
			let (left_rhs, right_rhs) = rhs.split_at(end_set-1);
			let (left_rhs, mut right_rhs) = (left_rhs.to_vec(), right_rhs.to_vec());
			right_rhs.remove(0);
			lhs.push(Token::Set(left_rhs));
			lhs.append(&mut right_rhs);
		}
		for i in (0..lhs.len()).rev() {
			if lhs.get(i).unwrap() == &Token::Close {
				lhs.remove(i);
				break;
			}
		}
		expr.replace_all_tokens(lhs);
	}
	Ok(expr)
}

#[test]
fn test_parse() {
	let input: String = String::from("+");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Add)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("-");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Sub)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("/");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Div)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("*");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Mul)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("^");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Pow)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("()");
	assert_eq!(Expression::new(vec![Token::Set(Vec::new())], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(+)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Add)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(-)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Sub)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(*)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Mul)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(/)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Div)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(^)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Pow)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(())");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Set(Vec::new())])], 0.0), parse_input(&input).unwrap());
}<commit_msg>Deleted bad function<commit_after>use std::io;
use std::io::Write;

#[derive(Debug, PartialEq, Clone)]
pub enum Token {
    Unknown(String), // Invalid test (basically non-ascii)
    Literal(String), // Numeric literal number
    Func(Function), // Pre-defined function (like cos() )
    Const(Constant), // Constant like pi or e
    Var(String), // str arbitrary single char variable name
    Op(Operator), // Any of the 4 operators (+-*/)
    Open, // Open parens '('
    Close, // Closing parens ')'
    Set(Vec<Token>), // [ (, tokens..., ) ]
}

#[derive(Debug, PartialEq, Clone)]
pub enum Function {
    Sqrt(Vec<Token>),
    Ln(Vec<Token>),
    Log(f64, Vec<Token>),
    Sin(Vec<Token>),
    Cos(Vec<Token>),
    Tan(Vec<Token>),
    Asin(Vec<Token>),
    Acos(Vec<Token>),
    Atan(Vec<Token>),
    Sinh(Vec<Token>),
    Cosh(Vec<Token>),
    Tanh(Vec<Token>),
    Asinh(Vec<Token>),
    Acosh(Vec<Token>),
    Atanh(Vec<Token>),
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Constant {
	Pi,
	E,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Operator {
    Add,
    Sub,
    Div,
    Mul,
    Pow,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Assoc {
    Left,
    Right,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Order {
    AddSub = 1,
    MulDiv = 2,
    IMul = 3, // Implicit multiplication
    Pow = 4,
    Paren = 5,
}

#[derive(Debug, PartialEq, Clone)]
struct Expression {
    tokens: Vec<Token>,
    constant: f64,
}

#[allow(dead_code)]
impl Expression {
	fn new(tokens: Vec<Token>, constant: f64) -> Self {
		Expression {tokens: tokens, constant: constant}
	}

	fn push(&mut self, token: Token) {
		self.tokens.push(token);
	}

	fn update_constant(&mut self, constant: &f64) {
		self.constant += *constant;
	}

	fn get_constant(&self) -> f64 {
		self.constant
	}

	fn get_tokens(&self) -> &[Token] {
		self.tokens.as_slice()
	}

	fn get_mut_tokens(&mut self) -> &mut [Token] {
		self.tokens.as_mut_slice()
	}

	fn replace_token(&mut self, index: usize, new_token: Token) {
		self.tokens.remove(index);
		self.tokens.insert(index, new_token);
	}

	fn replace_all_tokens(&mut self, new_token: Vec<Token>) {
		self.tokens = new_token
	}

	fn find_first(&self, token: &Token) -> Option<usize> {
		for i in 0..self.tokens.len() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn find_last(&self, token: &Token) -> Option<usize> {
		for i in (0..self.tokens.len()).rev() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn split_at(&self, index: usize) -> (&[Token], &[Token]) {
		self.tokens.split_at(index)
	}

	fn len(&self) -> usize {
		self.tokens.len()
	}
}

fn main() {
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let mut input = String::new();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
    	input.clear();
    	print!(">>>> ");
    	stdout.flush().ok();
        stdin.read_line(&mut input).unwrap();
        input = strip_white_space(&input);
        input = input.to_lowercase();
        if input == "quit" {
        	print!("Exiting...");
        	break;
        }
        let expr = parse_input(&input).unwrap();
        println!("{:?}", &expr);
    }
}

fn strip_white_space(input: &String) -> String {
	input.split_whitespace().collect::<Vec<&str>>().join("")
}

fn parse_input(input: &String) -> Result<Expression, ()> {
	let mut expr: Expression = Expression::new(Vec::new(), 0.0);
	for c in input.chars() {
		match c {
			'-' => {
				expr.push(Token::Op(Operator::Sub));
			},
			'+' => {
				expr.push(Token::Op(Operator::Add));
			},
			'/' => {
				expr.push(Token::Op(Operator::Div));
			},
			'*' => {
				expr.push(Token::Op(Operator::Mul));
			},
			'^' => {
				expr.push(Token::Op(Operator::Pow));
			},
			'(' => {
				expr.push(Token::Open);
			},
			')' => {
				expr.push(Token::Close);
			},
			_ => continue,
		}
	}
	// Once we find an outermost (), split the rest of the expression after that off into a new vector
	//let mut expr_vecs: Vec<Vec<Token>> = Vec::new();
	while let Some(index) = expr.find_first(&Token::Open) { // If we find an index of an Open
		let end_set: usize = expr.find_last(&Token::Close).unwrap(); // Finds the last Close, need to find the one that actually matches the proper Open (if two Sets are on same depth)
		let mut lhs: Vec<Token> = Vec::new();
		{
			let (temp_lhs, temp_rhs) = expr.split_at(index); // [0, where set should be placed)
			lhs = temp_lhs.to_vec();
			let mut rhs = temp_rhs.to_vec(); // [where set should be placed, len)
			rhs.remove(0);
			let (left_rhs, right_rhs) = rhs.split_at(end_set-1);
			let (left_rhs, mut right_rhs) = (left_rhs.to_vec(), right_rhs.to_vec());
			right_rhs.remove(0);
			lhs.push(Token::Set(left_rhs));
			lhs.append(&mut right_rhs);
		}
		for i in (0..lhs.len()).rev() {
			if lhs.get(i).unwrap() == &Token::Close {
				lhs.remove(i);
				break;
			}
		}
		expr.replace_all_tokens(lhs);
	}
	Ok(expr)
}

#[test]
fn test_parse() {
	let input: String = String::from("+");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Add)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("-");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Sub)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("/");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Div)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("*");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Mul)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("^");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Pow)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("()");
	assert_eq!(Expression::new(vec![Token::Set(Vec::new())], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(+)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Add)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(-)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Sub)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(*)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Mul)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(/)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Div)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(^)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Pow)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(())");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Set(Vec::new())])], 0.0), parse_input(&input).unwrap());
}<|endoftext|>


<commit_before>#![feature(phase)]
#![feature(if_let)]

#[phase(plugin)]
extern crate rustecs_macros;

extern crate rustecs;
extern crate serialize;
extern crate piston;
extern crate sdl2_game_window;
extern crate opengl_graphics;
use std::default::Default;
use std::rand;
use std::rand::Rng;
use std::num::abs;

use opengl_graphics::{
    Gl,
};
use sdl2_game_window::WindowSDL2;
use piston::{
    EventIterator,
    EventSettings,
    WindowSettings,
};
use piston::graphics::{
    AddBorder,
    AddRectangle,
    AddEllipse,
    AddColor,
    Context,
    Draw,
};
use piston::event::{
    PressEvent,
    ReleaseEvent,
    Event,
    Render,
    Update,
    Input,
};
use piston::input::{
    keyboard,
    Keyboard,
};
use rustecs::{
    Entities,
    Components,
};

static WINDOW_W: f64 = 800.0;
static WINDOW_H: f64 = 600.0;

fn draw_system(event: &Event,
              gl: &mut Gl,
              positions: &mut Components<Position>,
              shapes: &mut Components<Shape>,
              colors: &mut Components<Color>) {
    if let &Render(args) = event {
        let w = args.width as f64;
        let h = args.height as f64;
        gl.viewport(0, 0, w as i32, h as i32);
        let c = Context::abs(w, h);
        // Clear background.
        c.rgb(0.0, 0.0, 0.0).draw(gl);

        for (eid, pos) in positions.iter_mut() {
          let mut shape = Point;
          let mut border = None;
          if shapes.contains_key(eid) {
            shape = shapes.get_mut(eid).shape;
            border = shapes.get_mut(eid).border;
          }
          let (r, g, b) = if colors.contains_key(eid) {
              (colors.get_mut(eid).r, colors.get_mut(eid).g, colors.get_mut(eid).b)
          } else {
              (1.0, 1.0, 1.0)
          };
          let drawing = c.rgb(r, g, b);
          match (shape, border) {
              (Point, None)    => drawing.rect(1.0, 1.0, w, h).draw(gl),
              (Point, Some(b)) => drawing.rect(1.0, 1.0, w, h).border_radius(b).draw(gl),

              (Circle(rad), None)    => drawing.ellipse(pos.x, pos.y, rad, rad).draw(gl),
              (Circle(rad), Some(b)) => drawing.ellipse(pos.x, pos.y, rad, rad).border_radius(b).draw(gl),

              (Square(w,h), None)    => drawing.rect(pos.x, pos.y, w, h).draw(gl),
              (Square(w,h), Some(b)) => drawing.rect(pos.x, pos.y, w, h).border_radius(b).draw(gl),
          };
        }
    }
}

fn shimmer_system(shimmers: &mut Components<Shimmer>,
                 colors: &mut Components<Color>) {
    for (eid, _) in shimmers.iter_mut() {
        if !colors.contains_key(eid) {
            continue;
        }
        let color = colors.get_mut(eid);
        let ref mut rng = rand::task_rng();
        color.r = rng.gen_range(0.5, 1.0);
        color.g = rng.gen_range(0.5, 1.0);
        color.b = rng.gen_range(0.5, 1.0);
    }
}

fn move_system(event: &Event,
              positions: &mut Components<Position>,
              velocities: &mut Components<Velocity>) {
    if let &Update(args) = event {
        let dt = args.dt;
        for (eid, position) in positions.iter_mut() {
            if !velocities.contains_key(eid) {
                continue;
            }

            // If we have both a position and a velocity, integrate.
            let velocity = velocities.get_mut(eid);
            position.x += velocity.x * dt;
            position.y += velocity.y * dt;
            if position.x > WINDOW_W || position.x < 0.0 {
                velocity.x *= -1.0;
            }
            if position.y > WINDOW_H || position.y < 0.0 {
                velocity.y *= -1.0;
            }
        }
    }
}

fn control_system(event: &Event,
              player_eids: &[u32, ..2],
              velocities: &mut Components<Velocity>) {

    const PADDLE_V: f64 = 800.0;
    let p1 = &player_eids[0];
    let p2 = &player_eids[1];
    event.press(|button| {
        if button == Keyboard(keyboard::W) {
            velocities.get_mut(p1).y = -PADDLE_V;
        } else if button == Keyboard(keyboard::S) {
            velocities.get_mut(p1).y = PADDLE_V;
        } else if button == Keyboard(keyboard::I) {
            velocities.get_mut(p2).y = -PADDLE_V;
        } else if button == Keyboard(keyboard::K) {
            velocities.get_mut(p2).y = PADDLE_V;
        }
    });
    event.release(|button| {
        if button == Keyboard(keyboard::W)
        || button == Keyboard(keyboard::S) {
            velocities.get_mut(p1).y = 0.0;
        } else if button == Keyboard(keyboard::I)
               || button == Keyboard(keyboard::K) {
            velocities.get_mut(p2).y = 0.0;
        }
    });
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Position {
    x: f64,
    y: f64
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Shimmer;

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Color {
    r: f32,
    g: f32,
    b: f32
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub enum ShapeVarient {
    Point,
    Circle(f64), // radius
    Square(f64, f64), // width, height
}

impl Default for ShapeVarient {
    fn default() -> ShapeVarient { Point }
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Shape {
    shape: ShapeVarient,
    border: Option<f64>
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Velocity {
    x: f64,
    y: f64
}

world! {
    World,
    components Position, Shape, Velocity, Color, Shimmer;
}

fn make_ball() -> Entity {
    const BALL_R: f64 = 20.0;
    let shape = Circle(BALL_R);
    let x = (WINDOW_W - BALL_R) / 2.0;
    let y = (WINDOW_H - BALL_R) / 2.0;

    fn random_vel() -> f64 {
        let ref mut rng = rand::task_rng();
        rng.gen_range(80.0, 100.0) * if rng.gen() { 1.0 } else { -1.0 }
    }

    Entity::new()
        .with_shimmer(Shimmer)
        .with_position(
            Position{
                x: x,
                y: y
            })
        .with_velocity(
            Velocity {
                x: random_vel(),
                y: random_vel()
            })
        .with_shape(
            Shape {
                shape: shape,
                border: None
            })
        .with_color(
            Color{
                r: 1.0,
                g: 0.5,
                b: 0.2
            })
}

fn make_player(p1: bool) -> Entity {
    const FROM_WALL: f64 = 20.0;
    const PADDLE_W: f64 = 20.0;
    const PADDLE_H: f64 = 150.0;
    let x = if p1 {
        FROM_WALL
    } else {
        WINDOW_W - FROM_WALL - PADDLE_W
    };
    let y = (WINDOW_H - PADDLE_H) / 2.0;
    Entity::new()
        .with_velocity(Velocity { x: 0.0, y: 0.0 } )
        .with_position(
            Position{
                x: x,
                y: y
            })
        .with_shape(
            Shape {
                shape: Square(PADDLE_W, PADDLE_H),
                border: None
            })
        .with_color(
            Color{
                r: 0.5,
                g: 0.2,
                b: 0.8
            })
}

fn main() {
    let opengl = piston::shader_version::opengl::OpenGL_3_2;
    let mut window = WindowSDL2::new(
        opengl,
        WindowSettings {
            title: "Pong".to_string(),
            size: [WINDOW_W as u32, WINDOW_H as u32],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut gl = Gl::new(opengl);
    let mut world = World::new();

    let players = [
        world.add(make_player(true)),
        world.add(make_player(false))
    ];
    world.add(make_ball());

    let event_settings = EventSettings {
        updates_per_second: 120,
        max_frames_per_second: 60,
    };

    for e in EventIterator::new(&mut window, &event_settings) {
        control_system(&e, &players, &mut world.velocities);
        move_system(&e, &mut world.positions, &mut world.velocities);
        shimmer_system(&mut world.shimmers, &mut world.colors);
        draw_system(&e, &mut gl, &mut world.positions, &mut world.shapes, &mut world.colors);
    }
}
<commit_msg>Better controller factoring.<commit_after>#![feature(phase)]
#![feature(if_let)]

#[phase(plugin)]
extern crate rustecs_macros;

extern crate rustecs;
extern crate serialize;
extern crate piston;
extern crate sdl2_game_window;
extern crate opengl_graphics;
use std::default::Default;
use std::rand;
use std::rand::Rng;
use std::num::abs;

use opengl_graphics::{
    Gl,
};
use sdl2_game_window::WindowSDL2;
use piston::{
    EventIterator,
    EventSettings,
    WindowSettings,
};
use piston::graphics::{
    AddBorder,
    AddRectangle,
    AddEllipse,
    AddColor,
    Context,
    Draw,
};
use piston::event::{
    PressEvent,
    ReleaseEvent,
    Event,
    Render,
    Update,
    Input,
};
use piston::input::{
    keyboard,
    Keyboard,
    Button,
};
use rustecs::{
    Entities,
    Components,
};

static WINDOW_W: f64 = 800.0;
static WINDOW_H: f64 = 600.0;

fn draw_system(event: &Event,
              gl: &mut Gl,
              positions: &mut Components<Position>,
              shapes: &mut Components<Shape>,
              colors: &mut Components<Color>) {
    if let &Render(args) = event {
        let w = args.width as f64;
        let h = args.height as f64;
        gl.viewport(0, 0, w as i32, h as i32);
        let c = Context::abs(w, h);
        // Clear background.
        c.rgb(0.0, 0.0, 0.0).draw(gl);

        for (eid, pos) in positions.iter_mut() {
          let mut shape = Point;
          let mut border = None;
          if shapes.contains_key(eid) {
            shape = shapes.get_mut(eid).shape;
            border = shapes.get_mut(eid).border;
          }
          let (r, g, b) = if colors.contains_key(eid) {
              (colors.get_mut(eid).r, colors.get_mut(eid).g, colors.get_mut(eid).b)
          } else {
              (1.0, 1.0, 1.0)
          };
          let drawing = c.rgb(r, g, b);
          match (shape, border) {
              (Point, None)    => drawing.rect(1.0, 1.0, w, h).draw(gl),
              (Point, Some(b)) => drawing.rect(1.0, 1.0, w, h).border_radius(b).draw(gl),

              (Circle(rad), None)    => drawing.ellipse(pos.x, pos.y, rad, rad).draw(gl),
              (Circle(rad), Some(b)) => drawing.ellipse(pos.x, pos.y, rad, rad).border_radius(b).draw(gl),

              (Square(w,h), None)    => drawing.rect(pos.x, pos.y, w, h).draw(gl),
              (Square(w,h), Some(b)) => drawing.rect(pos.x, pos.y, w, h).border_radius(b).draw(gl),
          };
        }
    }
}

fn shimmer_system(shimmers: &mut Components<Shimmer>,
                 colors: &mut Components<Color>) {
    for (eid, _) in shimmers.iter_mut() {
        if !colors.contains_key(eid) {
            continue;
        }
        let color = colors.get_mut(eid);
        let ref mut rng = rand::task_rng();
        color.r = rng.gen_range(0.5, 1.0);
        color.g = rng.gen_range(0.5, 1.0);
        color.b = rng.gen_range(0.5, 1.0);
    }
}

fn move_system(event: &Event,
              positions: &mut Components<Position>,
              velocities: &mut Components<Velocity>) {
    if let &Update(args) = event {
        let dt = args.dt;
        for (eid, position) in positions.iter_mut() {
            if !velocities.contains_key(eid) {
                continue;
            }

            // If we have both a position and a velocity, integrate.
            let velocity = velocities.get_mut(eid);
            position.x += velocity.x * dt;
            position.y += velocity.y * dt;
            if position.x > WINDOW_W || position.x < 0.0 {
                velocity.x *= -1.0;
            }
            if position.y > WINDOW_H || position.y < 0.0 {
                velocity.y *= -1.0;
            }
        }
    }
}

fn control_system(event: &Event,
              controllers: &mut Components<PlayerController>,
              velocities: &mut Components<Velocity>) {

    const PADDLE_V: f64 = 800.0;

    for (eid, controller) in controllers.iter_mut() {
        event.press(|button| {
            if button == Keyboard(controller.up) {
                velocities.get_mut(eid).y = -PADDLE_V;
            } else if button == Keyboard(controller.down) {
                velocities.get_mut(eid).y = PADDLE_V;
            }
        });
        event.release(|button| {
            if button == Keyboard(controller.up)
            || button == Keyboard(controller.down) {
                velocities.get_mut(eid).y = 0.0;
            }
        });
    }
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct PlayerController {
    up: keyboard::Key,
    down: keyboard::Key
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Position {
    x: f64,
    y: f64
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Shimmer;

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Color {
    r: f32,
    g: f32,
    b: f32
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub enum ShapeVarient {
    Point,
    Circle(f64), // radius
    Square(f64, f64), // width, height
}

impl Default for ShapeVarient {
    fn default() -> ShapeVarient { Point }
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Shape {
    shape: ShapeVarient,
    border: Option<f64>
}

#[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
pub struct Velocity {
    x: f64,
    y: f64
}

world! {
    World,
    components Position, Shape, Velocity, Color, Shimmer, PlayerController;
}

fn make_ball() -> Entity {
    const BALL_R: f64 = 20.0;
    let shape = Circle(BALL_R);
    let x = (WINDOW_W - BALL_R) / 2.0;
    let y = (WINDOW_H - BALL_R) / 2.0;

    fn random_vel() -> f64 {
        let ref mut rng = rand::task_rng();
        rng.gen_range(80.0, 100.0) * if rng.gen() { 1.0 } else { -1.0 }
    }

    Entity::new()
        .with_shimmer(Shimmer)
        .with_position(
            Position{
                x: x,
                y: y
            })
        .with_velocity(
            Velocity {
                x: random_vel(),
                y: random_vel()
            })
        .with_shape(
            Shape {
                shape: shape,
                border: None
            })
        .with_color(
            Color{
                r: 1.0,
                g: 0.5,
                b: 0.2
            })
}

fn make_player(p1: bool) -> Entity {
    const FROM_WALL: f64 = 20.0;
    const PADDLE_W: f64 = 20.0;
    const PADDLE_H: f64 = 150.0;
    let x = if p1 {
        FROM_WALL
    } else {
        WINDOW_W - FROM_WALL - PADDLE_W
    };
    let y = (WINDOW_H - PADDLE_H) / 2.0;
    Entity::new()
        .with_player_controller(
            PlayerController {
                up: if p1 { keyboard::W } else { keyboard::I },
                down: if p1 { keyboard::S } else { keyboard::K }
            })
        .with_velocity(Velocity { x: 0.0, y: 0.0 } )
        .with_position(
            Position{
                x: x,
                y: y
            })
        .with_shape(
            Shape {
                shape: Square(PADDLE_W, PADDLE_H),
                border: None
            })
        .with_color(
            Color{
                r: 0.5,
                g: 0.2,
                b: 0.8
            })
}

fn main() {
    let opengl = piston::shader_version::opengl::OpenGL_3_2;
    let mut window = WindowSDL2::new(
        opengl,
        WindowSettings {
            title: "Pong".to_string(),
            size: [WINDOW_W as u32, WINDOW_H as u32],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut gl = Gl::new(opengl);
    let mut world = World::new();

    world.add(make_player(true));
    world.add(make_player(false));
    world.add(make_ball());

    let event_settings = EventSettings {
        updates_per_second: 120,
        max_frames_per_second: 60,
    };

    for e in EventIterator::new(&mut window, &event_settings) {
        control_system(&e, &mut world.player_controllers, &mut world.velocities);
        move_system(&e, &mut world.positions, &mut world.velocities);
        shimmer_system(&mut world.shimmers, &mut world.colors);
        draw_system(&e, &mut gl, &mut world.positions, &mut world.shapes, &mut world.colors);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2016 William (B.J.) Snow Orvis
//
// 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.

extern crate argparse;
extern crate graphics;
extern crate piston;
extern crate piston_window;

extern crate fractal;
mod glwindow;

use argparse::{ArgumentParser, Store, StoreTrue};

use fractal::curves::cesaro::CesaroFractal;
use fractal::curves::cesarotri::CesaroTriFractal;
use fractal::curves::dragon::DragonFractal;
use fractal::curves::kochcurve::KochCurve;
use fractal::curves::levyccurve::LevyCCurve;
use fractal::curves::terdragon::TerdragonFractal;
use fractal::lindenmayer::LindenmayerSystemTurtleProgram;
use fractal::turtle::TurtleProgram;

struct Arguments {
    curve_name: String,
    iterations: u64,
    animate: u64,
    version: bool,
}

fn parse_args() -> Arguments {
    let mut retargs = Arguments { curve_name: String::from(""), iterations: 0, animate: 0, version: false };
    {
        let mut parser = ArgumentParser::new();
        parser.set_description("Renders fractal curves.");
        parser.refer(&mut retargs.animate).add_option(&["--animate"], Store, "Animate the drawing of the fractal instead of drawing it all at once. ANIMATE specifies the number of moves to make per frame of animation. Set to 0 to explicitly disable.");
        parser.refer(&mut retargs.version).add_option(&["-v", "--version"], StoreTrue, "Display the version");

        parser.refer(&mut retargs.curve_name).add_argument("curve", Store, "Which curve to draw. Valid options are: cesaro, cesarotri, dragon, kochcurve, levyccurve, and terdragon.");
        parser.refer(&mut retargs.iterations).add_argument("iterations", Store, "The iteration of the specified curve to draw. should be a non-negative integer.");
        parser.parse_args_or_exit();
    }

    retargs
}

fn construct_program(program_name: &str, iterations: u64) -> Box<TurtleProgram> {
    match program_name {
        "cesaro"     => Box::new(LindenmayerSystemTurtleProgram::new(CesaroFractal::new(iterations))),
        "cesarotri"  => Box::new(LindenmayerSystemTurtleProgram::new(CesaroTriFractal::new(iterations))),
        "dragon"     => Box::new(DragonFractal::new(iterations)),
        "kochcurve"  => Box::new(LindenmayerSystemTurtleProgram::new(KochCurve::new(iterations))),
        "levyccurve" => Box::new(LindenmayerSystemTurtleProgram::new(LevyCCurve::new(iterations))),
        "terdragon"  => Box::new(LindenmayerSystemTurtleProgram::new(TerdragonFractal::new(iterations))),
        _            => panic!("Unknown program type")
    }
}

fn main() {
    let args = parse_args();

    let program = construct_program(args.curve_name.as_ref(), args.iterations);

    glwindow::run(&*program, args.animate);
}
<commit_msg>Making the curve name and iteration both required<commit_after>// Copyright (c) 2015-2016 William (B.J.) Snow Orvis
//
// 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.

extern crate argparse;
extern crate graphics;
extern crate piston;
extern crate piston_window;

extern crate fractal;
mod glwindow;

use argparse::{ArgumentParser, Store, StoreTrue};

use fractal::curves::cesaro::CesaroFractal;
use fractal::curves::cesarotri::CesaroTriFractal;
use fractal::curves::dragon::DragonFractal;
use fractal::curves::kochcurve::KochCurve;
use fractal::curves::levyccurve::LevyCCurve;
use fractal::curves::terdragon::TerdragonFractal;
use fractal::lindenmayer::LindenmayerSystemTurtleProgram;
use fractal::turtle::TurtleProgram;

struct Arguments {
    curve_name: String,
    iterations: u64,
    animate: u64,
    version: bool,
}

fn parse_args() -> Arguments {
    let mut retargs = Arguments { curve_name: String::from(""), iterations: 0, animate: 0, version: false };
    {
        let mut parser = ArgumentParser::new();
        parser.set_description("Renders fractal curves.");
        parser.refer(&mut retargs.animate).add_option(&["--animate"], Store, "Animate the drawing of the fractal instead of drawing it all at once. ANIMATE specifies the number of moves to make per frame of animation. Set to 0 to explicitly disable.");
        parser.refer(&mut retargs.version).add_option(&["-v", "--version"], StoreTrue, "Display the version");

        parser.refer(&mut retargs.curve_name).add_argument("curve", Store, "Which curve to draw. Valid options are: cesaro, cesarotri, dragon, kochcurve, levyccurve, and terdragon.").required();
        parser.refer(&mut retargs.iterations).add_argument("iterations", Store, "The iteration of the specified curve to draw. should be a non-negative integer.").required();
        parser.parse_args_or_exit();
    }

    retargs
}

fn construct_program(program_name: &str, iterations: u64) -> Box<TurtleProgram> {
    match program_name {
        "cesaro"     => Box::new(LindenmayerSystemTurtleProgram::new(CesaroFractal::new(iterations))),
        "cesarotri"  => Box::new(LindenmayerSystemTurtleProgram::new(CesaroTriFractal::new(iterations))),
        "dragon"     => Box::new(DragonFractal::new(iterations)),
        "kochcurve"  => Box::new(LindenmayerSystemTurtleProgram::new(KochCurve::new(iterations))),
        "levyccurve" => Box::new(LindenmayerSystemTurtleProgram::new(LevyCCurve::new(iterations))),
        "terdragon"  => Box::new(LindenmayerSystemTurtleProgram::new(TerdragonFractal::new(iterations))),
        _            => panic!("Unknown program type")
    }
}

fn main() {
    let args = parse_args();

    let program = construct_program(args.curve_name.as_ref(), args.iterations);

    glwindow::run(&*program, args.animate);
}
<|endoftext|>


<commit_before>//! Muxed. A tmux project manager with no runtime dependencies.
extern crate common;
extern crate docopt;
extern crate edit;
extern crate load;
extern crate new;
extern crate snapshot;

use common::args::Args;
use docopt::Docopt;
use std::env;
use std::process::exit;

#[macro_export]
macro_rules! try_or_err (
    ($expr: expr) => ({
        match $expr {
            Ok(val) => val,
            Err(e) => {
                println!("Muxed ran in to a problem: {}", e);
                exit(1);
            }
        }
    })
);

static DISALLOWED_PROJECT_NAMES: [&str; 3] = ["new", "edit", "load"];

static USAGE: &str = "
Usage:
    muxed edit [options] <project>
    muxed new [options] <project>
    muxed snapshot [options] <project>
    muxed load [options] <project>
    muxed [options] <project>
    muxed (-h | --help)
    muxed (-v | --version)

Flags:
    -d                  If you want to create a muxed session without connecting to it
    -f                  Overwrite existing file if one exists
    --debug             Prints debug information while executing (project opening only)
    -h, --help          Prints help information
    -v, --version       Prints version information

Options:
    -p <project_dir>    The directory your project config files live in. Defaults to ~/.muxed/
    -t <session>        The name of the running TMUX session to codify

Args:
    <project>           The name of your project to open

Subcommands:
    edit <project>                   Edit an existing project file
    new <project>                    To create a new project file
    snapshot -t <session> <project>  Capture a running session and create a config file for it
";

/// The main execution method.
/// Currently accepts a single option. The option represents a configuration
/// file in the same naming format. Given a project file name `projectName.yml`
/// in the `~/.muxed/` directory.
///
/// # Examples
///
/// ~/.muxed/projectName.yml
///
/// ```
/// root: ~/projects/muxed/
/// windows:
///     - cargo: "cargo build"
///     - vim: "vim ."
///     - git: ""
/// ```
///
/// You can run the command:
///
/// ```
/// $ ./muxed projectName
/// ```
pub fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    if args.flag_v {
        println!("Muxed {}", env!("CARGO_PKG_VERSION"));
        exit(0);
    };

    if args.cmd_new {
        try_or_err!(new::exec(args))
    } else if args.cmd_edit {
        try_or_err!(edit::exec(args))
    } else if args.cmd_snapshot {
        try_or_err!(snapshot::exec(args))
    } else if DISALLOWED_PROJECT_NAMES.contains(&args.arg_project.as_ref()) {
        println!(
            "Tried to call sub-command {} without a project. Please specify a project name.",
            args.arg_project
        );
        exit(1);
    } else {
        try_or_err!(load::exec(args))
    }
}
<commit_msg>Re-order cause orig had it here, and this had no effect on the parsing<commit_after>//! Muxed. A tmux project manager with no runtime dependencies.
extern crate common;
extern crate docopt;
extern crate edit;
extern crate load;
extern crate new;
extern crate snapshot;

use common::args::Args;
use docopt::Docopt;
use std::env;
use std::process::exit;

#[macro_export]
macro_rules! try_or_err (
    ($expr: expr) => ({
        match $expr {
            Ok(val) => val,
            Err(e) => {
                println!("Muxed ran in to a problem: {}", e);
                exit(1);
            }
        }
    })
);

static DISALLOWED_PROJECT_NAMES: [&str; 3] = ["new", "edit", "load"];

static USAGE: &str = "
Usage:
    muxed [options] <project>
    muxed edit [options] <project>
    muxed new [options] <project>
    muxed snapshot [options] <project>
    muxed load [options] <project>
    muxed (-h | --help)
    muxed (-v | --version)

Flags:
    -d                  If you want to create a muxed session without connecting to it
    -f                  Overwrite existing file if one exists
    --debug             Prints debug information while executing (project opening only)
    -h, --help          Prints help information
    -v, --version       Prints version information

Options:
    -p <project_dir>    The directory your project config files live in. Defaults to ~/.muxed/
    -t <session>        The name of the running TMUX session to codify

Args:
    <project>           The name of your project to open

Subcommands:
    edit <project>                   Edit an existing project file
    new <project>                    To create a new project file
    snapshot -t <session> <project>  Capture a running session and create a config file for it
";

/// The main execution method.
/// Currently accepts a single option. The option represents a configuration
/// file in the same naming format. Given a project file name `projectName.yml`
/// in the `~/.muxed/` directory.
///
/// # Examples
///
/// ~/.muxed/projectName.yml
///
/// ```
/// root: ~/projects/muxed/
/// windows:
///     - cargo: "cargo build"
///     - vim: "vim ."
///     - git: ""
/// ```
///
/// You can run the command:
///
/// ```
/// $ ./muxed projectName
/// ```
pub fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    if args.flag_v {
        println!("Muxed {}", env!("CARGO_PKG_VERSION"));
        exit(0);
    };

    if args.cmd_new {
        try_or_err!(new::exec(args))
    } else if args.cmd_edit {
        try_or_err!(edit::exec(args))
    } else if args.cmd_snapshot {
        try_or_err!(snapshot::exec(args))
    } else if DISALLOWED_PROJECT_NAMES.contains(&args.arg_project.as_ref()) {
        println!(
            "Tried to call sub-command {} without a project. Please specify a project name.",
            args.arg_project
        );
        exit(1);
    } else {
        try_or_err!(load::exec(args))
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("YAML files as iptables configuration sources");
}
<commit_msg>Added basic command-line usage<commit_after>
// YAML files as iptables configuration sources

extern crate clap;

use clap::{Arg, App};

fn main() {
    let matches = App::new("iptables-init")
        .version("1.0.0")
        .author("Samuel. <sam@infinitely.io>")
        .arg(Arg::with_name("CONFIG")
             .short("c")
             .long("config")
             .help("Yaml file as iptables configuration source")
             .takes_value(true))
        .get_matches();

    println!("YAML files as iptables configuration sources");

    let config = matches.value_of("CONFIG").unwrap_or("");
    println!("Value for config: {}", config);
}
<|endoftext|>


<commit_before>//    Copyright 2017 Vector Creations Limited
//
//    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.

// extern crate base64;
// extern crate blake2_rfc;
#[macro_use]
extern crate clap;
extern crate humansize;
extern crate linear_map;
extern crate rusqlite;
extern crate twox_hash;
extern crate walkdir;
extern crate indicatif;

// use blake2_rfc::blake2b::Blake2b;
use humansize::{FileSize, file_size_opts as options};
use clap::{App, Arg};
use linear_map::LinearMap;
use std::io;
use std::io::Read;
use std::fs::File;
use std::hash::Hasher;
use std::collections::BTreeMap;
use std::path::PathBuf;
use walkdir::WalkDir;

fn copy<R: io::Read, W: Hasher>(reader: &mut R, writer: &mut W) -> io::Result<u64> {
    let mut buf = [0; 64 * 1024];
    let mut written = 0;
    loop {
        let len = match reader.read(&mut buf) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write(&buf[..len]);
        written += len as u64;
    }
}

fn to_hash(path: &PathBuf) -> u64 {
    let mut file = File::open(path).unwrap();
    let mut hasher = twox_hash::XxHash::default();
    copy(&mut file, &mut hasher).unwrap();
    hasher.finish()
}

fn read_file(path: &PathBuf) -> Vec<u8> {
    let mut file = File::open(path).unwrap();
    let mut vec = Vec::new();
    file.read_to_end(&mut vec).unwrap();
    vec
}

fn partition_by<I, F, R>(paths: I, f: F) -> LinearMap<R, Vec<PathBuf>>
    where I: Iterator<Item=PathBuf>, F: Fn(&PathBuf) -> R, R: Eq
{
    let mut map = LinearMap::with_capacity(paths.size_hint().0);
    for path in paths {
        let key = f(&path);
        map.entry(key).or_insert_with(Vec::new).push(path);
    }
    map
}

const DB_TABLE_SCHEMA: &'static str = r#"
CREATE TABLE files (
    hash BIGINT NOT NULL,
    path TEXT NOT NULL,
    size BIGINT NOT NULL
);
"#;

fn main() {
    let matches = App::new(crate_name!())
        .version(crate_version!())
        .author(crate_authors!("\n"))
        .arg(Arg::with_name("media_directory")
            .help("The location of the media store")
            .index(1)
            .required(true))
        .get_matches();

    let path = matches.value_of("media_directory").unwrap();

    println!("Creating DB...");

    let db = rusqlite::Connection::open_in_memory().expect("failed to open sqlite db");
    db.execute_batch(DB_TABLE_SCHEMA).expect("failed to create db schema");

    let mut paths_by_size = BTreeMap::new();
    let mut total_files = 0;
    let mut total_size = 0;

    println!("Walking fs...");

    let pb = indicatif::ProgressBar::new_spinner();

    for entry in WalkDir::new(path) {
        let entry = entry.unwrap();
        if !entry.file_type().is_file() {
            continue
        }

        let file_size = entry.metadata().unwrap().len() as usize;
        paths_by_size.entry(file_size).or_insert_with(Vec::new).push(entry.path().to_owned());

        total_files += 1;
        total_size += file_size;

        pb.inc(1);
        if total_files % 100 == 0 {
            // println!("Handled {} files", total_files);
            // pb.set_message(&format!("Handled {} files", total_files));
        }
        pb.set_message(&format!("Handled {} files", total_files));
    }

    pb.finish_and_clear();

    println!("Handled {} files", total_files);
    println!();

     let pb = indicatif::ProgressBar::new(total_size as u64);

    let mut total_wasted_size = 0;

    for (file_size, paths) in paths_by_size {
        if paths.len() == 1 {
            pb.inc(file_size as u64);
            continue
        }

        let by_hash = partition_by(paths.into_iter(), to_hash);

        for (hash, paths) in by_hash {
            if paths.len() == 1 {
                pb.inc(file_size as u64);
                continue
            }

            let by_contents = partition_by(paths.into_iter(), read_file);

            for (_, paths) in by_contents {
                if paths.len() == 1 {
                    pb.inc(file_size as u64);
                    continue
                }

                // print!("Duplicate {} paths (hash: {})\n", paths.len(), hash);
                for path in &paths {
                    db.execute("INSERT INTO files (hash, path, size) VALUES (?, ?, ?)", &[&(hash as i64), &path.to_str().unwrap(), &(file_size as i64)]).expect("failed to write to db");
                    // print!("  {}\n", path.display());
                }

                let wasted = file_size * (paths.len() - 1);
                // print!(
                //     " Size: {}. Wasting {}.\n",
                //     file_size.file_size(options::CONVENTIONAL).unwrap(),
                //     wasted.file_size(options::CONVENTIONAL).unwrap(),
                // );

                total_wasted_size += wasted;

                pb.inc((file_size * paths.len()) as u64);
            }
        }
    }

    pb.finish();

    println!();
    println!("Total wasted size: {}", total_wasted_size.file_size(options::CONVENTIONAL).unwrap());
    println!("Total size: {}", total_size.file_size(options::CONVENTIONAL).unwrap());

    let mut disk_db = rusqlite::Connection::open("media_store_sizes.db").expect("failed to open sqlite db");
    let backup = rusqlite::backup::Backup::new(&db, &mut disk_db).expect("failed to create backup");
    backup.run_to_completion(5, std::time::Duration::from_millis(0), None).expect("failed to write to disk");
}
<commit_msg>Percentage<commit_after>//    Copyright 2017 Vector Creations Limited
//
//    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.

// extern crate base64;
// extern crate blake2_rfc;
#[macro_use]
extern crate clap;
extern crate humansize;
extern crate linear_map;
extern crate rusqlite;
extern crate twox_hash;
extern crate walkdir;
extern crate indicatif;

// use blake2_rfc::blake2b::Blake2b;
use humansize::{FileSize, file_size_opts as options};
use clap::{App, Arg};
use linear_map::LinearMap;
use std::io;
use std::io::Read;
use std::fs::File;
use std::hash::Hasher;
use std::collections::BTreeMap;
use std::path::PathBuf;
use walkdir::WalkDir;

fn copy<R: io::Read, W: Hasher>(reader: &mut R, writer: &mut W) -> io::Result<u64> {
    let mut buf = [0; 64 * 1024];
    let mut written = 0;
    loop {
        let len = match reader.read(&mut buf) {
            Ok(0) => return Ok(written),
            Ok(len) => len,
            Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
            Err(e) => return Err(e),
        };
        writer.write(&buf[..len]);
        written += len as u64;
    }
}

fn to_hash(path: &PathBuf) -> u64 {
    let mut file = File::open(path).unwrap();
    let mut hasher = twox_hash::XxHash::default();
    copy(&mut file, &mut hasher).unwrap();
    hasher.finish()
}

fn read_file(path: &PathBuf) -> Vec<u8> {
    let mut file = File::open(path).unwrap();
    let mut vec = Vec::new();
    file.read_to_end(&mut vec).unwrap();
    vec
}

fn partition_by<I, F, R>(paths: I, f: F) -> LinearMap<R, Vec<PathBuf>>
    where I: Iterator<Item=PathBuf>, F: Fn(&PathBuf) -> R, R: Eq
{
    let mut map = LinearMap::with_capacity(paths.size_hint().0);
    for path in paths {
        let key = f(&path);
        map.entry(key).or_insert_with(Vec::new).push(path);
    }
    map
}

const DB_TABLE_SCHEMA: &'static str = r#"
CREATE TABLE files (
    hash BIGINT NOT NULL,
    path TEXT NOT NULL,
    size BIGINT NOT NULL
);
"#;

fn main() {
    let matches = App::new(crate_name!())
        .version(crate_version!())
        .author(crate_authors!("\n"))
        .arg(Arg::with_name("media_directory")
            .help("The location of the media store")
            .index(1)
            .required(true))
        .get_matches();

    let path = matches.value_of("media_directory").unwrap();

    println!("Creating DB...");

    let db = rusqlite::Connection::open_in_memory().expect("failed to open sqlite db");
    db.execute_batch(DB_TABLE_SCHEMA).expect("failed to create db schema");

    let mut paths_by_size = BTreeMap::new();
    let mut total_files = 0;
    let mut total_size = 0;

    println!("Walking fs...");

    let pb = indicatif::ProgressBar::new_spinner();

    for entry in WalkDir::new(path) {
        let entry = entry.unwrap();
        if !entry.file_type().is_file() {
            continue
        }

        let file_size = entry.metadata().unwrap().len() as usize;
        paths_by_size.entry(file_size).or_insert_with(Vec::new).push(entry.path().to_owned());

        total_files += 1;
        total_size += file_size;

        pb.inc(1);
        if total_files % 100 == 0 {
            // println!("Handled {} files", total_files);
            // pb.set_message(&format!("Handled {} files", total_files));
        }
        pb.set_message(&format!("Handled {} files", total_files));
    }

    pb.finish_and_clear();

    println!("Handled {} files", total_files);
    println!();

     let pb = indicatif::ProgressBar::new(total_size as u64);

    let mut total_wasted_size = 0;

    for (file_size, paths) in paths_by_size {
        if paths.len() == 1 {
            pb.inc(file_size as u64);
            continue
        }

        let by_hash = partition_by(paths.into_iter(), to_hash);

        for (hash, paths) in by_hash {
            if paths.len() == 1 {
                pb.inc(file_size as u64);
                continue
            }

            let by_contents = partition_by(paths.into_iter(), read_file);

            for (_, paths) in by_contents {
                if paths.len() == 1 {
                    pb.inc(file_size as u64);
                    continue
                }

                // print!("Duplicate {} paths (hash: {})\n", paths.len(), hash);
                for path in &paths {
                    db.execute("INSERT INTO files (hash, path, size) VALUES (?, ?, ?)", &[&(hash as i64), &path.to_str().unwrap(), &(file_size as i64)]).expect("failed to write to db");
                    // print!("  {}\n", path.display());
                }

                let wasted = file_size * (paths.len() - 1);
                // print!(
                //     " Size: {}. Wasting {}.\n",
                //     file_size.file_size(options::CONVENTIONAL).unwrap(),
                //     wasted.file_size(options::CONVENTIONAL).unwrap(),
                // );

                total_wasted_size += wasted;

                pb.inc((file_size * paths.len()) as u64);
            }
        }
    }

    pb.finish();

    println!();
    println!(
        "Total wasted size: {} out of {}. Percentage: {:.2}%",
        total_wasted_size.file_size(options::CONVENTIONAL).unwrap(),
        total_size.file_size(options::CONVENTIONAL).unwrap(),
        (total_wasted_size * 100) as f64 / total_size as f64,
    );

    let mut disk_db = rusqlite::Connection::open("media_store_sizes.db").expect("failed to open sqlite db");
    let backup = rusqlite::backup::Backup::new(&db, &mut disk_db).expect("failed to create backup");
    backup.run_to_completion(5, std::time::Duration::from_millis(0), None).expect("failed to write to disk");
}
<|endoftext|>


<commit_before>use std::io;
use std::io::BufReader;
use std::io::BufRead;
use request::Request;
use turn::Turn;

mod request;
mod turn;

fn main()
{
	let input = io::stdin();
	let input = BufReader::new(input);
	let input = input.lines();
	let input = input
		.map(Result::unwrap)
		.filter(|s|s.len()>0)
		.map(|s|s.parse::<Request>())
		.map(Result::unwrap);

	for req in input
	{
		use request::Request::*;
		match req
		{
			_ => unreachable!(),
		}
	}
}

<commit_msg>request-action template<commit_after>use std::io;
use std::io::BufReader;
use std::io::BufRead;
use request::Request;
use turn::Turn;

mod request;
mod turn;

fn main()
{
	let input = io::stdin();
	let input = BufReader::new(input);
	let input = input.lines();
	let input = input
		.map(Result::unwrap)
		.filter(|s|s.len()>0)
		.map(|s|s.parse::<Request>())
		.map(Result::unwrap);

	for req in input
	{
		use request::Request::*;
		match req
		{
			ListSuperRegions(sregions) =>
			{
			},
			ListRegions(regions) =>
			{
			},
			ListNeighbours(relations) =>
			{
			},
			RequestStartingRegions(available) =>
			{
			},
			SettingNameYou(name) =>
			{
			},
			SettingNameOther(name) =>
			{
			},
			SettingArmies(count) =>
			{
			},
			UpdateMap(updates) =>
			{
			},
			TurnOther(turns) =>
			{
			},
			TurnPlace =>
			{
			},
			TurnArmies =>
			{
			},
		}
	}
}

<|endoftext|>