<commit_before>#![allow(unused_must_use)]
use std::net::{TcpStream, TcpListener};
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::{Read, Write, BufReader};
use std::thread;
use std::env;

fn main() {
    let ipaddr = match env::args().nth(1) {
        Some(ipaddr) => ipaddr,
        None => {
            eprintln!("Missing IP address to bind to.");
            return;
        }
    };
    let directory = match env::args().nth(2) {
        Some(dir) => dir,
        None => ".".to_owned(),
    };
    let address = &format!("{}:70", ipaddr);
    let server = match TcpListener::bind(address) {
        Ok(server) => server,
        Err(_) => {
            eprintln!("Failed to start server.");
            return;
        }
    };
    println!("argoserv listening on {}:70", ipaddr);

    for client in server.incoming() {
        match client {
            Ok(client) => {
                let addr = ipaddr.clone();
                let dir = directory.clone();
                thread::spawn(move || { handle(client, addr, dir); });
            }
            Err(e) => eprintln!("ERROR : {:?}", e),
        }
    }
}

fn handle(mut client: TcpStream, ipaddr: String, directory: String) {
    let client_ip = client.peer_addr().unwrap().ip();

    let mut buffer = [0; 1024];
    let read = client.read(&mut buffer);
    let mut selector = match read {
        Ok(n) => {
            let mut wordbuf = String::new();
            let mut index = 0;
            'outer: while index < n {
                wordbuf.push(buffer[index] as char);
                if index + 2 < buffer.len() {
                    //If the next two bytes are \r\n, we're done parsing the selector.
                    if buffer[index + 1] == 0x0d && buffer[index + 2] == 0x0a {
                        break 'outer;
                    }
                }
                index += 1;
            }
            wordbuf
        }
        Err(e) => {
            eprintln!("READ ERROR {} <- {}", e, client_ip);
            return;
        }
    };
    println!("LIST '{}' -> {}", selector, client_ip);
    // Prepend a "." to the selector to keep us in the working directory of the server
    if selector == "/" {
        selector = ".".to_owned();
    } else if selector.starts_with("/") {
        selector = ".".to_owned() + &selector;
    }

    let _selector = selector.clone();
    let home = Path::new(&directory); //The home directory of the server
    let mut dest = Path::new(&directory).to_path_buf();
    dest.push(_selector);
    let mut dest = dest.as_path();

    let canonical_path = dest.canonicalize().unwrap_or(PathBuf::new());
    let canonical_cwd = home.canonicalize().unwrap_or(PathBuf::new());
    if !dest.exists() {
        client.write(b"iNo content.\r\n");
        client.write(&format!("1Return home\t/\t{}\t70\r\n.", ipaddr).as_bytes());
        return;
    } else if !canonical_path.starts_with(canonical_cwd) {
        dest = Path::new(&directory);
    }

    //Serve the client
    if dest.is_file() {
        //Send the data of this file.
        let mut file = File::open(dest).unwrap();
        let mut buffer = vec![];
        match file.read_to_end(&mut buffer) {
            Ok(_) => (),
            Err(e) => {
                eprintln!("READ FILE ERROR : {} -> {}", e, client_ip);
                client.write(b"Error reading requested file.");
                return;
            }
        }
        match client.write_all(&buffer) {
            Ok(_) => println!("SEND '{}' -> {}", selector, client_ip),
            Err(e) => eprintln!("SEND FILE ERROR: {} -> {}", e, client_ip),
        }
    } else {
        let mut menu_file = dest.to_path_buf();
        menu_file.push("index.gph");
        let menu_file = menu_file.as_path();
        if menu_file.exists() {
            let contents = read_file(&menu_file);
            match contents {
                Ok(contents) => {
                    for line in contents.lines() {
                        let mut line = line.to_owned();
                        line += "\r\n";
                        line = line
                                .replace("$ADDRESS$", ipaddr.as_ref()) // IP replacement
                                .replace("\\t", "\t"); // More convenient than inserting tabs manually.
                        client.write(line.as_bytes());
                    }
                    client.write(b".");
                }
                Err(_) => {
                    client.write(b"iFailed to read gophermenu for this directory.\r\n.");
                    client.write(&format!("1Return home\t/\t{}\t70\r\n.", ipaddr).as_bytes());
                }
            }
        } else {
            client.write(b"iNo content.\r\n");
            client.write(&format!("1Return home\t/\t{}\t70\r\n.", ipaddr).as_bytes());
        }
    }
}

fn read_file<P: AsRef<Path>>(path: P) -> Result<String, std::io::Error> {
    let file = File::open(path)?;
    let mut reader = BufReader::new(file);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    Ok(contents)
}
<commit_msg>Fixed missing line ending for client bound message.<commit_after>#![allow(unused_must_use)]
use std::net::{TcpStream, TcpListener};
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::{Read, Write, BufReader};
use std::thread;
use std::env;

fn main() {
    let ipaddr = match env::args().nth(1) {
        Some(ipaddr) => ipaddr,
        None => {
            eprintln!("Missing IP address to bind to.");
            return;
        }
    };
    let directory = match env::args().nth(2) {
        Some(dir) => dir,
        None => ".".to_owned(),
    };
    let address = &format!("{}:70", ipaddr);
    let server = match TcpListener::bind(address) {
        Ok(server) => server,
        Err(_) => {
            eprintln!("Failed to start server.");
            return;
        }
    };
    println!("argoserv listening on {}:70", ipaddr);

    for client in server.incoming() {
        match client {
            Ok(client) => {
                let addr = ipaddr.clone();
                let dir = directory.clone();
                thread::spawn(move || { handle(client, addr, dir); });
            }
            Err(e) => eprintln!("ERROR : {:?}", e),
        }
    }
}

fn handle(mut client: TcpStream, ipaddr: String, directory: String) {
    let client_ip = client.peer_addr().unwrap().ip();

    let mut buffer = [0; 1024];
    let read = client.read(&mut buffer);
    let mut selector = match read {
        Ok(n) => {
            let mut wordbuf = String::new();
            let mut index = 0;
            'outer: while index < n {
                wordbuf.push(buffer[index] as char);
                if index + 2 < buffer.len() {
                    //If the next two bytes are \r\n, we're done parsing the selector.
                    if buffer[index + 1] == 0x0d && buffer[index + 2] == 0x0a {
                        break 'outer;
                    }
                }
                index += 1;
            }
            wordbuf
        }
        Err(e) => {
            eprintln!("READ ERROR {} <- {}", e, client_ip);
            return;
        }
    };
    println!("LIST '{}' -> {}", selector, client_ip);
    // Prepend a "." to the selector to keep us in the working directory of the server
    if selector == "/" {
        selector = ".".to_owned();
    } else if selector.starts_with("/") {
        selector = ".".to_owned() + &selector;
    }

    let _selector = selector.clone();
    let home = Path::new(&directory); //The home directory of the server
    let mut dest = Path::new(&directory).to_path_buf();
    dest.push(_selector);
    let mut dest = dest.as_path();

    let canonical_path = dest.canonicalize().unwrap_or(PathBuf::new());
    let canonical_cwd = home.canonicalize().unwrap_or(PathBuf::new());
    if !dest.exists() {
        client.write(b"iNo content.\r\n");
        client.write(&format!("1Return home\t/\t{}\t70\r\n.", ipaddr).as_bytes());
        return;
    } else if !canonical_path.starts_with(canonical_cwd) {
        dest = Path::new(&directory);
    }

    //Serve the client
    if dest.is_file() {
        //Send the data of this file.
        let mut file = File::open(dest).unwrap();
        let mut buffer = vec![];
        match file.read_to_end(&mut buffer) {
            Ok(_) => (),
            Err(e) => {
                eprintln!("READ FILE ERROR : {} -> {}", e, client_ip);
                client.write(b"Error reading requested file.\r\n.");
                return;
            }
        }
        match client.write_all(&buffer) {
            Ok(_) => println!("SEND '{}' -> {}", selector, client_ip),
            Err(e) => eprintln!("SEND FILE ERROR: {} -> {}", e, client_ip),
        }
    } else {
        let mut menu_file = dest.to_path_buf();
        menu_file.push("index.gph");
        let menu_file = menu_file.as_path();
        if menu_file.exists() {
            let contents = read_file(&menu_file);
            match contents {
                Ok(contents) => {
                    for line in contents.lines() {
                        let mut line = line.to_owned();
                        line += "\r\n";
                        line = line
                                .replace("$ADDRESS$", ipaddr.as_ref()) // IP replacement
                                .replace("\\t", "\t"); // More convenient than inserting tabs manually.
                        client.write(line.as_bytes());
                    }
                    client.write(b".");
                }
                Err(_) => {
                    client.write(b"iFailed to read gophermenu for this directory.\r\n.");
                    client.write(&format!("1Return home\t/\t{}\t70\r\n.", ipaddr).as_bytes());
                }
            }
        } else {
            client.write(b"iNo content.\r\n");
            client.write(&format!("1Return home\t/\t{}\t70\r\n.", ipaddr).as_bytes());
        }
    }
}

fn read_file<P: AsRef<Path>>(path: P) -> Result<String, std::io::Error> {
    let file = File::open(path)?;
    let mut reader = BufReader::new(file);
    let mut contents = String::new();
    reader.read_to_string(&mut contents);
    Ok(contents)
}
<|endoftext|>


<commit_before>// Copyright © 2014, Peter Atashian

#![feature(slicing_syntax, tuple_indexing)]

extern crate core;
extern crate image;
extern crate lodepng;
extern crate serialize;

use core::slice::{Found, NotFound};
use serialize::json::{decode};
use std::cell::{Cell};
use std::cmp::{max};
use std::collections::{PriorityQueue};
use std::io::{File};
use std::iter::{AdditiveIterator};
use std::num::{Zero};

#[deriving(Show, Clone)]
struct TermColor(Pixel, u8);
impl PartialEq for TermColor {
    fn eq(&self, o: &TermColor) -> bool {
        self.0 == o.0
    }
}

#[deriving(Show)]
struct Coverage(char, f32);
impl PartialEq for Coverage {
    fn eq(&self, o: &Coverage) -> bool {
        self.1 == o.1
    }
}

#[deriving(Show, PartialEq, PartialOrd, Clone)]
struct Pixel(f32, f32, f32);
impl Pixel {
    fn gray(&self) -> f32 {
        (self.0 + self.1 + self.2) / 3.
    }
    fn abs(&self) -> Pixel {
        Pixel(self.0.abs(), self.1.abs(), self.2.abs())
    }
    fn sqsum(&self) -> f32 {
        self.0 * self.0 + self.1 * self.1 + self.2 * self.2
    }
    fn magnitude(&self) -> f32 {
        self.sqsum().sqrt()
    }
    fn dot(&self, o: &Pixel) -> f32 {
        self.0 * o.0 + self.1 * o.1 + self.2 * o.2
    }
}
impl Add<Pixel, Pixel> for Pixel {
    fn add(&self, o: &Pixel) -> Pixel {
        Pixel(self.0 + o.0, self.1 + o.1, self.2 + o.2)
    }
}
impl Sub<Pixel, Pixel> for Pixel {
    fn sub(&self, o: &Pixel) -> Pixel {
        Pixel(self.0 - o.0, self.1 - o.1, self.2 - o.2)
    }
}
impl Zero for Pixel {
    fn zero() -> Pixel {
        Pixel(0., 0., 0.)
    }
    fn is_zero(&self) -> bool {
        *self == Zero::zero()
    }
}
impl Mul<Pixel, Pixel> for Pixel {
    fn mul(&self, o: &Pixel) -> Pixel {
        Pixel(self.0 * o.0, self.1 * o.1, self.2 * o.2)
    }
}
impl Div<Pixel, Pixel> for Pixel {
    fn div(&self, o: &Pixel) -> Pixel {
        Pixel(self.0 / o.0, self.1 / o.1, self.2 / o.2)
    }
}

#[deriving(Show)]
struct Image {
    pixels: Vec<Cell<Pixel>>,
    width: u32,
    height: u32,
}
impl Image {
    fn get(&self, x: u32, y: u32) -> Pixel {
        self.pixels[(y * self.width + x) as uint].get()
    }
    fn resize(&self, width: u32, height: u32) -> Image {
        let (rw, rh) = (self.width as f32 / (width as f32), self.height as f32 / (height as f32));
        let mut pixels = Vec::with_capacity((width * height) as uint);
        for y in range(0, height) {
            for x in range(0, width) {
                let (x1, x2) = ((x as f32 * rw) as u32, ((x + 1) as f32 * rw) as u32);
                let (y1, y2) = ((y as f32 * rh) as u32, ((y + 1) as f32 * rh) as u32);
                let (x2, y2) = (max(x2, x1 + 1), max(y2, y1 + 1));
                let c = range(x1, x2).map(|x| {
                    range(y1, y2).map(|y| {
                        self.get(x, y)
                    }).sum()
                }).sum();
                let m = 1. / (((x2 - x1) * (y2 - y1)) as f32);
                pixels.push(Cell::new(c * Pixel(m, m, m)));
            }
        }
        assert!(pixels.len() as u32 == width * height);
        Image {
            pixels: pixels,
            width: width,
            height: height,
        }
    }
}

#[deriving(Decodable, Show)]
struct Config {
    winwidth: u32,
    winheight: u32,
    charwidth: u32,
    charheight: u32,
    offsetx: u32,
    offsety: u32,
    chars: String,
    fullcolor: bool,
}
impl Config {
    fn load() -> Config {
        let mut file = File::open(&Path::new("config.json")).unwrap();
        let data = file.read_to_string().unwrap();
        decode(data.as_slice()).unwrap()
    }
}

#[deriving(Show)]
struct Ascii {
    config: Config,
    table: Vec<f32>,
    colors: Vec<TermColor>,
    chars: Vec<Coverage>,
}
impl Ascii {
    fn new() -> Ascii {
        let config = Config::load();
        Ascii {
            config: config,
            table: Vec::new(),
            colors: Vec::new(),
            chars: Vec::new(),
        }
    }
    #[allow(dead_code)]
    fn print_chars(&self) {
        for x in range(0u16, 256) {
            bg(x as u8);
            print!(" ");
        }
        println!("");
        fg(15);
        bg(0);
        println!("{}", self.config.chars);
        let lines = 256 / self.config.winwidth;
        let lines = lines + self.config.chars[].chars().count() as u32 / self.config.winwidth;
        for _ in range(lines + 5, self.config.winheight) {
            println!("");
        }
    }
    fn build_table(&mut self) {
        fn decode(x: f32) -> f32 {
            if x <= 0.04045 {
                x / 12.92
            } else {
                ((x + 0.055) / (1. + 0.055)).powf(2.4)
            }
        }
        self.table = range(0u32, 256).map(|x| decode(x as f32 * (1. / 255.))).collect();
    }
    fn load(&self, p: &Path) -> Image {
        use image::GenericImage;
        assert!(self.table.len() == 256);
        let img = match lodepng::load(p) {
            Ok(x) => x,
            Err(_) => image::open(p).unwrap().to_rgba(),
        };
        let (w, h) = img.dimensions();
        let pixels = img.into_vec();
        let pixels = pixels.iter().map(|p| {
            let (&r, &g, &b, &a) = unsafe {(
                self.table[].unsafe_get(p.0 as uint),
                self.table[].unsafe_get(p.1 as uint),
                self.table[].unsafe_get(p.2 as uint),
                self.table[].unsafe_get(p.3 as uint),
            )};
            Cell::new(Pixel(r * a, g * a, b * a))
        }).collect();
        Image {
            pixels: pixels,
            width: w,
            height: h,
        }
    }
    fn calc_colors(&mut self) {
        let img = self.load(&Path::new("colors.png"));
        self.colors = range(0u32, if self.config.fullcolor { 256 } else { 16 }).map(|i| {
            let x = i % self.config.winwidth * self.config.charwidth + self.config.offsetx;
            let y = i / self.config.winwidth * self.config.charheight + self.config.offsety;
            TermColor(img.get(x, y), i as u8)
        }).collect();
        let offset = (256 / self.config.winwidth + 1) * self.config.charheight
            + self.config.offsety;
        let (lo, hi) = (self.colors[0].0.gray(), self.colors[15].0.gray());
        self.chars = self.config.chars[].chars().enumerate().map(|(i, c)| {
            let x = i as u32 % self.config.winwidth * self.config.charwidth + self.config.offsetx;
            let y = i as u32 / self.config.winwidth * self.config.charheight + offset;
            let p = range(x, x + self.config.charwidth).map(|x| {
                range(y, y + self.config.charheight).map(|y| {
                    img.get(x, y).gray()
                }).sum()
            }).sum() / (self.config.charwidth * self.config.charheight) as f32;
            Coverage(c, (p - lo) / (hi - lo))
        }).collect();
        self.colors.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
        self.colors.dedup();
        self.chars.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
        self.chars.dedup();
        self.chars.retain(|x| x.1 <= 0.5);
    }
    fn prepare(&mut self) {
        self.build_table();
        self.calc_colors();
    }
    fn fit_window(&self, img: &Image) -> Image {
        let (ww, wh) = (self.config.winwidth - 1, self.config.winheight - 3);
        let (cw, ch) = (self.config.charwidth, self.config.charheight);
        let fw = (cw * ww) as f32;
        let fh = (ch * wh) as f32;
        let ratio = fh / fw;
        let imgratio = img.height as f32 / img.width as f32;
        if ratio > imgratio {
            let h = (fw * imgratio / ch as f32) as u32;
            img.resize(ww, h)
        } else {
            let w = (fh / imgratio / cw as f32) as u32;
            img.resize(w, wh)
        }
    }
    fn get_closest(&self, p: &Pixel) -> Vec<TermColor> {
        struct Entry(Pixel, u8, f32);
        impl Ord for Entry {
            fn cmp(&self, o: &Entry) -> Ordering {
                self.partial_cmp(o).unwrap()
            }
        }
        impl PartialOrd for Entry {
            fn partial_cmp(&self, o: &Entry) -> Option<Ordering> {
                self.2.partial_cmp(&o.2).map(|x| x.reverse())
            }
        }
        impl Eq for Entry {}
        impl PartialEq for Entry {
            fn eq(&self, o: &Entry) -> bool {
                self.2 == o.2
            }
        }
        if self.config.fullcolor {
            let mut colors: PriorityQueue<_> = self.colors.iter().map(|c| {
                let d = (c.0 - *p).abs().gray();
                Entry(c.0, c.1, d)
            }).collect();
            range(0, 20u).map(|_| {
                let e = colors.pop().unwrap();
                TermColor(e.0, e.1)
            }).collect()
        } else {
            self.colors.clone()
        }
    }
    fn closest(&self, p: &Pixel) -> (u8, u8, char, Pixel) {
        let colors = self.get_closest(p);
        let mut bestdiff = 100f32;
        let mut best = (0, colors[0].1, ' ', p - colors[0].0);
        for c1 in colors.iter() {
            for c2 in colors.iter() {
                let (v1, v2) = (p - c1.0, c2.0 - c1.0);
                let cover = if v2.abs().gray() < 0.0001 {
                    0.
                } else {
                    v1.dot(&v2) / v2.sqsum()
                };
                if cover < 0. || cover > 0.5 { continue }
                let Coverage(ch, n) = match self.chars[].binary_search(|x| {
                    x.1.partial_cmp(&cover).unwrap()
                }) {
                    Found(x) => self.chars[x],
                    NotFound(x) => self.chars[x - 1],
                };
                let color = c1.0 * Pixel(1. - n, 1. - n, 1. - n) + c2.0 * Pixel(n, n, n);
                let diff = *p - color;
                let sdiff = c2.0 - c1.0;
                let d = diff.abs().magnitude() + sdiff.abs().magnitude() * 0.2;
                if d < bestdiff {
                    bestdiff = d;
                    best = (c2.1, c1.1, ch, diff);
                }
            }
        }
        best
    }
    fn convert(&self, p: &Path) {
        let img = self.load(p);
        let mut img = self.fit_window(&img);
        let width = img.width;
        img.pixels.reserve_additional(width as uint * 2);
        let pixels = img.pixels[];
        for (y, chunk) in pixels.chunks(img.width as uint).enumerate() {
            for (x, p) in chunk.iter().enumerate() {
                let (f, b, c, diff) = self.closest(&p.get());
                let adjust = |ox, oy, mult| {
                    let cell = unsafe { pixels.unsafe_get((y + oy) * (width as uint) + x + ox) };
                    cell.set(cell.get() + diff * Pixel(mult, mult, mult));
                };
                adjust( 1, 0, 5. / 32.);
                adjust( 2, 0, 3. / 32.);
                adjust( 2, 1, 2. / 32.);
                adjust(-1, 1, 4. / 32.);
                adjust(-0, 1, 5. / 32.);
                adjust( 1, 1, 4. / 32.);
                adjust( 2, 1, 2. / 32.);
                adjust(-1, 2, 2. / 32.);
                adjust( 0, 2, 3. / 32.);
                adjust( 1, 2, 2. / 32.);
                fg(f);
                bg(b);
                print!("{}", c);
            }
            bg(0);
            println!("");
        }
    }
}

fn fg(x: u8) {
    print!("\x1b[38;5;{}m", x);
}
fn bg(x: u8) {
    print!("\x1b[48;5;{}m", x);
}

fn main() {
    let mut ascii = Ascii::new();
    let args = std::os::args();
    if args.len() <= 1 {
        ascii.print_chars();
    } else {
        ascii.prepare();
        ascii.convert(&Path::new(args[1][]));
    }
}
<commit_msg>Optimize fg/bg changing for slow terminals<commit_after>// Copyright © 2014, Peter Atashian

#![feature(slicing_syntax, tuple_indexing)]

extern crate core;
extern crate image;
extern crate lodepng;
extern crate serialize;

use core::slice::{Found, NotFound};
use serialize::json::{decode};
use std::cell::{Cell};
use std::cmp::{max};
use std::collections::{PriorityQueue};
use std::io::{File};
use std::iter::{AdditiveIterator};
use std::num::{Zero};

#[deriving(Show, Clone)]
struct TermColor(Pixel, u8);
impl PartialEq for TermColor {
    fn eq(&self, o: &TermColor) -> bool {
        self.0 == o.0
    }
}

#[deriving(Show)]
struct Coverage(char, f32);
impl PartialEq for Coverage {
    fn eq(&self, o: &Coverage) -> bool {
        self.1 == o.1
    }
}

#[deriving(Show, PartialEq, PartialOrd, Clone)]
struct Pixel(f32, f32, f32);
impl Pixel {
    fn gray(&self) -> f32 {
        (self.0 + self.1 + self.2) / 3.
    }
    fn abs(&self) -> Pixel {
        Pixel(self.0.abs(), self.1.abs(), self.2.abs())
    }
    fn sqsum(&self) -> f32 {
        self.0 * self.0 + self.1 * self.1 + self.2 * self.2
    }
    fn magnitude(&self) -> f32 {
        self.sqsum().sqrt()
    }
    fn dot(&self, o: &Pixel) -> f32 {
        self.0 * o.0 + self.1 * o.1 + self.2 * o.2
    }
}
impl Add<Pixel, Pixel> for Pixel {
    fn add(&self, o: &Pixel) -> Pixel {
        Pixel(self.0 + o.0, self.1 + o.1, self.2 + o.2)
    }
}
impl Sub<Pixel, Pixel> for Pixel {
    fn sub(&self, o: &Pixel) -> Pixel {
        Pixel(self.0 - o.0, self.1 - o.1, self.2 - o.2)
    }
}
impl Zero for Pixel {
    fn zero() -> Pixel {
        Pixel(0., 0., 0.)
    }
    fn is_zero(&self) -> bool {
        *self == Zero::zero()
    }
}
impl Mul<Pixel, Pixel> for Pixel {
    fn mul(&self, o: &Pixel) -> Pixel {
        Pixel(self.0 * o.0, self.1 * o.1, self.2 * o.2)
    }
}
impl Div<Pixel, Pixel> for Pixel {
    fn div(&self, o: &Pixel) -> Pixel {
        Pixel(self.0 / o.0, self.1 / o.1, self.2 / o.2)
    }
}

#[deriving(Show)]
struct Image {
    pixels: Vec<Cell<Pixel>>,
    width: u32,
    height: u32,
}
impl Image {
    fn get(&self, x: u32, y: u32) -> Pixel {
        self.pixels[(y * self.width + x) as uint].get()
    }
    fn resize(&self, width: u32, height: u32) -> Image {
        let (rw, rh) = (self.width as f32 / (width as f32), self.height as f32 / (height as f32));
        let mut pixels = Vec::with_capacity((width * height) as uint);
        for y in range(0, height) {
            for x in range(0, width) {
                let (x1, x2) = ((x as f32 * rw) as u32, ((x + 1) as f32 * rw) as u32);
                let (y1, y2) = ((y as f32 * rh) as u32, ((y + 1) as f32 * rh) as u32);
                let (x2, y2) = (max(x2, x1 + 1), max(y2, y1 + 1));
                let c = range(x1, x2).map(|x| {
                    range(y1, y2).map(|y| {
                        self.get(x, y)
                    }).sum()
                }).sum();
                let m = 1. / (((x2 - x1) * (y2 - y1)) as f32);
                pixels.push(Cell::new(c * Pixel(m, m, m)));
            }
        }
        assert!(pixels.len() as u32 == width * height);
        Image {
            pixels: pixels,
            width: width,
            height: height,
        }
    }
}

#[deriving(Decodable, Show)]
struct Config {
    winwidth: u32,
    winheight: u32,
    charwidth: u32,
    charheight: u32,
    offsetx: u32,
    offsety: u32,
    chars: String,
    fullcolor: bool,
}
impl Config {
    fn load() -> Config {
        let mut file = File::open(&Path::new("config.json")).unwrap();
        let data = file.read_to_string().unwrap();
        decode(data.as_slice()).unwrap()
    }
}

#[deriving(Show)]
struct Ascii {
    config: Config,
    table: Vec<f32>,
    colors: Vec<TermColor>,
    chars: Vec<Coverage>,
}
impl Ascii {
    fn new() -> Ascii {
        let config = Config::load();
        Ascii {
            config: config,
            table: Vec::new(),
            colors: Vec::new(),
            chars: Vec::new(),
        }
    }
    #[allow(dead_code)]
    fn print_chars(&self) {
        for x in range(0u16, 256) {
            bg(x as u8);
            print!(" ");
        }
        println!("");
        fg(15);
        bg(0);
        println!("{}", self.config.chars);
        let lines = 256 / self.config.winwidth;
        let lines = lines + self.config.chars[].chars().count() as u32 / self.config.winwidth;
        for _ in range(lines + 5, self.config.winheight) {
            println!("");
        }
    }
    fn build_table(&mut self) {
        fn decode(x: f32) -> f32 {
            if x <= 0.04045 {
                x / 12.92
            } else {
                ((x + 0.055) / (1. + 0.055)).powf(2.4)
            }
        }
        self.table = range(0u32, 256).map(|x| decode(x as f32 * (1. / 255.))).collect();
    }
    fn load(&self, p: &Path) -> Image {
        use image::GenericImage;
        assert!(self.table.len() == 256);
        let img = match lodepng::load(p) {
            Ok(x) => x,
            Err(_) => image::open(p).unwrap().to_rgba(),
        };
        let (w, h) = img.dimensions();
        let pixels = img.into_vec();
        let pixels = pixels.iter().map(|p| {
            let (&r, &g, &b, &a) = unsafe {(
                self.table[].unsafe_get(p.0 as uint),
                self.table[].unsafe_get(p.1 as uint),
                self.table[].unsafe_get(p.2 as uint),
                self.table[].unsafe_get(p.3 as uint),
            )};
            Cell::new(Pixel(r * a, g * a, b * a))
        }).collect();
        Image {
            pixels: pixels,
            width: w,
            height: h,
        }
    }
    fn calc_colors(&mut self) {
        let img = self.load(&Path::new("colors.png"));
        self.colors = range(0u32, if self.config.fullcolor { 256 } else { 16 }).map(|i| {
            let x = i % self.config.winwidth * self.config.charwidth + self.config.offsetx;
            let y = i / self.config.winwidth * self.config.charheight + self.config.offsety;
            TermColor(img.get(x, y), i as u8)
        }).collect();
        let offset = (256 / self.config.winwidth + 1) * self.config.charheight
            + self.config.offsety;
        let (lo, hi) = (self.colors[0].0.gray(), self.colors[15].0.gray());
        self.chars = self.config.chars[].chars().enumerate().map(|(i, c)| {
            let x = i as u32 % self.config.winwidth * self.config.charwidth + self.config.offsetx;
            let y = i as u32 / self.config.winwidth * self.config.charheight + offset;
            let p = range(x, x + self.config.charwidth).map(|x| {
                range(y, y + self.config.charheight).map(|y| {
                    img.get(x, y).gray()
                }).sum()
            }).sum() / (self.config.charwidth * self.config.charheight) as f32;
            Coverage(c, (p - lo) / (hi - lo))
        }).collect();
        self.colors.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
        self.colors.dedup();
        self.chars.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
        self.chars.dedup();
        self.chars.retain(|x| x.1 <= 0.5);
    }
    fn prepare(&mut self) {
        self.build_table();
        self.calc_colors();
    }
    fn fit_window(&self, img: &Image) -> Image {
        let (ww, wh) = (self.config.winwidth - 1, self.config.winheight - 3);
        let (cw, ch) = (self.config.charwidth, self.config.charheight);
        let fw = (cw * ww) as f32;
        let fh = (ch * wh) as f32;
        let ratio = fh / fw;
        let imgratio = img.height as f32 / img.width as f32;
        if ratio > imgratio {
            let h = (fw * imgratio / ch as f32) as u32;
            img.resize(ww, h)
        } else {
            let w = (fh / imgratio / cw as f32) as u32;
            img.resize(w, wh)
        }
    }
    fn get_closest(&self, p: &Pixel) -> Vec<TermColor> {
        struct Entry(Pixel, u8, f32);
        impl Ord for Entry {
            fn cmp(&self, o: &Entry) -> Ordering {
                self.partial_cmp(o).unwrap()
            }
        }
        impl PartialOrd for Entry {
            fn partial_cmp(&self, o: &Entry) -> Option<Ordering> {
                self.2.partial_cmp(&o.2).map(|x| x.reverse())
            }
        }
        impl Eq for Entry {}
        impl PartialEq for Entry {
            fn eq(&self, o: &Entry) -> bool {
                self.2 == o.2
            }
        }
        if self.config.fullcolor {
            let mut colors: PriorityQueue<_> = self.colors.iter().map(|c| {
                let d = (c.0 - *p).abs().gray();
                Entry(c.0, c.1, d)
            }).collect();
            range(0, 20u).map(|_| {
                let e = colors.pop().unwrap();
                TermColor(e.0, e.1)
            }).collect()
        } else {
            self.colors.clone()
        }
    }
    fn closest(&self, p: &Pixel) -> (u8, u8, char, Pixel) {
        let colors = self.get_closest(p);
        let mut bestdiff = 100f32;
        let mut best = (0, colors[0].1, ' ', p - colors[0].0);
        for c1 in colors.iter() {
            for c2 in colors.iter() {
                let (v1, v2) = (p - c1.0, c2.0 - c1.0);
                let cover = if v2.abs().gray() < 0.0001 {
                    0.
                } else {
                    v1.dot(&v2) / v2.sqsum()
                };
                if cover < 0. || cover > 0.5 { continue }
                let Coverage(ch, n) = match self.chars[].binary_search(|x| {
                    x.1.partial_cmp(&cover).unwrap()
                }) {
                    Found(x) => self.chars[x],
                    NotFound(x) => self.chars[x - 1],
                };
                let color = c1.0 * Pixel(1. - n, 1. - n, 1. - n) + c2.0 * Pixel(n, n, n);
                let diff = *p - color;
                let sdiff = c2.0 - c1.0;
                let d = diff.abs().magnitude() + sdiff.abs().magnitude() * 0.2;
                if d < bestdiff {
                    bestdiff = d;
                    best = (c2.1, c1.1, ch, diff);
                }
            }
        }
        best
    }
    fn convert(&self, p: &Path) {
        let img = self.load(p);
        let mut img = self.fit_window(&img);
        let width = img.width;
        img.pixels.reserve_additional(width as uint * 2);
        let pixels = img.pixels[];
        let mut fg = 15;
        let mut bg = 0;
        let set = |f: u8, b: u8| {
            if f == fg && b == bg { return }
            if f == fg {
                print!("\x1b[48;5;{}m", b);
            } else if b == bg {
                print!("\x1b[38;5;{}m", f);
            } else {
                print!("\x1b[38;5;{};48;5;{}m", f, b);
            }
            fg = f;
            bg = b;
        };
        for (y, chunk) in pixels.chunks(img.width as uint).enumerate() {
            for (x, p) in chunk.iter().enumerate() {
                let (f, b, c, diff) = self.closest(&p.get());
                let adjust = |ox, oy, mult| {
                    let cell = unsafe { pixels.unsafe_get((y + oy) * (width as uint) + x + ox) };
                    cell.set(cell.get() + diff * Pixel(mult, mult, mult));
                };
                adjust( 1, 0, 5. / 32.);
                adjust( 2, 0, 3. / 32.);
                adjust( 2, 1, 2. / 32.);
                adjust(-1, 1, 4. / 32.);
                adjust(-0, 1, 5. / 32.);
                adjust( 1, 1, 4. / 32.);
                adjust( 2, 1, 2. / 32.);
                adjust(-1, 2, 2. / 32.);
                adjust( 0, 2, 3. / 32.);
                adjust( 1, 2, 2. / 32.);
                set(f, b);
                print!("{}", c);
            }
            set(15, 0);
            println!("");
        }
    }
}

fn fg(x: u8) {
    print!("\x1b[38;5;{}m", x);
}
fn bg(x: u8) {
    print!("\x1b[48;5;{}m", x);
}

fn main() {
    let mut ascii = Ascii::new();
    let args = std::os::args();
    if args.len() <= 1 {
        ascii.print_chars();
    } else {
        ascii.prepare();
        ascii.convert(&Path::new(args[1][]));
    }
}
<|endoftext|>


<commit_before>use std::env;

fn main() {
    let arguments = env::args().collect::<Vec<_>>();

    match arguments.len() {
        1 => { loop { println!("y") } },
        _ => { loop { println!("{}", arguments[1]) } },
    }
}
<commit_msg>remove unnecessary scope<commit_after>use std::env;

fn main() {
    let arguments = env::args().collect::<Vec<_>>();

    match arguments.len() {
        1 => loop { println!("y") },
        _ => loop { println!("{}", arguments[1]) },
    }
}
<|endoftext|>


<commit_before>extern crate john;

#[cfg(not(test))]
fn main() {
    john::Server::new(3100).start()
}
<commit_msg>support PORT for heroku<commit_after>extern crate john;

use std::os::getenv;
use std::io::net::ip::Port;

#[cfg(not(test))]
/// Look up our server port number in PORT, for compatibility with Heroku.
fn get_server_port() -> Port {
    getenv("PORT")
        .and_then(|s| from_str::<Port>(s.as_slice()))
        .unwrap_or(3000)
}

#[cfg(not(test))]
fn main() {
    john::Server::new(get_server_port()).start()
}
<|endoftext|>


<commit_before>// Worklog is for recording your hours.
//

extern crate chrono;
extern crate csv;
extern crate clap;
extern crate rustc_serialize;

mod error;
mod timeclock;
mod util;

use chrono::*;
use clap::{Arg, ArgGroup, App};
use error::WorklogError;
use std::env;
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::path::PathBuf;
use timeclock::Direction;
use timeclock::now;

#[cfg(target_family = "unix")]
static CSV_FILE_NAME: &'static str = ".worklog.csv";
#[cfg(target_family = "windows")]
static CSV_FILE_NAME: &'static str = "worklog.csv";

// TODO This belongs in a config file somewhere
const WEEKSTART: i64 = Weekday::Sat as i64;

fn print_csv_entries<R: Read>(file: R) -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    for rec in csv_entries {
        println!("{}", rec);
    }
    Ok(())
}

fn print_full_summary<R: Read>(file: R,
                               rounding: util::Rounding)
                               -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    let records = timeclock::collect_date_records(csv_entries);

    let mut total_hours: f64 = 0.0;
    for rec in records {
        let hours = util::round(rec.seconds(), rounding) / 3600.0;
        total_hours += hours;
        println!("{} {:.2} {}", rec.date().format("%F"), hours, rec.memo());
    }

    println!("Total Hours: {:.2}", total_hours);
    Ok(())
}

fn print_short_summary<R: Read>(file: R,
                                since: Date<FixedOffset>,
                                rounding: util::Rounding)
                                -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    let records = timeclock::collect_date_records(csv_entries);

    let mut total_hours: f64 = 0.0;
    for rec in records {
        if rec.date() >= since {
            let hours = util::round(rec.seconds(), rounding) / 3600.0;
            total_hours += hours;
            println!("{} {:.2} {}", rec.date().format("%F"), hours, rec.memo());
        }
    }

    println!("Total Hours: {:.2}", total_hours);
    Ok(())
}

/// Get the path for the csv data file
fn get_csv_path() -> Result<PathBuf, WorklogError> {
    let mut data_path = match env::home_dir() {
        Some(path) => path,
        None => {
            return Err(env::VarError::NotPresent).map_err(WorklogError::Env)
        }
    };

    data_path.push(CSV_FILE_NAME);
    Ok(data_path)
}

fn main0() -> Result<(), WorklogError> {
    // Using std env macro rather than depending on clap's. No difference
    // as far as I can tell.
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .arg(Arg::from_usage("[in] -i, --in 'Record an In entry'"))
        .arg(Arg::from_usage("[out] -o, --out 'Record an Out entry'"))
        .arg(Arg::from_usage("[time] -t, --time <TIME> 'time'")
            .requires("inout"))
        .arg(Arg::from_usage("[memo] -m, --memo <MEMO> 'Memo for the entry'")
            .requires("inout"))
        .arg(Arg::from_usage("[summary] -s, --summary 'Print a summary'")
            .conflicts_with("inout"))
        .arg(Arg::from_usage("[log] -l, --log 'Print the full log'")
            .conflicts_with("inout"))
        .arg(Arg::from_usage("[round] -r, --round 'Round totals up to the next quarter hour'")
            .conflicts_with("inout"))
        .group(ArgGroup::with_name("inout").args(&["in", "out"]))
        .get_matches();

    let csv_path = try!(get_csv_path());

    let mut csv_file = try!(OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(csv_path));

    let rounding = {
        if matches.is_present("round") {
            // round up in 15min intervals
            util::Rounding::Up(900.0)
        } else {
            util::Rounding::None
        }
    };

    if matches.is_present("in") || matches.is_present("out") {
        let dir = if matches.is_present("in") {
            Direction::In
        } else {
            Direction::Out
        };

        let time = matches.value_of("time").unwrap_or("now");
        let time = try!(util::parse_multi_time_fmt(&time));

        let memo = matches.value_of("memo").unwrap_or("").to_owned();
        timeclock::mark_time(dir, time, memo, &mut csv_file);

        println!("Clocked {:#} at {}", dir, time.format("%F %I:%M %P"));

    } else if matches.is_present("summary") {
        try!(print_full_summary(&csv_file, rounding));

    } else if matches.is_present("log") {
        try!(print_csv_entries(&csv_file));

    } else {
        let today = now().date();
        let weekday = today.weekday() as i64;
        let days_back = (7 - WEEKSTART + weekday) % 7;
        let start_date = today - Duration::days(days_back);
        try!(print_short_summary(&csv_file, start_date, rounding));
    }

    Ok(())
}

fn main() {
    match main0() {
        Ok(_) => {}
        Err(err) => {
            let _ = writeln!(&mut std::io::stderr(), "Error: {}", err);
        }
    };
}
<commit_msg>Added end_date arg to print_short_summary<commit_after>// Worklog is for recording your hours.
//

extern crate chrono;
extern crate csv;
extern crate clap;
extern crate rustc_serialize;

mod error;
mod timeclock;
mod util;

use chrono::*;
use clap::{Arg, ArgGroup, App};
use error::WorklogError;
use std::env;
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::path::PathBuf;
use timeclock::Direction;
use timeclock::now;

#[cfg(target_family = "unix")]
static CSV_FILE_NAME: &'static str = ".worklog.csv";
#[cfg(target_family = "windows")]
static CSV_FILE_NAME: &'static str = "worklog.csv";

// TODO This belongs in a config file somewhere
const WEEKSTART: i64 = Weekday::Sat as i64;

fn print_csv_entries<R: Read>(file: R) -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    for rec in csv_entries {
        println!("{}", rec);
    }
    Ok(())
}

fn print_full_summary<R: Read>(file: R,
                               rounding: util::Rounding)
                               -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    let records = timeclock::collect_date_records(csv_entries);

    let mut total_hours: f64 = 0.0;
    for rec in records {
        let hours = util::round(rec.seconds(), rounding) / 3600.0;
        total_hours += hours;
        println!("{} {:.2} {}", rec.date().format("%F"), hours, rec.memo());
    }

    println!("Total Hours: {:.2}", total_hours);
    Ok(())
}

fn print_short_summary<R: Read>(file: R,
                                start_date: Date<FixedOffset>,
                                end_date: Date<FixedOffset>,
                                rounding: util::Rounding)
                                -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    let records = timeclock::collect_date_records(csv_entries);

    let mut total_hours: f64 = 0.0;
    for rec in records {
        if start_date <= rec.date() && rec.date() <= end_date {
            let hours = util::round(rec.seconds(), rounding) / 3600.0;
            total_hours += hours;
            println!("{} {:.2} {}", rec.date().format("%F"), hours, rec.memo());
        }
    }

    println!("Total Hours: {:.2}", total_hours);
    Ok(())
}

/// Get the path for the csv data file
fn get_csv_path() -> Result<PathBuf, WorklogError> {
    let mut data_path = match env::home_dir() {
        Some(path) => path,
        None => {
            return Err(env::VarError::NotPresent).map_err(WorklogError::Env)
        }
    };

    data_path.push(CSV_FILE_NAME);
    Ok(data_path)
}

fn main0() -> Result<(), WorklogError> {
    // Using std env macro rather than depending on clap's. No difference
    // as far as I can tell.
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .arg(Arg::from_usage("[in] -i, --in 'Record an In entry'"))
        .arg(Arg::from_usage("[out] -o, --out 'Record an Out entry'"))
        .arg(Arg::from_usage("[time] -t, --time <TIME> 'time'")
            .requires("inout"))
        .arg(Arg::from_usage("[memo] -m, --memo <MEMO> 'Memo for the entry'")
            .requires("inout"))
        .arg(Arg::from_usage("[summary] -s, --summary 'Print a summary'")
            .conflicts_with("inout"))
        .arg(Arg::from_usage("[log] -l, --log 'Print the full log'")
            .conflicts_with("inout"))
        .arg(Arg::from_usage("[round] -r, --round 'Round totals up to the next quarter hour'")
            .conflicts_with("inout"))
        .group(ArgGroup::with_name("inout").args(&["in", "out"]))
        .get_matches();

    let csv_path = try!(get_csv_path());

    let mut csv_file = try!(OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(csv_path));

    let rounding = {
        if matches.is_present("round") {
            // round up in 15min intervals
            util::Rounding::Up(900.0)
        } else {
            util::Rounding::None
        }
    };

    if matches.is_present("in") || matches.is_present("out") {
        let dir = if matches.is_present("in") {
            Direction::In
        } else {
            Direction::Out
        };

        let time = matches.value_of("time").unwrap_or("now");
        let time = try!(util::parse_multi_time_fmt(&time));

        let memo = matches.value_of("memo").unwrap_or("").to_owned();
        timeclock::mark_time(dir, time, memo, &mut csv_file);

        println!("Clocked {:#} at {}", dir, time.format("%F %I:%M %P"));

    } else if matches.is_present("summary") {
        try!(print_full_summary(&csv_file, rounding));

    } else if matches.is_present("log") {
        try!(print_csv_entries(&csv_file));

    } else {
        let today = now().date();
        let weekday = today.weekday() as i64;
        let days_back = (7 - WEEKSTART + weekday) % 7;
        let start_date = today - Duration::days(days_back);
        try!(print_short_summary(&csv_file, start_date, today, rounding));
    }

    Ok(())
}

fn main() {
    match main0() {
        Ok(_) => {}
        Err(err) => {
            let _ = writeln!(&mut std::io::stderr(), "Error: {}", err);
        }
    };
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]

#![allow(dead_code)]
#![allow(unused_assignments)]
#![allow(unused_variables)]

#[macro_use] extern crate lazy_static;

use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::{ Path, PathBuf };

lazy_static! {
    static ref HOME: PathBuf = std::env::home_dir().unwrap();

    static ref build_props: PathBuf = PathBuf::from("project/build.properties");

    static ref sbt_launch_dir: PathBuf = { let mut p = PathBuf::from(&*HOME); p.push(".sbt/launchers"); p };

    static ref script_name: String = {
        let n = std::env::args().nth(0).unwrap();
        let n = Path::new(&n).file_name().unwrap().to_str().unwrap();
        n.to_string()
    };

}

const sbt_launch_ivy_release_repo: &'static str = "http://repo.typesafe.com/typesafe/ivy-releases";
const sbt_launch_mvn_release_repo: &'static str = "http://repo.scala-sbt.org/scalasbt/maven-releases";

macro_rules! echoerr(($($arg:tt)*) => (writeln!(&mut ::std::io::stderr(), $($arg)*).unwrap();));

fn build_props_sbt() -> String {
    if let Ok(f) = File::open(&*build_props) {
        let f = BufReader::new(f);
        for line in f.lines() {
            let line = line.unwrap();
            if line.starts_with("sbt.version") {
                let line = line.replace("=", " ");
                let line = line.replace("\r", " ");
                return line.split_whitespace().nth(1).unwrap().to_owned();
            }
        }
    }
    "".to_owned()
}

fn jar_file(version: &str) -> PathBuf {
    let mut p = PathBuf::from(&*sbt_launch_dir);
    p.push(version);
    p.push("sbt-launch.jar");
    p
}

fn url_base(version: &str) -> &'static str { match version {
    s if s.starts_with("0.7.")  => "http://simple-build-tool.googlecode.com",
    s if s.starts_with("0.10.") => sbt_launch_ivy_release_repo,
    "0.11.1" | "0.11.2"         => sbt_launch_ivy_release_repo,
 // "0.*-yyyymmdd-hhMMss"       => sbt_launch_ivy_snapshot_repo, // https://repo.scala-sbt.org/scalasbt/ivy-snapshots
    s if s.starts_with("0.")    => sbt_launch_ivy_release_repo,
 // "*-yyyymmdd-hhMMss"         => sbt_launch_mvn_snapshot_repo, // http://repo.scala-sbt.org/scalasbt/maven-snapshots
    _                           => sbt_launch_mvn_release_repo,
} }

fn make_url(version: &str) -> String {
    let base = url_base(version);
    match version {
        s if s.starts_with("0.7.")  => format!("{}/files/sbt-launch-0.7.7.jar", base),
        s if s.starts_with("0.10.") => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        "0.11.1" | "0.11.2"         => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        s if s.starts_with("0.")    => format!("{}/org.scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        _                           => format!("{}/org/scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
    }
}

fn download_url(sbt_version: &str, url: &str, jar: &Path) {
    echoerr!("Downloading sbt launcher for {}:", sbt_version);
    echoerr!("  From  {}", url);
    echoerr!("    To  {}", jar.display());

    std::fs::create_dir_all(jar.parent().unwrap()).unwrap();

    extern crate hyper;
    let mut r = BufReader::new(hyper::client::Client::new().get(url).send().unwrap());
    let mut buf = [0; 16384];
    let mut jar = std::io::BufWriter::new(File::create(jar).unwrap());
    while {
        let bc = r.read(&mut buf).unwrap();
        jar.write(&buf[0..bc]).unwrap();
        bc > 0
    } {}
    jar.flush().unwrap();
}

fn exec_runner<S: AsRef<OsStr>>(args: &[S]) {
    use std::os::unix::process::CommandExt;
    let err = std::process::Command::new(&args[0]).args(&args[1..]).exec();
    println!("error: {}", err);
    if let Some(err) = err.raw_os_error() {
        std::process::exit(err);
    }
    std::process::exit(-1)
}

struct App<'a> {
           verbose: bool,
          java_cmd: &'a OsStr,
    extra_jvm_opts: Vec<&'a OsStr>,
         java_args: Vec<&'a OsStr>,
      sbt_commands: Vec<&'a OsStr>,
     residual_args: Vec<&'a OsStr>,
}

impl<'a> App<'a> {
    fn new() -> App<'a> {
        App {
                 verbose: Default::default(),
                java_cmd: "java".as_ref(),
          extra_jvm_opts: vec!["-Xms512m".as_ref(), "-Xmx1536m".as_ref(), "-Xss2m".as_ref()],
               java_args: Default::default(),
            sbt_commands: Default::default(),
           residual_args: Default::default(),
        }
    }

    fn vlog(&self, s: &str) { if self.verbose { echoerr!("{}", s); } }

    fn add_residual(&mut self, s: &'a str) {
        self.vlog(&format!("[residual] arg = {}", s));
        self.residual_args.push(s.as_ref());
    }

    fn run(&mut self) {
        for arg in std::env::args().skip(1) {
            match arg.as_ref() {
                "-v" => self.verbose = true,
                s    => panic!("fu"), // self.add_residual(&s),
            }
        }

        let argument_count = std::env::args().len();
        if argument_count > 0 {
            self.vlog(&format!("Starting {}: invoke with -help for other options", *script_name));
            self.residual_args = vec!["shell".as_ref()];
        }

        let sbt_version = build_props_sbt();
        let mut sbt_jar = jar_file(&sbt_version);
        if !sbt_jar.exists() {
            sbt_jar = PathBuf::from(&*HOME);
            sbt_jar.push(format!(".ivy2/local/org.scala-sbt/sbt-launch/{}/jars/sbt-launch.jar", sbt_version));
        }
        if !sbt_jar.exists() {
            sbt_jar = jar_file(&sbt_version);
            download_url(&sbt_version, &make_url(&sbt_version), &sbt_jar);
        }
        let sbt_jar = sbt_jar.as_path();

        let mut exec_args: Vec<&OsStr> = Vec::new();
        exec_args.push(self.java_cmd.as_ref());
        exec_args.append(&mut self.extra_jvm_opts.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.java_args.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut vec!["-jar".as_ref(), sbt_jar.as_ref()]);
        exec_args.append(&mut self.sbt_commands.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.residual_args.iter().map(AsRef::as_ref).collect());

        exec_runner(&exec_args)
    }
}

fn main() {
    App::new().run()
}
<commit_msg>Introduce process_args & tweak argument_count<commit_after>#![allow(non_upper_case_globals)]

#![allow(dead_code)]
#![allow(unused_assignments)]
#![allow(unused_variables)]

#[macro_use] extern crate lazy_static;

use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::{ Path, PathBuf };

lazy_static! {
    static ref HOME: PathBuf = std::env::home_dir().unwrap();

    static ref build_props: PathBuf = PathBuf::from("project/build.properties");

    static ref sbt_launch_dir: PathBuf = { let mut p = PathBuf::from(&*HOME); p.push(".sbt/launchers"); p };

    static ref script_name: String = {
        let n = std::env::args().nth(0).unwrap();
        let n = Path::new(&n).file_name().unwrap().to_str().unwrap();
        n.to_string()
    };

}

const sbt_launch_ivy_release_repo: &'static str = "http://repo.typesafe.com/typesafe/ivy-releases";
const sbt_launch_mvn_release_repo: &'static str = "http://repo.scala-sbt.org/scalasbt/maven-releases";

macro_rules! echoerr(($($arg:tt)*) => (writeln!(&mut ::std::io::stderr(), $($arg)*).unwrap();));

fn build_props_sbt() -> String {
    if let Ok(f) = File::open(&*build_props) {
        let f = BufReader::new(f);
        for line in f.lines() {
            let line = line.unwrap();
            if line.starts_with("sbt.version") {
                let line = line.replace("=", " ");
                let line = line.replace("\r", " ");
                return line.split_whitespace().nth(1).unwrap().to_owned();
            }
        }
    }
    "".to_owned()
}

fn jar_file(version: &str) -> PathBuf {
    let mut p = PathBuf::from(&*sbt_launch_dir);
    p.push(version);
    p.push("sbt-launch.jar");
    p
}

fn url_base(version: &str) -> &'static str { match version {
    s if s.starts_with("0.7.")  => "http://simple-build-tool.googlecode.com",
    s if s.starts_with("0.10.") => sbt_launch_ivy_release_repo,
    "0.11.1" | "0.11.2"         => sbt_launch_ivy_release_repo,
 // "0.*-yyyymmdd-hhMMss"       => sbt_launch_ivy_snapshot_repo, // https://repo.scala-sbt.org/scalasbt/ivy-snapshots
    s if s.starts_with("0.")    => sbt_launch_ivy_release_repo,
 // "*-yyyymmdd-hhMMss"         => sbt_launch_mvn_snapshot_repo, // http://repo.scala-sbt.org/scalasbt/maven-snapshots
    _                           => sbt_launch_mvn_release_repo,
} }

fn make_url(version: &str) -> String {
    let base = url_base(version);
    match version {
        s if s.starts_with("0.7.")  => format!("{}/files/sbt-launch-0.7.7.jar", base),
        s if s.starts_with("0.10.") => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        "0.11.1" | "0.11.2"         => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        s if s.starts_with("0.")    => format!("{}/org.scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        _                           => format!("{}/org/scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
    }
}

fn download_url(sbt_version: &str, url: &str, jar: &Path) {
    echoerr!("Downloading sbt launcher for {}:", sbt_version);
    echoerr!("  From  {}", url);
    echoerr!("    To  {}", jar.display());

    std::fs::create_dir_all(jar.parent().unwrap()).unwrap();

    extern crate hyper;
    let mut r = BufReader::new(hyper::client::Client::new().get(url).send().unwrap());
    let mut buf = [0; 16384];
    let mut jar = std::io::BufWriter::new(File::create(jar).unwrap());
    while {
        let bc = r.read(&mut buf).unwrap();
        jar.write(&buf[0..bc]).unwrap();
        bc > 0
    } {}
    jar.flush().unwrap();
}

fn exec_runner<S: AsRef<OsStr>>(args: &[S]) {
    use std::os::unix::process::CommandExt;
    let err = std::process::Command::new(&args[0]).args(&args[1..]).exec();
    println!("error: {}", err);
    if let Some(err) = err.raw_os_error() {
        std::process::exit(err);
    }
    std::process::exit(-1)
}

struct App<'a> {
           verbose: bool,
          java_cmd: &'a OsStr,
    extra_jvm_opts: Vec<&'a OsStr>,
         java_args: Vec<&'a OsStr>,
      sbt_commands: Vec<&'a OsStr>,
     residual_args: Vec<&'a OsStr>,
}

impl<'a> App<'a> {
    fn new() -> App<'a> {
        App {
                 verbose: Default::default(),
                java_cmd: "java".as_ref(),
          extra_jvm_opts: vec!["-Xms512m".as_ref(), "-Xmx1536m".as_ref(), "-Xss2m".as_ref()],
               java_args: Default::default(),
            sbt_commands: Default::default(),
           residual_args: Default::default(),
        }
    }

    fn vlog(&self, s: &str) { if self.verbose { echoerr!("{}", s); } }

    fn add_residual(&mut self, s: &'a str) {
        self.vlog(&format!("[residual] arg = {}", s));
        self.residual_args.push(s.as_ref());
    }

    fn process_args(&mut self) {
        for arg in std::env::args().skip(1) {
            match arg.as_ref() {
                "-v" => self.verbose = true,
                s    => panic!("fu"), // self.add_residual(&s),
            }
        }
    }

    fn run(&mut self) {
        let argument_count = self.residual_args.len();
        if argument_count == 0 {
            self.vlog(&format!("Starting {}: invoke with -help for other options", *script_name));
            self.residual_args = vec!["shell".as_ref()];
        }

        let sbt_version = build_props_sbt();
        let mut sbt_jar = jar_file(&sbt_version);
        if !sbt_jar.exists() {
            sbt_jar = PathBuf::from(&*HOME);
            sbt_jar.push(format!(".ivy2/local/org.scala-sbt/sbt-launch/{}/jars/sbt-launch.jar", sbt_version));
        }
        if !sbt_jar.exists() {
            sbt_jar = jar_file(&sbt_version);
            download_url(&sbt_version, &make_url(&sbt_version), &sbt_jar);
        }
        let sbt_jar = sbt_jar.as_path();

        let mut exec_args: Vec<&OsStr> = Vec::new();
        exec_args.push(self.java_cmd.as_ref());
        exec_args.append(&mut self.extra_jvm_opts.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.java_args.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut vec!["-jar".as_ref(), sbt_jar.as_ref()]);
        exec_args.append(&mut self.sbt_commands.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.residual_args.iter().map(AsRef::as_ref).collect());

        exec_runner(&exec_args)
    }
}

fn main() {
    let mut app = App::new();
    app.process_args();
    app.run()
}
<|endoftext|>


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

// TODO revisit these after 1.0.0beta
#![feature(io)]
#![feature(path)]

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;
extern crate quack;

#[macro_use]
extern crate log;
extern crate env_logger;

extern crate chip8_vm;

use std::cell::RefCell;
use sdl2_window::Sdl2Window;
use window::WindowSettings;
use opengl_graphics::{
    Gl,
};

use std::env;
use std::io::{Read, BufReader};
use std::fs::File;
use std::path::Path;
use quack::Set;
use input::Button;

use chip8_vm::vm::Vm;

const TITLE: &'static str = "Chip8";
const BEEP_TITLE: &'static str = "♬ Chip8 ♬";

const INTRO_ROM: &'static [u8] = include_bytes!("intro/intro.ch8");

fn main() {
    env_logger::init().unwrap();

    let mut vm = Vm::new();

    let mut rom: Option<File> = None;

    if let Some(rom_path) = env::args().skip(1).next() {
        if let Ok(f) = File::open(&Path::new(&rom_path)) {
            rom = Some(f);
        } else {
            error!("Could not open ROM {}", rom_path);
        }
    }

    let intro_reader = &mut BufReader::new(INTRO_ROM) as &mut Read;
    let mut rom_reader = match &mut rom {
        &mut Some(ref mut r) => r as &mut Read,
        _ => {
            info!("You can provide a path to a CHIP-8 ROM to run it.");
            intro_reader
        }
    };

    match vm.load_rom(rom_reader) {
        Ok(size) => debug!("Loaded ROM of size: {}", size),
        Err(e) => {
            error!("Error loading ROM: {}", e);
            return;
        }
    }

    let (width, height) = (800, 400);
    let opengl = shader_version::OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: TITLE.to_string(),
            size: [width, height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let ref mut gl = Gl::new(opengl);
    let window = RefCell::new(window);

    fn keymap(k: Option<Button>) -> Option<u8> {
        use input::Key::*;
        if let Some(Button::Keyboard(k)) = k {
            return match k {
                D1 => Some(0x1),
                D2 => Some(0x2),
                D3 => Some(0x3),

                Q  => Some(0x4),
                W  => Some(0x5),
                E  => Some(0x6),

                A  => Some(0x7),
                S  => Some(0x8),
                D  => Some(0x9),

                Z  => Some(0xA),
                X  => Some(0x0),
                C  => Some(0xB),

                D4 => Some(0xC),
                R  => Some(0xD),
                F  => Some(0xE),
                V  => Some(0xF),

                _ => None
            }
        }
        return None
    }

    for e in event::events(&window) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            vm.step(args.dt as f32);
            if vm.beeping() {
                (*window.borrow_mut()).window.set_title(BEEP_TITLE).unwrap();
            } else {
                (*window.borrow_mut()).window.set_title(TITLE).unwrap();
            }
        }
        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([0.0, 0.0, 0.0, 1.0], gl);
                let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
                let off = Color([0.0, 0.0, 0.0, 1.0]);
                let on = Color([1.0, 1.0, 1.0, 1.0]);

                let w = args.width as f64 / 64.0;
                let h = args.height as f64 / 32.0;

                for (y,row) in vm.screen_rows().enumerate() {
                    for (x,byte) in row.iter().enumerate() {
                        let x = x as f64 * w;
                        let y = y as f64 * h;
                        r.set(match *byte { 0 => off, _ => on })
                        .draw([x, y, w, h], &c.draw_state, c.transform, gl);
                    }
                }
            });
        }
        if let Some(keynum) = keymap(e.press_args()) {
            vm.set_key(keynum);
        }
        if let Some(keynum) = keymap(e.release_args()) {
            vm.unset_key(keynum);
        }
    }
}
<commit_msg>Update feature gates<commit_after>#![cfg_attr(test, allow(dead_code))]

extern crate shader_version;
extern crate input;
extern crate event;
extern crate graphics;
extern crate sdl2_window;
extern crate window;
extern crate opengl_graphics;
extern crate quack;

#[macro_use]
extern crate log;
extern crate env_logger;

extern crate chip8_vm;

use std::cell::RefCell;
use sdl2_window::Sdl2Window;
use window::WindowSettings;
use opengl_graphics::{
    Gl,
};

use std::env;
use std::io::{Read, BufReader};
use std::fs::File;
use std::path::Path;
use quack::Set;
use input::Button;

use chip8_vm::vm::Vm;

const TITLE: &'static str = "Chip8";
const BEEP_TITLE: &'static str = "♬ Chip8 ♬";

const INTRO_ROM: &'static [u8] = include_bytes!("intro/intro.ch8");

fn main() {
    env_logger::init().unwrap();

    let mut vm = Vm::new();

    let mut rom: Option<File> = None;

    if let Some(rom_path) = env::args().skip(1).next() {
        if let Ok(f) = File::open(&Path::new(&rom_path)) {
            rom = Some(f);
        } else {
            error!("Could not open ROM {}", rom_path);
        }
    }

    let intro_reader = &mut BufReader::new(INTRO_ROM) as &mut Read;
    let mut rom_reader = match &mut rom {
        &mut Some(ref mut r) => r as &mut Read,
        _ => {
            info!("You can provide a path to a CHIP-8 ROM to run it.");
            intro_reader
        }
    };

    match vm.load_rom(rom_reader) {
        Ok(size) => debug!("Loaded ROM of size: {}", size),
        Err(e) => {
            error!("Error loading ROM: {}", e);
            return;
        }
    }

    let (width, height) = (800, 400);
    let opengl = shader_version::OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        WindowSettings {
            title: TITLE.to_string(),
            size: [width, height],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let ref mut gl = Gl::new(opengl);
    let window = RefCell::new(window);

    fn keymap(k: Option<Button>) -> Option<u8> {
        use input::Key::*;
        if let Some(Button::Keyboard(k)) = k {
            return match k {
                D1 => Some(0x1),
                D2 => Some(0x2),
                D3 => Some(0x3),

                Q  => Some(0x4),
                W  => Some(0x5),
                E  => Some(0x6),

                A  => Some(0x7),
                S  => Some(0x8),
                D  => Some(0x9),

                Z  => Some(0xA),
                X  => Some(0x0),
                C  => Some(0xB),

                D4 => Some(0xC),
                R  => Some(0xD),
                F  => Some(0xE),
                V  => Some(0xF),

                _ => None
            }
        }
        return None
    }

    for e in event::events(&window) {
        use event::{ ReleaseEvent, UpdateEvent, PressEvent, RenderEvent };

        if let Some(args) = e.update_args() {
            vm.step(args.dt as f32);
            if vm.beeping() {
                (*window.borrow_mut()).window.set_title(BEEP_TITLE).unwrap();
            } else {
                (*window.borrow_mut()).window.set_title(TITLE).unwrap();
            }
        }
        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([0.0, 0.0, 0.0, 1.0], gl);
                let r = Rectangle::new([1.0, 1.0, 1.0, 1.0]);
                let off = Color([0.0, 0.0, 0.0, 1.0]);
                let on = Color([1.0, 1.0, 1.0, 1.0]);

                let w = args.width as f64 / 64.0;
                let h = args.height as f64 / 32.0;

                for (y,row) in vm.screen_rows().enumerate() {
                    for (x,byte) in row.iter().enumerate() {
                        let x = x as f64 * w;
                        let y = y as f64 * h;
                        r.set(match *byte { 0 => off, _ => on })
                        .draw([x, y, w, h], &c.draw_state, c.transform, gl);
                    }
                }
            });
        }
        if let Some(keynum) = keymap(e.press_args()) {
            vm.set_key(keynum);
        }
        if let Some(keynum) = keymap(e.release_args()) {
            vm.unset_key(keynum);
        }
    }
}
<|endoftext|>


<commit_before>//! [한국 러스트 사용자 그룹 홈페이지][rust-kr] 소스코드
//! --------
//!
//! ### 사용법
//! ```bash
//! git clone https://github.com/rust-kr/rust-kr.org.wiki.git docs
//! cargo run
//! # 웹 브라우저에서 http://localhost:8000 를 열어보세요
//! ```
//!
//! [rust-kr]: http://rust-kr.org

#[macro_use(itry)] extern crate iron;
#[macro_use(router)] extern crate router;
extern crate mount;
extern crate staticfile;
extern crate handlebars_iron as hbs;
extern crate pulldown_cmark as cmark;

use std::collections::BTreeMap;
use iron::prelude::*;
use iron::status;
use iron::middleware::AfterMiddleware;
use mount::Mount;
use staticfile::Static;
use hbs::{Template, HandlebarsEngine, DirectorySource};

//
// Configs
//
/// 서버가 소켓을 열 주소
const ADDR: &'static str = "localhost:8000";
/// 마크다운 문서가 담긴 주소
const DOCS_DIR: &'static str = "docs";

/// Entry point
fn main() {
    // Declarative definition of request handling
    let app = Iron::new({
        let mut c = Chain::new({
            // '/static/*'          -> static file serving
            // '/'                  -> Main page
            // '/pages/:name'       -> Specific documents
            // '/pages/_pages'      -> See all documents

            let mut m = Mount::new();
            m.mount("/static/", Static::new("static/"));
            m.mount("/", router! {
                get "/" => index,
                get "/pages/:name" => page,
                get "/pages/_pages" => all_docs,
            });
            m
        });
        // 404 page handler
        c.link_after(catch(|mut err: IronError| {
            if err.response.body.is_some() { return Err(err); }
            if err.response.status != Some(status::NotFound) { return Err(err); }

            // TODO: 좀더 내용 채우기
            let mut data = BTreeMap::new();
            data.insert("content", r#"

404

This is not the web page you are looking for.

            "#);
            err.response.set_mut(Template::new("default", data));
            Err(err)
        }));
        // Handlebar templating
        c.link_after({
            let mut hbr = HandlebarsEngine::new();
            hbr.add(Box::new(DirectorySource::new("templates", ".hbs")));
            if let Err(r) = hbr.reload() {
                use std::error::Error;
                panic!("{}", r.description());
            }
            hbr
        });
        c
    });

    println!("\nServer running at \x1b[33mhttp://{}\x1b[0m\n", ADDR);
    app.http(ADDR).unwrap();
}

/// Root page handler
fn index(_: &mut Request) -> IronResult<Response> {
    read_docs("Home")
}

/// Wiki page handler
fn page(req: &mut Request) -> IronResult<Response> {
    use router::Router;

    // Parse URL
    let name = req.extensions.get::<Router>().unwrap().find("name").unwrap_or("Home");
    read_docs(name)
}

/// "All documents" page handler
fn all_docs(_: &mut Request) -> IronResult<Response> {
    use std::fs::read_dir;

    let mut paths: Vec<_> = itry!(read_dir(DOCS_DIR))
        .filter_map(|f| f.ok())
        .map(|f| f.path())
        .filter(|p| p.is_file())
        .filter(|p| p.as_os_str().to_str()
            .map(|s| s.ends_with(".md"))
            .unwrap_or(false))
        .collect();
    paths.sort();

    let pages = paths.iter()
        .filter_map(|p| p.file_stem())
        .filter_map(|stem| stem.to_str());

    // TODO: 러스트로 이짓하지 말고 Handlebar로 대체
    let mut html = "
".to_string();
    for page in pages {
        use std::fmt::Write;
        write!(&mut html, r#"
{0}
"#, page).unwrap();
    }
    html.push_str("
");

    // Fill in to the template
    let mut data = BTreeMap::new();
    data.insert("content", html);
    Ok(Response::with((status::Ok, Template::new("default", data))))
}

/// `name`을 인자로 받아, `docs/<name>.md` 파일을 렌더링하여 `IronResult<Response>`로 반환합니다.
fn read_docs(name: &str) -> IronResult<Response> {
    use std::fs::File;
    use std::io::Read;
    use cmark::Parser;
    use cmark::html::push_html;

    // Read file
    let path = format!("{}/{}.md", DOCS_DIR, name);
    let mut file = itry!(File::open(&path));
    let mut md = String::new();
    itry!(file.read_to_string(&mut md));

    // Parse markdown
    let parser = Parser::new(&md);
    let mut html = String::new();
    push_html(&mut html, parser);

    // Fill in to the template
    let mut data = BTreeMap::new();
    data.insert("content", html);
    Ok(Response::with((status::Ok, Template::new("default", data))))
}

/// Helper struct for handle 404 page of rust-kr
struct RustkrHandler<F> { handler: F }
/// Helper function for handle 404 page of rust-kr
fn catch<F>(handler: F) -> RustkrHandler<F> { RustkrHandler { handler: handler } }
impl<F> AfterMiddleware for RustkrHandler<F>
    where F: Send + Sync + 'static + Fn(IronError) -> IronResult<Response> {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        (self.handler)(err)
    }
}
<commit_msg>Use proper http status code instead of 500<commit_after>//! [한국 러스트 사용자 그룹 홈페이지][rust-kr] 소스코드
//! --------
//!
//! ### 사용법
//! ```bash
//! git clone https://github.com/rust-kr/rust-kr.org.wiki.git docs
//! cargo run
//! # 웹 브라우저에서 http://localhost:8000 를 열어보세요
//! ```
//!
//! [rust-kr]: http://rust-kr.org

#[macro_use(itry)] extern crate iron;
#[macro_use(router)] extern crate router;
extern crate mount;
extern crate staticfile;
extern crate handlebars_iron as hbs;
extern crate pulldown_cmark as cmark;

use std::collections::BTreeMap;
use iron::prelude::*;
use iron::status;
use iron::middleware::AfterMiddleware;
use mount::Mount;
use staticfile::Static;
use hbs::{Template, HandlebarsEngine, DirectorySource};

//
// Configs
//
/// 서버가 소켓을 열 주소
const ADDR: &'static str = "localhost:8000";
/// 마크다운 문서가 담긴 주소
const DOCS_DIR: &'static str = "docs";

/// Entry point
fn main() {
    // Declarative definition of request handling
    let app = Iron::new({
        let mut c = Chain::new({
            // '/static/*'          -> static file serving
            // '/'                  -> Main page
            // '/pages/:name'       -> Specific documents
            // '/pages/_pages'      -> See all documents

            let mut m = Mount::new();
            m.mount("/static/", Static::new("static/"));
            m.mount("/", router! {
                get "/" => index,
                get "/pages/:name" => page,
                get "/pages/_pages" => all_docs,
            });
            m
        });
        // 404 page handler
        c.link_after(catch(|mut err: IronError| {
            if err.response.body.is_some() { return Err(err); }
            if err.response.status != Some(status::NotFound) { return Err(err); }

            // TODO: 좀더 내용 채우기
            let mut data = BTreeMap::new();
            data.insert("content", r#"

404

This is not the web page you are looking for.

            "#);
            err.response.set_mut(Template::new("default", data));
            Err(err)
        }));
        // Handlebar templating
        c.link_after({
            let mut hbr = HandlebarsEngine::new();
            hbr.add(Box::new(DirectorySource::new("templates", ".hbs")));
            if let Err(r) = hbr.reload() {
                use std::error::Error;
                panic!("{}", r.description());
            }
            hbr
        });
        c
    });

    println!("\nServer running at \x1b[33mhttp://{}\x1b[0m\n", ADDR);
    app.http(ADDR).unwrap();
}

/// Root page handler
fn index(_: &mut Request) -> IronResult<Response> {
    read_docs("Home")
}

/// Wiki page handler
fn page(req: &mut Request) -> IronResult<Response> {
    use router::Router;

    // Parse URL
    let name = req.extensions.get::<Router>().unwrap().find("name").unwrap_or("Home");
    read_docs(name)
}

/// "All documents" page handler
fn all_docs(_: &mut Request) -> IronResult<Response> {
    use std::fs::read_dir;

    let mut paths: Vec<_> = itry!(read_dir(DOCS_DIR), status::NotFound)
        .filter_map(|f| f.ok())
        .map(|f| f.path())
        .filter(|p| p.is_file())
        .filter(|p| p.as_os_str().to_str()
            .map(|s| s.ends_with(".md"))
            .unwrap_or(false))
        .collect();
    paths.sort();

    let pages = paths.iter()
        .filter_map(|p| p.file_stem())
        .filter_map(|stem| stem.to_str());

    // TODO: 러스트로 이짓하지 말고 Handlebar로 대체
    let mut html = "
".to_string();
    for page in pages {
        use std::fmt::Write;
        write!(&mut html, r#"
{0}
"#, page).unwrap();
    }
    html.push_str("
");

    // Fill in to the template
    let mut data = BTreeMap::new();
    data.insert("content", html);
    Ok(Response::with((status::Ok, Template::new("default", data))))
}

/// `name`을 인자로 받아, `docs/<name>.md` 파일을 렌더링하여 `IronResult<Response>`로 반환합니다.
fn read_docs(name: &str) -> IronResult<Response> {
    use std::fs::File;
    use std::io::Read;
    use cmark::Parser;
    use cmark::html::push_html;

    // Read file
    let path = format!("{}/{}.md", DOCS_DIR, name);
    let mut file = itry!(File::open(&path), status::NotFound);
    let mut md = String::new();
    itry!(file.read_to_string(&mut md), status::ServiceUnavailable);

    // Parse markdown
    let parser = Parser::new(&md);
    let mut html = String::new();
    push_html(&mut html, parser);

    // Fill in to the template
    let mut data = BTreeMap::new();
    data.insert("content", html);
    Ok(Response::with((status::Ok, Template::new("default", data))))
}

/// Helper struct for handle 404 page of rust-kr
struct RustkrHandler<F> { handler: F }
/// Helper function for handle 404 page of rust-kr
fn catch<F>(handler: F) -> RustkrHandler<F> { RustkrHandler { handler: handler } }
impl<F> AfterMiddleware for RustkrHandler<F>
    where F: Send + Sync + 'static + Fn(IronError) -> IronResult<Response> {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        (self.handler)(err)
    }
}
<|endoftext|>


<commit_before>extern crate ncurses;
extern crate voodoo;

use ncurses::*;

fn main() {
    use voodoo::terminal::{Mode, Terminal};

    let locale = LcCategory::all;
    setlocale(locale, "en_US.UTF-8");

    let term = Terminal::new();
    term.cbreak(Mode::Enabled).unwrap();
    term.echo(Mode::Disabled).unwrap();

    keypad(stdscr(), true);
    curs_set(CURSOR_VISIBILITY::CURSOR_INVISIBLE);

    mousemask((ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION) as u64, None);

    start_color();
    init_pair(1, COLOR_BLACK, COLOR_WHITE);

    wbkgd(stdscr(), 1);

    let info = newwin(24, 20, 0, 0);
    let map = newwin(24, 60, 0, 20);

    box_(info, 0, 0);
    box_(map, 0, 0);

    refresh();
    wrefresh(info);
    wrefresh(map);

    print!("\x1B[?1003h\n"); // Makes the terminal report mouse movement events

    loop {
        match voodoo::poll_event() {
            Some(voodoo::Event::Mouse) => {
                let event = get_mouse_state();
                mvwprintw(map, event.y, event.x - 20, "y");
                wrefresh(map);
            }

            Some(voodoo::Event::Char('\n')) => {
                break;
            }

            _ => {}
        }
    }

    print!("\x1B[?1003l\n"); // Disable mouse movement events, as l = low

    endwin();
}

fn get_mouse_state() -> MEVENT {
    let mut event = MEVENT { id: 0, x: 0, y: 0, z: 0, bstate: 0 };
    let res = getmouse(&mut event);
    if res != 0 {
        panic!("getmouse");
    }
    event
}
<commit_msg>feat: draw basic map<commit_after>extern crate ncurses;
extern crate voodoo;

use ncurses::*;
use voodoo::window::WindowLike;

const level: [&'static str; 22] = [
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "   o....                                                  ",
    "   o....                                                  ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
    "                                                          ",
];

fn main() {
    use voodoo::terminal::{Mode, Terminal};
    use voodoo::window::Window;

    let locale = LcCategory::all;
    setlocale(locale, "en_US.UTF-8");

    let term = Terminal::new();
    term.cbreak(Mode::Enabled).unwrap();
    term.echo(Mode::Disabled).unwrap();

    keypad(stdscr(), true);
    curs_set(CURSOR_VISIBILITY::CURSOR_INVISIBLE);

    mousemask((ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION) as u64, None);

    start_color();
    init_pair(1, COLOR_BLACK, COLOR_WHITE);

    wbkgd(stdscr(), 1);

    refresh();

    let mut info = Window::new(0, 0, 20, 24);
    let mut map = Window::new(20, 0, 60, 24);
    info.box_(0, 0);
    map.box_(0, 0);

    for (y, line) in level.iter().enumerate() {
        let y = (y + 1) as i32;
        for (x, tile) in line.chars().enumerate() {
            let x = (x + 1) as i32;
            match tile {
                '.' => map.put_at(y, x, '.'), // '·'
                'o' => map.put_at(y, x, 'O'),
                _ => {}
            }
        }
    }

    info.refresh();
    map.refresh();

    print!("\x1B[?1003h\n"); // Makes the terminal report mouse movement events

    loop {
        match voodoo::poll_event() {
            Some(voodoo::Event::Mouse) => {
                let event = get_mouse_state();
                map.put_at(event.y, event.x - 20, 'y');
                map.refresh();
            }

            Some(voodoo::Event::Char('\n')) => {
                break;
            }

            _ => {}
        }
    }

    print!("\x1B[?1003l\n"); // Disable mouse movement events, as l = low

    endwin();
}

fn get_mouse_state() -> MEVENT {
    let mut event = MEVENT { id: 0, x: 0, y: 0, z: 0, bstate: 0 };
    let res = getmouse(&mut event);
    if res != 0 {
        panic!("getmouse");
    }
    event
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

extern crate git;
extern crate hyper;
extern crate serialize;

use git::Error;
use std::default::Default;
use std::os::args;

use description::Description;

mod description;

fn main() {
    macro_rules! ok(
        ($result:expr) => (
            match $result {
                Err(e) => {
                    error(e);
                    return;
                },
                _ => {},
            }
        );
    )

    let args = args();

    if args.len() != 3 {
        usage();
        return;
    }

    let (command, path) = (args[1].clone(), Path::new(args[2].clone()));

    match command.as_slice() {
        "status" => ok!(status(&path)),
        "push" => ok!(push(&path)),
        _ => usage(),
    }
}

fn status(path: &Path) -> Result<(), Error> {
    #![allow(unused_assignments)]

    macro_rules! print(
        ($title:expr, $paths:expr, $sep:expr) => {
            if !$paths.is_empty() {
                if $sep {
                    println!("");
                }
                $sep = print($title, &$paths);
            }
        };
    )

    let (new, updated, removed) = try!(check(path));
    let mut sep = false;

    print!("New", new, sep);
    print!("Updated", updated, sep);
    print!("Deleted", removed, sep);

    Ok(())
}

fn push(path: &Path) -> Result<(), Error> {
    let mut git = try!(git::open(path));

    try!(git.add_all());
    try!(git.commit("Synchronized with the official repository"));
    try!(git.push());

    Ok(())
}

fn error(e: Error) {
    println!("{}", e);
}

fn usage() {
    println!("Usage: {} (status|push) <path>", args()[0]);
}

fn check(dir: &Path) -> Result<(Vec<Path>, Vec<Path>, Vec<Path>), Error> {
    use git::status;
    use git::status::Flags;

    const NEW: Flags = Flags(status::IndexNew as u32 | status::WorkDirNew as u32);
    const UPDATED: Flags = Flags(status::IndexModified as u32 | status::WorkDirModified as u32);
    const REMOVED: Flags = Flags(status::IndexDeleted as u32 | status::WorkDirDeleted as u32);

    let repo = try!(git::Repository::open(dir));
    let list = try!(repo.status(&Default::default()));

    let mut new = vec![];
    let mut updated = vec![];
    let mut removed = vec![];

    fn push(vec: &mut Vec<Path>, path: &Path) {
        if vec.iter().find(|&p| p == path).is_none() {
            vec.push(path.clone());
        }
    }

    for entry in list.iter() {
        let status = entry.status();
        let path = dir.join(entry.new_path()).dir_path();

        if status.any(NEW) {
            push(&mut new, &path);
        } else if status.any(UPDATED) {
            push(&mut updated, &path);
        } else if status.any(REMOVED) {
            push(&mut removed, &path);
        }
    }

    let new = new.into_iter().filter(|path| {
        if removed.iter().find(|&p| p == path).is_some() {
            push(&mut updated, path);
            false
        } else {
            true
        }
    }).collect::<Vec<_>>();

    let removed = removed.into_iter().filter(|path| {
        updated.iter().find(|&p| p == path).is_none()
    }).collect::<Vec<_>>();

    Ok((new, updated, removed))
}

fn print(title: &str, paths: &Vec<Path>) -> bool {
    let lines = paths.iter().by_ref()
                     .map(|path| format(path))
                     .filter(|line| line.is_some())
                     .map(|line| line.unwrap())
                     .collect::<Vec<_>>();

    let len = paths.len();
    if len == 0 {
        return false;
    }

    println!("{}:", title);

    for (i, line) in lines.iter().enumerate() {
        if i + 1 == len {
            println!(" * {}.", line);
        } else if i + 2 == len {
            println!(" * {} and", line);
        } else {
            println!(" * {},", line);
        }
    }

    true
}

fn format(path: &Path) -> Option<String> {
    let mut line = String::new();

    let desc = Description::load(path);

    match desc.name {
        Some(ref name) => line.push_str(name.as_slice()),
        None => return None,
    }

    match desc.url {
        Some(ref url) => {
            line.insert(0, '[');
            line.push_str("](");
            line.push_str(url.as_slice());
            line.push_str(")");
        },
        None => {},
    }

    match desc.designer {
        Some(ref designer) => {
            line.push_str(" by ");
            line.push_str(designer.as_slice());
        },
        None => {},
    }

    Some(line)
}
<commit_msg>A minor adjustment to error handling<commit_after>#![feature(if_let, macro_rules)]

extern crate git;
extern crate hyper;
extern crate serialize;

use git::Error;
use std::default::Default;
use std::os::args;

use description::Description;

mod description;

fn main() {
    macro_rules! ok(
        ($result:expr) => (
            if let Err(e) = $result {
                error(e);
                return;
            }
        );
    )

    let args = args();

    if args.len() != 3 {
        usage();
        return;
    }

    let (command, path) = (args[1].clone(), Path::new(args[2].clone()));

    match command.as_slice() {
        "status" => ok!(status(&path)),
        "push" => ok!(push(&path)),
        _ => usage(),
    }
}

fn status(path: &Path) -> Result<(), Error> {
    #![allow(unused_assignments)]

    macro_rules! print(
        ($title:expr, $paths:expr, $sep:expr) => {
            if !$paths.is_empty() {
                if $sep {
                    println!("");
                }
                $sep = print($title, &$paths);
            }
        };
    )

    let (new, updated, removed) = try!(check(path));
    let mut sep = false;

    print!("New", new, sep);
    print!("Updated", updated, sep);
    print!("Deleted", removed, sep);

    Ok(())
}

fn push(path: &Path) -> Result<(), Error> {
    let mut git = try!(git::open(path));

    try!(git.add_all());
    try!(git.commit("Synchronized with the official repository"));
    try!(git.push());

    Ok(())
}

fn error(e: Error) {
    println!("{}", e);
}

fn usage() {
    println!("Usage: {} (status|push) <path>", args()[0]);
}

fn check(dir: &Path) -> Result<(Vec<Path>, Vec<Path>, Vec<Path>), Error> {
    use git::status;
    use git::status::Flags;

    const NEW: Flags = Flags(status::IndexNew as u32 | status::WorkDirNew as u32);
    const UPDATED: Flags = Flags(status::IndexModified as u32 | status::WorkDirModified as u32);
    const REMOVED: Flags = Flags(status::IndexDeleted as u32 | status::WorkDirDeleted as u32);

    let repo = try!(git::Repository::open(dir));
    let list = try!(repo.status(&Default::default()));

    let mut new = vec![];
    let mut updated = vec![];
    let mut removed = vec![];

    fn push(vec: &mut Vec<Path>, path: &Path) {
        if vec.iter().find(|&p| p == path).is_none() {
            vec.push(path.clone());
        }
    }

    for entry in list.iter() {
        let status = entry.status();
        let path = dir.join(entry.new_path()).dir_path();

        if status.any(NEW) {
            push(&mut new, &path);
        } else if status.any(UPDATED) {
            push(&mut updated, &path);
        } else if status.any(REMOVED) {
            push(&mut removed, &path);
        }
    }

    let new = new.into_iter().filter(|path| {
        if removed.iter().find(|&p| p == path).is_some() {
            push(&mut updated, path);
            false
        } else {
            true
        }
    }).collect::<Vec<_>>();

    let removed = removed.into_iter().filter(|path| {
        updated.iter().find(|&p| p == path).is_none()
    }).collect::<Vec<_>>();

    Ok((new, updated, removed))
}

fn print(title: &str, paths: &Vec<Path>) -> bool {
    let lines = paths.iter().by_ref()
                     .map(|path| format(path))
                     .filter(|line| line.is_some())
                     .map(|line| line.unwrap())
                     .collect::<Vec<_>>();

    let len = paths.len();
    if len == 0 {
        return false;
    }

    println!("{}:", title);

    for (i, line) in lines.iter().enumerate() {
        if i + 1 == len {
            println!(" * {}.", line);
        } else if i + 2 == len {
            println!(" * {} and", line);
        } else {
            println!(" * {},", line);
        }
    }

    true
}

fn format(path: &Path) -> Option<String> {
    let mut line = String::new();

    let desc = Description::load(path);

    match desc.name {
        Some(ref name) => line.push_str(name.as_slice()),
        None => return None,
    }

    match desc.url {
        Some(ref url) => {
            line.insert(0, '[');
            line.push_str("](");
            line.push_str(url.as_slice());
            line.push_str(")");
        },
        None => {},
    }

    match desc.designer {
        Some(ref designer) => {
            line.push_str(" by ");
            line.push_str(designer.as_slice());
        },
        None => {},
    }

    Some(line)
}
<|endoftext|>


<commit_before>extern crate porthole;

fn main() {
  for p in porthole::iter().take(5) {
    println!("{:?}", p);
  }
}
<commit_msg>rm main<commit_after><|endoftext|>


<commit_before>/// Executable for proton_cli

extern crate proton_cli;
extern crate git2;

use std::env;
use std::path::Path;

fn main() {
    let root_arg = env::args().nth(1).unwrap();
    let root = Path::new(&root_arg);

    match proton_cli::initialize_project(root) {
        Ok(_) => println!("Worked!"),
        Err(e) => println!("{:?}", e),
    }
}
<commit_msg>Added check for number of arguments (#5)<commit_after>/// Executable for proton_cli

extern crate proton_cli;
extern crate git2;

use std::env;
use std::path::Path;

fn main() {
    if env::args().count() != 2 {
        panic!("Invalid number of arguments given");
    }
    let root_arg = env::args().nth(1).unwrap();
    let root = Path::new(&root_arg);

    match proton_cli::initialize_project(root) {
        Ok(_) => println!("Worked!"),
        Err(e) => println!("{:?}", e),
    }
}
<|endoftext|>


<commit_before>use casile::i18n;
use std::{env, error, io, path, str};
use structopt::{clap, StructOpt};

/// The command line interface to the CaSILE toolkit, a book publishing
/// workflow employing SILE and other wizardry
#[derive(Debug)]
// #[structopt(about = "bob is a turtle")]
#[derive(StructOpt)]
#[structopt(version = env!("VERGEN_SEMVER"))]
#[structopt(setting = clap::AppSettings::InferSubcommands)]
struct Cli {
    /// Activate debug mode
    #[structopt(short, long)]
    debug: bool,

    /// Set language
    #[structopt(short, long, required = false, env = "LANG")]
    language: String,

    /// Outputs verbose feedback where possible
    #[structopt(short, long)]
    verbose: bool,

    #[structopt(subcommand)]
    subcommand: Subcommand,
}

#[derive(Debug, StructOpt)]
enum Subcommand {
    /// Executes a make target
    Make {
        /// Target as defined in CaSILE makefile
        target: Vec<String>,
    },

    /// Configure a book repository
    Setup {
        /// Path to project repository
        #[structopt(parse(from_os_str), default_value = "./")]
        path: path::PathBuf,

        /// Output Bash, Fish, Zsh, PowerShell, or Elvish shell completion rules
        #[structopt(long)]
        completions: Option<clap::Shell>,
    },

    /// Pass through other commands to shell
    #[structopt(external_subcommand)]
    Other(Vec<String>),
}

fn main() -> Result<(), Box<dyn error::Error>> {
    let clap = Cli::clap();
    // let clap = Cli::clap().about("what about bob");
    // println!("First pass {:?}", a.language);

    let args = Cli::from_clap(&clap.get_matches());

    let config = casile::Config {
        verbose: args.verbose,
        debug: args.debug,
        locale: i18n::Locale::negotiate(args.language),
    };

    match args.subcommand {
        Subcommand::Make { target } => casile::make::run(&config, target),
        Subcommand::Setup { path, completions } => match completions {
            None => casile::setup::run(&config, path),
            Some(shell) => {
                Cli::clap().gen_completions_to(env!("CARGO_PKG_NAME"), shell, &mut io::stdout());
                Ok(())
            }
        },
        Subcommand::Other(input) => casile::shell::run(&config, input),
    }
}
<commit_msg>chore(cli): Switch from StructOpt to Clap's derive (minus completion)<commit_after>use casile::i18n;
use clap::{AppSettings, Clap};
use std::{env, error, path, str};

/// The command line interface to the CaSILE toolkit, a book publishing
/// workflow employing SILE and other wizardry
#[derive(Clap, Debug)]
// #[clap(about = "bob is a turtle")]
#[clap(version = env!("VERGEN_SEMVER"))]
#[clap(setting = AppSettings::InferSubcommands)]
#[clap(setting = AppSettings::AllowExternalSubcommands)]
struct Cli {
    /// Activate debug mode
    #[clap(short, long)]
    debug: bool,

    /// Set language
    #[clap(short, long, required = false, env = "LANG")]
    language: String,

    /// Outputs verbose feedback where possible
    #[clap(short, long)]
    verbose: bool,

    #[clap(subcommand)]
    subcommand: Subcommand,
}

#[derive(Clap, Debug)]
enum Subcommand {
    /// Executes a make target
    Make {
        /// Target as defined in CaSILE makefile
        target: Vec<String>,
    },

    /// Configure a book repository
    Setup {
        /// Path to project repository
        #[clap(parse(from_os_str), default_value = "./")]
        path: path::PathBuf,
        // /// Output Bash, Fish, Zsh, PowerShell, or Elvish shell completion rules
        // #[clap(long)]
        // // completions: clap::Shell,
        // completions: Option<String>,
    },

    /// Pass through other commands to shell
    #[clap(external_subcommand)]
    Other(Vec<String>),
}

fn main() -> Result<(), Box<dyn error::Error>> {
    let args = Cli::parse();
    let config = casile::Config {
        verbose: args.verbose,
        debug: args.debug,
        locale: i18n::Locale::negotiate(args.language),
    };
    match args.subcommand {
        Subcommand::Make { target } => casile::make::run(&config, target),
        Subcommand::Setup { path } => casile::setup::run(&config, path),
        // Subcommand::Setup { path, completions } => match completions {
        //     None => casile::setup::run(&config, path),
        //     Some(_shell) => {
        //         Cli::clap_completions::generate_to(env!("CARGO_PKG_NAME"), "Zsh", &mut io::stdout());
        //         Ok(())
        //     }
        // },
        Subcommand::Other(input) => casile::shell::run(&config, input),
    }
}
<|endoftext|>


<commit_before>

mod curses;

use std::ffi::CString;

use curses::*;

fn main() {
    let mut x = 0;
    let mut y = 0;
    unsafe {
        initscr();
        cbreak();
        noecho();

        let mut c = getch();

        while c as u8 as char != 'q' {
            if c as u8 as char == 'j' {
                y+=1;
                cursor_move( y, x );
            } else if c as u8 as char == 'k' {
                y-=1;
                cursor_move( y, x );
            } else if c as u8 as char == 'l' {
               x+=1;
               cursor_move( y, x );
            } else if c as u8 as char == 'h' {
               x-=1;
               cursor_move( y, x );
            }
            refresh();
            c = getch();
        }

        endwin();
    }
}

<commit_msg>adding drawables<commit_after>
mod curses;

use std::ffi::CString;

use curses::*;

enum DrawMe {
    Circle { radius : i32, x : i32, y : i32 },
    /*Rec { width : i32, height : i32, x : i32, y : i32 },
    VHall { length : i32, x : i32, y : i32 },
    HHall { length : i32, x : i32, y : i32 },*/
}

fn main() {
    let mut x = 0;
    let mut y = 0;
    unsafe {
        initscr();
        cbreak();
        noecho();

        let mut c = getch();

        while c as u8 as char != 'q' {
            if c as u8 as char == 'j' {
                y+=1;
                cursor_move( y, x );
            } else if c as u8 as char == 'k' {
                y-=1;
                cursor_move( y, x );
            } else if c as u8 as char == 'l' {
               x+=1;
               cursor_move( y, x );
            } else if c as u8 as char == 'h' {
               x-=1;
               cursor_move( y, x );
            }
            refresh();
            c = getch();
        }

        endwin();
    }
}

<|endoftext|>