From cce51e0269e38706e3c233c000f48cc6ba1dfbb5 Mon Sep 17 00:00:00 2001 From: Amidamaru Date: Sat, 15 Feb 2025 18:16:05 +0700 Subject: [PATCH] feat: add auto completion shell support for `poststation-cli` Support auto-completion for your shell. --- tools/Cargo.lock | 10 ++++++++ tools/poststation-cli/Cargo.toml | 1 + tools/poststation-cli/src/device/mod.rs | 28 +++++++++++----------- tools/poststation-cli/src/main.rs | 31 ++++++++++++++++++++++--- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/tools/Cargo.lock b/tools/Cargo.lock index ded4e90..999921f 100644 --- a/tools/Cargo.lock +++ b/tools/Cargo.lock @@ -202,6 +202,15 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_complete" +version = "4.5.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375f9d8255adeeedd51053574fd8d4ba875ea5fa558e86617b07f09f1680c8b6" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" version = "4.5.18" @@ -735,6 +744,7 @@ version = "0.4.3" dependencies = [ "anyhow", "clap", + "clap_complete", "directories", "postcard", "postcard-rpc", diff --git a/tools/poststation-cli/Cargo.toml b/tools/poststation-cli/Cargo.toml index ec9bfa0..8e76046 100644 --- a/tools/poststation-cli/Cargo.toml +++ b/tools/poststation-cli/Cargo.toml @@ -11,6 +11,7 @@ license = "MIT OR Apache-2.0" [dependencies] anyhow = "1.0.89" clap = { version = "4.5.19", features = ["derive"] } +clap_complete = "4.5.44" directories = "5.0.1" rand = "0.8.5" serde_json = "1.0.128" diff --git a/tools/poststation-cli/src/device/mod.rs b/tools/poststation-cli/src/device/mod.rs index 9c99a0c..fadeeb7 100644 --- a/tools/poststation-cli/src/device/mod.rs +++ b/tools/poststation-cli/src/device/mod.rs @@ -27,15 +27,19 @@ pub enum DeviceCommands { /// View all topics handled by a given device TopicsIn, /// View the most recent logs from a given device - Logs { count: Option }, + Logs { + #[arg(default_value = "8")] + count: u32, + }, /// View the selected range of logs from a given device LogsRange { - /// Number of logs to print - count: Option, /// The UUID of the log to start from start: String, /// Direction to print from ('before' or 'after') direction: String, + /// Number of logs to print + #[arg(default_value = "8")] + count: u32, }, /// Proxy message to device endpoint Proxy { @@ -153,20 +157,15 @@ async fn device_types(serial: u64, schema: &SchemaReport) -> anyhow::Result<()> Ok(()) } -async fn device_logs( - client: PoststationClient, - serial: u64, - count: &Option, -) -> anyhow::Result<()> { - let count = count.unwrap_or(8); +async fn device_logs(client: PoststationClient, serial: u64, count: &u32) -> anyhow::Result<()> { let logs = client - .get_device_logs(serial, count) + .get_device_logs(serial, *count) .await .expect("expected to be able to get logs for device") .expect("expected device to have known logs"); println!(); - println!("Logs (last {} messages):", count.min(logs.len() as u32)); + println!("Logs (last {} messages):", count.min(&(logs.len() as u32))); println!(); for log in logs { // println!("* {} => {}", log.uuidv7.id_to_time().time(), log.msg); @@ -185,11 +184,10 @@ async fn device_logs( async fn device_logs_range( client: PoststationClient, serial: u64, - count: &Option, + count: &u32, start: &str, direction: &str, ) -> anyhow::Result<()> { - let count = count.unwrap_or(8); let start = start.parse::()?; let dir = match direction.to_lowercase().as_str() { "after" => Direction::After, @@ -200,7 +198,7 @@ async fn device_logs_range( let logs = client .get_device_logs_range( serial, - count, + *count, dir, poststation_api_icd::postsock::Anchor::Uuid(start.into()), ) @@ -209,7 +207,7 @@ async fn device_logs_range( .expect("expected device to have known logs"); println!(); - println!("Logs (last {} messages):", count.min(logs.len() as u32)); + println!("Logs (last {} messages):", count.min(&(logs.len() as u32))); println!(); for log in logs { // println!("* {} => {}", log.uuidv7.id_to_time().time(), log.msg); diff --git a/tools/poststation-cli/src/main.rs b/tools/poststation-cli/src/main.rs index bfc2f05..5374d98 100644 --- a/tools/poststation-cli/src/main.rs +++ b/tools/poststation-cli/src/main.rs @@ -1,12 +1,17 @@ -use std::{net::SocketAddr, path::{Path, PathBuf}, time::Instant}; +use std::{ + net::SocketAddr, + path::{Path, PathBuf}, + time::Instant, +}; use anyhow::bail; -use clap::{command, Parser, Subcommand}; +use clap::{arg, command, CommandFactory, Parser, Subcommand}; use device::{device_cmds, Device}; use directories::ProjectDirs; use postcard_rpc::host_client::{EndpointReport, TopicReport}; use poststation_sdk::{ - connect, connect_insecure, connect_with_ca_pem, schema::schema::owned::OwnedDataModelType, ConnectError, PoststationClient + connect, connect_insecure, connect_with_ca_pem, schema::schema::owned::OwnedDataModelType, + ConnectError, PoststationClient, }; mod device; @@ -46,6 +51,12 @@ enum Commands { /// Interact with a specific device Device(Device), + + /// Generate auto-completion for given shell + Completion { + #[arg(value_enum)] + shell: clap_complete::Shell, + }, } #[tokio::main] @@ -61,6 +72,19 @@ async fn main() -> anyhow::Result<()> { } async fn inner_main(cli: Cli) -> anyhow::Result<()> { + // Handle completion command first, before any server connection + if let Commands::Completion { shell } = cli.command { + println!("Start generating completion script for {shell} shell"); + clap_complete::generate( + shell, + &mut Cli::command(), + env!("CARGO_PKG_NAME"), + &mut std::io::stdout().lock(), + ); + println!("Successfully generated completion script."); + return Ok(()); + } + let server = cli .server .unwrap_or_else(|| "127.0.0.1:51837".parse().unwrap()); @@ -136,6 +160,7 @@ async fn inner_main(cli: Cli) -> anyhow::Result<()> { println!(); Ok(()) } + Commands::Completion { .. } => Ok(()), } }