aboutsummaryrefslogtreecommitdiffstats
path: root/teleterm/src/cmd.rs
diff options
context:
space:
mode:
Diffstat (limited to 'teleterm/src/cmd.rs')
-rw-r--r--teleterm/src/cmd.rs138
1 files changed, 138 insertions, 0 deletions
diff --git a/teleterm/src/cmd.rs b/teleterm/src/cmd.rs
new file mode 100644
index 0000000..8d7faa7
--- /dev/null
+++ b/teleterm/src/cmd.rs
@@ -0,0 +1,138 @@
+use crate::prelude::*;
+
+mod play;
+mod record;
+mod server;
+mod stream;
+mod watch;
+mod web;
+
+struct Command {
+ name: &'static str,
+ cmd: &'static dyn for<'a, 'b> Fn(clap::App<'a, 'b>) -> clap::App<'a, 'b>,
+ config: &'static dyn Fn(
+ Option<config::Config>,
+ ) -> Result<Box<dyn crate::config::Config>>,
+ log_level: &'static str,
+}
+
+const COMMANDS: &[Command] = &[
+ Command {
+ name: "stream",
+ cmd: &stream::cmd,
+ config: &stream::config,
+ log_level: "error",
+ },
+ Command {
+ name: "server",
+ cmd: &server::cmd,
+ config: &server::config,
+ log_level: "info",
+ },
+ Command {
+ name: "web",
+ cmd: &web::cmd,
+ config: &web::config,
+ log_level: "info",
+ },
+ Command {
+ name: "watch",
+ cmd: &watch::cmd,
+ config: &watch::config,
+ log_level: "error",
+ },
+ Command {
+ name: "record",
+ cmd: &record::cmd,
+ config: &record::config,
+ log_level: "error",
+ },
+ Command {
+ name: "play",
+ cmd: &play::cmd,
+ config: &play::config,
+ log_level: "error",
+ },
+];
+
+pub fn parse<'a>() -> Result<clap::ArgMatches<'a>> {
+ let mut app = clap::App::new(program_name()?)
+ .about("Stream your terminal for other people to watch")
+ .author(clap::crate_authors!())
+ .version(clap::crate_version!())
+ .arg(
+ clap::Arg::with_name("config-file")
+ .long("config-file")
+ .takes_value(true)
+ .value_name("FILE")
+ .help("Read configuration from FILE"),
+ )
+ .global_setting(clap::AppSettings::DontCollapseArgsInUsage)
+ .global_setting(clap::AppSettings::GlobalVersion)
+ .global_setting(clap::AppSettings::UnifiedHelpMessage)
+ .global_setting(clap::AppSettings::VersionlessSubcommands);
+
+ for cmd in COMMANDS {
+ let subcommand = clap::SubCommand::with_name(cmd.name);
+ app = app.subcommand(
+ (cmd.cmd)(subcommand).setting(clap::AppSettings::NextLineHelp),
+ );
+ }
+
+ app.get_matches_safe().context(crate::error::ParseArgs)
+}
+
+pub fn run(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ let mut chosen_cmd = &COMMANDS[0];
+ let mut chosen_submatches = &clap::ArgMatches::<'_>::default();
+ for cmd in COMMANDS {
+ if let Some(submatches) = matches.subcommand_matches(cmd.name) {
+ chosen_cmd = cmd;
+ chosen_submatches = submatches;
+ }
+ }
+
+ env_logger::from_env(
+ env_logger::Env::default().default_filter_or(chosen_cmd.log_level),
+ )
+ .init();
+
+ let config = crate::config::config(
+ matches.value_of("config-file").map(std::path::Path::new),
+ )?;
+ let mut cmd_config = (chosen_cmd.config)(config)?;
+ cmd_config.merge_args(chosen_submatches)?;
+ log::debug!("{:?}", cmd_config);
+
+ // XXX ideally we'd be able to run everything on the current_thread
+ // runtime, but this is blocked on
+ // https://github.com/tokio-rs/tokio/issues/1356 (fixed in the 0.2 branch
+ // which is not yet stable)
+
+ // let mut runtime = tokio::runtime::current_thread::Runtime::new()
+ // .unwrap();
+ // runtime
+ // .block_on(cmd_config.run().map_err(|e| {
+ // log::error!("{}", e);
+ // }))
+ // .unwrap();
+
+ tokio::run(cmd_config.run().map_err(|e| {
+ log::error!("{}", e);
+ }));
+
+ Ok(())
+}
+
+fn program_name() -> Result<String> {
+ let program =
+ std::env::args().next().context(crate::error::MissingArgv)?;
+ let path = std::path::Path::new(&program);
+ let filename = path.file_name();
+ Ok(filename
+ .ok_or_else(|| Error::NotAFileName {
+ path: path.to_string_lossy().to_string(),
+ })?
+ .to_string_lossy()
+ .to_string())
+}