diff --git a/src/commands/create.rs b/src/commands/create.rs index bd165c9..be99d46 100644 --- a/src/commands/create.rs +++ b/src/commands/create.rs @@ -1,9 +1,9 @@ -use anyhow::{anyhow, Context, Result}; +use anyhow::{Context, Result}; use clap::Parser; use std::{collections::BTreeMap, path::PathBuf}; -use crate::utils::prompt_for_input; +use crate::utils::{prompt_for_input, parse_package_id}; const DEFAULT_COMPILE_SDK_VERSION: &str = "33"; const DEFAULT_TARGET_SDK_VERSION: &str = "33"; @@ -46,22 +46,6 @@ pub struct Create { fn get_vars(args: &Create) -> Result> { let mut map = BTreeMap::::new(); - // FIXME: this is a hack, we should use a proper parser - let get_package_id = |package_id: String| { - let mut parts = package_id.split('.'); - let domain = parts - .next() - .ok_or_else(|| anyhow!("domain part missing in package"))?; - let org = parts - .next() - .ok_or_else(|| anyhow!("org part missing in package"))?; - let name = parts - .next() - .ok_or_else(|| anyhow!("name part missing in package"))?; - - anyhow::Ok((domain.to_owned(), org.to_owned(), name.to_owned())) - }; - // Metadata map.insert( "project_name".into(), @@ -70,7 +54,7 @@ fn get_vars(args: &Create) -> Result> { map.insert("app_name".into(), args.name.as_ref().unwrap().to_owned()); // Package identifiers - let (domain, org, name) = get_package_id(args.package_id.as_ref().unwrap().to_owned()) + let (domain, org, name) = parse_package_id(args.package_id.as_ref().unwrap().to_owned()) .context("failed to parse package id")?; map.insert("package_id_domain".into(), domain); map.insert("package_id_org".into(), org); @@ -94,7 +78,7 @@ fn post_create(args: Create) -> Result<()> { let dest = args.dest.clone().unwrap(); android_cli::create_local_properties_file(&dest, &args.sdk_path.unwrap())?; - android_cli::create_dot_android(&dest, args.package_id.unwrap())?; + android_cli::create_dot_android(&dest, args.project_name.unwrap(), args.package_id.unwrap(), None)?; Ok(()) } diff --git a/src/commands/link.rs b/src/commands/link.rs new file mode 100644 index 0000000..8e72648 --- /dev/null +++ b/src/commands/link.rs @@ -0,0 +1,32 @@ +use std::path::Path; + +use anyhow::{Context, Result}; +use clap::Parser; + +use crate::utils::{prompt_for_input, safe_name}; + +#[derive(Parser, Debug)] +pub struct Link {} + +pub fn handle(_args: Link) -> Result<()> { + let project_name = prompt_for_input("Enter project name", None)?; + let package_id = prompt_for_input("Enter package identifier", None) + .map(safe_name) + .unwrap(); + let main_activity_name = prompt_for_input( + "Main Activity name", + Some(android_cli::DEFAULT_MAIN_ACTIVITY.into()), + )?; + + android_cli::create_dot_android( + &Path::new("."), + project_name, + package_id, + Some(main_activity_name.into()), + ) + .context("Failed to link project")?; + + println!("Successfully linked the project"); + + Ok(()) +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 6fd47d0..cd392f4 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -4,3 +4,4 @@ pub mod install; pub mod run; pub mod launch; pub mod devices; +pub mod link; diff --git a/src/lib.rs b/src/lib.rs index b21eccc..1d65d95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,16 +13,17 @@ use std::{ use utils::{find_adb, find_gradle}; -const VERSION: &str = env!("CARGO_PKG_VERSION"); +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); +pub const DEFAULT_MAIN_ACTIVITY: &str = "MainActivity"; const DEFAULT_TEMPLATE_REPO: &str = "https://github.com/SyedAhkam/android-cli-template"; const TEMPLATE_REV: &str = "master"; const DOTFILE_COMMENT: &str = "// DO NOT MODIFY; Generated by Android CLI for internal usage.\n"; -const DEFAULT_MAIN_ACTIVITY: &str = "MainActivity"; #[derive(Debug, Serialize, Deserialize)] pub struct DotAndroid { + pub project_name: String, pub package_id: String, pub gen_at_version: String, pub main_activity_name: String, @@ -82,12 +83,13 @@ pub fn invoke_adb_command(args: &[&str]) -> Result { Ok(run.status()?) } -pub fn create_dot_android(dest: &Path, package_id: String) -> Result<()> { +pub fn create_dot_android(dest: &Path, project_name: String, package_id: String, main_activity_name: Option) -> Result<()> { // Construct the structure let dot_android = DotAndroid { package_id, + project_name, gen_at_version: VERSION.to_owned(), - main_activity_name: DEFAULT_MAIN_ACTIVITY.to_owned(), + main_activity_name: main_activity_name.unwrap_or(DEFAULT_MAIN_ACTIVITY.to_owned()) }; // Serialize into Ron diff --git a/src/main.rs b/src/main.rs index 681f775..1404d0e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,8 @@ enum SubCommand { Install(commands::install::Install), Run(commands::run::Run), Launch(commands::launch::Launch), - Devices(commands::devices::Devices) + Devices(commands::devices::Devices), + Link(commands::link::Link) } fn main() { @@ -35,7 +36,8 @@ fn main() { SubCommand::Install(args) => commands::install::handle(args), SubCommand::Run(args) => commands::run::handle(args), SubCommand::Launch(args) => commands::launch::handle(args), - SubCommand::Devices(args) => commands::devices::handle(args) + SubCommand::Devices(args) => commands::devices::handle(args), + SubCommand::Link(args) => commands::link::handle(args) }; if result.is_err() { diff --git a/src/utils.rs b/src/utils.rs index e1a9718..3cc2838 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -use anyhow::{Context, Result}; +use anyhow::{anyhow, Context, Result}; use which::which; pub fn prompt_for_input(prompt: &str, default: Option) -> Result { @@ -17,6 +17,29 @@ pub fn prompt_for_input(prompt: &str, default: Option) -> Result .context("failed to prompt user")?) } +// FIXME: this is a hack, we should use a proper parser +pub fn parse_package_id(package_id: String) -> Result<(String, String, String)> { + let mut parts = package_id.split('.'); + let domain = parts + .next() + .ok_or_else(|| anyhow!("domain part missing in package"))?; + + let org = parts + .next() + .ok_or_else(|| anyhow!("org part missing in package"))?; + + let name = parts + .next() + .ok_or_else(|| anyhow!("name part missing in package"))?; + + anyhow::Ok((domain.to_owned(), org.to_owned(), name.to_owned())) +} + + +pub fn safe_name(name: String) -> String { + name.to_lowercase().replace(" ", "_") +} + pub fn find_gradle() -> Option { if std::path::Path::new("./gradlew").exists() { return Some("./gradlew".to_owned());