From 561a3e325678c08f75e40d92f1d1a236f02a4983 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Jun 2021 17:05:55 -0400 Subject: [PATCH] Modernize serve subcommand --- src/cli/mod.rs | 28 ++------------------ src/cli/serve.rs | 69 +++++++++++++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 50 deletions(-) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 60ce87f4..30081d77 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -13,7 +13,6 @@ use std::{ env, error::Error, fmt, - net::IpAddr, path::{Path, PathBuf}, str::FromStr, }; @@ -26,7 +25,7 @@ pub use self::doc::DocCommand; pub use self::fmt_project::FmtProjectCommand; pub use self::init::{InitCommand, InitKind}; pub use self::plugin::{PluginCommand, PluginSubcommand}; -pub use self::serve::*; +pub use self::serve::ServeCommand; pub use self::upload::*; /// Command line options that Rojo accepts, defined using the structopt crate. @@ -45,7 +44,7 @@ impl Options { pub fn run(self) -> anyhow::Result<()> { match self.subcommand { Subcommand::Init(subcommand) => subcommand.run(), - Subcommand::Serve(serve_options) => serve(self.global, serve_options), + Subcommand::Serve(subcommand) => subcommand.run(self.global), Subcommand::Build(subcommand) => subcommand.run(), Subcommand::Upload(upload_options) => upload(upload_options), Subcommand::FmtProject(subcommand) => subcommand.run(), @@ -125,29 +124,6 @@ pub enum Subcommand { Plugin(PluginCommand), } -/// Expose a Rojo project to the Rojo Studio plugin. -#[derive(Debug, StructOpt)] -pub struct ServeCommand { - /// Path to the project to serve. Defaults to the current directory. - #[structopt(default_value = "")] - pub project: PathBuf, - - /// The IP address to listen on. Defaults to `127.0.0.1`. - #[structopt(long)] - pub address: Option, - - /// The port to listen on. Defaults to the project's preference, or `34872` if - /// it has none. - #[structopt(long)] - pub port: Option, -} - -impl ServeCommand { - pub fn absolute_project(&self) -> Cow<'_, Path> { - resolve_path(&self.project) - } -} - /// Builds the project and uploads it to Roblox. #[derive(Debug, StructOpt)] pub struct UploadCommand { diff --git a/src/cli/serve.rs b/src/cli/serve.rs index bc2cc1aa..abd3dd8e 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -1,52 +1,73 @@ use std::{ io::{self, Write}, - net::IpAddr, - net::Ipv4Addr, + net::{IpAddr, Ipv4Addr}, + path::PathBuf, sync::Arc, }; -use anyhow::Result; use memofs::Vfs; +use structopt::StructOpt; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; -use crate::{ - cli::{GlobalOptions, ServeCommand}, - serve_session::ServeSession, - web::LiveServer, -}; +use crate::{serve_session::ServeSession, web::LiveServer}; + +use super::{resolve_path, GlobalOptions}; const DEFAULT_BIND_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); const DEFAULT_PORT: u16 = 34872; -pub fn serve(global: GlobalOptions, options: ServeCommand) -> Result<()> { - let vfs = Vfs::new_default(); +/// Expose a Rojo project to the Rojo Studio plugin. +#[derive(Debug, StructOpt)] +pub struct ServeCommand { + /// Path to the project to serve. Defaults to the current directory. + #[structopt(default_value = "")] + pub project: PathBuf, - let session = Arc::new(ServeSession::new(vfs, &options.absolute_project())?); + /// The IP address to listen on. Defaults to `127.0.0.1`. + #[structopt(long)] + pub address: Option, - let ip = options.address.unwrap_or(DEFAULT_BIND_ADDRESS.into()); + /// The port to listen on. Defaults to the project's preference, or `34872` if + /// it has none. + #[structopt(long)] + pub port: Option, +} - let port = options - .port - .or_else(|| session.project_port()) - .unwrap_or(DEFAULT_PORT); +impl ServeCommand { + pub fn run(self, global: GlobalOptions) -> anyhow::Result<()> { + let project_path = resolve_path(&self.project); - let server = LiveServer::new(session); + let vfs = Vfs::new_default(); - let _ = show_start_message(ip, port, global.color.into()); - server.start((ip, port).into()); + let session = Arc::new(ServeSession::new(vfs, &project_path)?); - Ok(()) + let ip = self.address.unwrap_or(DEFAULT_BIND_ADDRESS.into()); + + let port = self + .port + .or_else(|| session.project_port()) + .unwrap_or(DEFAULT_PORT); + + let server = LiveServer::new(session); + + let _ = show_start_message(ip, port, global.color.into()); + server.start((ip, port).into()); + + Ok(()) + } } fn show_start_message(bind_address: IpAddr, port: u16, color: ColorChoice) -> io::Result<()> { + let mut green = ColorSpec::new(); + green.set_fg(Some(Color::Green)).set_bold(true); + let writer = BufferWriter::stdout(color); let mut buffer = writer.buffer(); writeln!(&mut buffer, "Rojo server listening:")?; write!(&mut buffer, " Address: ")?; - buffer.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?; - + buffer.set_color(&green)?; if bind_address.is_loopback() { writeln!(&mut buffer, "localhost")?; } else { @@ -55,7 +76,7 @@ fn show_start_message(bind_address: IpAddr, port: u16, color: ColorChoice) -> io buffer.set_color(&ColorSpec::new())?; write!(&mut buffer, " Port: ")?; - buffer.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?; + buffer.set_color(&green)?; writeln!(&mut buffer, "{}", port)?; writeln!(&mut buffer)?; @@ -63,7 +84,7 @@ fn show_start_message(bind_address: IpAddr, port: u16, color: ColorChoice) -> io buffer.set_color(&ColorSpec::new())?; write!(&mut buffer, "Visit ")?; - buffer.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?; + buffer.set_color(&green)?; write!(&mut buffer, "http://localhost:{}/", port)?; buffer.set_color(&ColorSpec::new())?;