#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
pub use std::fs;
pub use std::io::Read;
pub use std::env;
use super::types::*;
use super::data;
pub fn get_subcommand<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name("tutorial")
.about("start the interactive tutorial")
.settings(&[AS::DeriveDisplayOrder, COLOR])
.arg(Arg::with_name("part").help("the part to set the tutorial at"))
}
pub fn get_tutorial_cmd(matches: &ArgMatches) -> Result<u8, String> {
let part = match matches.value_of("part").unwrap_or("1").parse::<u8>() {
Ok(p) => p,
Err(e) => return Err(e.to_string()),
};
if 1 <= part && part <= 5 {
Ok(part)
} else {
let mut msg = String::new();
write!(msg, "part must be between 1 and 5. Got: {}", part).unwrap();
Err(msg)
}
}
fn remove_files_force(files: &HashSet<PathBuf>) {
for p in files.iter() {
trace!("removing file: {}", p.display());
let _ = fs::remove_file(p);
}
}
fn write_file(path: &PathBuf, data: &str) -> io::Result<()> {
trace!("creating file: {}", path.display());
let mut f = try!(fs::File::create(path.as_path()));
try!(f.write_all(data.as_ref()));
Ok(())
}
fn create_dir(path: &PathBuf) {
trace!("creating dir: {}", path.display());
let _ = fs::create_dir(path);
}
pub fn do_tutorial(part: u8) -> io::Result<()> {
let CWD: PathBuf = env::current_dir().unwrap();
let RST_DIR: PathBuf = CWD.join(PathBuf::from(".rst"));
let REQS_DIR: PathBuf = CWD.join(PathBuf::from("reqs"));
let SRC_DIR: PathBuf = CWD.join(PathBuf::from("flash"));
let TESTS_DIR: PathBuf = SRC_DIR.join(PathBuf::from("tests"));
let SETTINGS_TOML: PathBuf = RST_DIR.join(PathBuf::from("settings.toml"));
let TUTORIAL_TOML: PathBuf = CWD.join(PathBuf::from("tutorial.toml"));
let TUTORIAL_MD: PathBuf = CWD.join(PathBuf::from("tutorial.md"));
let CAPITOLS_CSV: PathBuf = CWD.join(PathBuf::from("capitols.csv"));
let EXERCISE_HTM: PathBuf = CWD.join(PathBuf::from("flash_card_challenge.htm"));
let PURPOSE_TOML: PathBuf = REQS_DIR.join(PathBuf::from("purpose.toml"));
let HIGH_LEVEL_TOML: PathBuf = REQS_DIR.join(PathBuf::from("high_level.toml"));
let LOAD_TOML: PathBuf = REQS_DIR.join(PathBuf::from("load.toml"));
let INIT_PY: PathBuf = SRC_DIR.join(PathBuf::from("__init__.py"));
let LOAD_PY: PathBuf = SRC_DIR.join(PathBuf::from("load.py"));
let TEST_INIT_PY: PathBuf = TESTS_DIR.join(PathBuf::from("__init__.py"));
let TEST_LOAD_PY: PathBuf = TESTS_DIR.join(PathBuf::from("test_load.py"));
let EXAMPLE_CSV: PathBuf = TESTS_DIR.join(PathBuf::from("example.csv"));
let PART_1_FILES: HashSet<PathBuf> = HashSet::from_iter(vec![SETTINGS_TOML.clone(),
TUTORIAL_TOML.clone()]);
let PART_2_FILES: HashSet<PathBuf> = HashSet::from_iter(vec![SETTINGS_TOML.clone(),
TUTORIAL_MD.clone(),
CAPITOLS_CSV.clone(),
EXERCISE_HTM.clone(),
PURPOSE_TOML.clone(),
HIGH_LEVEL_TOML.clone()]);
let mut PART_3_FILES: HashSet<PathBuf> = HashSet::from_iter(vec![LOAD_TOML.clone(),
INIT_PY.clone(),
LOAD_PY.clone(),
TEST_INIT_PY.clone(),
TEST_LOAD_PY.clone()]);
PART_3_FILES.extend(PART_2_FILES.iter().cloned());
let mut ALL_FILES: HashSet<PathBuf> = HashSet::new();
ALL_FILES.extend(PART_1_FILES.iter().cloned());
ALL_FILES.extend(PART_3_FILES.iter().cloned());
let already_tutorial = match fs::File::open(&SETTINGS_TOML) {
Ok(mut f) => {
let mut buffer = [0; 14];
match f.read_exact(&mut buffer) {
Ok(_) => buffer == "#TUTORIAL=true".as_ref(),
Err(_) => false,
}
}
Err(_) => false,
};
debug!("running with cwd: {}", CWD.display());
if !already_tutorial {
debug!("cwd is not a tutorial");
if try!(fs::read_dir(&CWD)).next().is_some() {
println!("ERROR: can only start the rst tutorial in an empty directory. \
To make an empty directory and change-dir to it, run:\n \
mkdir ~/tryrst; cd ~/tryrst");
return Ok(());
}
} else {
debug!("cwd is already a tutorial")
}
debug!("running tutorial at part: {}", part);
remove_files_force(&ALL_FILES);
create_dir(&RST_DIR);
println!("## Tutorial Loaded!");
if part == 1 {
println!(" Tutorial part 1: open tutorial.toml with a text editor");
try!(write_file(&SETTINGS_TOML, data::settings_1::DATA));
try!(write_file(&TUTORIAL_TOML, data::tutorial_toml::DATA));
} else {
create_dir(&REQS_DIR);
try!(write_file(&TUTORIAL_MD, data::tutorial_md::DATA));
try!(write_file(&CAPITOLS_CSV, data::capitols_csv::DATA));
try!(write_file(&EXERCISE_HTM, data::exercise_htm::DATA));
try!(write_file(&PURPOSE_TOML, data::purpose_toml::DATA));
try!(write_file(&HIGH_LEVEL_TOML, data::high_level_toml::DATA));
if part == 2 {
println!(" Tutorial part 2: open tutorial.md with a text editor and see part 2");
try!(write_file(&SETTINGS_TOML, data::settings_2::DATA));
} else {
if part == 3 {
println!(" Tutorial part 3: open tutorial.md with a text editor and see part 3");
}
try!(write_file(&SETTINGS_TOML, data::settings_2::DATA)); if part != 5 {
try!(write_file(&LOAD_TOML, data::load_toml::DATA));
}
if part >= 4 {
create_dir(&SRC_DIR);
create_dir(&TESTS_DIR);
try!(write_file(&SETTINGS_TOML, data::settings_4::DATA));
try!(write_file(&TEST_LOAD_PY, data::test_load_py::DATA));
try!(write_file(&EXAMPLE_CSV, data::example_csv::DATA));
try!(write_file(&INIT_PY, ""));
try!(write_file(&TEST_INIT_PY, ""));
if part == 4 {
println!(" Tutorial part 4: open tutorial.md with a text editor and see part 4");
try!(write_file(&LOAD_PY, data::load_py::DATA));
} else {
println!(" Tutorial part 5: open tutorial.md with a text editor and see part 5");
try!(write_file(&LOAD_TOML, data::load_toml2::DATA));
try!(write_file(&LOAD_PY, data::load_py2::DATA));
}
}
}
}
Ok(())
}