1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
#[macro_use] extern crate serde_derive; use std::env; use std::path::PathBuf; use clap::{App, SubCommand, AppSettings}; pub mod project; pub mod music; pub mod parser; pub mod book; pub mod render; pub mod watch; pub mod util; pub mod error; use crate::project::Project; use crate::watch::{Watch, WatchEvent}; use crate::error::*; fn get_cwd() -> Result<PathBuf> { let cwd = env::current_dir().context("Could not read current directory") ?; ensure!(cwd.as_path().to_str().is_some(), format!("Path is not valid unicode: '{}'", cwd.display())); Ok(cwd) } pub fn bard_init() -> Result<()> { let cwd = get_cwd() ?; Project::init(&cwd) .context("Could not initialize a new project") } pub fn bard_make() -> Result<Project> { let cwd = get_cwd() ?; Project::new(&cwd).and_then(|project| { project.render() ?; Ok(project) }).context("Could not make project") } pub fn bard_watch() -> Result<()> { let (mut watch, cancellation) = Watch::new() ?; let _ = ctrlc::set_handler(move || { cancellation.cancel(); }); loop { eprintln!("Making project ..."); let project = bard_make() ?; eprintln!("Watching for changes ..."); match watch.watch(&project)? { WatchEvent::Path(path) => eprintln!("Modification detected at '{}' ...", path.display()), WatchEvent::Pathless => eprintln!("Modification detected ..."), WatchEvent::Cancel => break, } } Ok(()) } pub fn bard() -> Result<()> { let args = App::new("bard") .version("0.3") .author("Vojtech Kral <vojtech@kral.hk>") .about("bard: Songbook compiler") .setting(AppSettings::VersionlessSubcommands) .setting(AppSettings::ArgRequiredElseHelp) .subcommand(SubCommand::with_name("init") .about("Initialize and empty project with default settings")) .subcommand(SubCommand::with_name("make") .about("Process the current project and generate output files")) .subcommand(SubCommand::with_name("watch") .about("Watch the current project and its input files for changes, and re-make the project each time there's a change")) .get_matches(); if let Some(_args) = args.subcommand_matches("init") { bard_init() ?; } else if let Some(_args) = args.subcommand_matches("make") { bard_make() ?; } else if let Some(_args) = args.subcommand_matches("watch") { bard_watch() ?; } Ok(()) }