<commit_before>extern crate ansi_term;
extern crate argparse;
extern crate hyper;
extern crate libsnatch;

use ansi_term::Colour::{Green, Red};
use argparse::{ArgumentParser, Store, StoreTrue};
use hyper::client::Client;
use libsnatch::Chunks;
use libsnatch::client::GetResponse;
use libsnatch::contentlength::GetContentLength;
use libsnatch::download::download_chunks;
use libsnatch::http_version::ValidateHttpVersion;
use libsnatch::write::write_file;
use std::fs::File;
use std::io;
use std::sync::{Arc, Mutex};
use std::path::Path;
use std::process::exit;

fn main() {

    let mut file = String::from("");
    let mut threads : usize = 4;
    let mut url = String::from("");
    let mut verbose = false;

    {
        let mut argparse = ArgumentParser::new();
        argparse.set_description("Snatch, a simple, fast and interruptable download accelerator, written in Rust.");
        argparse.refer(&mut file)
                .add_option(&["-f", "--file"], Store,
                "The local file to save the remote content file")
                .required();
        argparse.refer(&mut threads)
                .add_option(&["-t", "--threads"], Store,
                "Number of threads available to download");
        argparse.refer(&mut url)
                .add_option(&["-u", "--url"], Store,
                "Remote content URL to download")
                .required();
        argparse.refer(&mut verbose)
                .add_option(&["-v", "--verbose"], StoreTrue,
                "Verbose mode");
        argparse.parse_args_or_exit();
    }

    let hyper_client = Client::new();

    // Get the first response from the server
    let client_response = hyper_client.get_http_response(&url).unwrap();

    print!("# Waiting a response from the remote content server... ");

    if ! client_response.version.greater_than_http_11() {
        println!("{}", Red.bold().paint("[ERROR] The version of HTTP requests must be >= HTTP1.1 !"));
        exit(0);
    } else {
        println!("{}", Green.bold().paint("OK !"));
    }

    let local_path = Path::new(&file);

    if local_path.exists() {
        if local_path.is_dir() {
            panic!(Red.bold().paint("[ERROR] The local path to store the remote content is already exists, and is a directory!"));
        }
        println!("{}", Red.bold().paint("[WARNING] The path to store the file already exists! Do you want to override it? [y/N]"));
        {
            let mut user_input = String::new();
            io::stdin().read_line(&mut user_input)
                .ok()
                .expect("[ERROR] Couldn't read line!");
            user_input = String::from(user_input.trim());
            if ! (user_input == "y" || user_input == "Y") {
                exit(0);
            }
        }

    }

    let remote_content_length = client_response.headers.get_content_length().unwrap();

    println!("# Remote content length: {:?} bytes", remote_content_length);

    let mut core_chunks = Chunks::with_capacity(threads);

    for _ in 0..threads {
        core_chunks.push(Vec::new());
    }

    let mut shared_chunks = Arc::new(Mutex::new(core_chunks));

    println!("# Downloading chunk (using {} threads)... ", threads);

    download_chunks(remote_content_length, &mut shared_chunks, threads as u64, &url);

    let mut local_file = File::create(local_path).expect("[ERROR] Canno't create a file !");

    match write_file(&mut local_file, &shared_chunks) {
        Ok(()) => println!("{}", Green.bold().paint("Chunks have been successfuly saved!")),
        Err(error) => println!("[ERROR] {}", error),
    }

}<commit_msg>Update main file<commit_after>extern crate ansi_term;
extern crate argparse;
extern crate hyper;
extern crate libsnatch;

use ansi_term::Colour::{Green, Red};
use argparse::{ArgumentParser, Store, StoreTrue};
use hyper::client::Client;
use libsnatch::Chunks;
use libsnatch::client::GetResponse;
use libsnatch::contentlength::GetContentLength;
use libsnatch::download::download_chunks;
use libsnatch::http_version::ValidateHttpVersion;
use libsnatch::write::write_file;
use std::fs::File;
use std::io;
use std::sync::{Arc, Mutex};
use std::path::Path;
use std::process::exit;

fn main() {

    let mut file = String::from("");
    let mut threads : usize = 4;
    let mut url = String::from("");
    let mut verbose = false;

    {
        let mut argparse = ArgumentParser::new();
        argparse.set_description("Snatch, a simple, fast and interruptable download accelerator, written in Rust.");
        argparse.refer(&mut file)
                .add_option(&["-f", "--file"], Store,
                "The local file to save the remote content file")
                .required();
        argparse.refer(&mut threads)
                .add_option(&["-t", "--threads"], Store,
                "Number of threads available to download");
        argparse.refer(&mut url)
                .add_option(&["-u", "--url"], Store,
                "Remote content URL to download")
                .required();
        argparse.refer(&mut verbose)
                .add_option(&["-v", "--verbose"], StoreTrue,
                "Verbose mode");
        argparse.parse_args_or_exit();
    }

    let hyper_client = Client::new();

    // Get the first response from the server
    let client_response = hyper_client.get_http_response(&url).unwrap();

    print!("# Waiting a response from the remote server... ");

    if ! client_response.version.greater_than_http_11() {
        println!("{}", Red.bold().paint("[ERROR] The version of HTTP requests must be >= HTTP1.1 !"));
        exit(0);
    } else {
        println!("{}", Green.bold().paint("OK !"));
    }

    let local_path = Path::new(&file);

    if local_path.exists() {
        if local_path.is_dir() {
            panic!(Red.bold().paint("[ERROR] The local path to store the remote content is already exists, and is a directory!"));
        }
        println!("{}", Red.bold().paint("[WARNING] The path to store the file already exists! Do you want to override it? [y/N]"));
        {
            let mut user_input = String::new();
            io::stdin().read_line(&mut user_input)
                .ok()
                .expect("[ERROR] Couldn't read line!");
            user_input = String::from(user_input.trim());
            if ! (user_input == "y" || user_input == "Y") {
                exit(0);
            }
        }

    }

    let remote_content_length = client_response.headers.get_content_length().unwrap();

    println!("# Remote content length: {:?} bytes", remote_content_length);

    let mut core_chunks = Chunks::with_capacity(threads);

    for _ in 0..threads {
        core_chunks.push(Vec::new());
    }

    let mut shared_chunks = Arc::new(Mutex::new(core_chunks));

    download_chunks(remote_content_length, &mut shared_chunks, threads as u64, &url);

    let mut local_file = File::create(local_path).expect("[ERROR] Canno't create a file !");

    match write_file(&mut local_file, &shared_chunks) {
        Ok(()) => println!("{}", Green.bold().paint("Chunks have been successfuly saved!")),
        Err(error) => println!("[ERROR] {}", error),
    }

}<|endoftext|>


<commit_before>/*
main.rs
Platypie's core executable
currently only requires Rust's standard API
*/
extern crate sodiumoxide;
extern crate serialize;

fn main() {
    use sodiumoxide::crypto::asymmetricbox::gen_keypair;
    use serialize::base64::{ToBase64, MIME};
    sodiumoxide::init();

    let (pk, sk) = gen_keypair();

    let message = [
      "Thanks for installing Platypie!",
      "We're trying to make the world a better place.",
      "We're very happy you've decided to get involved.",
      "Platypie is a work in progress.",
      "If you want to get involved, join us on IRC!",
      "irc.freenode.net/#platypie"
        ];

    for sptr in message.iter() {
        println!("{}",*sptr);
    }
}

#[test]
fn main_test() {
    assert!(true); // the simplest test possible, a tautology
}
<commit_msg>fix formatting and spit out the public key bytes<commit_after>/*
   main.rs
   Platypie's core executable
   currently only requires Rust's standard API
   */
extern crate sodiumoxide;
extern crate serialize;

fn main() {
    use sodiumoxide::crypto::asymmetricbox::gen_keypair;
    use serialize::base64::{ToBase64, MIME};
    sodiumoxide::init();

    let (pk, sk) = gen_keypair();
    println!("{:?}", pk);

    let message = [
        "Thanks for installing Platypie!",
        "We're trying to make the world a better place.",
        "We're very happy you've decided to get involved.",
        "Platypie is a work in progress.",
        "If you want to get involved, join us on IRC!",
        "irc.freenode.net/#platypie"
            ];

    for sptr in message.iter() {
        println!("{}",*sptr);
    }
}

#[test]
fn main_test() {
    assert!(true); // the simplest test possible, a tautology
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate las;
extern crate riscan_pro;
extern crate rustc_serialize;

use std::path::Path;

use docopt::Docopt;
use las::{PointFormat, Reader, Writer};
use riscan_pro::{PRCS, Point, Project};

const USAGE: &'static str = "
RiSCAN PRO utilities.

Usage:
    riscan-pro colorize <infile> <project> <outfile> [--scan-position=<name>] [--allow-missing-images=<bool>]
    riscan-pro (-h | --help)

Options:
    -h --help                       Show this screen.
    --scan-position=<name>          Specify the scan position name. If not provided, we will try to deduce the scan position from the infile name.
    --allow-missing-images=<bool>   Allow colorization even if some images are missing from the scan position [default: false].
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_colorize: bool,
    arg_infile: String,
    arg_project: String,
    arg_outfile: String,
    flag_scan_position: Option<String>,
    flag_allow_missing_images: bool,
}

fn main() {
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit());
    if args.cmd_colorize {
        let project = Project::from_path(args.arg_project).unwrap();
        let scan_position = if let Some(name) = args.flag_scan_position {
            project.scan_position(&name).expect(&format!("Cound not find scan position: {}", name))
        } else {
            Path::new(&args.arg_infile)
                .file_stem()
                .and_then(|name| project.scan_position_with_scan(&name.to_string_lossy()))
                .expect(&format!("Could not deduce scan position from file: {}",
                                 args.arg_infile))
        };
        if !args.flag_allow_missing_images {
            let images = scan_position.missing_images();
            if !images.is_empty() {
                panic!("Scan position is missing images: {}",
                       images.into_iter().map(|i| i.name()).collect::<Vec<_>>().join(", "));
            }
        }
        let reader = Reader::from_path(args.arg_infile).unwrap();
        let mut writer = Writer::from_path(args.arg_outfile)
            .unwrap()
            .header(reader.header().clone())
            .point_format(PointFormat(1))
            .open()
            .unwrap();
        for mut las_point in reader {
            let point = Point {
                crs: PRCS,
                x: las_point.x,
                y: las_point.y,
                z: las_point.z,
            };
            if let Some(color) = scan_position.color(point).unwrap() {
                las_point.gps_time = Some(color);
                writer.write_point(&las_point).unwrap();
            }
        }
    }
}
<commit_msg>More work on the executable<commit_after>extern crate docopt;
extern crate las;
extern crate riscan_pro;
extern crate rustc_serialize;

use std::path::Path;

use docopt::Docopt;
use las::{PointFormat, Reader, Writer};
use riscan_pro::{PRCS, Point, Project};

const USAGE: &'static str = "
RiSCAN PRO utilities.

Usage:
    riscan-pro colorize <infile> <project> <outfile> [--scan-position=<name>] [--allow-missing-images]
    riscan-pro (-h | --help)

Options:
    -h --help                       Show this screen.
    --scan-position=<name>          Specify the scan position name. If not provided, we will try to deduce the scan position from the infile name.
    --allow-missing-images          Allow colorization even if some images are missing from the scan position.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_colorize: bool,
    arg_infile: String,
    arg_project: String,
    arg_outfile: String,
    flag_scan_position: Option<String>,
    flag_allow_missing_images: bool,
}

fn main() {
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|e| e.exit());
    if args.cmd_colorize {
        let project = Project::from_path(&args.arg_project)
            .expect(&format!("Could not open projet file: {}", args.arg_project));
        let scan_position = if let Some(name) = args.flag_scan_position.as_ref() {
            project.scan_position(&name).expect(&format!("Cound not find scan position: {}", name))
        } else {
            Path::new(&args.arg_infile)
                .file_stem()
                .and_then(|name| project.scan_position_with_scan(&name.to_string_lossy()))
                .expect(&format!("Could not deduce scan position from file: {}",
                                 &args.arg_infile))
        };
        if !args.flag_allow_missing_images {
            let images = scan_position.missing_images();
            if !images.is_empty() {
                panic!("Scan position is missing images: {}",
                       images.into_iter().map(|i| i.name()).collect::<Vec<_>>().join(", "));
            }
        }
        let reader = Reader::from_path(&args.arg_infile)
            .expect(&format!("Could not open infile: {}", &args.arg_infile));
        let mut writer = Writer::from_path(&args.arg_outfile)
            .expect(&format!("Could not open outfile: {}", &args.arg_outfile))
            .header(reader.header().clone())
            .point_format(PointFormat(1))
            .open()
            .unwrap();
        for mut las_point in reader {
            let point = Point {
                crs: PRCS,
                x: las_point.x,
                y: las_point.y,
                z: las_point.z,
            };
            if let Some(color) = scan_position.color(point).unwrap() {
                las_point.gps_time = Some(color);
                writer.write_point(&las_point).unwrap();
            }
        }
    }
}
<|endoftext|>


<commit_before>//Author: J. Pace <github.com/jpace121>
//Copyright: 2015
//License: http://opensource.org/licenses/BSD-2-Clause

// Make units we can enforce math with.
// Use enums? Or structs? Or phantom something or the other?

// Use a struct for the current status of the coaster.
struct CoasterStatus{
    m:f32, //mass in kg
    v:f32, //velocity in m/s
    h:f32, //height in m
    U:f32, //Potential energy in J
    K:f32 //Kinetic Energy in J
}

fn main() {
    // Set some current parameters.
    let status = CoasterStatus{
        m:10f32,
        v:10f32,
        h:0f32,
        U:0f32,
        K:0f32
    };

    println!("Velocity is {} m/s.",status.v );
    println!("Mass is {} kg", status.m);
    println!("Height is {} m", status.h);
    println!("");
    println!("Kinetic Energy: {}", get_kinetic(&status));
    println!("Potential Energy: {}", get_potential(&status));
}

fn get_kinetic(status:&CoasterStatus) -> f32{
    // Calculate the energy given the mass and the velocity
    // mass in kg, velocity in m/s, energy in J
    0.5*status.m*status.v
}

fn get_potential(status:&CoasterStatus) -> f32{
    // Calculate the potential energy, gven the mass and current height
    // from the zeroth point.
    let g = 9.81; // acceleration of gravity in m/s^2
    status.m*g*status.h
}
<commit_msg>Fix pointer issues.<commit_after>//Author: J. Pace <github.com/jpace121>
//Copyright: 2015
//License: http://opensource.org/licenses/BSD-2-Clause

// Make units we can enforce math with.
// Use enums? Or structs? Or phantom something or the other?

// Use a struct for the current status of the coaster.
// (Should this be more OOP-ish?)
struct CoasterStatus{
    m:f32, //mass in kg
    v:f32, //velocity in m/s
    h:f32, //height in m
    u:f32, //Potential energy in J
    k:f32 //Kinetic Energy in J
}

fn main() {
    // Set some current parameters.
    let mut status = CoasterStatus{
        m:10f32,
        v:10f32,
        h:0f32,
        u:0f32,
        k:0f32
    };

    status.k = get_kinetic(&status);
    status.u = get_potential(&status);
    println!("Velocity is {} m/s.",status.v );
    println!("Mass is {} kg", status.m);
    println!("Height is {} m", status.h);
    println!("");
    println!("Kinetic Energy: {}", status.k);
    println!("Potential Energy: {}", status.u);
}

fn get_kinetic(status:&CoasterStatus) -> f32{
    // Calculate the energy given the mass and the velocity
    // mass in kg, velocity in m/s, energy in J
    0.5*status.m*status.v
}

fn get_potential(status:&CoasterStatus) -> f32{
    // Calculate the potential energy, gven the mass and current height
    // from the zeroth point.
    let g = 9.81; // acceleration of gravity in m/s^2
    status.m*g*status.h
}
<|endoftext|>


<commit_before>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// 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.
//
//! Alacritty - The GPU Enhanced Terminal
#![feature(question_mark)]
#![feature(inclusive_range_syntax)]
#![feature(drop_types_in_const)]
#![allow(stable_features)] // lying about question_mark because 1.14.0 isn't released!

#![feature(proc_macro)]

#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate alacritty;
extern crate cgmath;
extern crate copypasta;
extern crate errno;
extern crate font;
extern crate glutin;
extern crate libc;
extern crate mio;
extern crate notify;
extern crate parking_lot;
extern crate serde;
extern crate serde_json;
extern crate serde_yaml;
extern crate vte;

#[macro_use]
extern crate bitflags;

use std::sync::{mpsc, Arc};
use std::sync::atomic::Ordering;

use parking_lot::{MutexGuard};

use alacritty::Flag;
use alacritty::Rgb;
use alacritty::config::{self, Config};
use alacritty::event;
use alacritty::gl;
use alacritty::input;
use alacritty::meter::Meter;
use alacritty::renderer::{QuadRenderer, GlyphCache};
use alacritty::sync::FairMutex;
use alacritty::term::{self, Term};
use alacritty::tty::{self, Pty, process_should_exit};
use alacritty::event_loop::EventLoop;

/// Channel used by resize handling on mac
static mut RESIZE_CALLBACK: Option<Box<Fn(u32, u32)>> = None;

/// Resize handling for Mac
fn window_resize_handler(width: u32, height: u32) {
    unsafe {
        RESIZE_CALLBACK.as_ref().map(|func| func(width, height));
    }
}

fn main() {
    // Load configuration
    let (config, config_path) = match Config::load() {
        Err(err) => match err {
            // Use default config when not found
            config::Error::NotFound => (Config::default(), None),
            // Exit when there's a problem with it
            _ => die!("{}", err),
        },
        Ok((config, path)) => (config, Some(path)),
    };

    let mut ref_test = false;
    let mut columns = 80;
    let mut lines = 24;

    let mut args_iter = ::std::env::args();
    while let Some(arg) = args_iter.next() {
        match &arg[..] {
            // Generate ref test
            "--ref-test" => ref_test = true,
            // Set dimensions
            "-d" | "--dimensions" => {
                args_iter.next()
                    .map(|w| w.parse().map(|w| columns = w));
                args_iter.next()
                    .map(|h| h.parse().map(|h| lines = h));
            },
            // ignore unexpected
            _ => (),
        }
    }

    let font = config.font();
    let dpi = config.dpi();
    let render_timer = config.render_timer();

    let mut window = glutin::WindowBuilder::new()
                                           .with_vsync()
                                           .with_title("Alacritty")
                                           .build().unwrap();

    window.set_window_resize_callback(Some(window_resize_handler as fn(u32, u32)));

    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
    let (width, height) = window.get_inner_size_pixels().unwrap();
    let dpr = window.hidpi_factor();

    println!("device_pixel_ratio: {}", dpr);

    let _ = unsafe { window.make_current() };
    unsafe {
        // gl::Viewport(0, 0, width as i32, height as i32);
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);
        gl::Enable(gl::MULTISAMPLE);
    }

    let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr);

    // Create renderer
    let mut renderer = QuadRenderer::new(&config, width, height);

    // Initialize glyph cache
    let glyph_cache = {
        println!("Initializing glyph cache");
        let init_start = ::std::time::Instant::now();

        let cache = renderer.with_loader(|mut api| {
            GlyphCache::new(rasterizer, &config, &mut api)
        });

        let stop = init_start.elapsed();
        let stop_f = stop.as_secs() as f64 + stop.subsec_nanos() as f64 / 1_000_000_000f64;
        println!("Finished initializing glyph cache in {}", stop_f);

        cache
    };

    let metrics = glyph_cache.font_metrics();
    let cell_width = (metrics.average_advance + font.offset().x() as f64) as u32;
    let cell_height = (metrics.line_height + font.offset().y() as f64) as u32;

    // Resize window to be 80 col x 24 lines
    let width = cell_width * columns + 4;
    let height = cell_height * lines + 4;
    println!("set_inner_size: {} x {}", width, height);
    // Is this in points?
    let width_pts = (width as f32 / dpr) as u32;
    let height_pts = (height as f32 / dpr) as u32;
    println!("set_inner_size: {} x {}; pts: {} x {}", width, height, width_pts, height_pts);
    window.set_inner_size(width_pts, height_pts);
    renderer.resize(width as _, height as _);

    println!("Cell Size: ({} x {})", cell_width, cell_height);

    let size = term::SizeInfo {
        width: width as f32,
        height: height as f32,
        cell_width: cell_width as f32,
        cell_height: cell_height as f32
    };

    let terminal = Term::new(size);
    let pty = tty::new(size.lines(), size.cols());
    pty.resize(size.lines(), size.cols(), size.width as usize, size.height as usize);
    let pty_io = pty.reader();

    let (tx, rx) = mpsc::channel();

    let signal_flag = Flag::new(false);

    let terminal = Arc::new(FairMutex::new(terminal));
    let window = Arc::new(window);

    // Setup the rsize callback for osx
    let terminal_ref = terminal.clone();
    let signal_flag_ref = signal_flag.clone();
    let proxy = window.create_window_proxy();
    let tx2 = tx.clone();
    unsafe {
        RESIZE_CALLBACK = Some(Box::new(move |width: u32, height: u32| {
            let _ = tx2.send((width, height));
            if !signal_flag_ref.0.swap(true, Ordering::AcqRel) {
               // We raised the signal flag
                let mut terminal = terminal_ref.lock();
                terminal.dirty = true;
                proxy.wakeup_event_loop();
            }
        }));
    }

    let event_loop = EventLoop::new(
        terminal.clone(),
        window.create_window_proxy(),
        signal_flag.clone(),
        pty_io,
        ref_test,
    );

    let loop_tx = event_loop.channel();
    let event_loop_handle = event_loop.spawn(None);

    // Wraps a renderer and gives simple draw() api.
    let mut display = Display::new(
        window.clone(),
        renderer,
        glyph_cache,
        render_timer,
        rx,
        pty
    );

    // Event processor
    let mut processor = event::Processor::new(
        input::LoopNotifier(loop_tx),
        terminal.clone(),
        tx,
        &config,
        ref_test,
    );

    let (config_tx, config_rx) = mpsc::channel();

    // create a config watcher when config is loaded from disk
    let _config_reloader = config_path.map(|config_path| {
        config::Watcher::new(config_path, ConfigHandler {
            tx: config_tx,
            window: window.create_window_proxy(),
        })
    });

    // Main loop
    loop {
        // Wait for something to happen
        processor.process_events(&window);

        if let Ok(config) = config_rx.try_recv() {
            display.update_config(&config);
            processor.update_config(&config);
        }

        // Maybe draw the terminal
        let terminal = terminal.lock();
        signal_flag.set(false);
        if terminal.dirty {
            display.draw(terminal, &config);
        }

        if process_should_exit() {
            break;
        }
    }

    // FIXME need file watcher to work with custom delegates before
    //       joining config reloader is possible
    // config_reloader.join().ok();

    // shutdown
    event_loop_handle.join().ok();
    println!("Goodbye");
}

struct ConfigHandler {
    tx: mpsc::Sender<config::Config>,
    window: ::glutin::WindowProxy,
}

// TODO FIXME
impl config::OnConfigReload for ConfigHandler {
    fn on_config_reload(&mut self, config: Config) {
        if let Err(..) = self.tx.send(config) {
            err_println!("Failed to notify of new config");
            return;
        }

        self.window.wakeup_event_loop();
    }
}

struct Display {
    window: Arc<glutin::Window>,
    renderer: QuadRenderer,
    glyph_cache: GlyphCache,
    render_timer: bool,
    rx: mpsc::Receiver<(u32, u32)>,
    meter: Meter,
    pty: Pty,
}

impl Display {
    pub fn update_config(&mut self, config: &Config) {
        self.renderer.update_config(config);
        self.render_timer = config.render_timer();
    }

    pub fn new(window: Arc<glutin::Window>,
               renderer: QuadRenderer,
               glyph_cache: GlyphCache,
               render_timer: bool,
               rx: mpsc::Receiver<(u32, u32)>,
               pty: Pty)
               -> Display
    {
        Display {
            window: window,
            renderer: renderer,
            glyph_cache: glyph_cache,
            render_timer: render_timer,
            rx: rx,
            meter: Meter::new(),
            pty: pty,
        }
    }

    /// Draw the screen
    ///
    /// A reference to Term whose state is being drawn must be provided.
    ///
    /// This call may block if vsync is enabled
    pub fn draw(&mut self, mut terminal: MutexGuard<Term>, config: &Config) {
        terminal.dirty = false;

        // Resize events new_size and are handled outside the poll_events
        // iterator. This has the effect of coalescing multiple resize
        // events into one.
        let mut new_size = None;

        // Check for any out-of-band resize events (mac only)
        while let Ok(sz) = self.rx.try_recv() {
            new_size = Some(sz);
        }

        // Receive any resize events; only call gl::Viewport on last
        // available
        if let Some((w, h)) = new_size.take() {
            terminal.resize(w as f32, h as f32);
            let size = terminal.size_info();
            self.pty.resize(size.lines(), size.cols(), w as _, h as _);
            self.renderer.resize(w as i32, h as i32);
        }

        {
            let glyph_cache = &mut self.glyph_cache;
            // Draw grid
            {
                let _sampler = self.meter.sampler();

                let size_info = terminal.size_info().clone();
                self.renderer.with_api(config, &size_info, |mut api| {
                    api.clear();

                    // Draw the grid
                    api.render_cells(terminal.renderable_cells(), glyph_cache);
                });
            }

            // Draw render timer
            if self.render_timer {
                let timing = format!("{:.3} usec", self.meter.average());
                let color = alacritty::ansi::Color::Spec(Rgb { r: 0xd5, g: 0x4e, b: 0x53 });
                self.renderer.with_api(config, terminal.size_info(), |mut api| {
                    api.render_string(&timing[..], glyph_cache, &color);
                });
            }
        }

        // Unlock the terminal mutex
        drop(terminal);
        self.window.swap_buffers().unwrap();
    }
}
<commit_msg>Borrow glutin::Window instead of using Arc<commit_after>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// 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.
//
//! Alacritty - The GPU Enhanced Terminal
#![feature(question_mark)]
#![feature(inclusive_range_syntax)]
#![feature(drop_types_in_const)]
#![allow(stable_features)] // lying about question_mark because 1.14.0 isn't released!

#![feature(proc_macro)]

#[macro_use]
extern crate serde_derive;

#[macro_use]
extern crate alacritty;
extern crate cgmath;
extern crate copypasta;
extern crate errno;
extern crate font;
extern crate glutin;
extern crate libc;
extern crate mio;
extern crate notify;
extern crate parking_lot;
extern crate serde;
extern crate serde_json;
extern crate serde_yaml;
extern crate vte;

#[macro_use]
extern crate bitflags;

use std::sync::{mpsc, Arc};
use std::sync::atomic::Ordering;

use parking_lot::{MutexGuard};

use alacritty::Flag;
use alacritty::Rgb;
use alacritty::config::{self, Config};
use alacritty::event;
use alacritty::gl;
use alacritty::input;
use alacritty::meter::Meter;
use alacritty::renderer::{QuadRenderer, GlyphCache};
use alacritty::sync::FairMutex;
use alacritty::term::{self, Term};
use alacritty::tty::{self, Pty, process_should_exit};
use alacritty::event_loop::EventLoop;

/// Channel used by resize handling on mac
static mut RESIZE_CALLBACK: Option<Box<Fn(u32, u32)>> = None;

/// Resize handling for Mac
fn window_resize_handler(width: u32, height: u32) {
    unsafe {
        RESIZE_CALLBACK.as_ref().map(|func| func(width, height));
    }
}

fn main() {
    // Load configuration
    let (config, config_path) = match Config::load() {
        Err(err) => match err {
            // Use default config when not found
            config::Error::NotFound => (Config::default(), None),
            // Exit when there's a problem with it
            _ => die!("{}", err),
        },
        Ok((config, path)) => (config, Some(path)),
    };

    let mut ref_test = false;
    let mut columns = 80;
    let mut lines = 24;

    let mut args_iter = ::std::env::args();
    while let Some(arg) = args_iter.next() {
        match &arg[..] {
            // Generate ref test
            "--ref-test" => ref_test = true,
            // Set dimensions
            "-d" | "--dimensions" => {
                args_iter.next()
                    .map(|w| w.parse().map(|w| columns = w));
                args_iter.next()
                    .map(|h| h.parse().map(|h| lines = h));
            },
            // ignore unexpected
            _ => (),
        }
    }

    let font = config.font();
    let dpi = config.dpi();
    let render_timer = config.render_timer();

    let mut window = glutin::WindowBuilder::new()
                                           .with_vsync()
                                           .with_title("Alacritty")
                                           .build().unwrap();

    window.set_window_resize_callback(Some(window_resize_handler as fn(u32, u32)));

    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
    let (width, height) = window.get_inner_size_pixels().unwrap();
    let dpr = window.hidpi_factor();

    println!("device_pixel_ratio: {}", dpr);

    let _ = unsafe { window.make_current() };
    unsafe {
        // gl::Viewport(0, 0, width as i32, height as i32);
        gl::Enable(gl::BLEND);
        gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);
        gl::Enable(gl::MULTISAMPLE);
    }

    let rasterizer = font::Rasterizer::new(dpi.x(), dpi.y(), dpr);

    // Create renderer
    let mut renderer = QuadRenderer::new(&config, width, height);

    // Initialize glyph cache
    let glyph_cache = {
        println!("Initializing glyph cache");
        let init_start = ::std::time::Instant::now();

        let cache = renderer.with_loader(|mut api| {
            GlyphCache::new(rasterizer, &config, &mut api)
        });

        let stop = init_start.elapsed();
        let stop_f = stop.as_secs() as f64 + stop.subsec_nanos() as f64 / 1_000_000_000f64;
        println!("Finished initializing glyph cache in {}", stop_f);

        cache
    };

    let metrics = glyph_cache.font_metrics();
    let cell_width = (metrics.average_advance + font.offset().x() as f64) as u32;
    let cell_height = (metrics.line_height + font.offset().y() as f64) as u32;

    // Resize window to be 80 col x 24 lines
    let width = cell_width * columns + 4;
    let height = cell_height * lines + 4;
    println!("set_inner_size: {} x {}", width, height);
    // Is this in points?
    let width_pts = (width as f32 / dpr) as u32;
    let height_pts = (height as f32 / dpr) as u32;
    println!("set_inner_size: {} x {}; pts: {} x {}", width, height, width_pts, height_pts);
    window.set_inner_size(width_pts, height_pts);
    renderer.resize(width as _, height as _);

    println!("Cell Size: ({} x {})", cell_width, cell_height);

    let size = term::SizeInfo {
        width: width as f32,
        height: height as f32,
        cell_width: cell_width as f32,
        cell_height: cell_height as f32
    };

    let terminal = Term::new(size);
    let pty = tty::new(size.lines(), size.cols());
    pty.resize(size.lines(), size.cols(), size.width as usize, size.height as usize);
    let pty_io = pty.reader();

    let (tx, rx) = mpsc::channel();

    let signal_flag = Flag::new(false);

    let terminal = Arc::new(FairMutex::new(terminal));

    // Setup the rsize callback for osx
    let terminal_ref = terminal.clone();
    let signal_flag_ref = signal_flag.clone();
    let proxy = window.create_window_proxy();
    let tx2 = tx.clone();
    unsafe {
        RESIZE_CALLBACK = Some(Box::new(move |width: u32, height: u32| {
            let _ = tx2.send((width, height));
            if !signal_flag_ref.0.swap(true, Ordering::AcqRel) {
               // We raised the signal flag
                let mut terminal = terminal_ref.lock();
                terminal.dirty = true;
                proxy.wakeup_event_loop();
            }
        }));
    }

    let event_loop = EventLoop::new(
        terminal.clone(),
        window.create_window_proxy(),
        signal_flag.clone(),
        pty_io,
        ref_test,
    );

    let loop_tx = event_loop.channel();
    let event_loop_handle = event_loop.spawn(None);

    // Wraps a renderer and gives simple draw() api.
    let mut display = Display::new(
        &window,
        renderer,
        glyph_cache,
        render_timer,
        rx,
        pty
    );

    // Event processor
    let mut processor = event::Processor::new(
        input::LoopNotifier(loop_tx),
        terminal.clone(),
        tx,
        &config,
        ref_test,
    );

    let (config_tx, config_rx) = mpsc::channel();

    // create a config watcher when config is loaded from disk
    let _config_reloader = config_path.map(|config_path| {
        config::Watcher::new(config_path, ConfigHandler {
            tx: config_tx,
            window: window.create_window_proxy(),
        })
    });

    // Main loop
    loop {
        // Wait for something to happen
        processor.process_events(&window);

        if let Ok(config) = config_rx.try_recv() {
            display.update_config(&config);
            processor.update_config(&config);
        }

        // Maybe draw the terminal
        let terminal = terminal.lock();
        signal_flag.set(false);
        if terminal.dirty {
            display.draw(terminal, &config);
        }

        if process_should_exit() {
            break;
        }
    }

    // FIXME need file watcher to work with custom delegates before
    //       joining config reloader is possible
    // config_reloader.join().ok();

    // shutdown
    event_loop_handle.join().ok();
    println!("Goodbye");
}

struct ConfigHandler {
    tx: mpsc::Sender<config::Config>,
    window: ::glutin::WindowProxy,
}

// TODO FIXME
impl config::OnConfigReload for ConfigHandler {
    fn on_config_reload(&mut self, config: Config) {
        if let Err(..) = self.tx.send(config) {
            err_println!("Failed to notify of new config");
            return;
        }

        self.window.wakeup_event_loop();
    }
}

struct Display<'a> {
    window: &'a glutin::Window,
    renderer: QuadRenderer,
    glyph_cache: GlyphCache,
    render_timer: bool,
    rx: mpsc::Receiver<(u32, u32)>,
    meter: Meter,
    pty: Pty,
}

impl<'a> Display<'a> {
    pub fn update_config(&mut self, config: &Config) {
        self.renderer.update_config(config);
        self.render_timer = config.render_timer();
    }

    pub fn new(
        window: &glutin::Window,
        renderer: QuadRenderer,
        glyph_cache: GlyphCache,
        render_timer: bool,
        rx: mpsc::Receiver<(u32, u32)>,
        pty: Pty
    ) -> Display {
        Display {
            window: window,
            renderer: renderer,
            glyph_cache: glyph_cache,
            render_timer: render_timer,
            rx: rx,
            meter: Meter::new(),
            pty: pty,
        }
    }

    /// Draw the screen
    ///
    /// A reference to Term whose state is being drawn must be provided.
    ///
    /// This call may block if vsync is enabled
    pub fn draw(&mut self, mut terminal: MutexGuard<Term>, config: &Config) {
        terminal.dirty = false;

        // Resize events new_size and are handled outside the poll_events
        // iterator. This has the effect of coalescing multiple resize
        // events into one.
        let mut new_size = None;

        // Check for any out-of-band resize events (mac only)
        while let Ok(sz) = self.rx.try_recv() {
            new_size = Some(sz);
        }

        // Receive any resize events; only call gl::Viewport on last
        // available
        if let Some((w, h)) = new_size.take() {
            terminal.resize(w as f32, h as f32);
            let size = terminal.size_info();
            self.pty.resize(size.lines(), size.cols(), w as _, h as _);
            self.renderer.resize(w as i32, h as i32);
        }

        {
            let glyph_cache = &mut self.glyph_cache;
            // Draw grid
            {
                let _sampler = self.meter.sampler();

                let size_info = terminal.size_info().clone();
                self.renderer.with_api(config, &size_info, |mut api| {
                    api.clear();

                    // Draw the grid
                    api.render_cells(terminal.renderable_cells(), glyph_cache);
                });
            }

            // Draw render timer
            if self.render_timer {
                let timing = format!("{:.3} usec", self.meter.average());
                let color = alacritty::ansi::Color::Spec(Rgb { r: 0xd5, g: 0x4e, b: 0x53 });
                self.renderer.with_api(config, terminal.size_info(), |mut api| {
                    api.render_string(&timing[..], glyph_cache, &color);
                });
            }
        }

        // Unlock the terminal mutex
        drop(terminal);
        self.window.swap_buffers().unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate sendgrid;

use sendgrid::{mail, sg_client};

fn main() {
    let mut env_vars = std::env::vars();
    let api_key_check = env_vars.find(|var| var.0 == "SENDGRID_API_KEY");
    let api_key: String;
    match api_key_check {
        Some(key) => api_key = key.1,
        None => panic!("Must supply API key in environment variables to use!")
    }

    let sg = sg_client::SGClient::new(api_key);

    let mut mail_info = mail::Mail::new();
    mail_info.add_to("garrettsquire@gmail.com");
    mail_info.add_from("garrett.squire@sendgrid.net");
    mail_info.add_subject("Test");
    mail_info.add_html("
Cool
");

    sg.send(mail_info);
}
<commit_msg>clean up namespacing a bit<commit_after>extern crate sendgrid;

use sendgrid::mail::Mail;
use sendgrid::sg_client::SGClient;

fn main() {
    let mut env_vars = std::env::vars();
    let api_key_check = env_vars.find(|var| var.0 == "SENDGRID_API_KEY");
    let api_key: String;
    match api_key_check {
        Some(key) => api_key = key.1,
        None => panic!("Must supply API key in environment variables to use!")
    }

    let sg = SGClient::new(api_key);

    let mut mail_info = Mail::new();
    mail_info.add_to("garrettsquire@gmail.com");
    mail_info.add_from("garrett.squire@sendgrid.net");
    mail_info.add_subject("Test");
    mail_info.add_html("
Cool
");

    sg.send(mail_info);
}
<|endoftext|>


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

#![feature(test)]

extern crate jsrs_common;
extern crate jsrs_parser;
extern crate french_press;

extern crate walkdir;
extern crate unescape;
extern crate rustyline;
extern crate rustc_serialize;
extern crate docopt;

extern crate test;

mod js_error;
mod var;

mod eval;
mod native;
mod number;
mod bench;
mod preprocess;

use std::cell::RefCell;
use std::fs::{File, metadata};
use std::io::{self, BufReader};
use std::io::prelude::*;
use std::path::Path;
use std::process::exit;
use std::rc::Rc;

use rustyline::error::ReadlineError;
use rustyline::Editor;
use walkdir::WalkDir;

use jsrs_common::types::coerce::AsString;
use jsrs_common::types::js_var::JsPtrEnum;
use french_press::{init_gc, ScopeManager};

use eval::eval_string;
use native::add_pervasives;
use preprocess::{clean_string, add_semicolon};
use js_error::JsError;

docopt!(Args derive Debug, "
js.rs - a javascript interpreter

Usage:
jsrs
jsrs <file>
jsrs --test
");

fn eval_file(filename: String, debug: bool, should_repl: bool,
             scope_manager: Rc<RefCell<ScopeManager>>) -> js_error::Result<()> {
    if debug {
        println!("Reading from \"{}\"", filename);
    }

    let path = Path::new(&filename);
    let file = File::open(&path)
        .expect(&format!("Cannot open \"{}\": no such file or directory", filename));
    let file_buffer = BufReader::new(file);

    let mut line_builder = String::new();
    let mut braces = Vec::new();

    let mut file_iter = file_buffer.lines();
    let mut negative_test = false;
    loop {
        if let Some(line) = file_iter.next() {
            let input = String::from(line.expect(&format!("Cannot read from {}", filename)));
            let input = clean_string(input);
            if input.contains("@negative") {
                negative_test = true;
            }

            let mut last = '\0';
            // Match braces to see if we should wait for more input
            for c in input.chars() {
                if c == '(' {
                    braces.push('(');
                } else if c == '{' {
                    braces.push('{');
                } else if c == '*' && last == '/' {
                    braces.push('/');
                } else if c == ')' {
                    if braces.pop() != Some('(') {
                        return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                    }
                } else if c == '}' {
                    if braces.pop() != Some('{') {
                        return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                    }
                } else if c == '/' && last == '*' {
                    if braces.pop() != Some('/') {
                        return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                    }
                }
                last = c;
            }

            line_builder.push_str(&input);

            if braces.len() == 0 {
                let js_string = clean_string(line_builder.clone());
                line_builder = String::new();
                if js_string == "" {
                    continue;
                }

                if debug {
                    println!("\n{}", js_string);
                }

                let ret;
                let eval_result = eval_string(&js_string, scope_manager.clone());
                if negative_test {
                    match eval_result {
                        Ok((var, ptr)) => ret = (var, ptr),
                        Err(e) => {
                            if !e.is_meta_error() {
                                continue;
                            } else {
                                return Err(e);
                            }
                        }
                    }
                } else {
                    ret = try!(eval_result);
                }

                if debug {
                    println!("=> {:?}", ret);
                }
            }
        } else {
            break;
        }
    }
    if should_repl {
        repl(scope_manager);
    }
    Ok(())
}

fn test_dir(dir_name: String) {
    for entry in WalkDir::new(dir_name) {
        let entry = entry.unwrap();
        if !entry.path().is_dir() {
            let entry_path = entry.path().display().to_string();
            let scope_manager = Rc::new(RefCell::new(init_gc()));
            add_pervasives(scope_manager.clone());
            match eval_file(entry_path.clone(), false, false, scope_manager.clone()) {
                Ok(_) => {
                    println!("{}: {}", entry_path, "OK");
                }
                Err(e) => {
                    println!("{}: {}", entry_path, e);
                }
            }
        }
    }
}

fn repl(scope_manager: Rc<RefCell<ScopeManager>>) -> i32 {
    let mut rl = Editor::new();
    let mut stderr = io::stderr();

    if metadata(".history").is_ok() && rl.load_history(".history").is_err() {
        writeln!(stderr, "Error: unable to load history on startup").unwrap();
    }

    loop {
        // prompt
        let readline = rl.readline(">> ");

        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                let input = add_semicolon(clean_string(String::from(line)));
                if input == "" {
                    continue;
                }
                rl.add_history_entry(&input);

                match eval_string(&input, scope_manager.clone()) {
                    Ok((var, ptr)) => println!("{}", ptr.map(|p| p.as_string()).unwrap_or(var.t.as_string())),
                    Err(e) => println!("{:?}", e),
                }
            },
            Err(ReadlineError::Interrupted) => {
                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                return 1;
            },
            Err(ReadlineError::Eof) => {
                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);

                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                return 3;
            }
        }
    }
    0
}

fn main() {
    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());
    if args.flag_test {
        let dir_name = "sputnik";

        test_dir(String::from(dir_name))
    } else {
        let scope_manager = Rc::new(RefCell::new(init_gc()));
        add_pervasives(scope_manager.clone());

        if args.arg_file == "" {
            let ret = repl(scope_manager.clone());
            exit(ret)
        } else {
            eval_file(args.arg_file, true, true, scope_manager.clone())
                .expect("Error evaluating file");
        }
    }
}
<commit_msg>remove import that is no longer needed<commit_after>#![feature(plugin)]
#![plugin(docopt_macros)]

#![feature(test)]

extern crate jsrs_common;
extern crate jsrs_parser;
extern crate french_press;

extern crate walkdir;
extern crate unescape;
extern crate rustyline;
extern crate rustc_serialize;
extern crate docopt;

extern crate test;

mod js_error;
mod var;

mod eval;
mod native;
mod number;
mod bench;
mod preprocess;

use std::cell::RefCell;
use std::fs::{File, metadata};
use std::io::{self, BufReader};
use std::io::prelude::*;
use std::path::Path;
use std::process::exit;
use std::rc::Rc;

use rustyline::error::ReadlineError;
use rustyline::Editor;
use walkdir::WalkDir;

use jsrs_common::types::coerce::AsString;
use french_press::{init_gc, ScopeManager};

use eval::eval_string;
use native::add_pervasives;
use preprocess::{clean_string, add_semicolon};
use js_error::JsError;

docopt!(Args derive Debug, "
js.rs - a javascript interpreter

Usage:
jsrs
jsrs <file>
jsrs --test
");

fn eval_file(filename: String, debug: bool, should_repl: bool,
             scope_manager: Rc<RefCell<ScopeManager>>) -> js_error::Result<()> {
    if debug {
        println!("Reading from \"{}\"", filename);
    }

    let path = Path::new(&filename);
    let file = File::open(&path)
        .expect(&format!("Cannot open \"{}\": no such file or directory", filename));
    let file_buffer = BufReader::new(file);

    let mut line_builder = String::new();
    let mut braces = Vec::new();

    let mut file_iter = file_buffer.lines();
    let mut negative_test = false;
    loop {
        if let Some(line) = file_iter.next() {
            let input = String::from(line.expect(&format!("Cannot read from {}", filename)));
            let input = clean_string(input);
            if input.contains("@negative") {
                negative_test = true;
            }

            let mut last = '\0';
            // Match braces to see if we should wait for more input
            for c in input.chars() {
                if c == '(' {
                    braces.push('(');
                } else if c == '{' {
                    braces.push('{');
                } else if c == '*' && last == '/' {
                    braces.push('/');
                } else if c == ')' {
                    if braces.pop() != Some('(') {
                        return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                    }
                } else if c == '}' {
                    if braces.pop() != Some('{') {
                        return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                    }
                } else if c == '/' && last == '*' {
                    if braces.pop() != Some('/') {
                        return Err(JsError::ParseError(format!("Unexpected token {}", c)));
                    }
                }
                last = c;
            }

            line_builder.push_str(&input);

            if braces.len() == 0 {
                let js_string = clean_string(line_builder.clone());
                line_builder = String::new();
                if js_string == "" {
                    continue;
                }

                if debug {
                    println!("\n{}", js_string);
                }

                let ret;
                let eval_result = eval_string(&js_string, scope_manager.clone());
                if negative_test {
                    match eval_result {
                        Ok((var, ptr)) => ret = (var, ptr),
                        Err(e) => {
                            if !e.is_meta_error() {
                                continue;
                            } else {
                                return Err(e);
                            }
                        }
                    }
                } else {
                    ret = try!(eval_result);
                }

                if debug {
                    println!("=> {:?}", ret);
                }
            }
        } else {
            break;
        }
    }
    if should_repl {
        repl(scope_manager);
    }
    Ok(())
}

fn test_dir(dir_name: String) {
    for entry in WalkDir::new(dir_name) {
        let entry = entry.unwrap();
        if !entry.path().is_dir() {
            let entry_path = entry.path().display().to_string();
            let scope_manager = Rc::new(RefCell::new(init_gc()));
            add_pervasives(scope_manager.clone());
            match eval_file(entry_path.clone(), false, false, scope_manager.clone()) {
                Ok(_) => {
                    println!("{}: {}", entry_path, "OK");
                }
                Err(e) => {
                    println!("{}: {}", entry_path, e);
                }
            }
        }
    }
}

fn repl(scope_manager: Rc<RefCell<ScopeManager>>) -> i32 {
    let mut rl = Editor::new();
    let mut stderr = io::stderr();

    if metadata(".history").is_ok() && rl.load_history(".history").is_err() {
        writeln!(stderr, "Error: unable to load history on startup").unwrap();
    }

    loop {
        // prompt
        let readline = rl.readline(">> ");

        match readline {
            Ok(line) => {
                rl.add_history_entry(&line);
                let input = add_semicolon(clean_string(String::from(line)));
                if input == "" {
                    continue;
                }
                rl.add_history_entry(&input);

                match eval_string(&input, scope_manager.clone()) {
                    Ok((var, ptr)) => println!("{}", ptr.map(|p| p.as_string()).unwrap_or(var.t.as_string())),
                    Err(e) => println!("{:?}", e),
                }
            },
            Err(ReadlineError::Interrupted) => {
                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                return 1;
            },
            Err(ReadlineError::Eof) => {
                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);

                if rl.save_history(".history").is_err() {
                    writeln!(stderr, "Error: unable to save history on exit").unwrap();
                    return 2;
                }
                return 3;
            }
        }
    }
    0
}

fn main() {
    let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());
    if args.flag_test {
        let dir_name = "sputnik";

        test_dir(String::from(dir_name))
    } else {
        let scope_manager = Rc::new(RefCell::new(init_gc()));
        add_pervasives(scope_manager.clone());

        if args.arg_file == "" {
            let ret = repl(scope_manager.clone());
            exit(ret)
        } else {
            eval_file(args.arg_file, true, true, scope_manager.clone())
                .expect("Error evaluating file");
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate env_logger;

extern crate afterparty;
extern crate clap;
extern crate lettre;
extern crate git2;
extern crate hyper;
extern crate regex;
extern crate slack_hook;
extern crate toml;

mod auth;
mod config;
mod email;
mod repo;
mod slack;
mod taste;

use afterparty::{Delivery, Event, Hub};
use hyper::Server;
use std::path::Path;
use std::sync::Mutex;

#[cfg_attr(rustfmt, rustfmt_skip)]
const TASTER_USAGE: &'static str = "\
EXAMPLES:
  taste -w /path/to/workdir -s my_secret
  taste -l 0.0.0.0:1234 -w /path/to/workdir -s my_secret";

pub fn main() {
    use clap::{Arg, App};

    env_logger::init().unwrap();

    let args = App::new("taster")
        .version("0.0.1")
        .about("Tastes Soup commits.")
        .arg(Arg::with_name("listen_addr")
            .short("l")
            .long("listen_addr")
            .takes_value(true)
            .value_name("IP:PORT")
            .default_value("0.0.0.0:4567")
            .help("Listen address and port for webhook delivery"))
        .arg(Arg::with_name("github_repo")
            .short("r")
            .long("github_repo")
            .takes_value(true)
            .required(true)
            .value_name("GH_REPO")
            .default_value("https://github.com/ms705/taster")
            .help("GitHub repository to taste"))
        .arg(Arg::with_name("email_addr")
            .long("email_addr")
            .takes_value(true)
            .required(false)
            .help("Email address to send notifications to"))
        .arg(Arg::with_name("secret")
            .short("s")
            .long("secret")
            .takes_value(true)
            .required(true)
            .help("GitHub webhook secret"))
        .arg(Arg::with_name("slack_hook_url")
            .long("slack_hook_url")
            .takes_value(true)
            .required(false)
            .help("Slack webhook URL to push notifications to"))
        .arg(Arg::with_name("slack_channel")
            .long("slack_channel")
            .takes_value(true)
            .required(false)
            .default_value("#soup-test")
            .help("Slack channel for notifications"))
        .arg(Arg::with_name("workdir")
            .short("w")
            .long("workdir")
            .takes_value(true)
            .required(true)
            .value_name("REPO_DIR")
            .help("Directory holding the workspace repo"))
        .after_help(TASTER_USAGE)
        .get_matches();

    let addr = args.value_of("listen_addr").unwrap();
    let email_notification_addr = args.value_of("email_addr");
    let repo = args.value_of("github_repo").unwrap();
    let secret = args.value_of("secret").unwrap();
    let slack_hook_url = args.value_of("slack_hook_url");
    let slack_channel = args.value_of("slack_channel");
    let workdir = Path::new(args.value_of("workdir").unwrap());

    let wsl = Mutex::new(repo::Workspace::new(repo, workdir));
    let en = if let Some(addr) = email_notification_addr {
        Some(email::EmailNotifier::new(addr, repo))
    } else {
        None
    };
    let sn = if let Some(url) = slack_hook_url {
        Some(slack::SlackNotifier::new(url, slack_channel.unwrap(), repo))
    } else {
        None
    };

    if taste_head {
        let head_id = {
            let ws = wsl.lock().unwrap();
            let cid = ws.repo.head().unwrap().target().unwrap().clone();
            format!("{}", cid)
        };
        let res = taste::taste_commit(&wsl, &head_id, "HEAD");
        // email notification
        if en.is_some() {
            en.as_ref().unwrap().notify(&res).unwrap();
        }
        // slack notification
        if sn.is_some() {
            sn.as_ref().unwrap().notify(&res).unwrap();
        }
    }

    let mut hub = Hub::new();
    hub.handle_authenticated("push", secret, move |delivery: &Delivery| {
        match delivery.payload {
            Event::Push { ref commits, ref pusher, .. } => {
                println!("Handling {} commits pushed by {}",
                         commits.len(),
                         pusher.name);
                {
                    let ws = wsl.lock().unwrap();
                    ws.fetch().unwrap();
                }
                for c in commits.iter() {
                    // taste
                    let res = taste::taste_commit(&wsl, &c.id, &c.message);

                    // email notification
                    if en.is_some() {
                        en.as_ref().unwrap().notify(&res).unwrap();
                    }
                    // slack notification
                    if sn.is_some() {
                        sn.as_ref().unwrap().notify(&res).unwrap();
                    }
                }
            }
            _ => (),
        }
    });

    let srvc = Server::http(&addr[..])
        .unwrap()
        .handle(hub);

    println!("Taster listening on {}", addr);
    srvc.unwrap();
}
<commit_msg>Add option for one-off commit tasting<commit_after>#[macro_use]
extern crate log;
extern crate env_logger;

extern crate afterparty;
extern crate clap;
extern crate lettre;
extern crate git2;
extern crate hyper;
extern crate regex;
extern crate slack_hook;
extern crate toml;

mod auth;
mod config;
mod email;
mod repo;
mod slack;
mod taste;

use afterparty::{Delivery, Event, Hub};
use hyper::Server;
use std::path::Path;
use std::sync::Mutex;

#[cfg_attr(rustfmt, rustfmt_skip)]
const TASTER_USAGE: &'static str = "\
EXAMPLES:
  taste -w /path/to/workdir -s my_secret
  taste -l 0.0.0.0:1234 -w /path/to/workdir -s my_secret";

pub fn main() {
    use clap::{Arg, App};

    env_logger::init().unwrap();

    let args = App::new("taster")
        .version("0.0.1")
        .about("Tastes Soup commits.")
        .arg(Arg::with_name("listen_addr")
            .short("l")
            .long("listen_addr")
            .takes_value(true)
            .value_name("IP:PORT")
            .default_value("0.0.0.0:4567")
            .help("Listen address and port for webhook delivery"))
        .arg(Arg::with_name("github_repo")
            .short("r")
            .long("github_repo")
            .takes_value(true)
            .required(true)
            .value_name("GH_REPO")
            .default_value("https://github.com/ms705/taster")
            .help("GitHub repository to taste"))
        .arg(Arg::with_name("email_addr")
            .long("email_addr")
            .takes_value(true)
            .required(false)
            .help("Email address to send notifications to"))
        .arg(Arg::with_name("secret")
            .short("s")
            .long("secret")
            .takes_value(true)
            .required(false)
            .help("GitHub webhook secret"))
        .arg(Arg::with_name("slack_hook_url")
            .long("slack_hook_url")
            .takes_value(true)
            .required(false)
            .help("Slack webhook URL to push notifications to"))
        .arg(Arg::with_name("slack_channel")
            .long("slack_channel")
            .takes_value(true)
            .required(false)
            .default_value("#soup-test")
            .help("Slack channel for notifications"))
        .arg(Arg::with_name("taste_commit")
            .long("taste_commit")
            .short("t")
            .takes_value(true)
            .required(false)
            .help("Do a one-off taste of a specific commit"))
        .arg(Arg::with_name("workdir")
            .short("w")
            .long("workdir")
            .takes_value(true)
            .required(true)
            .value_name("REPO_DIR")
            .help("Directory holding the workspace repo"))
        .after_help(TASTER_USAGE)
        .get_matches();

    let addr = args.value_of("listen_addr").unwrap();
    let email_notification_addr = args.value_of("email_addr");
    let repo = args.value_of("github_repo").unwrap();
    let secret = args.value_of("secret");
    let slack_hook_url = args.value_of("slack_hook_url");
    let slack_channel = args.value_of("slack_channel");
    let taste_commit = args.value_of("taste_commit");
    let workdir = Path::new(args.value_of("workdir").unwrap());

    let wsl = Mutex::new(repo::Workspace::new(repo, workdir));
    let en = if let Some(addr) = email_notification_addr {
        Some(email::EmailNotifier::new(addr, repo))
    } else {
        None
    };
    let sn = if let Some(url) = slack_hook_url {
        Some(slack::SlackNotifier::new(url, slack_channel.unwrap(), repo))
    } else {
        None
    };

    if taste_commit.is_some() {
        let cid = if let Some("HEAD") = taste_commit {
            let ws = wsl.lock().unwrap();
            // yuck
            let cid = ws.repo.head().unwrap().target().unwrap().clone();
            format!("{}", cid)
        } else {
            String::from(taste_commit.unwrap())
        };
        let res = taste::taste_commit(&wsl, &cid, &cid);
        // email notification
        if en.is_some() {
            en.as_ref().unwrap().notify(&res).unwrap();
        }
        // slack notification
        if sn.is_some() {
            sn.as_ref().unwrap().notify(&res).unwrap();
        }
        return;
    }

    if let None = secret {
        panic!("--secret must be set when in continuous webhook handler mode");
    }

    let mut hub = Hub::new();
    hub.handle_authenticated("push", secret.unwrap(), move |delivery: &Delivery| {
        match delivery.payload {
            Event::Push { ref commits, ref pusher, .. } => {
                println!("Handling {} commits pushed by {}",
                         commits.len(),
                         pusher.name);
                {
                    let ws = wsl.lock().unwrap();
                    ws.fetch().unwrap();
                }
                for c in commits.iter() {
                    // taste
                    let res = taste::taste_commit(&wsl, &c.id, &c.message);

                    // email notification
                    if en.is_some() {
                        en.as_ref().unwrap().notify(&res).unwrap();
                    }
                    // slack notification
                    if sn.is_some() {
                        sn.as_ref().unwrap().notify(&res).unwrap();
                    }
                }
            }
            _ => (),
        }
    });

    let srvc = Server::http(&addr[..])
        .unwrap()
        .handle(hub);

    println!("Taster listening on {}", addr);
    srvc.unwrap();
}
<|endoftext|>


<commit_before>extern crate hkg;
extern crate rustbox;
extern crate rustc_serialize;

use std::default::Default;

use rustbox::{Color, RustBox};
use rustbox::Key;

use rustc_serialize::json;

use hkg::utility::cache;
use hkg::model::TopicItem;

fn main() {

    // GUI init
    let rustbox = match RustBox::init(Default::default()) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    let title = String::from("高登");
    let s = cache::readfile(String::from("topics.json"));
    let collection: Vec<TopicItem> = json::decode(&s).unwrap();

    let mut status = String::from(">");

    let mut selected_topic_index: usize = 0; // no selection by default

    loop {

        let w = rustbox.width();
        let h = rustbox.height();

        let body_height = if h >= 3 {
            h - 3
        } else {
            0
        };
        let body_width = if w >= 2 {
            w - 2
        } else {
            0
        };

        if selected_topic_index > body_height {
            selected_topic_index = body_height;
        }

        print_header(&rustbox, w, &title);
        print_body(&rustbox,
                   body_width,
                   2,
                   body_height,
                   &collection,
                   selected_topic_index);

        let status_width = if w > status.len() {
            w - status.len()
        } else {
            0
        };
        let status_spacing = (0..status_width).map(|_| " ").collect::<Vec<_>>().join("");

        rustbox.print(1,
                      h - 1,
                      rustbox::RB_BOLD,
                      Color::White,
                      Color::Black,
                      &format!("{status}{status_spacing}",
                               status = status,
                               status_spacing = status_spacing));

        rustbox.present();
        match rustbox.poll_event(false) {
            Ok(rustbox::Event::KeyEvent(key)) => {
                match key {
                    Key::Char('q') => {
                        break;
                    }

                    Key::Up => {
                        if status.len() >= w {
                            status = String::from("U");
                        } else {
                            status = String::from(format!("{}{}", &status, &"U"));
                        }

                        if selected_topic_index > 1 {
                            selected_topic_index = selected_topic_index - 1;
                        }
                    }
                    Key::Down => {
                        if status.len() >= w {
                            status = String::from("D");
                        } else {
                            status = String::from(format!("{}{}", &status, &"D"));
                        }

                        if selected_topic_index < body_height {
                            selected_topic_index = selected_topic_index + 1;
                        }
                    }

                    _ => {}
                }
            }
            Err(e) => panic!("{}", e),
            _ => {}
        }
    }
}

fn print_header(rustbox: &rustbox::RustBox, width: usize, text: &str) {
    let padding = (width - text.len()) / 2;
    let header_bottom = (0..width).map(|_| "─").collect::<Vec<_>>().join("");

    clearline(&rustbox, width, 0, 0);
    rustbox.print(padding,
                  0,
                  rustbox::RB_BOLD,
                  Color::White,
                  Color::Black,
                  text);
    rustbox.print(0,
                  1,
                  rustbox::RB_BOLD,
                  Color::Yellow,
                  Color::Black,
                  &header_bottom);
}

fn print_body(rustbox: &rustbox::RustBox,
              width: usize,
              offset_y: usize,
              rows: usize,
              collection: &Vec<TopicItem>,
              selected_topic_index: usize) {

    let right_offset = 3;
    let author_max_width = 12;
    let no_max_width = 5;
    let title_max_width = width - no_max_width - author_max_width - right_offset;

    for (i, item) in collection.iter().take(rows).enumerate() {

        let original_title = item.titles[0].text.clone();
        let title: String = substring(&original_title, title_max_width);
        let title_len = string_jks_len(&title);

        let title_spacin_minus = no_max_width + title_len + author_max_width + right_offset;
        let title_spacing_width = if width > title_spacin_minus {
            width - title_spacin_minus
        } else {
            0
        };
        let title_spacing = (0..title_spacing_width).map(|_| " ").collect::<Vec<_>>().join("");

        let author = item.author.name.clone();
        let author_spacing_width = author_max_width - string_jks_len(&author) + right_offset;
        let author_spacing = (0..author_spacing_width).map(|_| " ").collect::<Vec<_>>().join("");

        if selected_topic_index == i + 1 {
            rustbox.print(0,
                          i + offset_y,
                          rustbox::RB_NORMAL,
                          Color::Black,
                          Color::Yellow,
                          &format!("[{no:0>2}] {title}{title_spacing}| {author}{author_spacing}",
                                   no = i + 1,
                                   title = title,
                                   title_spacing = title_spacing,
                                   author = &author,
                                   author_spacing = author_spacing));
        } else {
            rustbox.print(0,
                          i + offset_y,
                          rustbox::RB_NORMAL,
                          Color::White,
                          Color::Black,
                          &format!("[{no:0>2}] {title}{title_spacing}| {author}{author_spacing}",
                                   no = i + 1,
                                   title = title,
                                   title_spacing = title_spacing,
                                   author = &author,
                                   author_spacing = author_spacing));
        }

    }

}

fn clearline(rustbox: &rustbox::RustBox, width: usize, x: usize, y: usize) {
    let s = (0..width).map(|_| "  ").collect::<Vec<_>>().join("");

    rustbox.print(x, y, rustbox::RB_NORMAL, Color::White, Color::Black, &s);
}

fn substring(s: &str, length: usize) -> String {
    let mut v = Vec::new();
    let mut c = 0;

    for x in s.chars() {
        if contains(x) {
            if c < length - 2 {
                v.push(x);
                c = c + 2;
            } else {
                break;
            }

        } else {
            if c < length - 1 {
                v.push(x);
                c = c + 1;
            } else {
                break;
            }
        }
    }

    let s: String = v.iter().cloned().collect();
    return s;
}

fn contains(c: char) -> bool {
    let cjks = vec![(0x4E00..0xA000),
                    (0x3400..0x4DC0),
                    (0x20000..0x2A6E0),
                    (0x2A700..0x2B740),
                    (0x2B740..0x2B820),
                    (0xF900..0xFB00),
                    (0x2F800..0x2FA20),
                    (0x9FA6..0x9FCC),

                    (0x3000..0x303F), // CJK Symbols and Punctuation
                    (0xff00..0xffef) /* Halfwidth and Fullwidth Forms */];

    for cjk in cjks {
        let h = c as u32;
        if cjk.start <= h && h < cjk.end {
            return true;
        }
    }
    return false;
}

fn string_jks_len(s: &str) -> usize {
    return s.chars()
            .map(|x| if contains(x) {
                2
            } else {
                1
            })
            .collect::<Vec<usize>>()
            .iter()
            .fold(0, |acc, &x| acc + x);
}

// fn debug_load_and_print_topics() {
//     let s = cache::readfile(String::from("topics.json"));
//     let collection: Vec<TopicItem> = json::decode(&s).unwrap();
//
//     println!("topics {:?}", collection.len());
//     debug_print_topics(collection);
// }
//
// fn debug_print_topics(collection: Vec<TopicItem>) {
//     for (i, item) in collection.iter().enumerate() {
//
//         println!("item[{}]= {title} {author_name} {last_replied_date} {last_replied_time} \
//                   {reply_count} {rating}",
//                  i,
//                  title = item.titles[0].text,
//                  author_name = item.author.name,
//                  last_replied_date = item.last_replied_date,
//                  last_replied_time = item.last_replied_time,
//                  reply_count = item.reply_count,
//                  rating = item.rating);
//     }
// }
<commit_msg>better status bar + refactor status code<commit_after>extern crate hkg;
extern crate rustbox;
extern crate rustc_serialize;

use std::default::Default;

use rustbox::{Color, RustBox};
use rustbox::Key;

use rustc_serialize::json;

use hkg::utility::cache;
use hkg::model::TopicItem;

fn main() {

    // GUI init
    let rustbox = match RustBox::init(Default::default()) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    let title = String::from("高登");
    let s = cache::readfile(String::from("topics.json"));
    let collection: Vec<TopicItem> = json::decode(&s).unwrap();

    let mut status = String::from("> ");

    let mut selected_topic_index: usize = 0; // no selection by default

    loop {

        let w = rustbox.width();
        let h = rustbox.height();

        let body_height = if h >= 3 {
            h - 3
        } else {
            0
        };
        let body_width = if w >= 2 {
            w - 2
        } else {
            0
        };

        if selected_topic_index > body_height {
            selected_topic_index = body_height;
        }

        print_header(&rustbox, w, &title);
        print_body(&rustbox,
                   body_width,
                   2,
                   body_height,
                   &collection,
                   selected_topic_index);

        let status_width = if w > status.len() {
            w - status.len()
        } else {
            0
        };
        let status_spacing = (0..status_width).map(|_| " ").collect::<Vec<_>>().join("");

        rustbox.print(0,
                      h - 1,
                      rustbox::RB_BOLD,
                      Color::White,
                      Color::Black,
                      &format!("{status}{status_spacing}",
                               status = status,
                               status_spacing = status_spacing));

        rustbox.present();
        match rustbox.poll_event(false) {
            Ok(rustbox::Event::KeyEvent(key)) => {
                match key {
                    Key::Char('q') => {
                        break;
                    }

                    Key::Up => {
                        status = format_status(status, w, "U");
                        if selected_topic_index > 1 {
                            selected_topic_index = selected_topic_index - 1;
                        }
                    }
                    Key::Down => {
                        status = format_status(status, w, "D");

                        if selected_topic_index < body_height {
                            selected_topic_index = selected_topic_index + 1;
                        }
                    }

                    _ => {}
                }
            }
            Err(e) => panic!("{}", e),
            _ => {}
        }
    }
}

fn format_status(status: String, w: usize, s: &str) -> String
{
    if status.len() >= w {
        String::from(format!("{}{}", &"> ", s))
    } else {
        String::from(format!("{}{}", &status, s))
    }
}

fn print_header(rustbox: &rustbox::RustBox, width: usize, text: &str) {
    let padding = (width - text.len()) / 2;
    let header_bottom = (0..width).map(|_| "─").collect::<Vec<_>>().join("");

    clearline(&rustbox, width, 0, 0);
    rustbox.print(padding,
                  0,
                  rustbox::RB_BOLD,
                  Color::White,
                  Color::Black,
                  text);
    rustbox.print(0,
                  1,
                  rustbox::RB_BOLD,
                  Color::Yellow,
                  Color::Black,
                  &header_bottom);
}

fn print_body(rustbox: &rustbox::RustBox,
              width: usize,
              offset_y: usize,
              rows: usize,
              collection: &Vec<TopicItem>,
              selected_topic_index: usize) {

    let right_offset = 3;
    let author_max_width = 12;
    let no_max_width = 5;
    let title_max_width = width - no_max_width - author_max_width - right_offset;

    for (i, item) in collection.iter().take(rows).enumerate() {

        let original_title = item.titles[0].text.clone();
        let title: String = substring(&original_title, title_max_width);
        let title_len = string_jks_len(&title);

        let title_spacin_minus = no_max_width + title_len + author_max_width + right_offset;
        let title_spacing_width = if width > title_spacin_minus {
            width - title_spacin_minus
        } else {
            0
        };
        let title_spacing = (0..title_spacing_width).map(|_| " ").collect::<Vec<_>>().join("");

        let author = item.author.name.clone();
        let author_spacing_width = author_max_width - string_jks_len(&author) + right_offset;
        let author_spacing = (0..author_spacing_width).map(|_| " ").collect::<Vec<_>>().join("");

        if selected_topic_index == i + 1 {
            rustbox.print(0,
                          i + offset_y,
                          rustbox::RB_NORMAL,
                          Color::Black,
                          Color::Yellow,
                          &format!("[{no:0>2}] {title}{title_spacing}| {author}{author_spacing}",
                                   no = i + 1,
                                   title = title,
                                   title_spacing = title_spacing,
                                   author = &author,
                                   author_spacing = author_spacing));
        } else {
            rustbox.print(0,
                          i + offset_y,
                          rustbox::RB_NORMAL,
                          Color::White,
                          Color::Black,
                          &format!("[{no:0>2}] {title}{title_spacing}| {author}{author_spacing}",
                                   no = i + 1,
                                   title = title,
                                   title_spacing = title_spacing,
                                   author = &author,
                                   author_spacing = author_spacing));
        }

    }

}

fn clearline(rustbox: &rustbox::RustBox, width: usize, x: usize, y: usize) {
    let s = (0..width).map(|_| "  ").collect::<Vec<_>>().join("");

    rustbox.print(x, y, rustbox::RB_NORMAL, Color::White, Color::Black, &s);
}

fn substring(s: &str, length: usize) -> String {
    let mut v = Vec::new();
    let mut c = 0;

    for x in s.chars() {
        if contains(x) {
            if c < length - 2 {
                v.push(x);
                c = c + 2;
            } else {
                break;
            }

        } else {
            if c < length - 1 {
                v.push(x);
                c = c + 1;
            } else {
                break;
            }
        }
    }

    let s: String = v.iter().cloned().collect();
    return s;
}

fn contains(c: char) -> bool {
    let cjks = vec![(0x4E00..0xA000),
                    (0x3400..0x4DC0),
                    (0x20000..0x2A6E0),
                    (0x2A700..0x2B740),
                    (0x2B740..0x2B820),
                    (0xF900..0xFB00),
                    (0x2F800..0x2FA20),
                    (0x9FA6..0x9FCC),

                    (0x3000..0x303F), // CJK Symbols and Punctuation
                    (0xff00..0xffef) /* Halfwidth and Fullwidth Forms */];

    for cjk in cjks {
        let h = c as u32;
        if cjk.start <= h && h < cjk.end {
            return true;
        }
    }
    return false;
}

fn string_jks_len(s: &str) -> usize {
    return s.chars()
            .map(|x| if contains(x) {
                2
            } else {
                1
            })
            .collect::<Vec<usize>>()
            .iter()
            .fold(0, |acc, &x| acc + x);
}

// fn debug_load_and_print_topics() {
//     let s = cache::readfile(String::from("topics.json"));
//     let collection: Vec<TopicItem> = json::decode(&s).unwrap();
//
//     println!("topics {:?}", collection.len());
//     debug_print_topics(collection);
// }
//
// fn debug_print_topics(collection: Vec<TopicItem>) {
//     for (i, item) in collection.iter().enumerate() {
//
//         println!("item[{}]= {title} {author_name} {last_replied_date} {last_replied_time} \
//                   {reply_count} {rating}",
//                  i,
//                  title = item.titles[0].text,
//                  author_name = item.author.name,
//                  last_replied_date = item.last_replied_date,
//                  last_replied_time = item.last_replied_time,
//                  reply_count = item.reply_count,
//                  rating = item.rating);
//     }
// }
<|endoftext|>