extern crate rustbox;
extern crate rustc_serialize;
extern crate gag;
extern crate toml;
extern crate itertools;
extern crate docopt;
use std::path::Path;
use std::error::Error;
use std::io;
use std::io::Write;
use std::process;
use docopt::Docopt;
use rustbox::{RustBox, Event, InputMode, InitOptions};
use rustbox::keyboard::Key;
use gag::Hold;
#[macro_use] mod signals;
mod config;
mod ui;
mod buffer;
mod util;
mod segment;
use ui::view::HexEdit;
use config::Config;
static USAGE: &'static str = "
Usage: rex [options] [-C CONF... FILE]
rex --help
rex --help-config
Options:
-h, --help Show this help message
-c FILE, --config FILE Use FILE as the config file
-C CONF Set a configuration option, for example: -C line_width=16
";
#[derive(RustcDecodable, Debug)]
struct Args {
flag_help_config: bool,
arg_FILE: Option<String>,
flag_config: Option<String>,
flag_C: Vec<String>,
}
fn exit_err<E: Error>(msg: &str, error: E) -> ! {
write!(&mut io::stderr(), "{}: {}", msg, error).unwrap();
process::exit(1);
}
fn main() {
let args: Args = Docopt::new(USAGE).and_then(
|d| d.decode()).unwrap_or_else(
|e| e.exit());
if args.flag_help_config {
println!("{}", Config::get_config_usage());
process::exit(0);
}
let config_res = if let Some(config_filename) = args.flag_config {
Config::from_file(config_filename)
} else {
Config::open_default()
};
let mut config = config_res.unwrap_or_else(
|e| exit_err("Couldn't open config file", e)
);
for config_line in &args.flag_C {
config.set_from_string(config_line).unwrap_or_else(
|e| exit_err("Couldn't parse command line config option", e)
);
}
let mut edit = HexEdit::new(config);
if let Some(ref filename) = args.arg_FILE {
edit.open(&Path::new(filename));
}
let hold = (Hold::stdout().unwrap(), Hold::stderr().unwrap());
let rb = RustBox::init(InitOptions{
buffer_stderr: false,
input_mode: InputMode::Esc,
}).unwrap();
edit.resize(rb.width() as i32, rb.height() as i32);
edit.draw(&rb);
rb.present();
loop {
let event = rb.poll_event(false).unwrap();
match event {
Event::KeyEvent(Some(Key::Ctrl('q'))) => break,
Event::KeyEvent(Some(key)) => edit.input(key),
Event::ResizeEvent(w, h) => { edit.resize(w, h) }
_ => ()
};
rb.clear();
edit.draw(&rb);
rb.present();
}
drop(rb);
drop(hold);
}